DIRECTORY Alloc: TYPE USING [AddNotify, Bounds, DropNotify, Handle, Notifier, Top, Words], BcdBindDefs: TYPE USING [Relocations, RelocHandle, RelocType], BcdComData: TYPE USING [currentName, literals, objectStamp, op, outputFti, table, textIndex, typeExported], BcdControlDefs: TYPE USING [], BcdDefs: TYPE USING [rftype, BCD, BcdBase, ControlItem, CTIndex, CTNull, CTRecord, cttype, cxtype, evtype, EXPIndex, EXPNull, EXPRecord, exptype, FPIndex, FPNull, FPRecord, fptype, FTIndex, FTNull, FTRecord, FTSelf, fttype, IMPIndex, IMPNull, IMPRecord, imptype, lftype, Link, LinkLocation, MaxNDMi, ModuleIndex, MTIndex, MTNull, MTRecord, mttype, NameRecord, nttype, NullLink, NullName, ProcLimit, RFNull, SGIndex, SGRecord, sgtype, SpaceID, SPIndex, SPNull, SPRecord, sptype, sstype, sttype, TFNull, tftype, treetype, TMIndex, TMRecord, tmtype, TYPIndex, TYPNull, typtype, VersionID], BcdErrorDefs: TYPE USING [Error, ErrorFile, ErrorHti, ErrorItem, ErrorModule, ErrorName, ErrorSti, Error2Files, GetSti], BcdFileDefs: TYPE USING [CapabilityForFile, UnknownFile], BcdLiterals: TYPE USING [Load, MapLitLink, MapTypeLink, Unload], BcdUtilDefs: TYPE USING [BcdBasePtr, BcdBases, BcdLimits, ContextForTree, CreateInstanceName, EnterConfig, EnterExport, EnterFramePack, EnterImport, EnterModule, EnterSegment, EnterSpace, EnterType, EnterTypeMap, FileForVersion, EqVersions, GetDummyGfi, GetGfi, HtiForName, MergeFile, NameForSti, NewSemanticEntry, SetFileVersion], FS: TYPE USING [OpenFile, Error, Read], OSMiscOps: TYPE USING [MergeStamps, TimeToStamp], PrincOpsUtils: TYPE USING [LongCopy], Symbols: TYPE USING [CXIndex, cxNull, HTIndex, htNull, STIndex, STMap, stNull], Table: TYPE USING [Base, Index], Tree: TYPE USING [Index, Link, NodeName, Scan, null, nullIndex], TreeOps: TYPE USING [GetNode, ListLength, ScanList, UpdateList], VM: TYPE USING [AddressForPageNumber, Allocate, Free, Interval, nullInterval]; BcdLoad: PROGRAM IMPORTS Alloc, BcdErrorDefs, BcdFileDefs, BcdUtilDefs, BcdLiterals, FS, OSMiscOps, PrincOpsUtils, TreeOps, VM, data: BcdComData EXPORTS BcdControlDefs = { OPEN BcdDefs, Symbols; Zero: PROC[p: LONG POINTER, l: CARDINAL] ~ INLINE { IF l # 0 THEN {p^ _ 0; PrincOpsUtils.LongCopy[from~p, to~(p+1), nwords~(l-1)]}}; FileMapItem: TYPE ~ RECORD [old, new: FTIndex]; InterfaceOp: TYPE ~ Tree.NodeName [$plus..$then]; ExportAssigner: TYPE ~ PROC; LoadError: PUBLIC ERROR ~ CODE; currentCx, loadCx: CXIndex; loadTree: Tree.Index; loadExpi: EXPIndex; packSti: STIndex; currentOp: InterfaceOp; table: Alloc.Handle; tb, stb, cxb: Table.Base; exportsALL: BOOL; localBases: BcdUtilDefs.BcdBasePtr _ NEW[BcdUtilDefs.BcdBases]; limits: BcdUtilDefs.BcdLimits; bcd: BcdUtilDefs.BcdBasePtr; Notifier: Alloc.Notifier ~ { tb _ base[treetype]; stb _ base[sttype]; cxb _ base[cxtype]; localBases^ _ [ ssb: LOOPHOLE[base[sstype]], ctb: base[cttype], mtb: base[mttype], lfb: base[lftype], rfb: base[rftype], tfb: base[tftype], etb: base[exptype], evb: base[evtype], itb: base[imptype], sgb: base[sgtype], ftb: base[fttype], tyb: base[typtype], tmb: base[tmtype], ntb: base[nttype], spb: base[sptype], fpb: base[fptype]] }; Error: PROC ~ {ERROR LoadError}; LoadRoot: PUBLIC PROC[root: Tree.Link] RETURNS[BcdBindDefs.RelocHandle] ~ { node: Tree.Index; table _ data.table; table.AddNotify[Notifier]; bcd _ localBases; currentOp _ $plus; currentParms _ Tree.null; processExports _ VerifyExports; relocationHead _ NIL; loadExpi _ EXPNull; loadTree _ Tree.nullIndex; loadCx _ cxNull; exportsALL _ FALSE; data.typeExported _ FALSE; node _ TreeOps.GetNode[root]; SELECT tb[node].name FROM $source => { packSti _ FindSti[tb[node].son[2]]; [] _ LoadLocalConfig[TreeOps.GetNode[tb[node].son[3]], $outer, htNull]}; ENDCASE => Error[]; table.DropNotify[Notifier]; table _ NIL; RETURN[relocationHead]}; FindSti: PROC[t: Tree.Link] RETURNS[STIndex] ~ { RETURN[IF t = Tree.null THEN stNull ELSE WITH t SELECT FROM symbol => index, subtree => FindSti[tb[index].son[1]], ENDCASE => ERROR LoadError] }; currentParms: Tree.Link; BodyWalk: Tree.Scan ~ { WITH t SELECT FROM symbol => LoadSti[index, htNull]; subtree => { node: Tree.Index ~ index; saveIndex: CARDINAL ~ data.textIndex; data.textIndex _ tb[node].info; SELECT tb[node].name FROM $list => TreeOps.ScanList[t, BodyWalk]; $item => LoadItem[t]; $config => NULL; $assign => LoadAssign[t]; $module => { currentParms _ tb[node].son[2]; LoadItem[tb[node].son[1]]}; ENDCASE => Error[]; data.textIndex _ saveIndex}; ENDCASE => Error[]}; LoadLocalConfig: PROC[ node: Tree.Index, level: BcdBindDefs.RelocType, name: HTIndex] RETURNS[Symbols.STMap] ~ { saveCx: CXIndex ~ currentCx; saveLhs: Tree.Link ~ lhs; saveAssigner: ExportAssigner ~ processExports; saveName: NameRecord ~ data.currentName; saveIndex: CARDINAL ~ data.textIndex; currentCti: CTIndex; firstConfig: CTIndex ~ table.Top[cttype]; firstModule: MTIndex ~ table.Top[mttype]; localRel: BcdBindDefs.RelocHandle; firstImport: IMPIndex ~ table.Top[imptype]; data.textIndex _ tb[node].info; lhs _ Tree.null; processExports _ NormalExports; currentCx _ BcdUtilDefs.ContextForTree[tb[node].son[4]]; AllocateRelocations[level]; localRel _ rel; localRel.parentcx _ saveCx; BodyWalk[tb[node].son[5]]; -- process body of config IF data.op = $bind THEN { nControls: CARDINAL _ 0; CountControl: PROC[item: ControlItem, sti: STIndex] ~ { nControls _ nControls + 1; IF item = [module[MTNull]] AND sti # stNull THEN BcdErrorDefs.ErrorHti[$error, "is not valid as a CONTROL module"L, stb[sti].hti]}; EnumerateControls[tb[node].son[3], CountControl]; currentCti _ table.Words[cttype, CTRecord.SIZE + nControls*ControlItem.SIZE]; BEGIN OPEN newConfig: localBases.ctb[currentCti]; i: CARDINAL _ 0; AssignControl: PROC[item: ControlItem, sti: STIndex] ~ { newConfig.controls[i] _ item; i _ i+1}; data.currentName _ newConfig.name _ NameForLink[tb[node].son[4]]; IF name = htNull THEN newConfig.namedInstance _ FALSE ELSE { newConfig.namedInstance _ TRUE; BcdUtilDefs.CreateInstanceName[name, [config[currentCti]]]}; newConfig.file _ FTSelf; newConfig.config _ CTNull; UpdateConfigParent[currentCti, firstConfig, currentCti]; UpdateModuleParent[currentCti, firstModule, table.Top[mttype]]; newConfig.nControls _ nControls; EnumerateControls[tb[node].son[3], AssignControl]; END}; lhs _ saveLhs; processExports _ saveAssigner; loadTree _ node; loadCx _ currentCx; currentCx _ saveCx; exportsALL _ tb[node].attrs[$exportsALL]; processExports[]; currentCx _ loadCx; localRel.import _ table.Bounds[imptype].size; localRel.dummygfi _ BcdUtilDefs.GetDummyGfi[0]; ProcessLocalImports[firstImport]; localRel.importLimit _ table.Top[imptype]; loadTree _ Tree.nullIndex; loadCx _ cxNull; currentCx _ saveCx; data.currentName _ saveName; data.textIndex _ saveIndex; RETURN[[config[currentCti]]]}; EnumerateControls: PROC[t: Tree.Link, proc: PROC[ControlItem, STIndex]] ~ { Item: Tree.Scan ~ { WITH t SELECT FROM symbol => { sti: STIndex ~ index; BEGIN WITH s~~stb[sti] SELECT FROM external => WITH m~~s.map SELECT FROM module => proc[[module[m.mti]], sti]; interface => IF localBases.etb[m.expi].port = $module THEN { gfi: ModuleIndex ~ localBases.etb[m.expi].links[0].gfi; FindModule: PROC[mti: MTIndex] RETURNS[stop: BOOL] ~ { RETURN[localBases.mtb[mti].gfi = gfi]}; limits.mt _ table.Top[mttype]; proc[[module[EnumerateModules[FindModule]]], sti]} ELSE GOTO notvalid; config => -- proc[[config[m.cti]], sti]; FOR i: CARDINAL IN [0 .. localBases.ctb[m.cti].nControls) DO proc[localBases.ctb[m.cti].controls[i], stNull]; ENDLOOP; ENDCASE => GOTO notvalid; local => WITH m~~s.map SELECT FROM config => -- proc[[config[m.cti]], sti]; FOR i: CARDINAL IN [0 .. localBases.ctb[m.cti].nControls) DO proc[localBases.ctb[m.cti].controls[i], stNull]; ENDLOOP; ENDCASE => GOTO notvalid; ENDCASE => GOTO notvalid; EXITS notvalid => proc[[module[MTNull]], sti]; END}; ENDCASE => Error[]}; TreeOps.ScanList[t, Item]}; NameForLink: PROC[t: Tree.Link] RETURNS[NameRecord] ~ { RETURN[WITH t SELECT FROM symbol => BcdUtilDefs.NameForSti[index], ENDCASE => NullName]}; LoadSti: PROC[sti: STIndex, name: HTIndex] ~ { ENABLE BcdErrorDefs.GetSti => {RESUME [sti]}; WITH s~~stb[sti] SELECT FROM external => WITH p~~s SELECT FROM file => s.map _ Load[sti, name]; instance => s.map _ Load[p.sti, name]; ENDCASE => Error[]; local => s.map _ LoadLocalConfig[s.info, $inner, name]; ENDCASE => NotLoadable[sti]}; NotLoadable: PROC[sti: STIndex] ~ { BcdErrorDefs.ErrorSti[$error, "is not loadable (probably needs ""[]"")"L, sti]}; FileForSti: PROC[sti: STIndex] RETURNS[FTIndex] ~ { RETURN[ IF sti = stNull THEN FTNull ELSE WITH s~~stb[sti] SELECT FROM unknown => FTNull, external => WITH p~~s SELECT FROM file => p.fti, instance => FileForSti[p.sti], ENDCASE => ERROR LoadError, ENDCASE => ERROR LoadError]}; FileForPortableItem: PROC[p: PortableItem] RETURNS[FTIndex] ~ { RETURN[WITH p SELECT FROM interface => MapFile[bcd.etb[expi].file], module => MapFile[bcd.mtb[mti].file], ENDCASE => ERROR LoadError]}; DeclarePortableItem: PROC[sti: STIndex, p: PortableItem] ~ { WITH p SELECT FROM interface => DeclareInterface[sti, expi, TRUE]; module => DeclareModule[sti, mti, TRUE]; ENDCASE => Error[]}; DeclareInterface: PROC[sti: STIndex, eti: EXPIndex, setMap: BOOL] ~ { fti: FTIndex ~ MapFile[bcd.etb[eti].file]; WITH s~~stb[sti] SELECT FROM external => { IF setMap THEN s.map _ [interface[EXPNull]]; WITH p~~s SELECT FROM instance => IF p.sti = stNull THEN s.pointer _ file[fti] ELSE DeclareInterface[p.sti, eti, FALSE]; file => p.fti _ fti; ENDCASE => Error[]}; unknown => stb[sti].body _ external[ pointer~file[fti], map~(IF setMap THEN [interface[EXPNull]] ELSE [unknown[]])]; ENDCASE => Error[]}; DeclareModule: PROC[sti: STIndex, mti: MTIndex, setMap: BOOL] ~ { WITH s~~stb[sti] SELECT FROM external => { IF setMap THEN s.map _ [module[MTNull]]; WITH p~~s SELECT FROM instance => DeclareModule[p.sti, mti, FALSE]; file => p.fti _ MapFile[bcd.mtb[mti].file]; ENDCASE => Error[]}; unknown => { fti: FTIndex ~ MapFile[bcd.mtb[mti].file]; stb[sti].body _ external[ pointer~file[fti], map~(IF setMap THEN [module[MTNull]] ELSE [unknown[]])]}; ENDCASE => Error[]}; currentLinkLoc: LinkLocation _ $frame; explicitLinkLoc: BOOL _ FALSE; LoadItem: PROC[t: Tree.Link] ~ { node: Tree.Index ~ TreeOps.GetNode[t]; IF tb[node].name # $item THEN Error[]; WITH s1~~tb[node].son[1] SELECT FROM symbol => { sti: STIndex ~ s1.index; currentLinkLoc _ IF tb[node].attrs[$codeLinks] THEN $code ELSE $frame; explicitLinkLoc _ tb[node].attrs[$explicitLinkLoc]; LoadSti[ sti, (IF tb[node].son[2] = Tree.null THEN htNull ELSE stb[sti].hti)] }; ENDCASE => Error[]}; BcdRelocations: TYPE ~ BcdBindDefs.Relocations; relocationHead: BcdBindDefs.RelocHandle; rel: BcdBindDefs.RelocHandle; FileMap: TYPE ~ RECORD [SEQUENCE length: CARDINAL OF FTIndex]; fileMap: REF FileMap _ NIL; MapFile: PROC[fti: FTIndex] RETURNS[FTIndex] ~ { SELECT TRUE FROM (bcd = localBases) => RETURN[fti]; (fti = FTSelf) => RETURN[bcdFti]; (fti = FTNull) => RETURN[FTNull]; ENDCASE => { fileIndex: CARDINAL ~ LOOPHOLE[fti, CARDINAL]/FTRecord.SIZE; IF fileMap[fileIndex] = FTNull THEN fileMap[fileIndex] _ bcd.MergeFile[fti]; RETURN[fileMap[fileIndex]]}}; AllocateRelocations: PROC[type: BcdBindDefs.RelocType] ~ { p: BcdBindDefs.RelocHandle ~ NEW[BcdRelocations]; IF relocationHead = NIL THEN relocationHead _ rel _ p ELSE {rel.link _ p; rel _ p}; IF (rel.type _ type) = $file THEN { rel.firstgfi _ rel.lastgfi _ BcdUtilDefs.GetGfi[0]; rel.dummygfi _ BcdUtilDefs.GetDummyGfi[0]; rel.import _ table.Bounds[imptype].size; rel.importLimit _ LOOPHOLE[rel.import]; rel.module _ table.Bounds[mttype].size; rel.config _ table.Bounds[cttype].size; rel.parentcx _ cxNull} ELSE rel.originalfirstdummy _ 1; rel.textIndex _ data.textIndex; rel.context _ currentCx; rel.parameters _ currentParms; currentParms _ Tree.null}; processExports: ExportAssigner; Load: PROC[sti: STIndex, name: HTIndex] RETURNS[map: Symbols.STMap] ~ { fti: FTIndex ~ FileForSti[sti]; nFiles: CARDINAL; BEGIN IF fti = FTNull THEN { NotLoadable[SIGNAL BcdErrorDefs.GetSti]; GOTO fail}; IF fti = data.outputFti THEN BcdErrorDefs.Error[$error, "Output file referenced as input"L]; LoadBcd[fti ! BcdFileDefs.UnknownFile => { BcdErrorDefs.ErrorFile[$error, "cannot be opened"L, fti]; GOTO fail}; EmptyBcdFile => { BcdErrorDefs.ErrorFile[$error, "is empty"L, fti]; GOTO fail}; DefsFile => { BcdErrorDefs.ErrorFile[$error, "is a definitions file"L, fti]; GOTO fail}; NonDefsFile => { BcdErrorDefs.ErrorFile[$error, "is not a definitions file"L, fti]; GOTO fail}; IncompatibleVersion => { BcdErrorDefs.ErrorFile[$error, "has an incompatible version"L, fti]; GOTO fail}]; EXITS fail => RETURN[[unknown[]]]; END; nFiles _ LOOPHOLE[limits.ft, CARDINAL]/FTRecord.SIZE; fileMap _ NEW[FileMap[nFiles]]; FOR i: CARDINAL IN [0..fileMap.length) DO fileMap[i] _ FTNull ENDLOOP; IF bHeader.extended THEN { IF ~(data.literals).Load[bHeader, MapFile, MapSegment].success THEN BcdErrorDefs.ErrorFile[$error, "has an incompatible version"L, fti] }; IF limits.ct # CTIndex.FIRST THEN { -- configuration map _ LoadConfigs[name, sti]; [] _ LoadModules[htNull, sti]} ELSE map _ LoadModules[name, sti]; ProcessTypeMap[]; processExports[]; ProcessImports[]; LoadSpaces[]; LoadFramePacks[]; rel.lastgfi _ BcdUtilDefs.GetGfi[0]-1; rel.importLimit _ LOOPHOLE[table.Bounds[imptype].size]; IF bHeader.typeExported THEN data.typeExported _ TRUE; IF bHeader.extended THEN (data.literals).Unload[]; UnloadBcd[]; fileMap _ NIL}; CheckInternalName: PROC[name: NameRecord, sti: STIndex] ~ { IF name # BcdUtilDefs.NameForSti[sti] THEN BcdErrorDefs.ErrorSti[$error, "does not match the module or configuration name in the Bcd"L, sti]}; bcdFile: FS.OpenFile; bcdInterval: VM.Interval _ VM.nullInterval; bcdFti: FTIndex; bHeader: BcdDefs.BcdBase; EmptyBcdFile: ERROR ~ CODE; DefsFile: ERROR ~ CODE; NonDefsFile: ERROR ~ CODE; IncompatibleVersion: ERROR ~ CODE; LoadBcd: PROC[fti: FTIndex] ~ { bcdPages: CARDINAL _ 1; DeleteHeader: PROC ~ { IF bcdInterval # VM.nullInterval THEN { bcdInterval.Free[]; bcdInterval _ VM.nullInterval}}; bcdInterval _ VM.nullInterval; bcdFile _ BcdFileDefs.CapabilityForFile[fti]; DO bcdInterval _ VM.Allocate[bcdPages]; bHeader _ VM.AddressForPageNumber[bcdInterval.page]; bcdFile.Read[from~0, nPages~bcdPages, to~bHeader ! FS.Error => {GO TO fail}]; IF bHeader.versionIdent # BcdDefs.VersionID THEN { DeleteHeader[]; ERROR IncompatibleVersion}; SELECT data.op FROM $bind => IF bHeader.definitions THEN {DeleteHeader[]; ERROR DefsFile}; $conc => IF ~bHeader.definitions THEN {DeleteHeader[]; ERROR NonDefsFile}; ENDCASE; IF bcdPages >= bHeader.nPages THEN EXIT; bcdPages _ bHeader.nPages; bcdInterval.Free[]; bcdInterval _ VM.nullInterval; REPEAT fail => {DeleteHeader[]; ERROR BcdFileDefs.UnknownFile[fti]}; ENDLOOP; bcdFti _ fti; BcdUtilDefs.SetFileVersion[fti, bHeader.version]; data.objectStamp _ OSMiscOps.MergeStamps[ data.objectStamp, OSMiscOps.TimeToStamp[bHeader.version]]; bcd _ NEW[BcdUtilDefs.BcdBases _ [ ctb~LOOPHOLE[bHeader + bHeader.ctOffset], mtb~LOOPHOLE[bHeader + bHeader.mtOffset], lfb~LOOPHOLE[bHeader + bHeader.lfOffset], rfb~LOOPHOLE[bHeader + bHeader.rfOffset], tfb~LOOPHOLE[bHeader + bHeader.tfOffset], etb~LOOPHOLE[bHeader + bHeader.expOffset], itb~LOOPHOLE[bHeader + bHeader.impOffset], sgb~LOOPHOLE[bHeader + bHeader.sgOffset], ftb~LOOPHOLE[bHeader + bHeader.ftOffset], ssb~LOOPHOLE[bHeader + bHeader.ssOffset], evb~LOOPHOLE[bHeader + bHeader.evOffset], tyb~LOOPHOLE[bHeader + bHeader.typOffset], tmb~LOOPHOLE[bHeader + bHeader.tmOffset], ntb~LOOPHOLE[bHeader + bHeader.ntOffset], spb~LOOPHOLE[bHeader + bHeader.spOffset], fpb~LOOPHOLE[bHeader + bHeader.fpOffset] ]]; limits _ [ ct~bHeader.ctLimit, mt~bHeader.mtLimit, et~bHeader.expLimit, it~bHeader.impLimit, sg~bHeader.sgLimit, ft~bHeader.ftLimit, tm~bHeader.tmLimit, nt~bHeader.ntLimit, sp~bHeader.spLimit, fp~bHeader.fpLimit]; AllocateRelocations[$file]; rel.originalfirstdummy _ bHeader.firstdummy}; UnloadBcd: PROC ~ { bcdInterval.Free[]; bcdInterval _ VM.nullInterval; bcd _ localBases}; CTRecordSize: PROC[bcd: BcdUtilDefs.BcdBasePtr, cti: CTIndex] RETURNS[NAT] ~ INLINE { RETURN[CTRecord.SIZE + bcd.ctb[cti].nControls*ControlItem.SIZE]}; EnumerateConfigurations: PROC[proc: PROC[CTIndex]] ~ { cti: CTIndex _ CTIndex.FIRST; UNTIL cti = limits.ct DO proc[cti]; cti _ cti + CTRecordSize[bcd, cti]; ENDLOOP}; LoadConfigs: PROC[name: HTIndex, sti: STIndex] RETURNS[Symbols.STMap] ~ { rootCti: CTIndex _ CTNull; LoadConfig: PROC[cti: CTIndex] ~ { root: BOOL ~ bcd.ctb[cti].config = CTNull; newCti: CTIndex ~ bcd.EnterConfig[cti, IF root THEN name ELSE htNull]; BEGIN OPEN new~~localBases.ctb[newCti]; IF ~root THEN new.config _ new.config + rel.config ELSE { CheckInternalName[new.name, sti]; IF rootCti # CTNull THEN BcdErrorDefs.ErrorSti[$warning, "contains multiple root configs"L, sti]; rootCti _ newCti; new.config _ CTNull}; new.file _ MapFile[new.file]; FOR i: CARDINAL IN [0 .. new.nControls) DO WITH c~~new.controls[i] SELECT FROM module => c.mti _ c.mti + rel.module; config => c.cti _ c.cti + rel.config; ENDCASE => ERROR; ENDLOOP; END}; EnumerateConfigurations[LoadConfig]; RETURN[[config[rootCti]]]}; UpdateConfigParent: PROC[parent: CTIndex, first, limit: CTIndex] ~ { FOR cti: CTIndex _ first, cti + CTRecordSize[localBases, cti] UNTIL cti = limit DO OPEN new~~localBases.ctb[cti]; IF new.config = CTNull THEN new.config _ parent; ENDLOOP}; MTRecordSize: PROC[bcd: BcdUtilDefs.BcdBasePtr, mti: MTIndex] RETURNS[NAT] ~ INLINE { RETURN[WITH m~~bcd.mtb[mti] SELECT FROM direct => MTRecord.direct.SIZE + m.length*Link.SIZE, indirect => MTRecord.indirect.SIZE, multiple => MTRecord.multiple.SIZE, ENDCASE => ERROR]}; EnumerateModules: PROC[ proc: PROC[MTIndex] RETURNS[BOOL]] RETURNS[mti: MTIndex] ~ { mti _ MTIndex.FIRST; UNTIL mti = limits.mt DO IF proc[mti] THEN RETURN; mti _ mti + MTRecordSize[bcd, mti]; ENDLOOP; RETURN[MTNull]}; CheckPacking: PROC[mti: MTIndex] ~ { name: NameRecord ~ localBases.mtb[mti].name; FOR sti: STIndex _ packSti, stb[sti].link UNTIL sti = stNull DO IF BcdUtilDefs.NameForSti[sti] = name THEN { stb[sti].body _ external[ map~[module[mti]], pointer~file[localBases.mtb[mti].file]]; EXIT}; ENDLOOP}; MapSegment: PROC[oldSgi: SGIndex] RETURNS[SGIndex] ~ { seg: SGRecord _ bcd.sgb[oldSgi]; seg.file _ MapFile[seg.file]; RETURN[BcdUtilDefs.EnterSegment[seg]]}; LoadModules: PROC[name: HTIndex, sti: STIndex] RETURNS[Symbols.STMap] ~ { rootMti: MTIndex _ MTNull; LoadModule: PROC[mti: MTIndex] RETURNS[BOOL _ FALSE] ~ { root: BOOL ~ bcd.mtb[mti].config = CTNull; newMti: MTIndex = bcd.EnterModule[mti, IF root THEN name ELSE htNull]; BEGIN OPEN new~~localBases.mtb[newMti]; name _ htNull; IF ~root THEN new.config _ new.config + rel.config ELSE { CheckInternalName[new.name, sti]; IF rootMti # MTNull THEN BcdErrorDefs.ErrorSti[$warning, "contains multiple modules"L, sti]; rootMti _ newMti; new.config _ CTNull}; new.gfi _ BcdUtilDefs.GetGfi[new.ngfi]; new.file _ MapFile[new.file]; new.code.sgi _ MapSegment[new.code.sgi]; new.sseg _ MapSegment[new.sseg]; CheckPacking[newMti]; IF root THEN new.linkLoc _ currentLinkLoc ELSE IF explicitLinkLoc AND currentLinkLoc # new.linkLoc THEN NULL; SELECT TRUE FROM new.altoCode => BcdErrorDefs.ErrorModule[$error, "was compiled for Alto"L, mti]; new.tableCompiled => NULL; (~bHeader.spare1) => BcdErrorDefs.ErrorModule[$error, " has obsolete format"L, mti]; ENDCASE; WITH m~~new SELECT FROM multiple => { IF m.types # TFNull THEN { OPEN tfh~~localBases.tfb[m.types]; FOR i: NAT IN [0..tfh.length) DO tfh.frag[i] _ (data.literals).MapTypeLink[tfh.frag[i]]; ENDLOOP }; IF m.refLiterals # RFNull THEN { OPEN rfh~~localBases.rfb[m.refLiterals]; FOR i: NAT IN [0..rfh.length) DO rfh.frag[i] _ (data.literals).MapLitLink[rfh.frag[i]]; ENDLOOP }; }; ENDCASE; END; RETURN}; [] _ EnumerateModules[LoadModule]; RETURN[[module[rootMti]]]}; UpdateModuleParent: PROC[parent: CTIndex, first, limit: MTIndex] ~ { FOR mti: MTIndex _ first, mti + MTRecordSize[localBases, mti] UNTIL mti = limit DO OPEN new~~localBases.mtb[mti]; IF new.config = CTNull THEN new.config _ parent; ENDLOOP}; ProcessTypeMap: PROC ~ { FOR tmi: TMIndex _ TMIndex.FIRST, tmi + TMRecord.SIZE UNTIL tmi = limits.tm DO newTypi: TYPIndex ~ bcd.EnterType[bcd.tmb[tmi].map]; newTmi: TMIndex ~ bcd.EnterTypeMap[tmi]; BEGIN OPEN new~~localBases.tmb[newTmi]; SELECT new.map FROM TYPNull => new.map _ newTypi; newTypi => NULL; ENDCASE => { fti: FTIndex ~ BcdUtilDefs.FileForVersion[new.version]; BcdErrorDefs.ErrorItem[$error, "is an exported type with clashing definitions"L, [NullName, fti], new.offset]}; END; ENDLOOP}; EnumerateSpaces: PROC[proc: PROC[SPIndex] RETURNS[BOOL]] RETURNS[spi: SPIndex] ~ { spi _ SPIndex.FIRST; UNTIL spi = limits.sp DO IF proc[spi] THEN RETURN; spi _ spi + SPRecord.SIZE + bcd.spb[spi].length*SpaceID.SIZE; ENDLOOP; RETURN[SPNull]}; LoadSpaces: PROC ~ { LoadSpace: PROC[spi: SPIndex] RETURNS[BOOL _ FALSE] ~ { newSpi: SPIndex ~ bcd.EnterSpace[spi]; localBases.spb[newSpi].seg _ MapSegment[bcd.spb[spi].seg]; RETURN}; [] _ EnumerateSpaces[LoadSpace]}; EnumerateFramePacks: PROC[proc: PROC[FPIndex] RETURNS[BOOL]] RETURNS[fpi: FPIndex] ~ { fpi _ FPIndex.FIRST; UNTIL fpi = limits.fp DO IF proc[fpi] THEN RETURN; fpi _ fpi + FPRecord.SIZE + bcd.fpb[fpi].length*MTIndex.SIZE; ENDLOOP; RETURN[FPNull]}; LoadFramePacks: PROC ~ { LoadFramePack: PROC[fpi: FPIndex] RETURNS[BOOL _ FALSE] ~ { newFpi: FPIndex ~ bcd.EnterFramePack[fpi]; FOR i: CARDINAL IN [0 .. localBases.fpb[newFpi].length) DO localBases.fpb[newFpi].modules[i] _ localBases.fpb[newFpi].modules[i] + rel.module; ENDLOOP; RETURN}; [] _ EnumerateFramePacks[LoadFramePack]}; ProcessImports: PROC ~ { FOR impi: IMPIndex _ FirstImport[], NextImport[impi] UNTIL impi = IMPNull DO newImpi: IMPIndex ~ bcd.EnterImport[impi, TRUE]; localBases.itb[newImpi].file _ MapFile[localBases.itb[newImpi].file]; [] _ BcdUtilDefs.GetDummyGfi[localBases.itb[newImpi].ngfi]; ENDLOOP}; FirstImport: PROC RETURNS[IMPIndex] ~ INLINE { OPEN localBases; RETURN[IF limits.it = IMPIndex.FIRST THEN IMPNull ELSE IMPIndex.FIRST]}; NextImport: PROC[impi: IMPIndex] RETURNS[IMPIndex] ~ INLINE { OPEN localBases; IF impi = IMPNull THEN RETURN[IMPNull]; impi _ impi + IMPRecord.SIZE; RETURN[IF impi = limits.it THEN IMPNull ELSE impi]}; nextLocalGfi: CARDINAL; GetLocalGfi: PROC[n: CARDINAL] RETURNS[gfi: ModuleIndex] ~ { gfi _ nextLocalGfi; nextLocalGfi _ nextLocalGfi + n; [] _ BcdUtilDefs.GetDummyGfi[n]}; ProcessLocalImports: PROC[start: IMPIndex] ~ { nextLocalGfi _ 1; FOR sti: STIndex _ FirstLocalImport[], NextLocalImport[sti] UNTIL sti = stNull DO WITH s~~stb[sti] SELECT FROM unknown => DeclareImportByName[sti, start]; external => WITH m~~s.map SELECT FROM interface => DeclareImport[sti, m.expi]; unknown => DeclareImportByName[sti, start]; config, module => BcdErrorDefs.ErrorSti[$error, "is both a component and an import of the config"L, sti]; ENDCASE => Error[]; ENDCASE => Error[]; ENDLOOP}; FirstLocalImport: PROC RETURNS[STIndex] ~ { OPEN localBases; FOR sti: STIndex _ cxb[loadCx].link, stb[sti].link UNTIL sti = stNull DO IF stb[sti].imported THEN RETURN[sti] ENDLOOP; RETURN[stNull]}; NextLocalImport: PROC[sti: STIndex] RETURNS[STIndex] ~ { OPEN localBases; IF sti = stNull THEN RETURN[stNull]; UNTIL (sti _ stb[sti].link) = stNull DO IF stb[sti].imported THEN RETURN[sti] ENDLOOP; RETURN[stNull]}; DeclareImportByName: PROC[sti: STIndex, start: IMPIndex] ~ { impi: IMPIndex; maxNgfi: [1..MaxNDMi] _ 1; firstImpi: IMPIndex _ IMPNull; impLimit: IMPIndex ~ LOOPHOLE[table.Bounds[imptype].size]; name: NameRecord ~ WITH s~~stb[sti] SELECT FROM external => WITH p~~s SELECT FROM file => BcdUtilDefs.NameForSti[sti], instance => BcdUtilDefs.NameForSti[p.sti], ENDCASE => ERROR LoadError, unknown => BcdUtilDefs.NameForSti[sti], ENDCASE => ERROR LoadError; FOR impi _ start, impi+IMPRecord.SIZE UNTIL impi = impLimit DO IF localBases.itb[impi].name = name THEN { IF firstImpi = IMPNull THEN firstImpi _ impi; maxNgfi _ MAX[maxNgfi, localBases.itb[impi].ngfi]}; ENDLOOP; IF firstImpi = IMPNull THEN { BcdErrorDefs.ErrorName[$warning, "is not IMPORTed by any modules"L, name]; stb[sti].imported _ FALSE; RETURN}; stb[sti].impi _ impi _ localBases.EnterImport[firstImpi, FALSE]; WITH s~~stb[sti] SELECT FROM external => IF s.ptype = $instance THEN { BcdUtilDefs.CreateInstanceName[s.hti, [import[impi]]]; localBases.itb[impi].namedInstance _ TRUE}; ENDCASE; localBases.itb[impi].ngfi _ maxNgfi; localBases.itb[impi].gfi _ GetLocalGfi[maxNgfi]; IF stb[sti].type = $unknown THEN stb[sti].body _ external[ map~[unknown[]], pointer~file[localBases.itb[impi].file]]}; DeclareImport: PROC[sti: STIndex, expi: EXPIndex] ~ { OPEN localBases, exp~~localBases.etb[expi]; impi: IMPIndex ~ table.Words[imptype, IMPRecord.SIZE]; ngfi: [0..MaxNDMi) ~ (exp.size + (BcdDefs.ProcLimit-1))/BcdDefs.ProcLimit; itb[impi] _ [ port~$interface, namedInstance~FALSE, file~exp.file, ngfi~ngfi, name~BcdUtilDefs.NameForSti[sti], gfi~GetLocalGfi[ngfi]]; stb[sti].impi _ impi; IF stb[sti].type = $unknown THEN stb[sti].body _ external[map~[unknown[]], pointer~file[exp.file]]}; Lookup: PROC[hti: HTIndex] RETURNS[sti: STIndex] ~ { last: STIndex; IF hti = htNull THEN RETURN[stNull]; FOR sti _ cxb[currentCx].link, stb[sti].link UNTIL sti = stNull DO IF stb[sti].hti = hti THEN EXIT; last _ sti; REPEAT FINISHED => { sti _ BcdUtilDefs.NewSemanticEntry[hti]; stb[sti].hti _ hti; stb[last].link _ sti}; ENDLOOP; RETURN}; PortableItem: TYPE ~ RECORD [ SELECT type: * FROM interface => [expi: EXPIndex], module => [mti: MTIndex], unknown => [name: HTIndex], null => [], ENDCASE]; PortNull: PortableItem ~ [null[]]; HtiForPortable: PROC[p: PortableItem] RETURNS[HTIndex] ~ { RETURN[ WITH p SELECT FROM interface => bcd.HtiForName[bcd.etb[expi].name], module => bcd.HtiForName[bcd.mtb[mti].name], ENDCASE => htNull]}; EnumerateExports: PROC[proc: PROC[PortableItem]] RETURNS[PortableItem] ~ { OPEN localBases; FindItem: Tree.Scan ~ { sti: STIndex ~ FindSti[t]; IF stb[sti].exported THEN WITH s~~stb[sti] SELECT FROM external => WITH m~~s.map SELECT FROM interface => proc[[interface[m.expi]]]; module => proc[[module[m.mti]]]; ENDCASE => proc[[unknown[s.hti]]]; ENDCASE => proc[[unknown[s.hti]]]}; SELECT TRUE FROM (loadExpi # EXPNull) => proc[[interface[loadExpi]]]; (loadTree = Tree.nullIndex) => FOR eti: EXPIndex _ EXPIndex.FIRST, eti+EXPRecord.SIZE+bcd.etb[eti].size UNTIL eti = limits.et DO proc[[interface[eti]]] ENDLOOP; ENDCASE => { IF exportsALL THEN { FOR sti: STIndex _ cxb[loadCx].link, stb[sti].link UNTIL sti = stNull DO IF ~stb[sti].filename THEN WITH s~~stb[sti] SELECT FROM external => WITH m~~s.map SELECT FROM interface => {s.exported _ TRUE; proc[[interface[m.expi]]]}; ENDCASE; ENDCASE ENDLOOP}; TreeOps.ScanList[tb[loadTree].son[2], FindItem]}; RETURN[PortNull]}; VerifyExports: ExportAssigner ~ { VerifyExport: PROC[p: PortableItem] ~ { WITH p SELECT FROM unknown => BcdErrorDefs.ErrorHti[$warning, "is not EXPORTed by any modules"L, name]; ENDCASE}; [] _ EnumerateExports[VerifyExport]}; NormalExports: ExportAssigner ~ { NormalExport: PROC[p: PortableItem] ~ { CombineExport[Lookup[HtiForPortable[p]], p, currentOp]}; [] _ EnumerateExports[NormalExport]}; lhs: Tree.Link; AssignedExports: ExportAssigner ~ { port: TYPE ~ MACHINE DEPENDENT RECORD[in, out: UNSPECIFIED]; left: PORT[Tree.Link] RETURNS[Tree.Link]; right: PORT RETURNS[PortableItem]; t: Tree.Link; p: PortableItem; nExports: CARDINAL _ 0; LOOPHOLE[left,port].out _ TreeOps.UpdateList; LOOPHOLE[right,port].out _ EnumerateExports; t _ LOOPHOLE[left,PORT[Tree.Link,POINTER] RETURNS[Tree.Link]][lhs, @left]; p _ LOOPHOLE[right,PORT[POINTER] RETURNS[PortableItem]][@right]; UNTIL p = PortNull DO nExports _ nExports+1; WITH t SELECT FROM symbol => CombineExport[index, p, currentOp]; subtree => { OPEN tb[index]; IF name # $item THEN Error[]; WITH son[1] SELECT FROM symbol => CombineExport[index, p, currentOp]; ENDCASE => Error[]}; ENDCASE => Error[]; t _ left[t]; p _ right[]; IF t = lhs THEN EXIT; ENDLOOP; UNTIL p = PortNull DO nExports _ nExports+1; p _ right[] ENDLOOP; UNTIL t = lhs DO t _ left[t] ENDLOOP; SELECT TreeOps.ListLength[lhs] FROM < nExports => BcdErrorDefs.Error[$error, "The right hand side exports more interfaces than required by the left hand side"L]; > nExports => BcdErrorDefs.Error[$error, "The left hand side requires more interfaces than exported by the right hand side"L]; ENDCASE}; LoadAssign: PROC[t: Tree.Link] ~ { node: Tree.Index ~ TreeOps.GetNode[t]; saveAssigner: ExportAssigner ~ processExports; processExports _ AssignedExports; lhs _ tb[node].son[1]; LoadRhs[tb[node].son[2]]; processExports _ saveAssigner}; NewExport: PROC[expi: EXPIndex] RETURNS[newExpi: EXPIndex] ~ { newExpi _ bcd.EnterExport[expi, TRUE]; localBases.etb[newExpi].file _ MapFile[localBases.etb[newExpi].file]}; CombineExport: PROC[sti: STIndex, p: PortableItem, op: InterfaceOp] ~ { target: FTIndex ~ FileForSti[sti]; WITH p SELECT FROM unknown => { BcdErrorDefs.ErrorHti[$warning, "is not EXPORTed by any modules"L, name]; RETURN}; ENDCASE; IF target = FTNull THEN DeclarePortableItem[sti, p] ELSE { source: FTIndex ~ FileForPortableItem[p]; IF ~BcdUtilDefs.EqVersions[source, target] THEN BcdErrorDefs.Error2Files[ class~$error, s~"is being exported, but required version is"L, ft1~source, ft2~target]}; WITH p SELECT FROM interface => CombineInterface[sti, expi, op]; module => CombineModule[sti, mti, op]; ENDCASE}; CombineModule: PROC[sti: STIndex, mti: MTIndex, op: InterfaceOp] ~ { WITH s~~stb[sti] SELECT FROM external => WITH m~~s.map SELECT FROM module => IF m.mti = MTNull THEN m.mti _ mti ELSE IF op = $plus THEN BcdErrorDefs.ErrorModule[$warning, "is a duplicate export"L, m.mti]; unknown => s.map _ [module[bcd.EnterModule[mti, htNull]]]; ENDCASE => Error[]; ENDCASE => Error[]}; CombineInterface: PROC[sti: STIndex, eti: EXPIndex, op: InterfaceOp] ~ { newEti: EXPIndex; WITH s~~stb[sti] SELECT FROM external => WITH m~~s.map SELECT FROM interface => { IF m.expi = EXPNull THEN m.expi _ NewExport[eti]; newEti _ m.expi}; unknown => { newEti _ NewExport[eti]; s.map _ [interface[newEti]]}; ENDCASE => NotOperand[sti]; ENDCASE => Error[]; BEGIN OPEN old~~bcd.etb[eti], new~~localBases.etb[newEti]; FOR i: CARDINAL IN [0..old.size) DO IF old.links[i] # NullLink THEN SELECT TRUE FROM (old.links[i].vtag = $type) => { cl: BcdDefs.Link ~ [type[ typeID~bcd.EnterType[old.links[i].typeID], type~TRUE, proc~FALSE]]; IF new.links[i] # NullLink AND new.links[i] # cl THEN BcdErrorDefs.ErrorItem[$error, "is an incompatible type definition"L, [name~localBases.etb[newEti].name, fti~localBases.etb[newEti].file], i]; new.links[i] _ cl}; (new.links[i] = NullLink) => new.links[i] _ RelocateExportLink[old.links[i]]; (op = $plus) => BcdErrorDefs.ErrorItem[$warning, "is a duplicate export"L, [name~localBases.etb[newEti].name, fti~localBases.etb[newEti].file], i]; ENDCASE; ENDLOOP; END}; RelocateExportLink: PROC[cl: BcdDefs.Link] RETURNS[BcdDefs.Link] ~ { IF loadExpi = EXPNull AND loadCx = cxNull THEN SELECT cl.vtag FROM $var => cl.vgfi _ cl.vgfi + rel.firstgfi-1; $proc0, $proc1 => cl.gfi _ cl.gfi + rel.firstgfi-1; $type => ERROR; ENDCASE; RETURN[cl]}; LoadRhs: PROC[exp: Tree.Link] ~ { WITH exp SELECT FROM subtree => SELECT tb[index].name FROM $module => {currentParms _ tb[index].son[2]; LoadItem[tb[index].son[1]]}; ENDCASE => LoadOperand[exp]; ENDCASE => LoadOperand[exp]}; LoadOperand: PROC[exp: Tree.Link] ~ { WITH exp SELECT FROM symbol => LoadOperandSti[index]; subtree => SELECT tb[index].name FROM $item => WITH s1~~tb[index].son[1] SELECT FROM symbol => LoadOperandSti[s1.index]; ENDCASE => Error[]; $module => { BcdErrorDefs.ErrorSti[$error, "must name an interface (no ""[]"")"L, FindSti[tb[index].son[1]]]; currentParms _ tb[index].son[2]; LoadItem[tb[index].son[1]]}; $plus, $then => { LoadOperand[tb[index].son[1]]; currentOp _ tb[index].name; LoadOperand[tb[index].son[2]]; currentOp _ $plus}; ENDCASE => Error[]; ENDCASE => Error[]}; NotOperand: PROC[sti: STIndex] ~ { BcdErrorDefs.ErrorSti[$error, "must name an interface"L, sti]; LoadSti[sti, htNull]}; LoadOperandSti: PROC[sti: STIndex] ~ { WITH s~~stb[sti] SELECT FROM external => WITH m~~s.map SELECT FROM interface => { IF m.expi = EXPNull THEN Error[]; loadExpi _ m.expi; processExports[]; loadExpi _ EXPNull}; unknown => BcdErrorDefs.ErrorSti[$error, "cannot be an operand"L, sti]; ENDCASE => NotOperand[sti]; unknown => IF s.imported THEN BcdErrorDefs.ErrorSti[$error, "is imported and cannot be an operand"L, sti] ELSE NotOperand[sti]; ENDCASE => NotOperand[sti]}; }. zBcdLoad.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Satterthwaite on April 17, 1986 1:24:39 pm PST Lewis on 27-Mar-81 9:49:56 Maxwell, August 11, 1983 2:29 pm Paul Rovner, October 7, 1983 10:10 am Russ Atkinson (RRA) March 7, 1985 0:18:40 am PST BcdErrorDefs.ErrorModule[ warning," has already been bound with a different link location"L, newMti]; Κ!™˜codešœ ™ Kšœ Οmœ1™Kšœ žœžœU˜kKšœžœžœ˜Kšœ žœžœ žœ¬˜ΜKšœžœžœ`˜xKšœ žœžœ"˜9Kšœ žœžœ)˜@Kšœ žœžœ΄˜ΛKšžœžœžœ˜'Kšœ žœžœ˜1Kšœžœžœ ˜%Kšœ žœžœ<˜OKšœžœžœ˜ Kšœžœžœ0˜@Kšœ žœžœ-˜@Kšžœžœžœ@˜NK˜—šœ ž˜Kšžœ<žœ%žœ˜Kšžœ˜Kšžœ˜K˜š Οnœžœžœžœžœžœ˜3KšžœžœC˜PK˜—Kšœ žœžœ˜/Kšœ žœ ˜1KšŸœžœžœ˜K˜Kšœ žœžœžœ˜K˜K˜K˜K˜K˜K˜K˜K˜Kšœ žœ˜K˜Kšœ%žœ˜?K˜K˜K˜˜K˜>˜Kšœžœ˜K˜&K˜:K˜&K˜K˜&K˜&K˜K˜&—˜K˜——KšŸœžœžœ ˜ K˜K˜šŸœžœžœžœ˜LK˜K˜/K˜K˜-K˜Kšœžœ˜K˜AKšœ žœ˜Kšœžœ˜K˜šžœž˜˜ K˜#K˜H—Kšžœ ˜—Kšœ%žœ˜)Kšžœ˜K˜—šŸœžœžœ ˜0šžœžœ˜Kšžœ˜ šž˜šžœžœž˜K˜K˜%Kšžœžœ ˜———šœ˜K˜——K˜K˜˜šžœžœž˜K˜!˜ K˜Kšœ žœ˜%K˜šžœž˜K˜)K˜Kšœ žœ˜K˜˜ K˜<—Kšžœ ˜—K˜—Kšžœ ˜K˜——šŸœžœ˜Kšœ>˜>Kšžœ˜K˜K˜K˜.K˜(Kšœ žœ˜%K˜K˜K˜)K˜)K˜"K˜+K˜K˜1K˜8K˜K˜,KšœΟc˜5šžœžœ˜Kšœ žœ˜K˜šŸ œžœ%˜7K˜šžœžœž˜0˜K˜4K˜———K˜1šœ*žœžœ˜MKšžœžœ'˜2Kšœžœ˜K˜šŸ œžœ%˜8K˜(K˜—K˜AKšžœžœž˜5šžœ˜Kšœžœ˜K˜<—K˜4K˜8K˜?K˜ K˜2Kšžœ˜——K˜.K˜:K˜*K˜K˜K˜-K˜/K˜!K˜*K˜,K˜K˜K˜Kšžœ˜K˜K˜—KšŸœžœžœ˜K˜˜šžœžœž˜˜ K˜Kšž˜šžœ žœž˜˜ šžœ žœž˜K˜%˜ šžœ'žœ˜/K˜7K˜šŸ œžœžœžœ˜6Kšžœ!˜'K˜—K˜K˜2—Kšžœžœ ˜—šœ  ˜(šžœžœžœ(ž˜Kšœ žœ žœ˜K˜šŸœžœžœ ˜0šžœžœž˜Kšœžœ˜"Kšœžœ ˜!Kšœžœ ˜!šžœ˜ Kš œ žœžœžœ žœ˜šžœ"žœ˜*Kšžœžœ˜-Kšœ žœ&˜3—Kšžœ˜—šžœžœ˜K˜JKšœžœ˜Kšžœ˜—Kšœ9žœ˜@šžœ žœž˜˜ šžœžœ˜K˜6Kšœ%žœ˜+——Kšžœ˜—K˜$K˜0šžœžœ˜!˜K˜;K˜———šŸ œžœ"˜5Kšžœ'˜+Kšœ0žœ˜6K˜J˜ Kšœžœ˜?K˜9—K˜šžœžœ˜!K˜CK˜——šŸœžœžœ˜4K˜Kšžœžœžœ ˜$šžœ*žœž˜BKšžœžœžœ˜"K˜ šž˜šžœ˜ K˜(K˜+——Kšžœ˜—Kšžœ˜K˜—šœžœžœ˜šžœ ž˜K˜K˜K˜Kšœ ˜ Kšžœ˜ K˜——K˜"K˜šŸœžœžœ ˜:šžœ˜šžœžœž˜K˜0K˜/Kšžœ ˜K˜———šŸœžœžœžœ˜JKšžœ ˜K˜˜K˜šžœž˜šžœ žœž˜˜ šžœ žœž˜K˜'K˜ Kšžœ˜"——Kšžœ˜#K˜———šžœžœž˜K˜4˜šžœžœžœ˜Hšžœž˜Kšœžœ˜———šžœ˜ šžœ žœ˜šžœ0žœž˜Hšžœžœ˜šžœ žœž˜˜ šžœ žœž˜Kšœžœ˜=Kšžœ˜——Kšž˜——Kšžœ˜ ——K˜1——Kšžœ ˜K˜—K˜!˜šŸ œžœ˜'šžœžœž˜K˜TKšžœ˜ K˜——K˜%K˜—K˜!˜šŸ œžœ˜'K˜8K˜—K˜%K˜—K˜K˜˜#Kš œžœžœž œžœ ž œ˜Kšœ žœ˜&K˜FK˜—šŸ œžœ4˜GK˜"šžœžœž˜˜ K˜IKšžœ˜—Kšžœ˜—Kšžœžœ˜3šžœ˜K˜)šžœ)ž˜/˜K˜ K˜0K˜———šžœžœž˜K˜-K˜)Kšžœ˜ K˜——šŸ œžœ1˜Dšžœ žœž˜˜ šžœ žœž˜˜ Kšžœžœ ˜"šžœžœ žœ˜K˜D——K˜:Kšžœ ˜——Kšžœ ˜K˜K˜——šŸœžœ2˜HK˜šžœ žœž˜˜ šžœ žœž˜˜Kšžœžœ˜1K˜—˜ K˜6—Kšžœ˜——Kšžœ ˜—Kšžœžœ0˜:šžœžœžœž˜#šžœž˜šžœžœž˜˜ ˜K˜*Kšœžœžœ˜—šžœžœž˜5˜K˜&K˜H——K˜—˜K˜0—˜˜:K˜H——Kšžœ˜——Kšžœ˜—Kšžœ˜K˜K˜—šŸœžœžœ˜Dšžœžœž˜.šžœ ž˜K˜,K˜3Kšœ žœ˜Kšžœ˜——Kšžœ˜ K˜K˜—šŸœžœ˜!šžœžœž˜˜ šžœž˜K˜JKšžœ˜——Kšžœ˜K˜——šŸ œžœ˜%šžœžœž˜K˜ ˜ šžœž˜˜šžœžœž˜%K˜#Kšžœ ˜——˜ ˜K˜&K˜—K˜>—˜K˜K˜K˜K˜—Kšžœ ˜——Kšžœ ˜K˜——šŸ œžœ˜"K˜>K˜K˜—šŸœžœ˜&šžœ žœž˜˜ šžœ žœž˜˜Kšžœžœ ˜!K˜;—K˜GKšžœ˜——˜ šžœ žœ˜K˜K—Kšžœ˜—Kšžœ˜K˜——K˜K˜——…—Φ’ι