StyleInfoProc: Commander.CommandProc ~ {
PROC [cmd: Handle] RETURNS [result: REF ← NIL, msg: Rope.ROPE ← NIL];
argv: CommandTool.ArgumentVector;
reader: TiogaAccess.Reader;
styleTable: SymTab.Ref;
entry: Entry;
argNum: INT ← 0;
val: SymTab.Val;
styleLogStream: IO.STREAM ~ cmd.out;
pattern: ROPE;
currentDirectory: ROPE;
PrintStyleStats:
PROC [s:
IO.
STREAM] ~ {
PrintTableEntry: SymTab.EachPairAction = {
[key: SymTab.Key, val: SymTab.Val] RETURNS [quit: BOOL]
e: Entry ← NARROW[val];
IO.PutF[s, " %g:\t%g\n", IO.rope[key], IO.int[e.nTimes]];
RETURN [FALSE];
};
IO.PutF[s, "\n\n\nStyle Counts for %g\n\n", IO.rope[pattern]];
[] ← SymTab.Pairs[styleTable, PrintTableEntry];
};
ProcessFile:
FS.NameProc = {
[fullFName: ROPE] RETURNS [continue: BOOL]
ext: ROPE;
positions: FS.ComponentPositions;
prefix, postfix, styleDef: ROPE;
prefixProp: ATOM ~ $Prefix;
fullFName ← FileNames.ResolveRelativePath[fullFName];
[fullFName, positions] ← FS.ExpandName[fullFName];
ext ← Rope.Substr[fullFName, positions.ext.start, positions.ext.length];
IF Rope.Equal[ext, "bcd",
FALSE]
OR Rope.Equal[ext, "press",
FALSE]
OR Rope.Equal[ext, "interpress",
FALSE]
OR Rope.Equal[ext, "ip",
FALSE]
OR Rope.Equal[ext, "ais",
FALSE]
OR Rope.Equal[ext, "boot",
FALSE]
THEN RETURN[TRUE];
reader ← TiogaAccess.FromFile[fullFName ! FS.Error => GO TO Error];
WHILE
NOT TiogaAccess.EndOf[reader]
DO
Process.CheckForAbort[];
styleDef ← TiogaAccess.GetExternalProp[
$StyleDef,
Atom.GetPropFromList[TiogaAccess.GetNodeProps[reader], $StyleDef]
];
IF styleDef #
NIL
THEN
LogFile[fullFName, positions, "StyleDef property"];
postfix ← TiogaAccess.GetExternalProp[
$Postfix,
Atom.GetPropFromList[TiogaAccess.GetNodeProps[reader], $Postfix]
];
IF
NOT postfix.IsEmpty
AND Rope.Find[s1:prefix, s2:".def", case:
FALSE] # -1
THEN
LogFile[fullFName, positions, Rope.Concat["Postfix property with .def:", postfix]];
prefix ← TiogaAccess.GetExternalProp[
prefixProp,
Atom.GetPropFromList[TiogaAccess.GetNodeProps[reader], prefixProp]
];
IF
NOT prefix.IsEmpty
THEN {
IF Rope.Find[s1:prefix, s2:"mesa", case:
FALSE] # -1
THEN
LogFile[fullFName, positions, "Obsolete Mesa style"];
val ← SymTab.Fetch[styleTable, prefix].val;
IF val =
NIL
THEN {
entry ← NEW[EntryRep];
entry.nTimes ← 1;
}
ELSE WITH val
SELECT
FROM
entry: Entry => entry.nTimes ← entry.nTimes+1;
ENDCASE;
[] ← SymTab.Store[styleTable, prefix, entry];
};
[] ← TiogaAccess.SkipToNextNode[reader];
ENDLOOP;
TiogaAccess.DoneWith[reader];
continue ← TRUE;
EXITS
Error => continue ← TRUE;
};
LogFile:
PROC [name: Rope.
ROPE, positions:
FS.ComponentPositions, msg:
ROPE] ~ {
dir: Rope.ROPE ← Rope.Substr[name, positions.server.start-1, positions.base.start-positions.server.start+1];
IF
NOT Rope.Equal[currentDirectory, dir]
THEN {
currentDirectory ← dir;
IO.PutF[styleLogStream, "\nDirectory %g:\n", IO.rope[currentDirectory]];
};
IO.PutF[styleLogStream, " %g => %g\n", IO.rope[Rope.Substr[name, positions.base.start, positions.base.length+positions.ext.length+positions.ver.length+2]], IO.rope[msg]];
};
argv ← CommandTool.Parse[cmd -- Exception handler should go here --];
IF argv.argc < 2 THEN GOTO Usage;
styleTable ← SymTab.Create[case: FALSE];
pattern ← argv[1];
pattern ← FileNames.ResolveRelativePath[pattern];
pattern ← FS.ExpandName[pattern].fullFName;
IO.PutF[styleLogStream, "Style information in %g\n\n", IO.rope[pattern]];
[] ← FS.EnumerateForNames[pattern, ProcessFile];
PrintStyleStats[styleLogStream];
styleLogStream.Close;
EXITS
Usage => RETURN [$Failure, "Usage: StyleInfo <filepattern>\n"];
};
Commander.Register["StyleInfo", StyleInfoProc, "StyleInfo <filepattern> -- Collect style property info."];