CompilerClientCommandImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Satterthwaite, October 21, 1985 5:52:55 pm PDT
Maxwell, January 26, 1984 9:05:33 am PST
Paul Rovner, December 4, 1983 11:57 am
Spreitzer, August 29, 1985 2:13:50 pm PDT
Russ Atkinson (RRA) April 3, 1985 4:02:43 pm PST
Bob Hagmann April 24, 1986 11:01:13 am PST
DIRECTORY
Ascii USING [Lower],
Booting USING [RegisterProcs, RollbackProc],
Commander USING [CommandObject, Handle, Register],
CommandTool USING [ArgumentVector, DoCommand, Failed, Parse, RegistrationDirectory, Run],
CommandUtil USING [PairList, Failed, GetNth, GetRootName, ListLength, Parse, SetExtension],
CompilerOps USING [LetterSwitches, StreamId, Transaction],
ComputeServerClient USING [BestServerStats, RemoteSuccess, StartService],
ComputeServerServer USING [Lookup, RegisteredProcHandle],
FileNames USING [ConvertToSlashFormat, CurrentWorkingDirectory, GetShortName, ResolveRelativePath],
FileParms USING [BindingProc],
FileViewerOps USING [AttachErrorLog, ShowLog, RemoveErrorLog, WaitUntilSaved],
FS USING [Delete, Error, ExpandName, nullOpenFile, OpenFile, StreamOpen],
IO USING [Close, EndOfStream, GetTokenRope, IDProc, PutRope, RIS, STREAM],
MessageWindow USING [Append, Blink, Clear],
Process USING [GetPriority, InitializeCondition, MsecToTicks, Priority, SetPriority],
Pup USING [nullSocket],
PupName USING [HisName, NameLookup],
Rope USING [Cat, Concat, Fetch, Find, FromChar, Equal, IsEmpty, Length, ROPE, Substr],
RopeFile USING [FromStream],
SystemVersion USING [machineType],
UserProfile USING [Boolean, Token];
CompilerClientCommandImpl:
MONITOR
IMPORTS Ascii, Booting, Commander, CommandTool, CommandUtil, ComputeServerClient, ComputeServerServer, FileNames, FileViewerOps, FS, IO, MessageWindow, Process, PupName, Rope, RopeFile, SystemVersion, UserProfile
= {
ROPE: TYPE = Rope.ROPE;
Outcome: TYPE = {ok, warnings, errors, aborted};
standardDefaults: CompilerOps.LetterSwitches = DefaultSwitches[];
directoriesToUseExistingLog: LIST OF ROPE ← NIL;
CompilerCondition: CONDITION;
Compile:
SAFE PROC [cmd: Commander.Handle]
RETURNS [result:
REF ←
NIL, msg: Rope.
ROPE ←
NIL] ~
TRUSTED {
Moved here from global frame by Spreitzer August 29, 1985:
parms: REF CompilerOps.Transaction = NEW[CompilerOps.Transaction];
sourceName, objectName, errorName, rootName, wDir: Rope.ROPE ← NIL;
sourceStream, objectStream, errorStream: IO.STREAM ← NIL;
useLog: BOOL; -- use compiler.log for error reporting
makeNewLog: BOOL ← TRUE;
destroyLogOnSuccess: BOOL;
createIconic: BOOL;
blinkIfIconic: BOOL;
viewSeparateLogs: BOOL;
userAbort: BOOL ← FALSE; -- set by ^DEL, STOP
errors, warnings: BOOL ← FALSE;
someNonSuccess: BOOL ← FALSE;
remoteMsg: Rope.ROPE ← NIL;
priority: Process.Priority = Process.GetPriority[];
switchDefaults: CompilerOps.LetterSwitches;
verboseComputeServer: BOOL;
moduleCount: CARDINAL ← 0;
complex: BOOL = SELECT cmd.procData.clientData FROM $Vanilla => FALSE, $Complex => TRUE, $RemoteVanilla => FALSE, ENDCASE => ERROR;
preferRemote: BOOL = cmd.procData.clientData = $RemoteVanilla;
compilerSwitches: Rope.ROPE ← UserProfile.Token["Compiler.Switches"];
cmdStream: IO.STREAM;
filesInit: BOOL ← FALSE;
started: BOOL ← FALSE;
Cleanup:
PROC = {
Process.SetPriority[priority];
IF useLog
THEN FileViewerOps.ShowLog[
fileName: FS.ExpandName["Compiler.log", wDir].fullFName,
destroyIt: ~someNonSuccess AND destroyLogOnSuccess,
createIconic: createIconic,
blinkIfIconic: blinkIfIconic
];
};
Finalize:
PROC [userAbort:
BOOL] = {
sourceFileName: Rope.ROPE;
IF sourceName #
NIL
THEN {
errorName = NIL iff useLog OR no errors or warnings, under normal circumstances
sourceFileName ← FS.ExpandName[sourceName, wDir].fullFName;
IF Rope.Length[remoteMsg] > 3 THEN appendRopeToLog[Rope.Substr[remoteMsg, 3]];
IF useLog OR ~(errors OR warnings)
THEN FileViewerOps.RemoveErrorLog[sourceFileName] -- removes ErrorLog button
ELSE {
FileViewerOps.ShowLog[fileName: sourceFileName,
createIconic: createIconic, blinkIfIconic: blinkIfIconic];
IF viewSeparateLogs
THEN {
IF ~errorName.IsEmpty[] THEN FileViewerOps.ShowLog[fileName: errorName, createIconic: createIconic, blinkIfIconic: blinkIfIconic];
}
ELSE FileViewerOps.AttachErrorLog[sourceFileName];
};
};
IF userAbort
OR errors
THEN {
IF objectName #
NIL
THEN
DO
FS.Delete[name: objectName, wDir: wDir
! FS.Error => IF error.group = lock OR error.code = $unknownFile THEN EXIT];
ENDLOOP;
};
IF errorName =
NIL
THEN {
errlogFileName: Rope.ROPE ← CommandUtil.SetExtension[rootName, "errlog"];
DO
FS.Delete[name: errlogFileName, wDir: wDir
! FS.Error => IF error.group = lock OR error.code = $unknownFile THEN EXIT];
ENDLOOP;
};
};
appendRopeToLog:
SAFE
PROC [logEntry:
ROPE] =
CHECKED {
slashWDir: ROPE ← FileNames.ConvertToSlashFormat[wDir];
tries: INT ← 0;
consCurrentDirectory: BOOL ← FALSE;
innerAppendRopeToLog:
ENTRY
SAFE
PROC =
CHECKED {
ENABLE UNWIND => NULL;
DO
openFailed: BOOL ← FALSE;
needNewLog: BOOL;
log: IO.STREAM;
oldLog: IO.STREAM;
consCurrentDirectory ← FALSE;
IF makeNewLog
THEN {
needNewLog ← TRUE;
consCurrentDirectory ← TRUE;
}
ELSE {
FOR l:
LIST
OF
ROPE ← directoriesToUseExistingLog, l.rest
UNTIL l =
NIL
DO
IF Rope.Equal[l.first, slashWDir]
THEN {
needNewLog ← FALSE;
EXIT;
};
REPEAT
FINISHED => {
consCurrentDirectory ← TRUE;
needNewLog ← TRUE;
};
ENDLOOP;
};
IF ~needNewLog
THEN oldLog ←
FS.StreamOpen[fileName: "Compiler.log", accessOptions: $read !
FS.Error => {
IF error.group = lock
THEN {
openFailed ← TRUE;
tries ← tries + 1;
IF tries > 10
THEN {
MessageWindow.Clear[];
MessageWindow.Append["Compiler lock failure after 10 retries for Compiler.log read"];
MessageWindow.Blink[];
};
CONTINUE;
}
ELSE CONTINUE;
};
];
IF openFailed
THEN {
IF tries > 10 THEN EXIT;
WAIT CompilerCondition;
LOOP;
};
log ←
FS.StreamOpen[fileName: "Compiler.log", accessOptions: $create !
FS.Error => {
IF error.group = lock
THEN {
openFailed ← TRUE;
tries ← tries + 1;
IF tries > 10
THEN {
MessageWindow.Clear[];
MessageWindow.Append["Compiler lock failure after 10 retries for Compiler.log create"];
MessageWindow.Blink[];
};
CONTINUE;
};
};
];
IF openFailed
THEN {
IF tries > 10 THEN EXIT;
WAIT CompilerCondition;
LOOP;
};
IF ~needNewLog
AND log #
NIL
THEN {
log.PutRope[RopeFile.FromStream[oldLog]];
};
IF openFailed
THEN {
IF tries > 10 THEN EXIT;
WAIT CompilerCondition;
LOOP;
};
log.PutRope[logEntry];
log.Close[];
IF consCurrentDirectory THEN directoriesToUseExistingLog ← CONS[slashWDir, directoriesToUseExistingLog];
EXIT;
ENDLOOP;
makeNewLog ← FALSE;
NOTIFY CompilerCondition;
};
innerAppendRopeToLog[];
};
get some parameters from the user's profile
verboseComputeServer ← UserProfile.Boolean["Compiler.VerboseComputeServer", FALSE];
destroyLogOnSuccess ← UserProfile.Boolean["Compiler.DestroyLogOnSuccess", TRUE];
createIconic ← UserProfile.Boolean["Compiler.IconicLogs", FALSE];
blinkIfIconic ← UserProfile.Boolean["Compiler.BlinkLogs", TRUE];
viewSeparateLogs ← UserProfile.Boolean["Compiler.ViewSeparateLogs", FALSE];
IF UserProfile.Boolean["Compiler.SeparateLogs",
FALSE]
THEN compilerSwitches ← Rope.Cat[compilerSwitches, "~g"];
IF compilerSwitches.Length[] # 0
THEN
cmd.commandLine ← Rope.Cat[(IF complex THEN "/" ELSE "-"), compilerSwitches, " ", cmd.commandLine];
cmdStream ← IO.RIS[cmd.commandLine];
sourceName ← rootName ← objectName ← errorName ← NIL;
parms.objectName ← NIL;
do the compilation
BEGIN
ENABLE
UNWIND => Cleanup[];
switchDefaults ← DefaultSwitches[];
wDir ← FileNames.CurrentWorkingDirectory[];
DO
first: BOOL;
args, results: CommandUtil.PairList;
switches: Rope.ROPE ← NIL;
localPause: BOOL;
sense: BOOL;
{
-- start scope for EXITS
cmdLine: Rope.ROPE ← NIL;
originalSourceName: Rope.ROPE ← NIL;
parms.switches ← switchDefaults;
parms.switches['p] ← FALSE;
IF complex
THEN
[sourceName, args, results, switches] ← CommandUtil.Parse[cmdStream
! CommandUtil.Failed => GOTO badSyntax]
ELSE {
use a simple syntax for the command line
token: Rope.ROPE;
token ← cmdStream.GetTokenRope[IO.IDProc ! IO.EndOfStream => EXIT].token;
IF token.Length[] > 0
THEN
SELECT token.Fetch[0]
FROM
'- => switches ← token.Substr[1, token.Length[]-1];
ENDCASE => sourceName ← token};
IF sourceName = NIL AND switches = NIL THEN EXIT;
IF CommandUtil.ListLength[results] > 1 THEN GOTO badSemantics;
IF sourceName = NIL THEN GOTO globalSwitches;
originalSourceName ← sourceName;
rootName ← CommandUtil.GetRootName[
IF CommandUtil.ListLength[results] = 1
THEN CommandUtil.GetNth[results, 0]
ELSE FileNames.GetShortName[sourceName]];
errorName ← CommandUtil.SetExtension[rootName, "errlog"];
IF switches #
NIL
THEN {
sense ← TRUE;
FOR i:
INT
IN [0..switches.Length[])
DO
c: CHAR = switches.Fetch[i];
SELECT c
FROM
'-, '~ => {sense ← ~sense; LOOP};
IN ['a..'z],
IN ['A..'Z] =>
parms.switches[Ascii.Lower[c]] ← sense;
IN ['1..'5] =>
parms.debugPass ← c-'0;
ENDCASE;
sense ← TRUE;
ENDLOOP;
switches ← NIL;
};
sourceName ← CommandUtil.SetExtension[sourceName, "mesa"];
FileViewerOps.WaitUntilSaved[
IF Rope.Find[sourceName, ">"] < 0
AND Rope.Find[sourceName, "/"] < 0
THEN FS.ExpandName[sourceName, wDir].fullFName
ELSE sourceName,
cmd.out ! ABORTED => {userAbort ← TRUE; GOTO truncateList}];
parms.source.locator ← FileNames.GetShortName[sourceName];
IF CommandUtil.ListLength[results] # 0
THEN {
objectName ← CommandUtil.GetNth[list: results, n: 0, delete: TRUE];
results ← NIL;
}
ELSE objectName ← rootName;
objectName ← CommandUtil.SetExtension[objectName, "bcd"];
parms.objectName ← objectName;
parms.objectFile ← FS.nullOpenFile;
moduleCount ← moduleCount + 1;
first ← TRUE;
makeNewLog ← ~parms.switches['h]; parms.switches['h] ← FALSE; -- set append or force new log
FOR c:
CHAR
IN ['a..'z]
DO
sd: BOOL = (IF c = 'p THEN FALSE ELSE standardDefaults[c]);
IF parms.switches[c] # sd
THEN {
IF first THEN {first ← FALSE; cmdLine ← IF complex THEN "/" ELSE "-"};
IF sd THEN cmdLine ← cmdLine.Concat["-"];
cmdLine ← cmdLine.Concat[Rope.FromChar[c]];
};
ENDLOOP;
cmdLine ← cmdLine.Concat[" "];
useLog ← parms.switches['g]; parms.switches['g] ← FALSE;
localPause ← parms.switches['p]; parms.switches['p] ← FALSE;
main line code
sourceName ← FileNames.GetShortName[sourceName];
IF complex
THEN {
first: BOOL ← TRUE;
cmdLine ← cmdLine.Cat[rootName, " ← ", originalSourceName, "["];
FOR p: CommandUtil.PairList ← args, p.rest
UNTIL p=
NIL
DO
IF ~first THEN cmdLine ← cmdLine.Concat[", "];
cmdLine ← cmdLine.Cat[p.first.key, ": ", p.first.val];
first ← FALSE;
ENDLOOP;
cmdLine ← cmdLine.Concat["]"];
}
ELSE cmdLine ← cmdLine.Concat[sourceName];
{
ENABLE
UNWIND => Finalize[userAbort];
found: BOOL ← FALSE;
success: ComputeServerClient.RemoteSuccess ← false;
successFalseCounter: INT ← 0;
serverInstance: Rope.ROPE ← NIL;
result ← $Blocked;
remoteMsg ← NIL;
WHILE result = $Blocked
DO
IF SystemVersion.machineType # dorado
THEN {
remSuccess: ComputeServerClient.RemoteSuccess;
selfBest: BOOL;
FigOfMerit: REAL;
[success: remSuccess, selfIsBest: selfBest, FOM: FigOfMerit] ← ComputeServerClient.BestServerStats[];
IF remSuccess # true
THEN {
result ← $TryLocal;
EXIT;
};
};
IF ~preferRemote THEN result ← $TryLocal;
IF result # $TryLocal
THEN {
IF verboseComputeServer THEN cmd.out.PutRope[" -- Trying remote compile\n"];
IF complex
THEN {
[found: found, success: success, remoteMsg: remoteMsg, serverInstance: serverInstance] ← ComputeServerClient.StartService[service: "RemoteComplexCompiler", cmdLine: cmdLine, in: NIL, out: cmd.out, queueService: TRUE, timeToWait: 600];
}
ELSE {
[found: found, success: success, remoteMsg: remoteMsg, serverInstance: serverInstance] ← ComputeServerClient.StartService[service: "RemoteCompiler", cmdLine: cmdLine, in: NIL, out: cmd.out, queueService: TRUE, timeToWait: 600];
};
SELECT
TRUE
FROM
~found
OR success = cantImportController
OR success = cantImportServer
OR success = communicationFailure
OR success = commandNotFound
OR success = clientNotRunning => {
IF verboseComputeServer THEN cmd.out.PutRope[" -- Remote compile did not work; do it locally\n"];
result ← $TryLocal;
};
success = false => {
IF successFalseCounter > 1
THEN {
IF verboseComputeServer THEN cmd.out.PutRope[" -- Remote compile did not work; do it locally\n"];
result ← $TryLocal;
}
ELSE {
IF verboseComputeServer THEN cmd.out.PutRope[" -- Remote compile did not work; try remote again\n"];
successFalseCounter ← successFalseCounter + 1;
};
};
success = aborted => {
userAbort ← TRUE;
};
success = timeOut
OR success = serverTooBusy => {
IF verboseComputeServer THEN cmd.out.PutRope[Rope.Cat[" -- Remote compile ", (IF success = timeOut THEN "timed out queuing" ELSE "found a server that was too busy"), "; try again\n"]];
LOOP;
};
found
AND success = true => {
printServerName:
PROC = {
serverName: ROPE ← serverInstance;
serverName ← PupName.HisName[PupName.NameLookup[serverInstance, Pup.nullSocket]];
IF ~serverName.IsEmpty[] THEN cmd.out.PutRope[Rope.Cat[" -- Compute Server used was ", serverName, "\n"]];
};
IF ~remoteMsg.IsEmpty[]
THEN
SELECT remoteMsg.Fetch[0]
FROM
'F => {
-- failure
result ← $Failure;
errors ← TRUE;
warnings ← FALSE;
IF verboseComputeServer
THEN {
printServerName[];
}
ELSE {
IF ~serverInstance.IsEmpty[] THEN cmd.out.PutRope[Rope.Cat[" Compute Server used was ", serverInstance, "\n"]];
};
};
'W => {
-- warnings
result ← $Warning;
errors ← FALSE;
warnings ← TRUE;
IF verboseComputeServer THEN printServerName[];
};
'S => {
-- success
result ← $Success;
errorName ← NIL;
errors ← FALSE;
warnings ← FALSE;
IF verboseComputeServer THEN printServerName[];
};
'A => {
-- aborted
result ← $Aborted;
errors ← TRUE;
warnings ← FALSE;
userAbort ← TRUE;
IF verboseComputeServer THEN printServerName[];
};
'B => {
-- blocked
bestSuccess: ComputeServerClient.RemoteSuccess;
selfIsBest: BOOL;
bestFOM: REAL;
result ← $Blocked;
[success: bestSuccess, selfIsBest: selfIsBest, FOM: bestFOM] ← ComputeServerClient.BestServerStats[];
IF verboseComputeServer
THEN {
cmd.out.PutRope[" -- Server tried was already busy.\n"];
printServerName[];
};
};
'C => {
-- crashed; try to mark the compiler bad
serverName: ROPE ← serverInstance;
serverName ← PupName.HisName[PupName.NameLookup[serverInstance, Pup.nullSocket]];
IF ~serverName.IsEmpty[] THEN [] ← CommandTool.DoCommand[commandLine: Rope.Cat["SummonerBadCommand ", serverName," RemoteCompiler"], parent: cmd ! CommandTool.Failed => CONTINUE];
};
ENDCASE;
};
ENDCASE;
};
ENDLOOP;
IF result = $TryLocal
THEN {
commandName: ROPE = IF complex THEN "RemoteComplexCompiler" ELSE "RemoteCompiler";
lookupProcData: ComputeServerServer.RegisteredProcHandle;
errMsg: ROPE ← NIL;
runError: BOOL ← FALSE;
lookupProcData ← ComputeServerServer.Lookup["RemoteCompiler", NIL];
IF verboseComputeServer THEN cmd.out.PutRope[" -- Trying to do the compile locally.\n"];
IF lookupProcData =
NIL
THEN {
dir: ROPE;
dir ← CommandTool.RegistrationDirectory[cmd];
IF verboseComputeServer THEN cmd.out.PutRope[Rope.Cat[" -- Trying to run CompilerServer.bcd from directory", dir, ".\n"]];
[errMsg: errMsg, error: runError] ← CommandTool.Run[bcdName: dir.Concat["CompilerServer.bcd"], runEvenIfAlreadyRun: FALSE, runEvenIfUnbound: FALSE];
lookupProcData ← ComputeServerServer.Lookup["RemoteCompiler", NIL];
};
IF lookupProcData =
NIL
THEN {
-- try the standard place
IF verboseComputeServer THEN cmd.out.PutRope[Rope.Cat[" -- Trying to run CompilerServer.bcd from directory ///Commands/\n"]];
[] ← CommandTool.Run[bcdName: "///Commands/CompilerServer.bcd", runEvenIfAlreadyRun: FALSE, runEvenIfUnbound: FALSE];
lookupProcData ← ComputeServerServer.Lookup["RemoteCompiler", NIL];
};
IF lookupProcData =
NIL
THEN {
msg ← "Failed to start up compiler (CompilerServer.bcd) on the workstation.\n";
IF runError AND ~errMsg.IsEmpty[] THEN msg ← msg.Cat[" Error from Run is ", errMsg];
appendRopeToLog[Rope.Concat[" -- ", msg]];
result ← $Failure;
}
ELSE {
myCmd: Commander.Handle;
myCmd ←
NEW[Commander.CommandObject ← [
in: cmd.in,
out: cmd.out,
err: cmd.err,
commandLine: cmdLine,
command: commandName,
propertyList: cmd.propertyList,
procData: cmd.procData
]];
result ← $Blocked;
WHILE result = $Blocked
DO
[result: result, msg: remoteMsg] ← lookupProcData.commanderProcHandle.proc[myCmd];
IF ~remoteMsg.IsEmpty[]
THEN
SELECT remoteMsg.Fetch[0]
FROM
'F => {
-- failure
result ← $Failure;
errors ← TRUE;
warnings ← FALSE;
};
'W => {
-- warnings
result ← $Warning;
errors ← FALSE;
warnings ← TRUE;
};
'S => {
-- success
result ← $Success;
errorName ← NIL;
errors ← FALSE;
warnings ← FALSE;
};
'A => {
-- aborted
result ← $Aborted;
errors ← TRUE;
userAbort ← TRUE;
warnings ← FALSE;
};
'B => {
-- blocked
result ← $Blocked;
};
'C => {
-- crashed
result ← $Failure;
cmd.out.PutRope[" Local compiler has had a FATAL error. No more compiles will be done locally.\n"];
};
ENDCASE;
ENDLOOP;
};
};
}; -- end ENABLE UNWIND => Finalize[];
IF result # $Success THEN someNonSuccess ← TRUE;
Finalize[userAbort];
EXITS
globalSwitches => {
objectName ← NIL;
sense ← TRUE;
FOR i:
INT
IN [0..switches.Length[])
DO
c: CHAR = switches.Fetch[i];
SELECT c
FROM
'-, '~ => sense ← ~sense;
IN ['a..'z] => {switchDefaults[c] ← sense; sense ← TRUE};
IN ['A..'Z] => {
switchDefaults[VAL['a.ORD+(c.ORD-'A.ORD)]] ← sense; sense ← TRUE};
ENDCASE => EXIT;
ENDLOOP;
switches ← NIL;
args ← NIL;
};
badSemantics => {
objectName ← NIL; errors ← TRUE;
appendRopeToLog[" -- Illegal command"];
args ← NIL;
};
};
Here after completion of subcommand
sourceName ← rootName ← objectName ← errorName ← NIL;
parms.objectName ← NIL;
results ← NIL;
IF userAbort THEN {appendRopeToLog["\n... command aborted\n"]; GOTO truncateList};
IF (errors OR warnings) AND localPause THEN GOTO truncateList;
REPEAT
badSyntax => {appendRopeToLog["\n-- Illegal syntax"]; errors ← TRUE};
truncateList => switchDefaults['p] ← TRUE;
ENDLOOP;
Here after completion of all subcommands
END; -- end catch phrase to release the resource and reset the process priority
Cleanup[];
};
rollback
RollbackRecovery: Booting.RollbackProc =
CHECKED {
directoriesToUseExistingLog ← NIL;
};
new log for compiler
NewCompilerLog:
ENTRY SAFE
PROC [cmd: Commander.Handle]
RETURNS [result:
REF ←
NIL, msg: Rope.
ROPE ←
NIL] =
CHECKED {
ENABLE UNWIND => NULL;
argv: CommandTool.ArgumentVector;
dir: ROPE;
prev: LIST OF ROPE;
argv ← CommandTool.Parse[cmd ! CommandTool.Failed => { msg ← errorMsg; CONTINUE; }];
dir ← FileNames.ConvertToSlashFormat[IF argv.argc < 2 THEN FileNames.CurrentWorkingDirectory[] ELSE FileNames.ResolveRelativePath[argv[1]]];
FOR l:
LIST
OF
ROPE ← directoriesToUseExistingLog, l.rest
UNTIL l =
NIL
DO
IF Rope.Equal[l.first, dir]
THEN {
IF l = directoriesToUseExistingLog THEN directoriesToUseExistingLog ← l.rest ELSE prev.rest ← l.rest;
EXIT;
};
prev ← l;
ENDLOOP;
};
compiler inquiries
DefaultSwitches:
PROC
RETURNS [CompilerOps.LetterSwitches] = {
RETURN [[
TRUE , -- A Address fault for NIL checks
TRUE , -- B Bounds checking
TRUE , -- C compile for Cedar (special FORK)
FALSE, -- D call Debugger on compiler error (FALSE => just log error)
TRUE , -- E fixed (big Eval stack)
TRUE , -- F Floating point microcode
TRUE , -- G TRUE => log goes to compiler.log, FALSE => use foo.errlog
FALSE, -- H TRUE => append to compiler.log, FALSE => write new compiler.log
FALSE, -- I unused
FALSE, -- J cross-Jumping optimization
FALSE, -- K unused
TRUE , -- L allocate space for code Links
TRUE , -- M reference counting Microcode
TRUE , -- N Nil pointer checking
FALSE, -- O unused
FALSE, -- P Pause after compilation with errors
FALSE, -- Q unused
FALSE, -- R unused
TRUE , -- S Sort (by static frequency) global vars & entry indexes
FALSE, -- T unused
FALSE, -- U uninitialized variable checking
FALSE, -- V unused
TRUE , -- W log Warning messages
FALSE, -- X unused
FALSE, -- Y complain about KFCB
TRUE -- Z FALSE => use old-style method to access ROPE & ATOM literals
]]};
START HERE
Booting.RegisterProcs[r: RollbackRecovery];
Process.InitializeCondition[@CompilerCondition, Process.MsecToTicks[250]];
Commander.Register["Compile", Compile, "Compile {-switches} xxx* - A simple syntax for compiling a list of cedar modules. (See 'ComplexCompile' for another syntax). Some useful switches are:
-b => bounds checking (default: TRUE -- don't turn this off unless you know what you are doing),
-d => call debugger on compiler error (else just log error),
-g => log goes to compiler.log (-~g => log goes to foo.errlog),
-j => cross-jump (default: FALSE -- don't turn this on unless you know what you are doing),
-n => nil checking (default: TRUE -- don't turn this off unless you know what you are doing),
-u => check for uninitialized variables,
-w => log warning messages (default: TRUE)
Switches can be negated with '~' (i.e. '-~bj~n'). The complete list of switches is in CompilerSequencer.DefaultSwitches. The defaults can be set in your user profile with Compiler.Switches.", $Vanilla];
Commander.Register["RCompile", Compile, "RCompile {-switches} xxx* - Same switches as Compile, but this prefers remote compilation", $RemoteVanilla];
Commander.Register["ComplexCompile", Compile, "ComplexCompile /j-b-n BcdTreeOps ← ProtoTreeOps[Literals: BcdSymbols, Symbols: BcdSymbols, Tree: BcdTree] . . . - Allows a parameterized compilation. Switches are marked with '/ and negated with '-. (See 'Compile' for more on switches.)", $Complex];
Commander.Register["NewCompilerLog", NewCompilerLog, "NewCompilerLog [directory] - Start a new Compiler.log for compiles done in the current directory or the specified directory. Useful only when the compiles are done with the g switch on "];
Bob Hagmann March 21, 1986 2:06:37 pm PST
Added "H" switch. Wrote NewCompilerLog and RollbackRecovery to support it.
Bob Hagmann April 15, 1986 11:49:54 am PST
removed extraneous code from appendRopeToLog
changes to: appendRopeToLog (local of Compile)
Bob Hagmann April 15, 1986 11:52:43 am PST
changes to: DIRECTORY, CompilerClientCommandImpl, appendRopeToLog (local of Compile)
Bob Hagmann April 24, 1986 10:58:23 am PST
changes to: DIRECTORY, CompilerClientCommandImpl, printServerName (local of Compile)