WalnutUtilsImpl.mesa
Copyright Ó 1991, 1992 by Xerox Corporation. All rights reserved.
Swinehar, November 10, 1991 2:51 pm PST
DIRECTORY
Atom USING [ MakeAtom ],
Commander USING [ Register, CommandProc ],
CommanderOps USING [ GetProp, NextArgument ],
IO,
LoganBerry USING [ Error, LogInfo, IndexInfo, SchemaInfo, Describe, nullDB, OpenDB, Open ],
Rope USING [ Concat, Equal, Fetch, Find, Length, ROPE, Substr ],
PFS USING [ ErrorGroup, Error, PATH, PathFromRope, FileInfo, RopeFromPath, StreamOpen ],
PFSNames USING [ ComponentRope, Directory, ShortName ],
SymTab USING [ Create, Erase, Fetch, Ref, Store ],
UserProfile USING [ Token ],
WalnutOps USING [ ValidOpsHandle ],
WalnutWindow USING [ WalnutHandle, GetHandleList, Shutdown, StartUp ]
;
WalnutUtilsImpl: CEDAR PROGRAM IMPORTS Atom, Commander, CommanderOps, IO, LoganBerry, Rope, PFS, PFSNames, SymTab, UserProfile, WalnutWindow, WalnutOps ~ {
OPEN IO;
ROPE: TYPE ~ Rope.ROPE;
WalnutFileInfo: TYPE ~ REF WalnutFileInfoBody;
WalnutFileInfoBody: TYPE ~ RECORD [
rootFileName: ROPE,
logFileName: ROPE,
dbName: ROPE,
lbLogFileName: ROPE,
indexNames: LIST OF IndexInfo
];
IndexInfo: TYPE ~ REF IndexInfoBody;
IndexInfoBody: TYPE ~ RECORD [
key: ATOM,
fileName: ROPE
];
wfis: SymTab.Ref;
FileExists: PROC[name: Rope.ROPE] RETURNS [exists: BOOL¬TRUE] ~ {
gotName: BOOL¬FALSE;
[] ¬ PFS.FileInfo[name: PFS.PathFromRope[name]!
PFS.Error => IF error.group=$user AND error.code=$unknownFile THEN {
exists¬FALSE; CONTINUE}];
};
GetTwiddleFile: PROC[name: Rope.ROPE]
RETURNS [baseExists: BOOL¬TRUE, twiddleName: Rope.ROPE] ~ {
IF ~FileExists[name] THEN RETURN[FALSE, NIL];
twiddleName ¬ name;
WHILE TRUE DO
twiddleName ¬ twiddleName.Concat["~"];
IF ~FileExists[twiddleName] THEN RETURN;
ENDLOOP;
};
FindTemp: Commander.CommandProc ~ {
baseExists: BOOL;
res: Rope.ROPE;
base: Rope.ROPE;
[baseExists, res] ¬ GetTwiddleFile[CommanderOps.NextArgument[cmd]];
IF baseExists THEN {
result ¬ res;
IO.PutRope[cmd.out, res];
}
ELSE {
result ¬ $Failure;
msg ¬ "No such file"
}
};
Wait: Commander.CommandProc ~ {
[] ¬ WalnutOps.ValidOpsHandle[NIL];
};
CloseAll: Commander.CommandProc ~ {
hl: LIST OF WalnutWindow.WalnutHandle ¬ WalnutWindow.GetHandleList[];
FOR l: LIST OF WalnutWindow.WalnutHandle ¬ hl, l.rest WHILE l#NIL DO
WalnutWindow.Shutdown[l.first];
ENDLOOP;
};
DirectoryOf: Commander.CommandProc ~ {
fileName: Rope.ROPE ¬ CommanderOps.NextArgument[cmd];
filePath: PFS.PATH ¬ PFS.FileInfo[PFS.PathFromRope[fileName]].fullFName;
IO.PutRope[cmd.out, PFS.RopeFromPath[PFSNames.Directory[filePath]]];
};
DirectoryIfGiven: Commander.CommandProc ~ {
fileName: Rope.ROPE ¬ CommanderOps.NextArgument[cmd];
filePath: PFS.PATH ¬ PFS.PathFromRope[fileName];
fileName ¬ PFS.RopeFromPath[PFSNames.Directory[filePath]];
IF fileName = NIL OR fileName.Length[] = 0 THEN fileName ¬ "./";
IO.PutRope[cmd.out, fileName];
};
DefaultDirectory: Commander.CommandProc ~ {
fileName: Rope.ROPE ¬ CommanderOps.NextArgument[cmd];
filePath: PFS.PATH;
defaultDirectory: Rope.ROPE ¬ CommanderOps.NextArgument[cmd];
IF fileName=NIL OR defaultDirectory=NIL THEN
RETURN[$Failure, "Usage: DefaultDirectory <fileName> <defaultDirectory>"];
filePath ¬ PFS.PathFromRope[fileName];
fileName ¬ PFS.RopeFromPath[PFSNames.Directory[filePath]];
IF fileName = NIL OR fileName.Length[] = 0 THEN fileName ¬ defaultDirectory;
IO.PutRope[cmd.out, fileName];
};
ShortNameOf: Commander.CommandProc ~ {
filePath: PFS.PATH ¬ PFS.PathFromRope[CommanderOps.NextArgument[cmd]];
shortName: Rope.ROPE ¬ PFSNames.ComponentRope[PFSNames.ShortName[filePath]];
IO.PutRope[cmd.out, shortName];
};
DefaultExtension: Commander.CommandProc ~ {
fileName: Rope.ROPE ¬ CommanderOps.NextArgument[cmd];
defaultExtension: Rope.ROPE ¬ CommanderOps.NextArgument[cmd];
index: INT;
IF fileName=NIL OR defaultExtension=NIL THEN
RETURN[$Failure, "Usage: DefaultExtension <fileName> <defaultExtension>"];
index ¬ Rope.Find[fileName, "."];
IF index=-1 THEN fileName ¬ IO.PutFR["%g.%g", rope[fileName], rope[defaultExtension]]
ELSE IF index=fileName.Length[]-1 THEN fileName ¬ fileName.Concat[defaultExtension];
IO.PutRope[cmd.out, fileName];
};
BaseName: Commander.CommandProc ~ {
index: INT;
shortName: Rope.ROPE;
filePath: PFS.PATH;
fileName: Rope.ROPE ¬ CommanderOps.NextArgument[cmd];
IF fileName=NIL THEN
RETURN[$Failure, "Usage: BaseName <fileName>"];
filePath ¬ PFS.PathFromRope[fileName];
shortName ¬ PFSNames.ComponentRope[PFSNames.ShortName[filePath]];
index ¬ Rope.Find[shortName, "."];
IF index#-1 THEN shortName ¬ shortName.Substr[len: index];
IO.PutRope[cmd.out, shortName];
};
ScriptDefault: Commander.CommandProc ~ {
default: Rope.ROPE ¬ CommanderOps.NextArgument[cmd];
userSupplied: Rope.ROPE ¬ CommanderOps.NextArgument[cmd];
IF userSupplied=NIL OR userSupplied.Length[]=0 OR userSupplied.Equal["."] OR
userSupplied.Fetch[0] = '$ THEN userSupplied ¬ default;
IO.PutRope[cmd.out, userSupplied];
};
MakeEmptyLBLog: Commander.CommandProc ~ {
fileName: Rope.ROPE ¬ CommanderOps.NextArgument[cmd];
s: IO.STREAM;
IF fileName=NIL THEN
RETURN[$Failure, "Usage: MakeEmptyLBLog <fileName>"];
s ¬ PFS.StreamOpen[PFS.PathFromRope[fileName], $create];
s.PutChar['\377];
s.Close[];
};
WalnutFile: Commander.CommandProc ~ TRUSTED {
spec: Rope.ROPE;
resultFile: Rope.ROPE;
rootRqst: BOOL;
wfi: WalnutFileInfo;
rootFileName: Rope.ROPE ¬ CommanderOps.NextArgument[cmd];
IF rootFileName.Equal["."] OR rootFileName=NIL THEN
rootFileName ¬ UserProfile.Token["Walnut.WalnutRootFile"];
IF rootFileName=NIL THEN { result¬$Failure; msg ¬ "no root file name"; RETURN; };
spec ¬ CommanderOps.NextArgument[cmd];
IF spec=NIL THEN spec ¬ "rootFile";
rootRqst ¬ spec.Equal["rootFile", FALSE];
IF spec.Equal["clear", FALSE] THEN {
IF wfis#NIL THEN SymTab.Erase[wfis]; msg ¬ "Walnut Info Cleared"; RETURN; };
IF ~rootRqst THEN wfi ¬ GetWFI[rootFileName];
IF ~rootRqst AND wfi=NIL THEN {
result ¬ $Failure; msg ¬ "Walnut db file information not available; check root file and ancillary LoganBerry databases."; RETURN; };
SELECT TRUE FROM
rootRqst => resultFile ¬ rootFileName;
spec.Equal["lblog", FALSE]=> resultFile ¬ wfi.lbLogFileName;
spec.Equal["db", FALSE]=> resultFile ¬ wfi.dbName;
spec.Equal["log", FALSE]=> resultFile ¬ wfi.logFileName;
spec.Equal["index", FALSE]=> {
indexKey: ATOM ¬ Atom.MakeAtom[CommanderOps.NextArgument[cmd]];
IF indexKey=NIL THEN { result ¬ $Failure; msg ¬ usage; };
FOR iList: LIST OF IndexInfo ¬ wfi.indexNames, iList.rest WHILE iList#NIL DO
IF iList.first.key#indexKey THEN LOOP;
resultFile ¬ iList.first.fileName;
EXIT;
ENDLOOP;
};
ENDCASE => { result ¬ $Failure; msg ¬ usage; };
IF resultFile=NIL THEN { result ¬ $Failure; RETURN; };
resultFile ← PFS.RopeFromPath[PFS.FileInfo[PFS.PathFromRope[resultFile]].fullFName];
IO.PutRope[cmd.out, resultFile];
};
GetWFI: PROC[rootFileName: ROPE] RETURNS [wfi: WalnutFileInfo] ~ TRUSTED {
s: IO.STREAM;
IF wfis=NIL THEN wfis ¬ SymTab.Create[case: TRUE];
wfi ¬ NARROW[SymTab.Fetch[wfis, rootFileName].val];
IF wfi#NIL THEN RETURN;
wfi ¬ NEW[WalnutFileInfoBody];
wfi.rootFileName ¬ rootFileName;
s ¬ PFS.StreamOpen[PFS.PathFromRope[rootFileName]];
WHILE ~s.EndOf[] DO
lineBuf: REF TEXT;
key: ROPE;
lineBuf ¬ s.GetLine[lineBuf];
key ¬ LOOPHOLE[lineBuf];
SELECT TRUE FROM
key.Equal["Database", FALSE] => {
db: LoganBerry.OpenDB ¬ LoganBerry.nullDB;
si: LoganBerry.SchemaInfo;
wfi.dbName ¬ s.GetLineRope[];
db ¬ LoganBerry.Open[dbName: wfi.dbName!LoganBerry.Error => CONTINUE];
IF db#LoganBerry.nullDB THEN {
si ¬ LoganBerry.Describe[db: db];
wfi.lbLogFileName ¬ si.logs.first.file;
FOR ii: LIST OF LoganBerry.IndexInfo ¬ si.indices, ii.rest WHILE ii#NIL DO
iInfo: IndexInfo ¬ NEW[IndexInfoBody ¬ [ii.first.key, ii.first.file]];
wfi.indexNames ¬ CONS[iInfo, wfi.indexNames];
ENDLOOP;
};
};
key.Equal["LogInfo", FALSE] => {
logFileName: ROPE ¬ s.GetLineRope[];
lineBuf ¬ s.GetLine[lineBuf];
lineBuf ¬ s.GetLine[lineBuf];
key ¬ LOOPHOLE[lineBuf];
IF key.Fetch[0] = '0 THEN wfi.logFileName ¬ logFileName;
};
ENDCASE;
ENDLOOP;
IF wfi.dbName=NIL OR wfi.logFileName=NIL THEN RETURN[NIL];
[] ¬ wfis.Store[rootFileName, wfi];
};
StartWalnutReadOnly: Commander.CommandProc ~ {
Doesn't work at the moment because the TRUE argument to StartUp is ignored!
rootFileName: Rope.ROPE ¬ CommanderOps.NextArgument[cmd];
[]¬WalnutWindow.StartUp[rootFileName, TRUE];
};
IFFailed: Commander.CommandProc ~ {
result ¬ CommanderOps.GetProp[cmd, $Result];
IF result = $Failure THEN result ¬ NIL ELSE result ¬ $Failure;
};
usage: Rope.ROPE ¬ "Usage: WalnutFile <spec>
etc. etc. etc.";
Commander.Register["Waitt", Wait, "Wait for scavenge or whatever to finish."];
Commander.Register["CloseAll", CloseAll, "Close all Walnut windows."];
Commander.Register["WalnutRO", StartWalnutReadOnly, "Start Walnut Read Only."];
Commander.Register["FindTemp", FindTemp, "Find unused temp file name by appending ~'s to base file name."];
Commander.Register["MakeEmptyLBLog", MakeEmptyLBLog, "Create empty log file (with valid termination character in it)
Usage: MakeEmptyLBLog <filename>"];
Commander.Register["WalnutFile", WalnutFile, "Obtain specified Walnut implementation file
Usage: WalnutFile <spec>
etc. etc. etc."];
Generic functions. Should not be part of Walnut.
Commander.Register["BaseName", BaseName, "/a/b/c/d/e/f.g => f"];
Commander.Register["DefaultExtension", DefaultExtension, "Produce file name given file name and default extension, using default extension if none was supplied."];
Commander.Register["DefaultDirectory", DefaultDirectory, "Produce directory name given file name and default directory, using default directory if none was supplied."];
Commander.Register["DirectoryOf", DirectoryOf, "Produce prefix given path name"];
Commander.Register["DirectoryIfGiven", DirectoryIfGiven, "Produce prefix, if any, given path name"];
Commander.Register["ShortNameOf", ShortNameOf, "Produce short file name given path name"];
Commander.Register["ScriptDefault", ScriptDefault, "ScriptDefault <default> <supplied>; provide the <default> value if the user-<supplied> value is in one way or another null"];
Null values: NIL, "", ".", "$anything".
Commander.Register["IFFailed", IFFailed, "Fail iff previous command did not."];
}.