<> <> <> <> <> <<>> <> << >> DIRECTORY Atom USING [GetPropFromList], Commander USING [CommandProc, Register], CommandTool USING [ArgumentVector, Parse], FileNames USING [ResolveRelativePath], IO USING [int, PutF, rope, STREAM, Close], FS USING [EnumerateForNames, NameProc, ExpandName, ComponentPositions, Error], Process USING [CheckForAbort], TiogaAccess USING [SkipToNextNode, EndOf, FromFile, GetExternalProp, GetNodeProps, Reader, DoneWith], SymTab USING [Create, EachPairAction, Fetch, Pairs, Ref, Store, Val], Rope USING [IsEmpty, Concat, ROPE, Substr, Equal, Find]; TiogaStyleInfoImpl: CEDAR PROGRAM IMPORTS Commander, CommandTool, FileNames, FS, IO, Process, TiogaAccess, Atom, SymTab, Rope = BEGIN ROPE: TYPE ~ Rope.ROPE; Entry: TYPE ~ REF EntryRep; EntryRep: TYPE ~ RECORD[ nTimes: INT ]; StyleInfoProc: Commander.CommandProc ~ { <> 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 \n"]; }; Commander.Register["StyleInfo", StyleInfoProc, "StyleInfo -- Collect style property info."]; END.