DIRECTORY AMModel, Atom, BasicTime, Commander, CommandTool, FS, HashTable, Install, InstallPrivate, IO, Process, ReadEvalPrint, Rope; InstallImpl: CEDAR MONITOR LOCKS d USING d: Data IMPORTS AMModel, Atom, BasicTime, Commander, CommandTool, FS, HashTable, IO, Process, Rope EXPORTS Install = BEGIN OPEN Install, InstallPrivate; LORA: TYPE = LIST OF REF ANY; FileData: TYPE = RECORD [name: ROPE, created: BasicTime.GMT]; notFound: FileData = [NIL, BasicTime.nullGMT]; data: Data _ WITH Atom.GetProp[$InstallImplData, $InstallImplData] SELECT FROM x: Data => x, ENDCASE => NIL; root: AMModel.Context = GetRoot[]; GetRoot: PROC RETURNS [AMModel.Context] = TRUSTED {RETURN [AMModel.RootContext[]]}; InstallCmd: PROC [cmd: Commander.Handle] RETURNS [result: REF ANY _ NIL, msg: ROPE _ NIL] --Commander.CommandProc-- = { from: IO.STREAM = IO.RIS[cmd.commandLine]; FOR i: INT _ from.SkipWhitespace[], from.SkipWhitespace[] WHILE NOT from.EndOf[] DO subject: ROPE = from.GetTokenRope[IO.IDProc].token; found, failed: BOOL; [found, failed] _ Install[subject, cmd]; IF NOT failed THEN NULL ELSE IF NOT found THEN { result _ $Failure; msg _ msg.Cat["Failed to find load file for ", subject, ".\n"]; } ELSE { result _ $Failure; msg _ msg.Cat["Load file for ", subject, " fails.\n"]; }; ENDLOOP; }; UnInstallCmd: PROC [cmd: Commander.Handle] RETURNS [result: REF ANY _ NIL, msg: ROPE _ NIL] --Commander.CommandProc-- = { from: IO.STREAM = IO.RIS[cmd.commandLine]; FOR i: INT _ from.SkipWhitespace[], from.SkipWhitespace[] WHILE NOT from.EndOf[] DO subject: ROPE = from.GetTokenRope[IO.IDProc].token; UnInstall[subject, cmd]; ENDLOOP; }; Install: PUBLIC PROC [subject: ROPE, parent: Commander.Handle] RETURNS [foundFile, failed: BOOL] = { status: Status = Acquire[data, subject]; SELECT status.state FROM notDone => ERROR; inProgress => { finalState: State _ done; { ENABLE UNWIND => SetState[data, status, notDone]; Already: PROC [suffix: ROPE] RETURNS [in: BOOL] = TRUSTED { in _ AMModel.MostRecentNamedContext[subject.Concat[suffix], root] # NIL; }; IF Already["Package"] OR Already[NIL] OR Already["Impl"] THEN { status.usedFile _ FALSE; failed _ status.failed _ FALSE; foundFile _ FALSE; } ELSE { fd: FileData = Find[subject, parent]; SELECT status.foundFile _ foundFile _ fd # notFound FROM FALSE => {finalState _ notDone; failed _ TRUE}; TRUE => { cp: FS.ComponentPositions; full, dir: ROPE; wDir: ROPE = CommandTool.CurrentWorkingDirectory[]; cd: BOOL; status.usedFile _ TRUE; [full, cp] _ FS.ExpandName[fd.name]; dir _ CommandTool.ConvertToSlashFormat[full.Substr[len: cp.base.start]]; cd _ NOT dir.Equal[wDir, FALSE]; IF cd THEN [] _ CommandTool.DoCommand[Rope.Cat["Push ", dir], parent]; failed _ status.failed _ CommandTool.DoCommand[Rope.Cat["SecondSource ", full], parent] = $Failure; IF failed THEN finalState _ notDone; IF cd THEN [] _ CommandTool.DoCommand["Pop", parent]; }; ENDCASE => ERROR; }; }; SetState[data, status, finalState]; }; done => {foundFile _ status.foundFile; failed _ status.failed}; ENDCASE => ERROR; }; UnInstall: PUBLIC PROC [subject: ROPE, parent: Commander.Handle] = { SetState[data, Acquire[data, subject], notDone]; }; Acquire: ENTRY PROC [d: Data, subject: ROPE] RETURNS [sought: Status] = { ENABLE UNWIND => {}; sought _ NARROW[d.statuses.Fetch[subject].value]; IF sought = NIL THEN { sought _ NEW [StatusPrivate _ []]; IF NOT d.statuses.Insert[subject, sought] THEN ERROR; }; WHILE sought.state = inProgress DO WAIT d.change ENDLOOP; IF sought.state = notDone THEN sought.state _ inProgress; }; SetState: ENTRY PROC [d: Data, status: Status, state: State] = { ENABLE UNWIND => {}; status.state _ state; BROADCAST d.change; }; Find: PROC [subject: ROPE, parent: Commander.Handle] RETURNS [fd: FileData] = { subjectDotLoad: ROPE = subject.Concat[".Load"]; loadSubjectCM: ROPE = Rope.Cat["Load", subject, ".cm"]; searchList: LORA _ CONS[CommandTool.CurrentWorkingDirectory[], NARROW[CommandTool.GetProp[parent, $SearchRules]]]; FOR searchList _ searchList, searchList.rest WHILE searchList # NIL DO wDir: ROPE = NARROW[searchList.first]; dotLoadData: FileData = GetFileData[subjectDotLoad, wDir]; loadCMData: FileData = GetFileData[loadSubjectCM, wDir]; dotLoadExists: BOOL = dotLoadData # notFound; loadCMExists: BOOL = loadCMData # notFound; IF dotLoadExists OR loadCMExists THEN { RETURN [ IF NOT dotLoadExists THEN loadCMData ELSE IF NOT loadCMExists THEN dotLoadData ELSE IF BasicTime.Period[from: dotLoadData.created, to: loadCMData.created] >= 0 THEN loadCMData ELSE dotLoadData ] }; ENDLOOP; fd _ notFound; }; GetFileData: PROC [short, wDir: ROPE] RETURNS [fd: FileData] = { fd _ notFound; [fullFName: fd.name, created: fd.created] _ FS.FileInfo[name: short, wDir: wDir, remoteCheck: FALSE !FS.Error => CONTINUE]; }; SecondSource: PROC [cmd: Commander.Handle] RETURNS [result: REF ANY _ NIL, msg: ROPE _ NIL] --Commander.CommandProc-- = { ENABLE CommandTool.Failed => {result _ $Failure; msg _ errorMsg; CONTINUE}; argv: CommandTool.ArgumentVector = CommandTool.Parse[cmd: cmd, starExpand: TRUE, switchChar: ' ]; FOR i: INT IN [1 .. argv.argc) DO fileName: ROPE = argv[i]; in: IO.STREAM = FS.StreamOpen[fileName !FS.Error => { msg _ IO.PutFR["Failed to open %g: %g %g\n", [rope[fileName]], [atom[error.code]], [rope[error.explanation]]]; result _ $Failure; LOOP}]; DO command: ROPE = in.GetLineRope[ !IO.EndOfStream => EXIT]; innerResult: REF ANY = CommandTool.DoCommand[command, cmd]; IF innerResult = $Failure THEN result _ $Failure; ENDLOOP; in.Close[]; ENDLOOP; }; DoCommand: PROC [commandLine: ROPE, parent: Commander.Handle] RETURNS [result: REF ANY] = { rep: ReadEvalPrint.Handle = NARROW[CommandTool.GetProp[parent, $ReadEvalPrintHandle]]; msg: ROPE = CommandTool.EachCommand[h: rep, command: commandLine]; parent.out.PutRope[msg]; IF msg.Length[] > 0 AND msg.Fetch[msg.Length[] - 1] # '\n THEN parent.out.PutRope["\n"]; result _ CommandTool.GetProp[parent, $Result]; }; Start: PROC = { IF data = NIL THEN { data _ NEW [DataPrivate _ [ statuses: HashTable.Create[equal: HashTable.RopeEqualModCase, hash: HashTable.HashRopeModCase] ]]; TRUSTED { Process.InitializeCondition[@data.change, Process.SecondsToTicks[60]]; Process.EnableAborts[@data.change]; }; Atom.PutProp[$InstallImplData, $InstallImplData, data]; }; Commander.Register["Install", InstallCmd, "Do load file once"]; Commander.Register["UnInstall", UnInstallCmd, "Forget having done load file"]; Commander.Register["SecondSource", SecondSource, "Like Source, but stops on $Failure"]; }; Start[]; END. าInstallImpl.Mesa Copyright c 1986 by Xerox Corporation. All rights reserved. Spreitzer, June 19, 1986 3:59:08 pm PDT Willie-Sue, June 18, 1986 4:52:09 pm PDT Mike Spreitzer July 10, 1986 1:58:36 pm PDT สV– "cedar" style˜code™Kšœ ฯmœ1™