-- File: BWSMLoaderImpl.mesa - last edit by -- DWR 13-Jan-86 13:13:51 -- MEW 23-May-86 17:46:40 -- Copyright (C) 1986 by Xerox Corporation. All rights reserved. DIRECTORY File USING [File, PageNumber], Heap USING [Create, Error], MLoader USING [ErrorCode, Options], MLoaderExtras, LoadState USING [GetModuleInfo, ModuleInfoRange, ModuleInfosOfBcd, ModuleInfoSequenceHandle], LoadStateFormat USING [ModuleInfo], MFile, MFileOnNSFileOps, PrincOps USING [GlobalFrameHandle], Runtime USING [ ConfigError, InvalidGlobalFrame, IsBound, LoadConfig, UnNewConfig, VersionMismatch], Space USING [Error, InsufficientSpace], SpecialMFile, SpecialRuntime USING [GlobalFrameFromProgram], Volume USING [ReadOnly]; BWSMLoaderImpl: MONITOR IMPORTS Heap, MFile, MFileOnNSFileOps, LoadState, SpecialMFile, SpecialRuntime, Runtime, Space, Volume EXPORTS MLoader, MLoaderExtras = BEGIN loaderPassword: CARDINAL = 042061B; -- my birthday Handle: TYPE = LONG POINTER TO Object; Object: PUBLIC TYPE = RECORD [ password: CARDINAL ¬ loaderPassword, file: MFile.Handle, options: Options, started: BOOLEAN, next: Handle, program: PROGRAM ¬ TRASH]; Options: TYPE = MLoader.Options; Error: PUBLIC ERROR [code: MLoader.ErrorCode, string: LONG STRING] = CODE; VersionMismatch: PUBLIC SIGNAL [module: LONG STRING] = CODE; heap: UNCOUNTED ZONE = Heap.Create[initial: 1]; handles: Handle ¬ NIL; -- procedures Load: PUBLIC PROC [file: MFile.Handle, options: Options] RETURNS [h: Handle ¬ NIL] = { program: PROGRAM; pilotFile: File.File; firstPage: File.PageNumber; AddHandle: ENTRY PROCEDURE = BEGIN h ¬ heap.NEW[Object ¬ [ options: options, file: file, started: FALSE, next: handles, program: program]]; handles ¬ h; END; IF MFile.GetAccess[file] # readOnly THEN ERROR Error[insufficientAccess, "Wrong access for file being loaded."L]; pilotFile ¬ SpecialMFile.GetCapaWithAccess[file]; firstPage ¬ MFileOnNSFileOps.FirstPageAfterLeader[file]; program ¬ Runtime.LoadConfig[ file: pilotFile, offset: firstPage, codeLinks: options.codeLinks ! Runtime.VersionMismatch => { SIGNAL VersionMismatch[module]; RESUME}; Runtime.ConfigError => ERROR Error[SELECT type FROM badCode => badCode, invalidConfig => invalidParameters, missingCode => missingCode, exportedTypeClash => exportedTypeClash, unknown => other, ENDCASE => other, NIL]; Volume.ReadOnly => IF options.codeLinks THEN { options.codeLinks ¬ FALSE; RETRY}; Space.InsufficientSpace => ERROR Error[gftFull, NIL]; Space.Error => ERROR Error[other, NIL]; Heap.Error => IF type = insufficientSpace THEN ERROR Error[gftFull, NIL]]; AddHandle[]; -- MFile.SetReleaseData[file, [MyRelease, h]]; }; -- MyRelease: MFile.PleaseReleaseProc = {RETURN[allowRename]}; Run: PUBLIC PROC [file: MFile.Handle, options: Options] RETURNS [h: Handle] = { h ¬ Load[file, options]; Start[h]}; Start: PUBLIC PROC [h: Handle] = { IF h.password # loaderPassword THEN ERROR Error[other, "Invalid handle"L]; IF h.started THEN ERROR Error[alreadyStarted, "Already started"L]; IF Runtime.IsBound[LOOPHOLE[h.program]] THEN -- makes me gag START h.program [ ! Runtime.InvalidGlobalFrame => ERROR Error[other, "Invalid global frame"L]]; h.started ¬ TRUE }; RemoveHandle: ENTRY PROC [h: Handle] = BEGIN handle: Handle ¬ handles; prev: Handle ¬ NIL; DO IF handle = NIL THEN EXIT; -- not in list, error condition? IF handle = h THEN { IF prev = NIL THEN handles ¬ h.next ELSE prev.next ¬ h.next; EXIT}; prev ¬ handle; handle ¬ handle.next; ENDLOOP END; Unload: PUBLIC PROC [h: Handle] = { -- bogus IF h.password # loaderPassword THEN ERROR Error[other, "Invalid handle"L]; IF Runtime.IsBound[LOOPHOLE[h.program]] THEN -- makes me gag Runtime.UnNewConfig[LOOPHOLE[h.program]]; MFile.Release[h.file]; RemoveHandle[h]; heap.FREE[@h]}; « HandleFromProgram: PUBLIC ENTRY PROC [prog: PROGRAM] RETURNS [Handle] = { FOR h: Handle ¬ handles, h.next UNTIL h = NIL DO IF h.program = prog THEN RETURN[h]; ENDLOOP; RETURN[NIL]}; » HandleFromProgram: PUBLIC ENTRY PROC [prog: PROGRAM] RETURNS [Handle] = { gf:PrincOps.GlobalFrameHandle = SpecialRuntime.GlobalFrameFromProgram[prog]; FOR h: Handle ¬ handles, h.next UNTIL h = NIL DO moduleInfo:LoadStateFormat.ModuleInfo = LoadState.GetModuleInfo[ SpecialRuntime.GlobalFrameFromProgram[h.program]]; moduleSeq:LoadState.ModuleInfoSequenceHandle ¬ LoadState.ModuleInfosOfBcd[ moduleInfo.index, heap]; FOR i:LoadState.ModuleInfoRange IN [0..moduleSeq.length) DO IF moduleSeq[i].gf = gf THEN {heap.FREE[@moduleSeq];RETURN[h]}; ENDLOOP; heap.FREE[@moduleSeq]; ENDLOOP; RETURN[NIL]; }; GetProgram: PUBLIC PROC [h: Handle] RETURNS [PROGRAM] = { RETURN[h.program]; }; END.