MakoCommands.mesa
Copyright Ó 1991, 1992 by Xerox Corporation. All rights reserved.
Michael Plass, February 19, 1992 1:01 pm PST
DIRECTORY IO, PFS, PFSNames, BasicTime, Commander, CommanderOps, Convert, RefText, Rope, RopeList, SymTab, RefTab, MakoDependency;
MakoCommands: CEDAR PROGRAM
IMPORTS IO, PFS, PFSNames, Commander, CommanderOps, Convert, RefText, Rope, RopeList, SymTab, RefTab, MakoDependency
~ BEGIN
ROPE: TYPE ~ Rope.ROPE;
PATH: TYPE ~ PFSNames.PATH;
SourceFile: TYPE ~ REF SourceFileRep;
SourceFileRep: TYPE ~ RECORD [
pathName: PFSNames.PATH,
arguments: Arguments,
extension: ROPE
];
Registration: TYPE ~ RECORD [
extension: ROPE,
dependencyProc: PROC [ROPE] RETURNS [LIST OF ROPE] ¬ NIL,
dependencyExtension: ROPE ¬ NIL
];
ParseConfig: PROC [fileName: ROPE] RETURNS [LIST OF ROPE] ~ {
c: MakoDependency.ConfigDependencies ¬ MakoDependency.ParseCMesaDirectory[fileName];
RETURN [RopeList.DAppend[c.interfaces, c.implementations]]
};
registry: LIST OF Registration ¬ LIST[
["mesa", MakoDependency.ParseMesaDirectory, "mob"],
["config", ParseConfig, "mob"],
["MakeIt", MakoDependency.ParseMakeItDependency, NIL],
["c", MakoDependency.ParseCDependency]
];
fileIDTab: SymTab.Ref ~ SymTab.Create[];
FileID: TYPE ~ REF FileIDRep;
FileIDRep: TYPE ~ RECORD [
shortName: ROPE,
uniqueID: PFS.UniqueID
];
DBEntry: TYPE ~ REF DBEntryRep;
DBEntryRep: TYPE ~ RECORD [
fileID: FileID,
commandName: ROPE,
switches: ROPE ¬ NIL,
using: LIST OF FileID ¬ NIL,
out: LIST OF FileID ¬ NIL
];
Relativize: PROC [path: PFSNames.PATH] RETURNS [ROPE] ~ {
isa: BOOL; suffix: PATH;
[isa, suffix] ¬ PFSNames.IsAPrefix[prefix: PFS.GetWDir[], name: path];
RETURN [PFS.RopeFromPath[IF isa THEN suffix ELSE path]];
};
MakeFileID: PROC [fileName: ROPE] RETURNS [fileID: FileID] ~ {
path: PFSNames.PATH ~ PFS.PathFromRope[fileName];
shortName: ROPE ~ Relativize[path];
uniqueID: PFS.UniqueID ~ PFS.FileInfo[path].uniqueID;
RETURN [FileIDFromData[shortName, uniqueID]]
};
FileIDFromData: PROC [shortName: ROPE, uniqueID: PFS.UniqueID] RETURNS [fileID: FileID] ~ {
Action: SymTab.UpdateAction ~ {
PROC [found: BOOL, val: Val] RETURNS [op: UpdateOperation ¬ none, new: Val ¬ NIL];
list: LIST OF FileID ¬ NARROW[val];
FOR tail: LIST OF FileID ¬ list, tail.rest UNTIL tail = NIL DO
IF tail.first.uniqueID = uniqueID THEN { fileID ¬ tail.first; RETURN };
ENDLOOP;
fileID ¬ NEW[FileIDRep ¬ [shortName, uniqueID]];
list ¬ CONS[fileID, list];
RETURN [store, list];
};
SymTab.Update[fileIDTab, shortName, Action];
};
MakeDBEntry: PROC [shortName: ROPE, commandName: ROPE, switches: ROPE] RETURNS [DBEntry] ~ {
fileID: FileID ~ MakeFileID[shortName];
dbe: DBEntry ~ NEW[DBEntryRep ¬ [fileID: fileID, commandName: commandName, switches: switches]];
RETURN [dbe]
};
Uses: PROC [dbe: DBEntry, shortName: ROPE] ~ {
dbe.using ¬ CONS[MakeFileID[shortName], dbe.using];
};
Output: PROC [dbe: DBEntry, shortName: ROPE] ~ {
dbe.out ¬ CONS[MakeFileID[shortName], dbe.out];
};
FilesExist: PROC [list: LIST OF FileID] RETURNS [BOOL ¬ FALSE] ~ {
ENABLE PFS.Error => { IF error.group = user THEN CONTINUE };
FOR tail: LIST OF FileID ¬ list, tail.rest UNTIL tail = NIL DO
IF PFS.FileInfo[PFS.PathFromRope[tail.first.shortName]].uniqueID # tail.first.uniqueID THEN RETURN [FALSE];
ENDLOOP;
RETURN [TRUE]
};
FileExists: PROC [fileID: FileID] RETURNS [BOOL ¬ FALSE] ~ {
ENABLE PFS.Error => { IF error.group = user THEN CONTINUE };
RETURN [PFS.FileInfo[PFS.PathFromRope[fileID.shortName]].uniqueID = fileID.uniqueID]
};
SourceExtension: PROC [rope: ROPE] RETURNS [ROPE] ~ {
size: INT ~ Rope.Size[rope];
FOR tail: LIST OF Registration ¬ registry, tail.rest UNTIL tail = NIL DO
x: ROPE ~ tail.first.extension;
xl: INT ~ Rope.Size[x];
IF size >= xl + 1 AND Rope.Fetch[rope, size-xl-1] = '. AND Rope.Run[s1: rope, pos1: size-xl, s2: x, case: FALSE] = xl THEN {
RETURN [Rope.Substr[rope, size-xl]]
};
ENDLOOP;
RETURN [NIL]
};
MakePattern: PROC [rope: ROPE] RETURNS [ROPE] ~ {
x: ROPE ~ SourceExtension[rope];
IF x # NIL THEN RETURN [rope] ELSE RETURN [Rope.Concat[rope, ".*"]]
};
ReplaceStar: PROC [rope: ROPE, ext: ROPE] RETURNS [ROPE] ~ {
size: INT ~ Rope.Size[rope];
IF size > 2 AND Rope.Run[rope, size-2, ".*"] = 2 THEN RETURN [Rope.Replace[rope, size-1, 1, ext]] ELSE RETURN [rope]
};
EnumerateSourceFiles: PROC [rope: ROPE, switches: Arguments, sourceFileProc: PROC [SourceFile]] ~ {
ENABLE PFS.Error => CommanderOps.Failed[error.explanation];
path: PATH ~ PFS.PathFromRope[rope];
shortName: ROPE ~ PFSNames.ComponentRope[PFSNames.ShortName[path]];
shortPattern: ROPE ~ MakePattern[shortName];
pattern: PATH ~ IF shortName=shortPattern THEN path ELSE PFSNames.ReplaceShortName[path, [[shortPattern, 0, Rope.Size[shortPattern]]]];
EachName: PFS.NameProc ~ {
PROC [name: PATH] RETURNS [continue: BOOL ¬ TRUE];
short: ROPE ~ PFSNames.ComponentRope[PFSNames.ShortName[name]];
ext: ROPE ~ SourceExtension[short];
IF ext # NIL AND Rope.Match[ReplaceStar[shortPattern, ext], short] THEN {
a: Arguments ~ NEW[ArgumentsRep ¬ switches­];
a.name ¬ Rope.Substr[short, 0, Rope.Size[short] - Rope.Size[ext] - 1];
sourceFileProc[NEW[SourceFileRep ¬ [
pathName: name,
arguments: a,
extension: ext
]]];
};
};
PFS.EnumerateForNames[pattern: pattern, proc: EachName];
};
PutQ: PROC [stream: IO.STREAM, rope: ROPE] ~ {
IO.PutF1[stream, "\"%g\" ", [rope[rope]]];
};
PutFileID: PROC [stream: IO.STREAM, fileID: FileID] ~ {
IO.PutRope[stream, "("];
PutQ[stream, fileID.shortName];
IO.PutFL[stream, "%g %g %g %g", LIST[
[cardinal[LOOPHOLE[fileID.uniqueID.egmt.gmt]]],
[cardinal[LOOPHOLE[fileID.uniqueID.egmt.usecs]]],
[cardinal[LOOPHOLE[fileID.uniqueID.host.a]]],
[cardinal[LOOPHOLE[fileID.uniqueID.host.b]]]
]];
IO.PutRope[stream, ")"];
};
PutFileIDs: PROC [stream: IO.STREAM, fileIDs: LIST OF FileID] ~ {
IO.PutRope[stream, "("];
FOR tail: LIST OF FileID ¬ fileIDs, tail.rest UNTIL tail = NIL DO
PutFileID[stream, tail.first];
IF tail.rest # NIL THEN IO.PutRope[stream, " "];
ENDLOOP;
IO.PutRope[stream, ")"];
};
PutDB: PROC [stream: IO.STREAM, db: RefTab.Ref] ~ {
Each: RefTab.EachPairAction ~ {
WITH key SELECT FROM
fileID: FileID => {
WITH val SELECT FROM
list: LIST OF DBEntry => {
FOR tail: LIST OF DBEntry ¬ list, tail.rest UNTIL tail = NIL DO
dbe: DBEntry ~ tail.first;
IF fileID=dbe.fileID AND FileExists[dbe.fileID] AND FilesExist[dbe.out] THEN {
IO.PutRope[stream, "\n ("];
PutFileID[stream, fileID];
IO.PutRope[stream, " "];
PutQ[stream, dbe.commandName];
PutQ[stream, dbe.switches];
PutFileIDs[stream, dbe.using];
IO.PutRope[stream, " "];
PutFileIDs[stream, dbe.out];
IO.PutRope[stream, ")"];
};
ENDLOOP;
};
ENDCASE;
};
ENDCASE;
};
IO.PutRope[stream, "("];
[] ¬ RefTab.Pairs[db, Each];
IO.PutRope[stream, ")\n"];
};
WriteDB: PROC [fileName: ROPE, db: RefTab.Ref] ~ {
stream: IO.STREAM ~ PFS.StreamOpen[PFS.PathFromRope[fileName], $create];
PutDB[stream, db];
IO.Close[stream];
};
InsertDBE: PROC [db: RefTab.Ref, dbe: DBEntry] ~ {
Action: RefTab.UpdateAction ~ {
newList: LIST OF DBEntry;
WITH val SELECT FROM
list: LIST OF DBEntry => newList ¬ CONS[dbe, list];
ENDCASE => newList ¬ LIST[dbe];
RETURN [store, newList]
};
RefTab.Update[db, dbe.fileID, Action];
};
GetDB: PROC [stream: IO.STREAM, db: RefTab.Ref] ~ {
token: REF TEXT ¬ RefText.ObtainScratch[100];
tokenKind: IO.TokenKind ¬ tokenERROR;
SingleMatch: PROC [c: CHAR] RETURNS [BOOL] ~ {
RETURN [tokenKind = tokenSINGLE AND token[0] = c];
};
Single: PROC [c: CHAR] ~ {
IF tokenKind = tokenSINGLE AND token[0] = c THEN Get[] ELSE Syntax[];
};
Get: PROC ~ {
[tokenKind: tokenKind, token: token] ¬ IO.GetCedarToken[stream, token];
};
Syntax: PROC ~ {
CommanderOps.Failed[IO.PutFR1[".makodb syntax error at location %g", [integer[IO.GetIndex[stream]]]]];
};
GetRope: PROC RETURNS [rope: ROPE ¬ NIL] ~ {
IF tokenKind = tokenROPE
THEN { rope ¬ Convert.RopeFromLiteral[RefText.TrustTextAsRope[token]]; Get[] }
ELSE Syntax[];
};
GetCard: PROC RETURNS [card: CARD ¬ 0] ~ {
IF tokenKind = tokenDECIMAL
THEN { card ¬ Convert.CardFromRope[RefText.TrustTextAsRope[token]]; Get[] }
ELSE Syntax[];
};
GetFileID: PROC RETURNS [FileID]~ {
Single['(]; {
shortName: ROPE ~ GetRope[];
gmt: BasicTime.GMT ~ LOOPHOLE[GetCard[]];
usec: CARD ~ GetCard[];
a: CARD ~ GetCard[];
b: CARD ~ GetCard[];
Single[')];
RETURN [FileIDFromData[shortName, [[gmt, usec],[a, b]]]]
};
};
GetFileIDs: PROC RETURNS [LIST OF FileID] ~ {
head: LIST OF FileID ¬ LIST[NIL];
last: LIST OF FileID ¬ head;
Single['(];
UNTIL SingleMatch[')] DO
last ¬ last.rest ¬ LIST[GetFileID[]];
ENDLOOP;
Get[];
RETURN [head.rest]
};
Get[];
Single['(];
UNTIL SingleMatch[')] DO
Single['(]; {
fileID: FileID ¬ GetFileID[];
commandName: ROPE ¬ GetRope[];
switches: ROPE ¬ GetRope[];
using: LIST OF FileID ¬ GetFileIDs[];
out: LIST OF FileID ¬ GetFileIDs[];
dbe: DBEntry ~ NEW[DBEntryRep ¬ [fileID: fileID, commandName: commandName, switches: switches, using: using, out: out]];
Single[')];
InsertDBE[db, dbe];
};
ENDLOOP;
};
LoadDB: PROC [fileName: ROPE, db: RefTab.Ref] ~ {
ENABLE PFS.Error => IF error.group = user THEN CONTINUE;
stream: IO.STREAM ~ PFS.StreamOpen[PFS.PathFromRope[fileName], $read];
GetDB[stream, db];
IO.Close[stream];
};
ReadDB: PROC [fileName: ROPE] RETURNS [RefTab.Ref] ~ {
db: RefTab.Ref ¬ RefTab.Create[];
LoadDB[fileName, db];
RETURN [db]
};
DoCommand: PROC [cmd: Commander.Handle, commandName: ROPE, switches: ROPE, baseName, extension: ROPE] RETURNS [result: REF ¬ NIL] ~ {
db: RefTab.Ref ~ WITH CommanderOps.GetProp[cmd, $MakoDB] SELECT FROM
x: RefTab.Ref => x,
ENDCASE => ReadDB[".makodb"];
shortName: ROPE ~ Rope.Cat[baseName, ".", extension];
fileID: FileID ~ MakeFileID[shortName];
WITH RefTab.Fetch[db, fileID].val SELECT FROM
list: LIST OF DBEntry => {
FOR tail: LIST OF DBEntry ¬ list, tail.rest UNTIL tail = NIL DO
dbe: DBEntry ¬ tail.first;
IF dbe.fileID = fileID AND Rope.Equal[dbe.commandName, commandName, FALSE] AND Rope.Equal[dbe.switches, switches] AND FilesExist[dbe.using] AND FilesExist[dbe.out] THEN RETURN [$OK];
ENDLOOP;
};
ENDCASE;
result ¬ CommanderOps.DoCommand[Rope.Cat[commandName, " ", switches, " ", baseName], cmd];
WITH result SELECT FROM
dbe: DBEntry => { InsertDBE[db, dbe] };
ENDCASE;
CommanderOps.PutProp[cmd, $MakoDB, db];
};
MakoCommand: Commander.CommandProc ~ {
head: LIST OF SourceFile = LIST[NIL];
last: LIST OF SourceFile ¬ head;
dryrun: BOOL ¬ FALSE;
EachSourceFile: PROC [s: SourceFile] ~ { last ¬ last.rest ¬ LIST[s] };
switches: Arguments ~ MakeDefaultArguments[];
FOR arg: ROPE ¬ CommanderOps.NextArgument[cmd], CommanderOps.NextArgument[cmd] UNTIL arg = NIL DO
IF Rope.Match["-*", arg]
THEN {
IF Rope.Equal[arg, "-dryrun"] THEN dryrun ¬ TRUE ELSE ParseSwitch[arg, cmd, switches];
}
ELSE {
was: LIST OF SourceFile ¬ last;
EnumerateSourceFiles[arg, switches, EachSourceFile];
IF was = last THEN CommanderOps.Failed[Rope.Concat["Missing source: ", arg]];
IF was.rest # last THEN CommanderOps.Failed[Rope.Concat["Ambiguous: ", arg]];
};
ENDLOOP;
IF head.rest = NIL THEN CommanderOps.Failed[cmd.procData.doc];
FOR tail: LIST OF SourceFile ¬ head.rest, tail.rest UNTIL tail = NIL DO
commandName: ROPE ~ Rope.Concat["Mako-", tail.first.extension];
IF dryrun
THEN {
IO.PutRope[cmd.out, commandName];
IO.PutRope[cmd.out, UnparseSwitches[tail.first.arguments]];
IO.PutRope[cmd.out, tail.first.arguments.name];
IO.PutRope[cmd.out, "\n"];
}
ELSE {
res: REF ~ DoCommand[cmd, commandName, UnparseSwitches[tail.first.arguments], tail.first.arguments.name, tail.first.extension];
IF res = $Failure THEN result ¬ res;
};
ENDLOOP;
IF NOT dryrun THEN WITH CommanderOps.GetProp[cmd, $MakoDB] SELECT FROM
x: RefTab.Ref => WriteDB[".makodb", x];
ENDCASE;
};
Arguments: TYPE ~ REF ArgumentsRep;
ArgumentsRep: TYPE ~ PACKED RECORD [
makeboot: BOOL ¬ FALSE,
debuggable: BOOL ¬ FALSE,
optimize: BOOL ¬ TRUE,
name: ROPE -- sans extension
];
MakeDefaultArguments: PROC RETURNS [Arguments] ~ {
RETURN [NEW[ArgumentsRep ¬ []]]
};
ParseSwitch: PROC [arg: ROPE, cmd: Commander.Handle, a: Arguments] ~ {
sense: BOOL ¬ TRUE;
FOR i: INT IN (0..Rope.Size[arg]) DO
SELECT Rope.Lower[Rope.Fetch[arg, i]] FROM
'~ => { sense ¬ NOT sense };
'b => { a.makeboot ¬ sense; sense ¬ TRUE };
'd => { a.debuggable ¬ sense; sense ¬ TRUE };
'o => { a.optimize ¬ sense; sense ¬ TRUE };
'u => { IF sense THEN a­ ¬ []; sense ¬ TRUE };
ENDCASE => CommanderOps.Failed[cmd.procData.doc];
ENDLOOP;
};
UnparseSwitches: PROC [a: Arguments] RETURNS [ROPE] ~ {
cmdbuf: REF TEXT ¬ RefText.New[20];
Emit: PROC [rope: ROPE] ~ {cmdbuf ¬ RefText.AppendRope[cmdbuf, rope]};
IF a.debuggable THEN Emit[" -d"];
IF a.makeboot THEN Emit[" -b"];
IF NOT a.optimize THEN Emit[" -~o"];
Emit[" "];
RETURN [Rope.FromRefText[cmdbuf]]
};
MakeCommandLine: PROC [commandName: ROPE, a: Arguments, name: ROPE] RETURNS [ROPE] ~ {
cmdbuf: REF TEXT ¬ RefText.New[200];
Emit: PROC [rope: ROPE] ~ {cmdbuf ¬ RefText.AppendRope[cmdbuf, rope]};
Emit[commandName];
Emit[UnparseSwitches[a]];
Emit[a.name];
RETURN [Rope.FromRefText[cmdbuf]]
};
GetArguments: PROC [cmd: Commander.Handle] RETURNS [Arguments] ~ {
a: Arguments ~ MakeDefaultArguments[];
FOR arg: ROPE ¬ CommanderOps.NextArgument[cmd], CommanderOps.NextArgument[cmd] UNTIL arg=NIL DO
IF Rope.Match["-*", arg]
THEN { ParseSwitch[arg, cmd, a] }
ELSE {
IF a.name # NIL THEN CommanderOps.Failed[cmd.procData.doc];
a.name ¬ arg;
};
ENDLOOP;
IF a.name = NIL THEN CommanderOps.Failed[cmd.procData.doc];
RETURN [a]
};
MakoMakeItCommand: Commander.CommandProc ~ {
ENABLE PFS.Error => CommanderOps.Failed[error.explanation];
arg: Arguments ~ GetArguments[cmd];
cmName: ROPE ~ Rope.Concat[arg.name, ".MakeIt"];
dbe: DBEntry ~ MakeDBEntry[cmName, "Mako-MakeIt", UnparseSwitches[arg]];
result ¬ CommanderOps.DoCommand[Rope.Concat["Source ", cmName], cmd];
IF result = $Failure
THEN { IO.PutRope[cmd.err, cmName]; IO.PutRope[cmd.err, " failed.\n"] }
ELSE {
FOR tail: LIST OF ROPE ¬ MakoDependency.ParseMakeItDependency[cmName], tail.rest UNTIL tail = NIL DO
Uses[dbe, tail.first];
ENDLOOP;
Output[dbe, arg.name];
result ¬ dbe;
};
};
MakoMesaCommand: Commander.CommandProc ~ {
arg: Arguments ~ GetArguments[cmd];
dbe: DBEntry ~ MakeDBEntry[Rope.Concat[arg.name, ".mesa"], "Mako-mesa", UnparseSwitches[arg]];
result ¬ CommanderOps.DoCommand[Rope.Concat["Mimosa -c ", arg.name], cmd];
IF result # $Failure THEN {
FOR tail: LIST OF ROPE ¬ MakoDependency.ParseMesaDirectory[arg.name], tail.rest UNTIL tail = NIL DO
Uses[dbe, Rope.Concat[tail.first, ".mob"]];
ENDLOOP;
Output[dbe, Rope.Concat[arg.name, ".mob"]];
};
IF result = $Implementation THEN {
result ¬ DoCommand[cmd, "Mako-c", UnparseSwitches[arg], Rope.Concat[arg.name, ".c2c"], "c"];
Output[dbe, Rope.Cat["sun4/", arg.name, ".c2c.o"]];
};
IF result # $Failure THEN result ¬ dbe;
};
MakoConfigCommand: Commander.CommandProc ~ {
arg: Arguments ~ GetArguments[cmd];
dbe: DBEntry ~ MakeDBEntry[Rope.Concat[arg.name, ".config"], "Mako-config", UnparseSwitches[arg]];
cmdRope: ROPE ¬ "Cind -l -m ";
IF arg.makeboot THEN cmdRope ¬ Rope.Concat[cmdRope, "-b "];
result ¬ CommanderOps.DoCommand[Rope.Concat[cmdRope, arg.name], cmd];
IF result # $Failure THEN {
c: MakoDependency.ConfigDependencies ~ MakoDependency.ParseCMesaDirectory[arg.name];
result ¬ Cinderella[cmd, arg.name, c.implementations];
IF result # $Failure THEN {
FOR tail: LIST OF ROPE ¬ c.interfaces, tail.rest UNTIL tail = NIL DO
Uses[dbe, Rope.Concat[tail.first, ".mob"]];
ENDLOOP;
FOR tail: LIST OF ROPE ¬ c.implementations, tail.rest UNTIL tail = NIL DO
IF Rope.Match["*.o*", tail.first]
THEN {
Uses[dbe, Rope.Concat["sun4/", tail.first]];
}
ELSE {
Uses[dbe, Rope.Concat[tail.first, ".mob"]];
Uses[dbe, Rope.Cat["sun4/", tail.first, ".c2c.o"]];
};
ENDLOOP;
Output[dbe, Rope.Concat[arg.name, ".mob"]];
Output[dbe, Rope.Cat["sun4/", arg.name, ".c2c.o"]];
result ¬ dbe;
};
};
};
Cinderella: PROC [cmd: Commander.Handle, package: ROPE, impls: LIST OF ROPE] RETURNS [result: REF] ~ {
class: ROPE ¬ "sun4";
dir: ROPE ¬ "sun4";
cSw: ROPE ¬ "-c -O2";
lSw: ROPE ¬ "-r";
cmdbuf: REF TEXT ¬ RefText.New[200];
Emit: PROC [rope: ROPE] ~ {cmdbuf ¬ RefText.AppendRope[cmdbuf, rope]};
Emit["ComplexCc -out "];
Emit[dir];
Emit["/"];
Emit[package];
Emit[".c2c.o"];
Emit[" -in "];
Emit[package];
Emit[".c2c.c"];
Emit[" -rload "];
FOR l: LIST OF ROPE ¬ impls, l.rest WHILE l # NIL DO
name: ROPE ¬ l.first;
IF NOT Rope.Match["*/*", name] THEN { Emit[dir]; Emit["/"] };
Emit[name];
IF NOT Rope.Match["*.o", name] THEN Emit[".c2c.o"];
Emit[" "];
ENDLOOP;
Emit[" -class "]; Emit[class];
Emit[" -cSwitch \""]; Emit[cSw]; Emit["\""];
Emit[" -lSwitch \""]; Emit[lSw]; Emit["\""];
Emit[" -lib "];
result ¬ CommanderOps.DoCommand[Rope.FromRefText[cmdbuf], cmd];
};
MakoCCommand: Commander.CommandProc ~ {
arg: Arguments ~ GetArguments[cmd];
fname: ROPE ~ Rope.Concat[arg.name, ".c"];
oname: ROPE ~ Rope.Cat["sun4/", arg.name, ".o"];
dbe: DBEntry ~ MakeDBEntry[fname, "Mako-c", UnparseSwitches[arg]];
cmdbuf: REF TEXT ¬ RefText.New[200];
Emit: PROC [rope: ROPE] ~ {cmdbuf ¬ RefText.AppendRope[cmdbuf, rope]};
FOR tail: LIST OF ROPE ¬ MakoDependency.ParseCDependency[fname], tail.rest UNTIL tail = NIL DO
Uses[dbe, tail.first];
ENDLOOP;
Emit["ComplexCc -out "];
Emit[oname];
Emit[" -in "];
Emit[fname];
Emit[" -class sparc -cSwitch \"-c "];
IF arg.debuggable THEN Emit[" -g"] ELSE IF arg.optimize THEN Emit[" -O2"];
Emit[" -fsingle\""];
result ¬ CommanderOps.DoCommand[Rope.FromRefText[cmdbuf], cmd];
IF result # $Failure THEN {
Output[dbe, oname];
result ¬ dbe;
};
};
Commander.Register["Mako", MakoCommand, "Compile a set of modules"];
Commander.Register["Mako-mesa", MakoMesaCommand, "Compile a mesa module"];
Commander.Register["Mako-config", MakoConfigCommand, "Compile a config module"];
Commander.Register["Mako-c", MakoCCommand, "Compile a c program"];
Commander.Register["Mako-MakeIt", MakoMakeItCommand, "Execute a .MakeIt script"];
END.