<> <> <> <> <> <> <<>> DIRECTORY Commander USING [CommandProc, Register, Handle], CommandTool USING [ArgumentVector, Parse, Failed], DefaultRemoteNames USING [Get], DFInternal USING [AbortDF, GetFileInfo, RemoteFileInfo, ReportFSError], DFUtilities USING [Date, DirectoryItem, FileItem, Filter, IncludeItem, ParseFromStream, ProcessItemProc, RemoveVersionNumber, SyntaxError], FS USING [Error, StreamOpen], IO USING [card, int, Close, GetIndex, rope, STREAM, PutF, Put, PutRope], IOClasses USING [CreateDribbleOutputStream], List USING [CompareProc, Sort], Process USING [CheckForAbort], Rope USING [Compare, Concat, Equal, Find, Flatten, Length, ROPE, Run, Substr]; DFIncludes: CEDAR PROGRAM IMPORTS Commander, CommandTool, DefaultRemoteNames, DFInternal, DFUtilities, FS, IO, IOClasses, List, Process, Rope = { ROPE: TYPE = Rope.ROPE; FileDesc: TYPE = RECORD [ shortName: ROPE, path: ROPE, parent: ROPE -- DF file containing defining occurrence of 'shortName' ]; StripPrefix: PROC [path: ROPE, prefix: ROPE] RETURNS [ROPE] = { len: INT = Rope.Length[prefix]; IF Rope.Run[path, 0, prefix, 0, FALSE] = len THEN RETURN [Rope.Flatten[path, len]]; RETURN [path]; }; Construct: PROC [dfFile: ROPE, cmd: Commander.Handle] RETURNS [errors, warnings, filesActedUpon: INT _ 0] = { logFileStream: IO.STREAM _ FS.StreamOpen[fileName: "DFIncludes.log", accessOptions: $create]; log: IO.STREAM _ IOClasses.CreateDribbleOutputStream[cmd.out, logFileStream]; listOfFileDescRefs: LIST OF REF ANY _ NIL; currentPrefix: ROPE = DefaultRemoteNames.Get[].current; Compare: List.CompareProc = { <> f1: REF FileDesc = NARROW[ref1]; f2: REF FileDesc = NARROW[ref2]; RETURN[f1.shortName.Compare[f2.shortName, FALSE]]; }; ConstructInner: PROC [dfFile: ROPE, date: DFUtilities.Date, filter: DFUtilities.Filter, nestingDepth: NAT] RETURNS [finished: BOOL _ FALSE] = { shortDirectoryPath: ROPE _ NIL; shortDfFile: ROPE _ StripDfPrefix[dfFile]; StripDfPrefix: PROC [path: ROPE] RETURNS [rest: ROPE] = { RETURN [StripPrefix[StripPrefix[path, currentPrefix], "Top>"]]; }; StripDirPrefix: PROC [path: ROPE] RETURNS [ROPE] = { RETURN [StripPrefix[path, currentPrefix]]; }; DoOneItem: DFUtilities.ProcessItemProc = { Process.CheckForAbort[]; WITH item SELECT FROM directory: REF DFUtilities.DirectoryItem => shortDirectoryPath _ StripDirPrefix[directory.path1]; file: REF DFUtilities.FileItem => { desc: REF FileDesc = NEW[FileDesc _ [ shortName: DFUtilities.RemoveVersionNumber[file.name], path: shortDirectoryPath, parent: shortDfFile ]]; listOfFileDescRefs _ CONS[desc, listOfFileDescRefs]; }; include: REF DFUtilities.IncludeItem => [] _ ConstructInner[include.path1, include.date, filter, nestingDepth + 1]; ENDCASE => ERROR; }; dfInfo: REF DFInternal.RemoteFileInfo = NEW[DFInternal.RemoteFileInfo _ [name: dfFile, date: date]]; dfStream: IO.STREAM; DFInternal.GetFileInfo[info: dfInfo, client: NIL ! FS.Error => {errors _ errors.SUCC; GO TO skip}]; dfStream _ FS.StreamOpen[fileName: dfInfo.name ! FS.Error => {errors _ errors.SUCC; DFInternal.ReportFSError[error, dfInfo, NIL]; GO TO skip} ]; dfInfo.name _ DFUtilities.RemoveVersionNumber[dfInfo.name]; FOR i: NAT IN [1..nestingDepth] DO log.PutRope[" "] ENDLOOP; log.Put[IO.rope["starting to look at "], IO.rope[dfInfo.name], IO.rope["\n"]]; DFUtilities.ParseFromStream[dfStream, DoOneItem, filter ! DFUtilities.SyntaxError -- [reason: ROPE]-- => { errors _ errors.SUCC; log.PutF[ "Error: Syntax error in '%g'[%d]: %g\NProcessing of this DF file aborted.", IO.rope[dfInfo.name], IO.card[dfStream.GetIndex[]], IO.rope[reason] ]; CONTINUE }; ABORTED => dfStream.Close[]; ]; dfStream.Close[]; RETURN[TRUE]; EXITS skip => NULL; }; <> { ENABLE { ABORTED => { errors _ errors.SUCC; log.Put[IO.rope["Error: ABORT looking at "], IO.rope[dfFile], IO.rope["\n"]]; <> }; DFInternal.AbortDF => { errors _ errors.SUCC; log.Put[IO.rope["Error: ABORT looking at "], IO.rope[dfFile], IO.rope["\n"]]; CONTINUE }; }; <> IF ConstructInner[dfFile: dfFile, date: [format: $explicit], filter: [filterA: $source, filterC: $defining], nestingDepth: 0] THEN { <> PrintFileDesc: PROC [file: REF FileDesc] = { out.PutF["%-30g %-20g %g\n", IO.rope[file.shortName], IO.rope[file.parent], IO.rope[file.path]]; }; fPrev, fCurrent: REF FileDesc _ NIL; nFiles: INT _ 0; out: IO.STREAM = FS.StreamOpen[fileName: "DFIncludes.txt", accessOptions: $create]; out.PutF["List of DF file inclusion relationships from %g\n\n", IO.rope[dfFile]]; listOfFileDescRefs _ List.Sort[listOfFileDescRefs, Compare]; FOR l: LIST OF REF ANY _ listOfFileDescRefs, l.rest UNTIL l = NIL DO { fCurrent _ NARROW[l.first]; IF fPrev # NIL AND fPrev.shortName.Equal[fCurrent.shortName, FALSE] THEN { warnings _ warnings.SUCC; IF fPrev.parent.Equal[s2: fCurrent.parent, case: FALSE] THEN { log.PutF[ "warning: '%g' appears more than once (via '%g')\n", IO.rope[fPrev.shortName], IO.rope[fPrev.parent] ]; GOTO next; } ELSE log.PutF[ "WARNING: '%g' appears more than once (via '%g' and '%g')\n", IO.rope[fPrev.shortName], IO.rope[fPrev.parent], IO.rope[fCurrent.parent] ]; }; PrintFileDesc[fCurrent]; nFiles _ nFiles.SUCC; GOTO next; EXITS next => fPrev _ fCurrent } ENDLOOP; out.PutF["\nEND of list of DF file inclusion relationships from %g\n%g files listed\n", IO.rope[dfFile], IO.int[nFiles]]; out.Close[]; log.PutF["\n***DF file inclusion relationships from %g written onto DFIncludes.txt", IO.rope[dfFile]]; IF errors # 0 OR warnings # 0 THEN { log.PutF["\n*** %g errors and %g warnings written onto DFIncludes.log\n", IO.int[errors], IO.int[warnings]]; } ELSE log.PutRope[".\n"]; }; -- end IF ConstructInner[dfFile, [format: $explicit], [], 0] THEN }; -- ENABLE logFileStream.Close[]; }; DoDFIncludes: Commander.CommandProc = { <> dfFileName: ROPE _ NIL; length: NAT; argv: CommandTool.ArgumentVector _ NIL; argv _ CommandTool.Parse[cmd ! CommandTool.Failed => { msg _ errorMsg; CONTINUE; }]; IF argv = NIL THEN RETURN[$Failure, msg]; IF argv.argc # 2 THEN RETURN[$Failure, "Usage: Dependencies dfFileName\n"]; dfFileName _ argv[1]; length _ dfFileName.Length[]; IF length < 4 OR (Rope.Compare[Rope.Substr[dfFileName, length - 3, 3], ".df", FALSE] # equal AND Rope.Find[dfFileName, "!", MAX[0, length-5]] = -1) THEN dfFileName _ Rope.Concat[dfFileName, ".df"]; [] _ Construct[dfFileName, cmd]; }; Commander.Register[ "DFIncludes", DoDFIncludes, "Build a list of df file inclusion relationships from a df file." ]; }.