-- BcdSEBuild.mesa -- Last edited by Satterthwaite on September 14, 1982 4:10 pm -- Last edited by Lewis on 17-Dec-80 16:30:26 DIRECTORY Alloc: TYPE USING [AddNotify, DropNotify, Notifier], BcdComData: TYPE USING [commandArgs, currentName, table, textIndex], BcdControlDefs: TYPE USING [], BcdDefs: TYPE USING [cttype, cxtype, FTIndex, FTNull, NameRecord, sttype, treetype], CommandUtil: TYPE USING [GetNthPair, ListLength, PairList], Symbols: TYPE USING [CXIndex, HTIndex, STIndex, STNull], SymbolOps: TYPE USING [EnterString, SubStringForHash], BcdUtilDefs: TYPE USING [EnterFile, NameForSti, NewContext, NewSemanticEntry], Strings: TYPE USING [AppendSubString, String, SubStringDescriptor], Table: TYPE USING [Base], Tree: TYPE USING [Index, Link, Map, Null], TreeOps: TYPE USING [FreeNode, GetNode, UpdateList]; BcdSEBuild: PROGRAM IMPORTS Alloc, BcdUtilDefs, CommandUtil, Strings, SymbolOps, TreeOps, data: BcdComData EXPORTS BcdControlDefs = { OPEN BcdDefs, Symbols; BuildSEError: PUBLIC ERROR ~ CODE; tb, stb, ctb, cxb: Table.Base; Notifier: Alloc.Notifier ~ { tb ← base[treetype]; stb ← base[sttype]; cxb ← base[cxtype]; ctb ← base[cttype]}; currentCtx, directoryCtx: CXIndex; BuildSemanticEntries: PUBLIC PROC [root: Tree.Link] ~ { node: Tree.Index; (data.table).AddNotify[Notifier]; node ← TreeOps.GetNode[root]; IF tb[node].name # $source THEN ERROR BuildSEError; currentCtx ← directoryCtx ← BcdUtilDefs.NewContext[]; IF CommandUtil.ListLength[data.commandArgs] > 0 THEN EnterArgsAsDirItems[]; tb[node].son[1] ← TreeOps.UpdateList[tb[node].son[1], DirItem]; currentCtx ← BcdUtilDefs.NewContext[]; tb[node].son[2] ← TreeOps.UpdateList[tb[node].son[2], PackId]; currentCtx ← BcdUtilDefs.NewContext[]; tb[node].son[3] ← Stmt[tb[node].son[3]]; (data.table).DropNotify[Notifier]}; Stmt: Tree.Map ~ { WITH t SELECT FROM hash => v ← Item[t]; symbol => v ← Item[t]; subtree => { node: Tree.Index ~ index; saveIndex: CARDINAL ~ data.textIndex; data.textIndex ← tb[node].info; v ← SELECT tb[node].name FROM $list => TreeOps.UpdateList[t, Stmt], $item => Item[t], $config => Config[node], $assign => Assign[node], $plus, $then => Expression[t], $module => Module[node], ENDCASE => ERROR BuildSEError; data.textIndex ← saveIndex}; ENDCASE => ERROR BuildSEError; RETURN}; PackId: Tree.Map ~ { RETURN [WITH t SELECT FROM hash => SemanticEntry[t], subtree => TreeOps.UpdateList[t, PackId], ENDCASE => ERROR BuildSEError]}; ProcessItem: PROC [t: Tree.Link] RETURNS [tl: Tree.Link, st1,st2: STIndex] ~ { stl: Tree.Link[symbol]; st2 ← STNull; WITH tt~~t SELECT FROM symbol => {tl ← tt; st1 ← tt.index}; hash => {tl ← stl ← SemanticEntry[t]; st1 ← stl.index}; subtree => { OPEN tb[tt.index]; tl ← t; son[1] ← stl ← SemanticEntry[son[1]]; st1 ← stl.index; IF son[2] # Tree.Null THEN { stb[st1].filename ← FALSE; son[2] ← stl ← SemanticEntry[son[2]]; st2 ← stl.index; stb[st1].body ← external[pointer~instance[st2], map~[unknown[]]]}}; ENDCASE => ERROR BuildSEError; RETURN}; SetFilename: PROC [sti: STIndex] ~ { OPEN stb[sti]; IF ~stb[sti].filename AND stb[sti].type = $unknown THEN { stb[sti].filename ← TRUE; stb[sti].body ← external[pointer~file[FTNull], map~[unknown[]]]}}; Item: Tree.Map ~ { st1, st2: STIndex; [v, st1, st2] ← ProcessItem[t]; SetFilename[IF st2 = STNull THEN st1 ELSE st2]; RETURN}; EnterArgsAsDirItems: PROC ~ { -- enter Idi: FileNamei pairs from command line as DIRECTORY entries lhs, rhs: Strings.String; lhsSS: Strings.SubStringDescriptor; lhsHti: Symbols.HTIndex; sti, last: Symbols.STIndex; rhsFti: BcdDefs.FTIndex; FOR n: CARDINAL IN [0 .. CommandUtil.ListLength[data.commandArgs]) DO { [lhs, rhs] ← CommandUtil.GetNthPair[list~data.commandArgs, n~n]; lhsSS ← [base~lhs, offset~0, length~lhs.length]; lhsHti ← SymbolOps.EnterString[@lhsSS]; last ← Symbols.STNull; FOR sti ← cxb[directoryCtx].link, stb[sti].link UNTIL sti = Symbols.STNull DO IF stb[sti].hti = lhsHti THEN GOTO AlreadyEntered; last ← sti; ENDLOOP; sti ← BcdUtilDefs.NewSemanticEntry[lhsHti]; IF last = Symbols.STNull THEN cxb[directoryCtx].link ← sti ELSE stb[last].link ← sti; rhsFti ← BcdUtilDefs.EnterFile[rhs]; stb[sti].body ← external[map~[unknown[]], pointer~file[rhsFti]]; EXITS AlreadyEntered => NULL}; ENDLOOP}; DirItem: Tree.Map ~ { lhs: Tree.Link; lhsHti: Symbols.HTIndex; dirSti, sti: STIndex; stl: Tree.Link[symbol]; fileName: STRING ← [40]; fti: FTIndex; name: Strings.SubStringDescriptor; WITH t SELECT FROM subtree => { lhs ← tb[index].son[1]; WITH lhs SELECT FROM hash => lhsHti ← index; ENDCASE => ERROR BuildSEError; FOR dirSti ← cxb[directoryCtx].link, stb[dirSti].link UNTIL dirSti = Symbols.STNull DO IF stb[dirSti].hti = lhsHti THEN RETURN [t]; -- already inserted ENDLOOP; stl ← SemanticEntry[lhs]; sti ← stl.index; WITH s2~~tb[index].son[2] SELECT FROM hash => SymbolOps.SubStringForHash[@name, s2.index]; ENDCASE}; ENDCASE; Strings.AppendSubString[fileName, @name]; fti ← BcdUtilDefs.EnterFile[fileName]; stb[sti].body ← external[map~[unknown[]], pointer~file[fti]]; RETURN [t]}; ImpItem: Tree.Map ~ { st1: STIndex; [v, st1, ] ← ProcessItem[t]; stb[st1].imported ← TRUE; RETURN}; ExpItem: Tree.Map ~ { st1: STIndex; [v, st1, ] ← ProcessItem[t]; stb[st1].exported ← TRUE; RETURN}; Config: PROC [node: Tree.Index] RETURNS [Tree.Link] ~ { OPEN tb[node]; saveCx: CXIndex ~ currentCtx; saveName: NameRecord ~ data.currentName; SeEntry: Tree.Map ~ {RETURN [SemanticEntry[t]]}; EnterConfig[node]; -- name son[1] ← TreeOps.UpdateList[son[1], ImpItem]; -- IMPORTS son[2] ← TreeOps.UpdateList[son[2], ExpItem]; -- EXPORTS son[3] ← TreeOps.UpdateList[son[3], SeEntry]; -- CONTROL son[5] ← TreeOps.UpdateList[son[5], Stmt]; -- body currentCtx ← saveCx; data.currentName ← saveName; RETURN [[subtree[node]]]}; AssignItem: Tree.Map ~ { st1, st2: STIndex; [v, st1, st2] ← ProcessItem[t]; stb[st1].assigned ← TRUE; IF stb[st1].filename THEN { OPEN stb[st1]; filename ← FALSE; body ← external[pointer~instance[st2], map~[unknown[]]]}; IF st2 # STNull THEN { OPEN stb[st2]; assigned ← TRUE; filename ← FALSE; body ← external[pointer~instance[STNull], map~[unknown[]]]}; RETURN}; Assign: PROC [node: Tree.Index] RETURNS [Tree.Link] ~ { tb[node].son[1] ← TreeOps.UpdateList[tb[node].son[1], AssignItem]; tb[node].son[2] ← Expression[tb[node].son[2]]; RETURN [[subtree[node]]]}; Expression: Tree.Map ~ { WITH t SELECT FROM symbol => v ← ProcessItem[t].tl; hash => v ← ProcessItem[t].tl; subtree => SELECT tb[index].name FROM $item => v ← ProcessItem[t].tl; $module => v ← Module[index]; $plus, $then => { OPEN tb[index]; son[1] ← Expression[son[1]]; son[2] ← Expression[son[2]]; v ← t}; ENDCASE => ERROR BuildSEError; ENDCASE => ERROR BuildSEError; RETURN}; ModItem: Tree.Map ~ { RETURN [WITH t SELECT FROM symbol => t, hash => SemanticEntry[t], ENDCASE => ERROR BuildSEError]}; Module: PROC [node: Tree.Index] RETURNS [Tree.Link] ~ { tb[node].son[1] ← Item[tb[node].son[1]]; tb[node].son[2] ← TreeOps.UpdateList[tb[node].son[2], ModItem]; RETURN [[subtree[node]]]}; SemanticEntry: PROC [tl: Tree.Link] RETURNS [Tree.Link[symbol]] ~ { sti, dirSti: STIndex; last: STIndex ← STNull; WITH t~~tl SELECT FROM symbol => RETURN [t]; hash => { FOR sti ← cxb[currentCtx].link, stb[sti].link UNTIL sti = STNull DO IF stb[sti].hti = t.index THEN RETURN [[symbol[sti]]]; last ← sti; ENDLOOP; FOR dirSti ← cxb[directoryCtx].link, stb[dirSti].link UNTIL dirSti = STNull DO IF stb[dirSti].hti = t.index THEN EXIT ENDLOOP; sti ← BcdUtilDefs.NewSemanticEntry[t.index]; IF last = STNull THEN cxb[currentCtx].link ← sti ELSE stb[last].link ← sti; IF dirSti # STNull THEN {stb[sti] ← stb[dirSti]; stb[sti].link ← STNull}; RETURN [[symbol[sti]]]}; subtree => { node: Tree.Index ~ t.index; l: Tree.Link; SELECT tb[node].name FROM $dot => {l ← tb[node].son[1]; tb[node].son[1] ← Tree.Null}; $slash => {l ← tb[node].son[2]; tb[node].son[2] ← Tree.Null}; ENDCASE => ERROR BuildSEError; TreeOps.FreeNode[node]; RETURN [SemanticEntry[l]]}; ENDCASE => ERROR BuildSEError}; EnterConfig: PROC [node: Tree.Index] ~ { sti: STIndex; stl: Tree.Link[symbol] ~ SemanticEntry[tb[node].son[4]]; tb[node].son[4] ← stl; stb[(sti ← stl.index)].filename ← FALSE; currentCtx ← BcdUtilDefs.NewContext[]; data.currentName ← BcdUtilDefs.NameForSti[sti]; SELECT stb[sti].type FROM $unknown => stb[sti].body ← local[info~node, context~currentCtx, map~[unknown[]]]; ENDCASE => ERROR BuildSEError}; }.