InitialCommandsA.mesa
Last editted: April 14, 1983 12:16 pm by L. Stewart
Last editted: May 27, 1983 9:57 am by Paul Rovner
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.ROPENIL;
destroyLogOnSuccess: BOOLFALSE;
connecting concrete and opaque types
abortProc: Resource.AbortProc = TRUSTED{
PROC [data: REF ANY] RETURNS[abort: BOOL];
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: BOOLFALSE;
otherOwner: Rope.ROPENIL;
aborted: BOOLFALSE;
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: BOOLFALSE;
otherOwner: Rope.ROPENIL;
aborted: BOOLFALSE;
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.STREAMIO.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];
log not there in case of no such source
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: BOOLFALSE] = 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: BOOLEANFALSE, 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