<> <> <> DIRECTORY AMBridge USING [TVForReferent], CedarVersion USING [major, minor, patch], CIFS USING [OpenFile, read, Open], Commander, ConvertUnsafe USING [ToRope], Directory USING [Lookup], ExecOps USING [Outcome], Feedback USING [BeginItemProc, CreateProc, DestroyProc, FinishItemProc, NoteProgressProc, Procs], File USING [Capability], IO USING [GetInt, int, NewLine, Put, PutF, PutRope, PutText, PutTV, ResetUserAbort, RIS, rope, STREAM, string, time, UserAbort, UserAborted], List USING [CompareProc, Sort], Loader USING [Start, Instantiate], Process USING [Priority, GetPriority, SetPriority, priorityBackground, Pause, MsecToTicks], Resource USING [Acquire, Release, AbortProc], Rope USING [Compare, Concat, IsEmpty, Length, ROPE, ToRefText, Cat, Index, Substr], Runtime USING [GetBuildTime, IsBound], TemporarySpecialExecOps USING [BindUsingFeedback, CompileUsingFeedback], TiogaMenuOps USING [Open], UECP USING [Argv, Parse], UserCredentials USING [GetUserCredentials], UserProfile USING [Boolean, Token], ViewerClasses USING [Viewer], ViewerOps USING [CreateViewer, FindViewer, RestoreViewer, BlinkIcon, DestroyViewer]; InitialCommandsA: CEDAR PROGRAM IMPORTS AMBridge, CedarVersion, CIFS, Commander, ConvertUnsafe, Directory, IO, List, Loader, Process, Resource, Rope, Runtime, TemporarySpecialExecOps, TiogaMenuOps, UserProfile, UECP, UserCredentials, ViewerOps = BEGIN compilerSwitches, binderSwitches: Rope.ROPE _ NIL; destroyLogOnSuccess: BOOL _ FALSE; <> abortProc: Resource.AbortProc = TRUSTED{ <> in: IO.STREAM = NARROW[data, IO.STREAM]; abort _ in.UserAbort[]; IF abort THEN in.ResetUserAbort[]; }; Bind: PROC[args: Rope.ROPE, in, out: IO.STREAM] RETURNS[outCome: ExecOps.Outcome] = TRUSTED { priority: Process.Priority = Process.GetPriority[]; success: BOOL _ FALSE; otherOwner: Rope.ROPE _ NIL; aborted: BOOL _ FALSE; BCreate: Feedback.CreateProc = {RETURN[NIL]}; BDestroy: Feedback.DestroyProc = { out.Put[IO.string[trailer] ! IO.UserAborted => {aborted _ TRUE; CONTINUE}]}; BBeginItem: Feedback.BeginItemProc = TRUSTED{ fileName: Rope.ROPE _ ConvertUnsafe.ToRope[item]; startIndex: INT _ Rope.Index[s1: fileName, s2: " "] + 1; stopIndex: INT _ Rope.Index[s1: fileName, pos1: startIndex, s2: "/"]; length: INT _ Rope.Length[fileName]; fileName _ Rope.Substr[base: fileName, start: startIndex, len: stopIndex - startIndex]; fileName _ Rope.Cat[fileName, ".config"]; WaitUntilSaved[fileName, out ! IO.UserAborted => {aborted _ TRUE; CONTINUE} ]; out.Put[IO.string[item] ! IO.UserAborted => {aborted _ TRUE; CONTINUE}]}; BFinishItem: Feedback.FinishItemProc = { out.PutF[" %g\n", IO.string[trailer] ! IO.UserAborted => {aborted _ TRUE; CONTINUE}]}; BNoteProgress: Feedback.NoteProgressProc = { out.PutRope[" ." ! IO.UserAborted => {aborted _ TRUE; CONTINUE}]; IF aborted OR in.UserAbort[] THEN { in.ResetUserAbort[]; ERROR IO.UserAborted; }; }; binderProcs: Feedback.Procs _ [BCreate, BDestroy, BBeginItem, BNoteProgress, BFinishItem]; [success, otherOwner] _ Resource.Acquire[resource: $Binder, owner: "Binder", waitForIt: FALSE]; IF NOT success THEN { out.PutRope[Rope.Cat["Waiting for ", otherOwner, " to finish..."]]; [success, ] _ Resource.Acquire [resource: $Binder, owner: "Binder", waitForIt: TRUE, abortProc: abortProc, abortProcData: in ]; IF NOT success THEN { out.PutRope["ABORTED\n"]; RETURN; } ELSE out.PutRope["proceeding\n"]; }; BEGIN ENABLE UNWIND => {Process.SetPriority[priority]; [] _ Resource.Release[$Binder]}; cmdText: REF StringBody; cmd: LONG POINTER TO PACKED ARRAY [0..0) OF CHARACTER; IF ~Runtime.IsBound[TemporarySpecialExecOps.BindUsingFeedback] THEN { ENABLE ANY => {out.PutText["Failed\n"]; GOTO Errors}; out.PutText["Loading and Starting Binder.bcd...\n"]; Loader.Start[Loader.Instantiate[Directory.Lookup["Binder.bcd"], 1, TRUE].cm]; }; cmdText _ LOOPHOLE[Rope.ToRefText[Rope.Concat[binderSwitches, args]], REF StringBody]; cmd _ LOOPHOLE[@(cmdText.text)]; Process.SetPriority[Process.priorityBackground]; outCome _ TemporarySpecialExecOps.BindUsingFeedback[cmd, @binderProcs]; ShowLog["Binder.log", outCome = ok]; EXITS Errors => outCome _ errors; END; -- ENABLE UNWIND Process.SetPriority[priority]; [] _ Resource.Release[$Binder]; }; -- end Bind Compile: PROC[args: Rope.ROPE, in, out: IO.STREAM] RETURNS[outCome: ExecOps.Outcome] = TRUSTED { priority: Process.Priority = Process.GetPriority[]; success: BOOL _ FALSE; otherOwner: Rope.ROPE _ NIL; aborted: BOOL _ FALSE; CCreate: Feedback.CreateProc = {RETURN[NIL]}; CDestroy: Feedback.DestroyProc = { out.Put[IO.string[trailer] ! IO.UserAborted => {aborted _ TRUE; CONTINUE}]}; CBeginItem: Feedback.BeginItemProc = TRUSTED{ fileName: Rope.ROPE _ ConvertUnsafe.ToRope[item]; startIndex: INT _ Rope.Index[s1: fileName, s2: " "] + 1; stopIndex: INT _ Rope.Index[s1: fileName, pos1: startIndex, s2: "/"]; length: INT _ Rope.Length[fileName]; fileName _ Rope.Substr[base: fileName, start: startIndex, len: stopIndex - startIndex]; fileName _ Rope.Cat[fileName, ".mesa"]; WaitUntilSaved[fileName, out ! IO.UserAborted => {aborted _ TRUE; CONTINUE} ]; out.Put[IO.string[item] ! IO.UserAborted => {aborted _ TRUE; CONTINUE}]}; CFinishItem: Feedback.FinishItemProc = { out.PutF[" %g\n", IO.string[trailer] ! IO.UserAborted => {aborted _ TRUE; CONTINUE}]}; CNoteProgress: Feedback.NoteProgressProc = { out.PutRope[" ." ! IO.UserAborted => {aborted _ TRUE; CONTINUE}]; IF aborted OR in.UserAbort[] THEN { in.ResetUserAbort[]; ERROR IO.UserAborted; }; }; compilerProcs: Feedback.Procs _ [CCreate, CDestroy, CBeginItem, CNoteProgress, CFinishItem]; [success, otherOwner] _ Resource.Acquire[resource: $Compiler, owner: "Compiler", waitForIt: FALSE]; IF NOT success THEN { out.PutRope[Rope.Cat["Waiting for ", otherOwner, " to finish..."]]; [success, ] _ Resource.Acquire [resource: $Compiler, owner: "Compiler", waitForIt: TRUE, abortProc: abortProc, abortProcData: in ]; IF NOT success THEN { out.PutRope["ABORTED\n"]; RETURN; } ELSE out.PutRope["proceeding\n"]; }; BEGIN ENABLE UNWIND => {Process.SetPriority[priority]; [] _ Resource.Release[$Compiler]}; cmdText: REF StringBody; cmd: LONG POINTER TO PACKED ARRAY [0..0) OF CHARACTER; IF ~Runtime.IsBound[TemporarySpecialExecOps.CompileUsingFeedback] THEN { ENABLE ANY => {out.PutText["Failed\n"]; GOTO Errors}; out.PutText["Loading and Starting Compiler.bcd...\n"]; Loader.Start[Loader.Instantiate[Directory.Lookup["Compiler.bcd"], 1, TRUE].cm]; }; cmdText _ LOOPHOLE[Rope.ToRefText[Rope.Concat[compilerSwitches, args]], REF StringBody]; cmd _ LOOPHOLE[@(cmdText.text)]; Process.SetPriority[Process.priorityBackground]; outCome _ TemporarySpecialExecOps.CompileUsingFeedback[cmd, @compilerProcs]; ShowLog["Compiler.log", outCome = ok]; EXITS Errors => outCome _ errors; END; -- ENABLE UNWIND Process.SetPriority[priority]; [] _ Resource.Release[$Compiler]; }; -- end Compile PrintResult: PROC [result: ExecOps.Outcome, out: IO.STREAM] = { SELECT result FROM warnings => out.PutRope[". . . warnings\n"]; errors => out.PutRope[". . . errors\n"]; errorsAndWarnings => out.PutRope[". . . errorsAndWarnings\n"]; aborted => out.PutRope[". . . aborted\n"] ENDCASE; }; MyCompile: Commander.CommandProc = { PrintResult[result: Compile[args: cmd.commandLine, in: cmd.in, out: cmd.out], out: cmd.out]; }; MyBind: Commander.CommandProc = { PrintResult[result: Bind[args: cmd.commandLine, in: cmd.in, out: cmd.out], out: cmd.out]; }; SetDefaultSwitches: Commander.CommandProc = { SetDefaultSwitchesInternal[]; IF compilerSwitches.Length[] > 0 THEN cmd.out.PutF["Compiler Switches now %g\n", IO.rope[compilerSwitches]] ELSE cmd.out.PutRope["No compiler switches,\n"]; IF binderSwitches.Length[] > 0 THEN cmd.out.PutF["Binder Switches now %g\n", IO.rope[binderSwitches]] ELSE cmd.out.PutRope["No binder switches,\n"]; }; SetDefaultSwitchesInternal: PROC = { compilerSwitches _ UserProfile.Token["Compiler.Switches"]; IF UserProfile.Boolean["Compiler.SeparateLogs", FALSE] THEN compilerSwitches _ Rope.Concat["/-g", compilerSwitches]; binderSwitches _ UserProfile.Token["Binder.Switches"]; destroyLogOnSuccess _ UserProfile.Boolean["Compiler.DestroyLogOnSuccess", TRUE]; }; Date: Commander.CommandProc = { cmd.out.PutF[" %t\n", IO.time[]]; }; User: Commander.CommandProc = { user: Rope.ROPE _ UserCredentials.GetUserCredentials[].name; IF user.Length[] = 0 THEN user _ "NIL"; cmd.out.PutF["User: %g\n", IO.rope[user]]; }; Version: Commander.CommandProc = { cmd.out.PutF["Cedar %g.%g", IO.int[CedarVersion.major], IO.int[CedarVersion.minor]]; IF CedarVersion.patch # 0 THEN cmd.out.PutF[".%g", IO.int[CedarVersion.patch]]; cmd.out.PutF[" of %t\n", IO.time[Runtime.GetBuildTime[]]]; }; Properties: Commander.CommandProc = TRUSTED { argStream: IO.STREAM _ IO.RIS[cmd.commandLine]; depth, width: INT; depth _ argStream.GetInt[ ! ANY => { depth _ 4; CONTINUE; }]; width _ argStream.GetInt[ ! ANY => { width _ 32; CONTINUE; }]; cmd.out.PutRope["propertyList = "]; cmd.out.PutTV[tv: AMBridge.TVForReferent[NEW[REF ANY _ cmd.propertyList]], depth: depth, width: width]; cmd.out.NewLine[]; }; ECell: TYPE = RECORD [name, doc: Rope.ROPE]; EnumerateCommands: Commander.CommandProc = { el: LIST OF REF ANY; eCell: REF ECell; EProc: PROC[name: Rope.ROPE, proc: Commander.CommandProc, doc: Rope.ROPE] RETURNS[stop: BOOL] = { IF proc # NIL THEN el _ CONS[NEW[ECell _ [name: name, doc: doc]], el]; RETURN[FALSE]; }; MyCompare: List.CompareProc = { a, b: REF ECell; a _ NARROW[ref1]; b _ NARROW[ref2]; RETURN[Rope.Compare[a.name, b.name]]; }; cmd.out.PutRope["Registered commands:\n"]; [] _ Commander.Enumerate[EProc]; el _ List.Sort[list: el, compareProc: MyCompare]; WHILE el # NIL DO eCell _ NARROW[el.first]; cmd.out.PutF["%-20g %g\n", IO.rope[eCell.name], IO.rope[eCell.doc]]; el _ el.rest; ENDLOOP; }; Alias: Commander.CommandProc = { argv: UECP.Argv _ UECP.Parse[cmd.commandLine]; oldProc: Commander.CommandProc; doc: Rope.ROPE; IF argv.argc > 2 THEN { [proc: oldProc, doc: doc] _ Commander.Lookup[argv[2]]; IF oldProc # NIL THEN Commander.Register[key: argv[1], proc: oldProc, doc: doc] ELSE cmd.out.PutF["Alias: %g not found\n", IO.rope[argv[2]]]; } ELSE cmd.out.PutRope["Usage: Alias newname oldname\n"]; }; Unregister: Commander.CommandProc = { argv: UECP.Argv _ UECP.Parse[cmd.commandLine]; IF argv.argc = 2 THEN { IF Commander.Lookup[argv[1]].proc # NIL THEN Commander.Register[key: argv[1], proc: NIL, doc: NIL] ELSE cmd.out.PutF["Unregister: %g not found\n", IO.rope[argv[1]]]; } ELSE cmd.out.PutRope["Usage: Unregister commandname\n"]; }; SetProperty: Commander.CommandProc = { argv: UECP.Argv _ UECP.Parse[cmd.commandLine]; IF argv.argc # 3 THEN cmd.out.PutRope["Usage: SetProperty key value\n"] ELSE [] _ Commander.PutProperty[key: argv[1], val: argv[2], aList: cmd.propertyList]; }; Open: Commander.CommandProc = { argv: UECP.Argv _ UECP.Parse[cmd.commandLine]; IF argv.argc # 2 THEN { cmd.out.PutRope["Usage: Open filename\n"]; RETURN; }; OpenViewer[argv[1], FALSE, cmd.out]; }; New: Commander.CommandProc = { OpenViewer[NIL, TRUE, cmd.out]; }; Comment: Commander.CommandProc = { }; ShowLog: PROC [fileName: Rope.ROPE, ok: BOOL] = { log: ViewerClasses.Viewer _ ViewerOps.FindViewer[fileName]; IF NOT ok THEN { createIconic: BOOL = UserProfile.Boolean["Compiler.IconicLogs", FALSE]; IF log # NIL THEN ViewerOps.RestoreViewer[log] ELSE IF FileExists[fileName] THEN log _ CreateLog[fileName: fileName, iconic: createIconic]; <> IF log # NIL AND log.iconic AND UserProfile.Boolean["Compiler.BlinkLogs", TRUE] THEN ViewerOps.BlinkIcon[log]; } ELSE IF log # NIL THEN {ViewerOps.DestroyViewer[log]; log _ NIL}; }; FileExists: PROC [fileName: Rope.ROPE] RETURNS[ans: BOOL] = { cifsFile: CIFS.OpenFile _ NIL; cifsFile _ CIFS.Open[Rope.Concat["/local/", fileName], CIFS.read ! ANY => CONTINUE]; ans _ (cifsFile # NIL); }; CreateLog: PROC [fileName: Rope.ROPE, iconic: BOOL] RETURNS[viewer: ViewerClasses.Viewer] = { IF iconic THEN viewer _ ViewerOps.CreateViewer [flavor: $Text, info: [name: fileName, file: fileName, iconic: iconic, icon: typescript]] ELSE {viewer _ TiogaMenuOps.Open[fileName]; viewer.icon _ typescript}; }; WaitUntilSaved: PROC [fileName: Rope.ROPE, out: IO.STREAM] = { viewer: ViewerClasses.Viewer = ViewerOps.FindViewer[fileName]; IF viewer # NIL AND viewer.newVersion THEN { SomeSaveInProgress: PROC RETURNS[ans: BOOL _ FALSE] = CHECKED { v: ViewerClasses.Viewer _ viewer; IF viewer.saveInProgress THEN RETURN[TRUE]; WHILE (v _ v.link) # NIL AND (v # viewer) DO IF v.saveInProgress THEN RETURN[TRUE]; ENDLOOP; }; IF NOT SomeSaveInProgress[] THEN out.PutRope[Rope.Cat["***Please save ", viewer.name, "..."]]; UNTIL SomeSaveInProgress[] DO Process.Pause[Process.MsecToTicks[1000]]; IF out.UserAbort[] THEN ERROR IO.UserAborted; ENDLOOP; IF SomeSaveInProgress[] THEN out.PutRope[Rope.Cat["***Waiting for ", viewer.name, " to finish being saved..."]]; WHILE SomeSaveInProgress[] DO TRUSTED { Process.Pause[Process.MsecToTicks[1000]]; IF out.UserAbort[] THEN ERROR IO.UserAborted; }; ENDLOOP; out.PutRope["ok\n"]; }; }; OpenViewer: PROC [name: Rope.ROPE, newViewer: BOOLEAN _ FALSE, out: IO.STREAM] = { viewer: ViewerClasses.Viewer; IF newViewer THEN viewer _ ViewerOps.CreateViewer[flavor: $Text, info: [name: IF Rope.IsEmpty[name] THEN "No Name" ELSE name, file: name, iconic: FALSE]] ELSE viewer _ TiogaMenuOps.Open[name]; -- workaround IF viewer = NIL THEN out.PutF["\tViewer file not found: %g\n", IO.rope[name]] ELSE out.PutF["\tCreated Viewer: %g\n", IO.rope[viewer.name]]; }; Init: PROC = { SetDefaultSwitchesInternal[]; Commander.Register[key: "Compile", proc: MyCompile, doc: "Compile programs"]; Commander.Register[key: "Bind", proc: MyBind, doc: "Bind configurations"]; Commander.Register[key: "SetCompilerSwitchesFromProfile", proc: SetDefaultSwitches, doc: "Read compiler and binder switches from user profile"]; Commander.Register[key: "Date", proc: Date, doc: "Print date and time"]; Commander.Register[key: "User", proc: User, doc: "Print name of logged in user"]; Commander.Register[key: "Version", proc: Version, doc: "Print Cedar version number"]; Commander.Register[key: "GetProperties", proc: Properties, doc: "Display command tool property list"]; Commander.Register[key: "Alias", proc: Alias, doc: "Alias newName oldName - Attach a new name to an existing command"]; Commander.Register[key: "?", proc: EnumerateCommands, doc: "List registered commands"]; Commander.Register[key: "SetProperty", proc: SetProperty, doc: "SetProperty propertyName value - change or add to the command tool property list"]; Commander.Register[key: "Open", proc: Open, doc: "Open fileName - open a viewer"]; Commander.Register[key: "New", proc: New, doc: "Open an empty viewer"]; Commander.Register[key: "Unregister", proc: Unregister, doc: "Unregister a command"]; Commander.Register[key: "/", proc: Comment, doc: "Comment"]; Commander.Register[key: "-", proc: Comment, doc: "Comment"]; }; Init[]; END. March 27, 1983 3:27 pm, Stewart, Created April 3, 1983 12:56 pm, Stewart, combined CompileAndBindImpl.mesa