DIRECTORY BasicTime USING [ GMT, latestGMT ], CStrings USING [CString], Loader USING [ LoadErrorType, LoadExceptionType ], Rope USING [ Cat, Concat, Equal, Find, FindBackward, IsEmpty, Length, ROPE, Substr ], SymTab USING [ Create, Delete, Fetch, Ref, Store ], UXProcs USING [ CProc, ToCedarProc ], UXStrings USING [ Create, ToRope ]; LoaderImpl: CEDAR PROGRAM IMPORTS BasicTime, Rope, SymTab, UXStrings, UXProcs EXPORTS Loader ~ BEGIN ROPE: TYPE ~ Rope.ROPE; LoadException: PUBLIC SIGNAL [ type: Loader.LoadExceptionType, message: ROPE ] = CODE; LoadError: PUBLIC ERROR [ type: Loader.LoadErrorType, message: ROPE ] = CODE; XRLoadFile: PROC [ fileName: CStrings.CString, funcName: CStrings.CString, checkLoad: INT32, nodebugger: INT32 ] RETURNS [ status: INT32 ] = TRUSTED MACHINE CODE { "+extern int load_file();.load_file" }; GetModuleName: PROC RETURNS [ moduleName: ROPE ] = { vStamp: CStrings.CString ~ UXStrings.Create["_versionStamp"]; addr: CStrings.CString ฌ LOOPHOLE[GetSymVal[vStamp]]; IF ( addr = NIL ) THEN ERROR LoadError[type: invalidObjectFile, message: "Mimosa version stamp not found."]; moduleName ฌ UXStrings.ToRope[addr]; { versionStampPrefix: ROPE = "@(#)mob_versio"; prefixLen: INT ~ versionStampPrefix.Length[]; front: ROPE ~ moduleName.Substr[len: prefixLen]; IF ( NOT versionStampPrefix.Equal[front] ) THEN { ERROR LoadError[type: invalidObjectFile, message: Rope.Concat["Mimosa version stamp not in proper format: ", front]]; }; }; { p1: INT ~ moduleName.FindBackward[" "].SUCC; r1: ROPE ฌ moduleName.Substr[start: p1]; p2: INT ~ r1.FindBackward["."]; moduleName ฌ IF ( p2 = -1 ) THEN r1 ELSE r1.Substr[len: p2]; }; RETURN[moduleName] }; GetSymVal: PROC [ which: CStrings.CString ] RETURNS [ UXProcs.CProc ] = TRUSTED MACHINE CODE {"%\n+extern caddr_t get_sym_val();.get_sym_val" }; ModuleNameFromFileName: PROC [ fileName: ROPE ] RETURNS [ moduleName: ROPE ] ~ { lastSlashIndex: INT ~ fileName.FindBackward["/"]; basename: ROPE ~ IF ( lastSlashIndex = -1 ) THEN fileName ELSE fileName.Substr[lastSlashIndex.SUCC]; firstDot: INT ~ basename.Find["."]; moduleName ฌ IF ( firstDot = -1 ) THEN basename ELSE basename.Substr[len: firstDot]; }; InstallProc: TYPE = PROC; RunProc: TYPE = PROC; UnloadProc: TYPE = PROC; Loadee: TYPE = REF LoadeeObject; LoadeeObject: TYPE = RECORD [ fileName: ROPE, moduleName: ROPE, installProc: InstallProc, runProc: RunProc, unloadProc: UnloadProc, installProcCalled: BOOL, runProcCalled: BOOL, unloadProcCalled: BOOL ]; table: SymTab.Ref ฌ NIL; LookupLoadee: PROC [ moduleName: ROPE ] RETURNS [ Loadee ] = { WITH table.Fetch[moduleName].val SELECT FROM loadee: Loadee => { RETURN [loadee] }; ENDCASE => { message: ROPE ~ Rope.Cat["Couldn't locate loadee record for module ", moduleName, "."]; LoadError[type: loadeeNotFound, message: message]; }; }; LoadFile: PUBLIC PROC [ file: ROPE ] RETURNS [ moduleName: ROPE ] = { GetModuleLink: PROC [ prefix: ROPE, code: Loader.LoadErrorType ] RETURNS [ proc: PROC ฌ NIL ] ~ { linkName: ROPE ฌ prefix.Concat[moduleName]; uxstring: CStrings.CString ฌ UXStrings.Create[linkName]; link: UXProcs.CProc ~ GetSymVal[uxstring]; proc ฌ LOOPHOLE[UXProcs.ToCedarProc[link]]; IF ( proc = NIL ) THEN { message: ROPE ~ Rope.Cat["Unable to locate proc [", linkName, "]\n"]; ERROR LoadError[type: code, message: message]; }; }; loadingFileString: CStrings.CString ฌ UXStrings.Create[file]; status: INT ฌ XRLoadFile[loadingFileString, NIL, 0, 0]; moduleName ฌ GetModuleName[]; IF ( moduleName.IsEmpty[] ) THEN moduleName ฌ ModuleNameFromFileName[file]; IF ( status = 0 ) THEN { message: ROPE ~ Rope.Concat["PCR load fails - No action taken for file", file]; LoadError[unknown, message]; }; { loadee: Loadee ~ NEW[LoadeeObject ฌ [fileName: file, moduleName: moduleName, installProc: NULL, runProc: NULL, unloadProc: NULL, installProcCalled: FALSE, runProcCalled: FALSE, unloadProcCalled: FALSE] ]; loadee.installProc ฌ GetModuleLink["_XR_install_", noInstallProc]; loadee.runProc ฌ GetModuleLink["_XR_run_", noRunProc]; loadee.unloadProc ฌ NIL; -- GetModuleLink["_XR_unload_", noUnloadProc]; IF ( table.Store[key: loadee.moduleName, val: loadee] = FALSE ) THEN { message: ROPE ~ Rope.Cat["Reload of ", file, ": latest load completed, old loadee lost."]; SIGNAL LoadException[type: previouslyLoaded, message: message]; }; }; }; Install: PUBLIC PROC [ moduleName: ROPE ] = { loadee: Loadee ฌ LookupLoadee[moduleName]; IF ( loadee.installProcCalled ) THEN { message: ROPE ~ Rope.Cat["The install proc for ", moduleName, " has already been called"]; SIGNAL LoadException[type: previouslyInstalled, message: message]; }; loadee.installProcCalled ฌ TRUE; loadee.installProc[]; }; Run: PUBLIC PROC [ moduleName: ROPE ] = { loadee: Loadee ฌ LookupLoadee[moduleName]; IF ( loadee.runProcCalled ) THEN { message: ROPE ~ Rope.Cat["The run proc for ", moduleName, " has already been called"]; SIGNAL LoadException[type: previouslyRun, message: message]; }; loadee.runProcCalled ฌ TRUE; loadee.runProc[]; }; Unload: PUBLIC PROC [ moduleName: ROPE ] = { loadee: Loadee ฌ LookupLoadee[moduleName]; unloadProc: UnloadProc ฌ loadee.unloadProc; IF ( loadee.unloadProcCalled ) THEN { message: ROPE ~ Rope.Cat["The unload proc for ", moduleName, " has already been called"]; SIGNAL LoadException[type: previouslyUnloaded, message: message]; }; loadee.unloadProcCalled ฌ TRUE; [] ฌ table.Delete[moduleName]; unloadProc[]; }; Zap: PUBLIC PROC [ moduleName: ROPE ] = { Unload[moduleName ! LoadError, LoadException => { [] ฌ table.Delete[moduleName]; CONTINUE } ]; }; BCDBuildTime: PUBLIC PROC --Loader-- [ proc: UNSAFE PROC ANY RETURNS ANY ฌ NIL ] RETURNS [ BasicTime.GMT ] = { RETURN[BasicTime.latestGMT] }; MakeProcedureResident: PUBLIC SAFE PROC [proc: PROC ANY RETURNS ANY] ~ { NULL }; MakeProcedureSwappable: PUBLIC PROC [proc: PROC ANY RETURNS ANY] ~ { NULL }; MakeGlobalFrameResident: PUBLIC SAFE PROC [proc: PROC ANY RETURNS ANY] ~ { NULL }; MakeGlobalFrameSwappable: PUBLIC PROC [proc: PROC ANY RETURNS ANY] ~ { NULL }; InitLoader: PROC = { table ฌ SymTab.Create[]; }; InitLoader[]; END. $LoaderImpl.mesa Copyright ำ 1988, 1989, 1991 by Xerox Corporation. All rights reserved. JKF December 13, 1988 1:52:18 pm PST Eduardo Pelegri-Llopart October 28, 1988 11:17:46 am PDT Bill Jackson (bj) January 6, 1989 8:48:59 pm PST Willie-Sue Orr, March 16, 1989 8:51:13 pm PST Willie-s, September 23, 1991 5:28 pm PDT same as XR_strip(); try to derive the module name this should report invalidObjectFile, loadStateFull, insufficientVM etc. file is loaded, now we need to find the install, run and unload procs it's not necessarily an error to load another module which has a name which conflicts with the name of a previously loaded module, but you ought to notify clients that this has happend because in most cases it IS an error - the client probably wanted to unload it first. Mainline code สื–(cedarcode) style•NewlineDelimiter ˜codešœ™Kšœ ฯeœ=™HKšฯkœž™$Kšœ5ž™8Kšœ0™0K™-K™(—K˜šž ˜ Kšœ žœžœ˜#Kšœ žœ ˜Kšœžœ&˜2Kšœžœ<žœ ˜UKšœžœ'˜3Kšœžœ˜%Kšœ žœ˜#—K˜šฯn œžœžœ˜Kšžœ-˜4Kšžœ ž˜Kšžœžœžœ˜K˜Kš Ÿ œžœžœ,žœžœ˜VKš Ÿ œžœžœ(žœžœ˜MK˜š Ÿ œžœFžœžœžœ žœ˜ŒKšžœžœžœ*˜>—K˜šŸ œžœžœžœ˜4Kšœ=˜=Kšœžœ˜5Kšžœ žœžœžœP˜lKšœ$˜$šœ˜Kšœžœ˜,Kšœ žœ˜-Kšœžœ%˜0šžœžœ#žœ˜1Kšžœp˜uK˜—K˜—šœ˜Kšœžœ žœ˜,Kšœžœ ˜(Kšœžœ˜Kšœ žœ žœžœ˜šžœžœž˜,Kšœžœ ˜&šžœ˜ Kšœ žœJ˜WKšœ2˜2Kšœ˜——K˜K˜—š Ÿœžœžœ žœžœžœ˜Eš Ÿ œžœ žœžœ žœžœ˜aKšœ žœ˜+Kšœ8˜8Kšœ*˜*Kšœžœ˜+šžœ žœžœ˜Kšœ žœ8˜EKšžœ)˜.Kšœ˜—Kšœ˜—Kšœ=˜=Kšœžœ!žœ˜7K˜Kšœ™K˜Kšœ˜šžœžœ,˜LK˜—šžœžœ˜Kšœ žœB˜OKšœ˜KšœH™HKšœ˜—šœ˜KšœE™EKšœžœFžœ žœžœžœžœžœ˜ฬK˜KšœB˜BKšœ6˜6Kšœžœฯc.˜GK˜šžœ6žœžœ˜FKšœาžœ:™ŽKšœ žœM˜ZKšžœ9˜?K˜—Kšœ˜—˜K˜——šŸœžœžœžœ˜-Kšœ*˜*šžœžœ˜&Kšœ žœM˜ZKšžœ<˜BKšœ˜—Kšœžœ˜ K˜K˜—K˜šŸœžœžœžœ˜)Kšœ*˜*šžœžœ˜"Kšœ žœI˜VKšžœ6˜