(* Copyright (C) 1990, Digital Equipment Corporation *) (* All rights reserved. *) (* See the file COPYRIGHT for a full description. *) MODULE M3DepInteract; IMPORT Command, Fmt, SList, Text, StdIO, IO, PathName, TextStream, TextTo, UnixRun, OSError, EnvVar, Err, TimeDate, FileOp; IMPORT M3Context, M3LProgContext, M3Args, M3Path; IMPORT M3DepM3Path, M3DepCompile, M3DepM3Makefile; IMPORT M3AST_AS, M3CUnit; IMPORT M3CFETool, M3DepDATool, M3CWarnTool, M3Browser, M3LTool, M3DepM3MFTool, M3CharTool; IMPORT M3Query; IMPORT M3CheckGC, M3ASTCacheTool; IMPORT SortText, TextExtras; IMPORT M3AST_FE_F; VAR context_g: M3Context.T; prev_m3path_g, cur_m3path_g: M3DepM3Path.T := NIL; target_g: TEXT := NIL; firstScan_g := TRUE; CONST DotM3Check = ".m3check"; EXCEPTION NoM3Path; PROCEDURE CheckM3Path(t: M3DepM3Path.T): M3DepM3Path.T RAISES {NoM3Path}= BEGIN IF t = NIL THEN Command.Put("You must \'ScanDirs\' first\n"); RAISE NoM3Path ELSE RETURN t END; END CheckM3Path; PROCEDURE Run(prompt: TEXT; c: M3Context.T; p: M3DepM3Path.T; initialCommands: Text.T) RAISES {}= VAR s: IO.Stream := NIL; BEGIN Command.SetPrompt(prompt); context_g := c; cur_m3path_g := p; firstScan_g := TRUE; IF FileOp.Accessible(DotM3Check) THEN IF initialCommands = NIL THEN initialCommands := ""; END; initialCommands := "@ " & DotM3Check & "\n" & initialCommands; END; IF initialCommands # NIL THEN s := TextStream.Open(initialCommands); END; (* if *) Command.Interact(s); END Run; PROCEDURE Scan() RAISES {}= BEGIN ScanDirs(); Compile(); END Scan; PROCEDURE Compile() RAISES {}= BEGIN TRY EVAL CheckM3Path(cur_m3path_g) EXCEPT NoM3Path => RETURN END; EVAL M3DepCompile.Run(context_g, prev_m3path_g, cur_m3path_g); prev_m3path_g := cur_m3path_g; END Compile; PROCEDURE ScanDirs() RAISES {}= BEGIN IF M3Args.GetFlag(M3DepDATool.Get(), M3DepDATool.Verbose_Arg) THEN Err.Print("scanning directories", Err.Severity.Comment); END; (* if *) cur_m3path_g := M3DepM3Path.Scan(); IF firstScan_g THEN SetReadOnlyStatus(); firstScan_g := FALSE; END; (* if *) END ScanDirs; PROCEDURE SetReadOnlyStatus() RAISES {}= VAR dirs := M3DepM3Path.Dirs(cur_m3path_g); elem: M3Path.Elem := dirs.head; VAR cid := M3Args.GetStringList(M3DepDATool.Get(), M3DepDATool.CompileInDir_Arg); cid_e: REF ARRAY OF M3Path.Elem; BEGIN IF cid # NIL THEN cid_e := NEW(REF ARRAY OF M3Path.Elem, NUMBER(cid^)); FOR i := 0 TO NUMBER(cid^)-1 DO cid_e[i] := M3Path.ElemFrom(cid[i]); END END; WHILE elem # NIL DO IF Text.Equal(M3Path.CurrentDir, elem.text) OR (cid # NIL AND ACompileInDir(elem, cid_e)) THEN M3Path.SetReadOnly(elem, FALSE); ELSE M3Path.SetReadOnly(elem, TRUE); END; (* if *) elem := elem.next; END; (* while *) END SetReadOnlyStatus; PROCEDURE ACompileInDir(dir: M3Path.Elem; cid_e: REF ARRAY OF M3Path.Elem): BOOLEAN= VAR cid_num: INTEGER := NUMBER(cid_e^); BEGIN IF cid_num = 0 THEN RETURN TRUE ELSE FOR i := 0 TO cid_num-1 DO IF M3Path.Same(dir, cid_e^[i]) THEN RETURN TRUE; END; (* if *) END; (* for *) RETURN FALSE; END END ACompileInDir; PROCEDURE ChangeDirStatus() RAISES {}= VAR status: TEXT; readOnly: BOOLEAN; dir: TEXT; dirElem: M3Path.Elem; BEGIN TRY EVAL CheckM3Path(cur_m3path_g) EXCEPT NoM3Path => RETURN END; IF Command.GetArg(dir) THEN IF Command.GetArg(status) THEN IF Text.Equal(status, "R") THEN readOnly := TRUE; ELSIF Text.Equal(status, "W") THEN readOnly := FALSE; ELSE Command.Put("'R' or 'W' expected"); RETURN END; (* if *) dirElem := M3DepM3Path.ValidateDir(cur_m3path_g, dir); IF dirElem = NIL THEN Command.Put(Fmt.F("directory: \'%s\' is not on the search path\n", dir)); ELSE M3Path.SetReadOnly(dirElem, readOnly); END; ELSE Command.Put("'dir' ('R'|'W') expected"); END; END; END ChangeDirStatus; PROCEDURE CompileInterfaces() RAISES {}= VAR interface: TEXT; BEGIN IF Command.GetArg(interface) THEN VAR units := NEW(REF ARRAY OF TEXT, 1); BEGIN units[0] := interface; EVAL M3DepCompile.CompileUnits(context_g, M3CUnit.Type.Interface, units); END; END; (* if *) END CompileInterfaces; PROCEDURE CompileModules() RAISES {}= VAR module: TEXT; BEGIN IF Command.GetArg(module) THEN VAR units := NEW(REF ARRAY OF TEXT, 1); BEGIN units[0] := module; EVAL M3DepCompile.CompileUnits(context_g, M3CUnit.Type.Module, units); END; END; (* if *) END CompileModules; PROCEDURE CompileAll() RAISES {}= BEGIN TRY EVAL M3DepCompile.CompileAll(context_g, CheckM3Path(cur_m3path_g)); EXCEPT NoM3Path => END; END CompileAll; PROCEDURE GenM3Make() RAISES {}= BEGIN TRY (* write makefile *) EVAL M3DepM3Makefile.Run(context_g, CheckM3Path(cur_m3path_g)); EXCEPT NoM3Path => END; END GenM3Make; PROCEDURE SetM3Makefile() RAISES {}= VAR p: TEXT; BEGIN IF Command.GetArg(p) THEN M3Args.SetString(M3DepM3MFTool.Get(), M3DepM3MFTool.MakeFile_Arg, p); ShowArgString(M3DepM3MFTool.Get(), M3DepM3MFTool.MakeFile_Arg); END; (* if *) END SetM3Makefile; PROCEDURE SetPrintUnits() RAISES {}= BEGIN EVAL ToggleFlag(M3CFETool.GetTool(), M3CFETool.PrintUnits_Arg); END SetPrintUnits; PROCEDURE SetTTimings() RAISES {}= BEGIN EVAL ToggleFlag(M3CFETool.GetTool(), M3CFETool.Timings_Arg); END SetTTimings; PROCEDURE SetVerbose() RAISES {}= BEGIN EVAL ToggleFlag(M3DepDATool.Get(), M3DepDATool.Verbose_Arg); END SetVerbose; PROCEDURE SetFilterUnits() RAISES {}= BEGIN EVAL ToggleFlag(M3DepDATool.Get(), M3DepDATool.NOFilterUnits_Arg); END SetFilterUnits; PROCEDURE SetFilterUnitsExact() RAISES {}= BEGIN EVAL ToggleFlag(M3DepDATool.Get(), M3DepDATool.FilterUnitsExact_Arg); END SetFilterUnitsExact; TYPE UnitTypeSet = SET OF M3CUnit.Type; CONST Interfaces = UnitTypeSet{M3CUnit.Type.Interface}; Modules = UnitTypeSet{M3CUnit.Type.Module}; InterfacesAndModules = UnitTypeSet{M3CUnit.Type.Interface, M3CUnit.Type.Module}; PROCEDURE ListPath() RAISES {}= BEGIN TRY VAR dirs := M3DepM3Path.Dirs(CheckM3Path(cur_m3path_g)); elem: M3Path.Elem := dirs.head; BEGIN WITH s = StdIO.Out() DO WHILE elem # NIL DO IO.PutText(s, elem.text); IF elem.readOnly THEN IO.PutText(s, " R"); ELSE IO.PutText(s, " W"); END; IO.Put(s, '\n'); elem := elem.next; END; (* while *) END; END; EXCEPT NoM3Path => END; END ListPath; PROCEDURE ListInterfaces() RAISES {}= VAR dir: TEXT := NIL; BEGIN EVAL Command.Argument(dir); DoListUnits(Interfaces, dir); END ListInterfaces; PROCEDURE ListModules() RAISES {}= VAR dir: TEXT := NIL; BEGIN EVAL Command.Argument(dir); DoListUnits(Modules, dir); END ListModules; PROCEDURE ListUnits() RAISES {}= VAR dir: TEXT := NIL; BEGIN EVAL Command.Argument(dir); DoListUnits(InterfacesAndModules, dir); END ListUnits; PROCEDURE DoListUnits( uts: UnitTypeSet; inDir: TEXT := NIL) RAISES {}= VAR elems: REF ARRAY OF TEXT; count := 0; tn: TEXT; cu: M3AST_AS.Compilation_Unit; u: M3DepM3Path.UpdateRec; dirElem: M3Path.Elem := NIL; BEGIN IF inDir # NIL AND Text.Equal(inDir, PathName.Current()) THEN inDir := ""; END; TRY EVAL CheckM3Path(cur_m3path_g) EXCEPT NoM3Path => RETURN END; IF inDir # NIL THEN dirElem := M3DepM3Path.ValidateDir(cur_m3path_g, inDir); IF dirElem = NIL THEN Err.Print(Fmt.F("directory: \'%s\' is not on the search path\n", inDir), Err.Severity.Warning); RETURN END; END; (* if inaccessible *) WITH s = StdIO.Out() DO FOR ut := M3CUnit.Type.Interface TO M3CUnit.Type.Module DO IF ut IN uts THEN IF ut = M3CUnit.Type.Interface THEN tn := "Interfaces" ELSE tn := "Modules"; END; IO.PutText(s, tn); IF inDir # NIL THEN IO.PutF(s, " in %s", inDir) END; IO.PutText(s, ":\n"); count := 0; IF ut = M3CUnit.Type.Interface THEN M3DepM3Path.Interfaces(NIL, cur_m3path_g, u, dirElem); ELSE M3DepM3Path.Modules(NIL, cur_m3path_g, u, dirElem); END; elems := ArrayFromSList(u[M3DepM3Path.Update.Added]); SortText.Array(elems^, TextExtras.Compare); FOR e := 0 TO NUMBER(elems^)-1 DO VAR name: TEXT := elems[e]; mark: TEXT := NIL; BEGIN IF (count MOD 4) = 0 THEN IO.Put(s, '\n'); END; IF M3Context.Find(context_g, name, ut, cu) THEN IF cu.fe_status * M3CUnit.Errors # M3CUnit.Status{} THEN mark := "*"; ELSE mark := " "; END; ELSE mark := "-"; END; (* if *) IO.PutF(s, "%-18s", name & mark); INC(count); END; END; IO.Put(s, '\n');IO.Put(s, '\n'); IO.Flush(s); END; END; END; END DoListUnits; PROCEDURE ArrayFromSList(sl: SList.T): REF ARRAY OF TEXT RAISES {} = VAR a := NEW(REF ARRAY OF TEXT, SList.Length(sl)); e: SList.TextElem; BEGIN e := sl.head; FOR i := FIRST(a^) TO LAST(a^) DO a[i] := e.text; e := e.next; END; RETURN a; END ArrayFromSList; PROCEDURE ShowUsesInterface() RAISES {}= VAR interface: TEXT; BEGIN IF Command.GetArg(interface) THEN M3Browser.ShowUses(context_g, StdIO.Out(), interface, M3CUnit.Type.Interface); END; END ShowUsesInterface; PROCEDURE ShowUsesModule() RAISES {}= VAR module: TEXT; BEGIN IF Command.GetArg(module) THEN M3Browser.ShowUses(context_g, StdIO.Out(), module, M3CUnit.Type.Module); END; END ShowUsesModule; PROCEDURE ShowDependsOn() RAISES {}= VAR module: TEXT; BEGIN IF Command.GetArg(module) THEN M3Browser.ShowDependsOn(context_g, StdIO.Out(), module); END; END ShowDependsOn; PROCEDURE WhoImports() RAISES {}= VAR interface: TEXT; BEGIN IF Command.GetArg(interface) THEN M3Browser.WhoImports(context_g, StdIO.Out(), interface); END; END WhoImports; PROCEDURE WhoExports() RAISES {}= VAR interface: TEXT; BEGIN IF Command.GetArg(interface) THEN M3Browser.WhoExports(context_g, StdIO.Out(), interface); END; END WhoExports; PROCEDURE WhoDependsOn() RAISES {}= VAR interface: TEXT; BEGIN IF Command.GetArg(interface) THEN M3Browser.WhoDependsOn(context_g, StdIO.Out(), interface); END; END WhoDependsOn; PROCEDURE TypeHierarchy() RAISES {}= VAR typeName: TEXT; BEGIN IF Command.GetArg(typeName) THEN M3Browser.ShowAncestors(context_g, StdIO.Out(), typeName, FALSE, TRUE); END; END TypeHierarchy; PROCEDURE ConcreteTypeHierarchy() RAISES {}= VAR typeName: TEXT; BEGIN IF Command.GetArg(typeName) THEN M3Browser.ShowAncestors(context_g, StdIO.Out(), typeName, TRUE, TRUE); END; END ConcreteTypeHierarchy; PROCEDURE PreLink() RAISES {}= VAR main: TEXT := NIL; prog_context: M3Context.T; BEGIN EVAL Command.Argument(main); prog_context := M3LProgContext.BuildC(context_g, main); IF prog_context = NIL THEN IF main = NIL THEN Command.Put("no main program modules!\n"); ELSE Command.PutF("no module named \'%s\' found\n", main); END; ELSE IF M3LTool.Run(prog_context) < 0 THEN Command.Put("prelink failed\n"); ELSE Command.Put("prelink ok\n"); END; END; END PreLink; PROCEDURE AR() RAISES {}= VAR name: TEXT; BEGIN IF Command.GetArg(name) THEN M3Args.SetString(M3DepM3MFTool.Get(), M3DepM3MFTool.AR_Arg, name); ShowArgString(M3DepM3MFTool.Get(), M3DepM3MFTool.AR_Arg); END; (* if *) END AR; PROCEDURE HeadersOnly() RAISES {}= BEGIN EVAL ToggleFlag(M3DepDATool.Get(), M3DepDATool.CompileHeadersOnly_Arg); END HeadersOnly; PROCEDURE SetWarnExceptions() RAISES {}= BEGIN EVAL ToggleFlag(M3CWarnTool.Get(), M3CWarnTool.WE_Arg); END SetWarnExceptions; PROCEDURE SetWarnUses() RAISES {}= BEGIN EVAL ToggleFlag(M3CWarnTool.Get(), M3CWarnTool.WU_Arg); END SetWarnUses; PROCEDURE SetWarnIgnoreFor() RAISES {}= BEGIN EVAL ToggleFlag(M3CWarnTool.Get(), M3CWarnTool.WIF_Arg); END SetWarnIgnoreFor; PROCEDURE SetWarnReturns() RAISES {}= BEGIN EVAL ToggleFlag(M3CWarnTool.Get(), M3CWarnTool.WR_Arg); END SetWarnReturns; PROCEDURE SetWarnNarrows() RAISES {}= BEGIN EVAL ToggleFlag(M3CWarnTool.Get(), M3CWarnTool.WN_Arg); END SetWarnNarrows; PROCEDURE SetWarnAll() RAISES {}= BEGIN EVAL ToggleFlag(M3CWarnTool.Get(), M3CWarnTool.WA_Arg); END SetWarnAll; PROCEDURE SetCharTypesToChange() RAISES {}= BEGIN EVAL ToggleFlag(M3CharTool.Get(), M3CharTool.TypesToChange_Arg); END SetCharTypesToChange; PROCEDURE SetCharStatsToConsider() RAISES {}= BEGIN EVAL ToggleFlag(M3CharTool.Get(), M3CharTool.StatsToConsider_Arg); END SetCharStatsToConsider; PROCEDURE SetCharExprsToReplace() RAISES {}= BEGIN EVAL ToggleFlag(M3CharTool.Get(), M3CharTool.ExprsToReplace_Arg); END SetCharExprsToReplace; PROCEDURE SetCharExprsToConsider() RAISES {}= BEGIN EVAL ToggleFlag(M3CharTool.Get(), M3CharTool.ExprsToConsider_Arg); END SetCharExprsToConsider; PROCEDURE SetCharExprsDistantlyRelated() RAISES {}= BEGIN EVAL ToggleFlag(M3CharTool.Get(), M3CharTool.ExprsDistantlyRelated_Arg); END SetCharExprsDistantlyRelated; PROCEDURE SetCharConsiderAll() RAISES {}= BEGIN EVAL ToggleFlag(M3CharTool.Get(), M3CharTool.ConsiderAll_Arg); END SetCharConsiderAll; PROCEDURE ToggleFlag(t: M3Args.T; key: TEXT): BOOLEAN= VAR v := M3Args.GetFlag(t, key); BEGIN M3Args.SetFlag(t, key, NOT v); ShowArgFlag(t, key); RETURN NOT v; END ToggleFlag; PROCEDURE ArgValues() RAISES {}= BEGIN ShowArgFlag(M3DepDATool.Get(), M3DepDATool.NOFilterUnits_Arg); ShowArgFlag(M3DepDATool.Get(), M3DepDATool.FilterUnitsExact_Arg); ShowArgFlag(M3DepDATool.Get(), M3DepDATool.CompileHeadersOnly_Arg); ShowArgStringList(M3DepDATool.Get(), M3DepDATool.CompileInDir_Arg); ShowArgString(M3DepM3MFTool.Get(), M3DepM3MFTool.MakeFile_Arg); ShowArgString(M3DepM3MFTool.Get(), M3DepM3MFTool.AR_Arg); ShowArgFlag(M3ASTCacheTool.Handle(), M3ASTCacheTool.NotifyGC_Arg); ShowArgFlag(M3CFETool.GetTool(), M3CFETool.PrintUnits_Arg); ShowArgFlag(M3CFETool.GetTool(), M3CFETool.Timings_Arg); ShowArgFlag(M3DepDATool.Get(), M3DepDATool.Verbose_Arg); ShowArgFlag(M3CWarnTool.Get(), M3CWarnTool.WA_Arg); ShowArgFlag(M3CWarnTool.Get(), M3CWarnTool.WE_Arg); ShowArgFlag(M3CWarnTool.Get(), M3CWarnTool.WIF_Arg); ShowArgFlag(M3CWarnTool.Get(), M3CWarnTool.WR_Arg); ShowArgFlag(M3CWarnTool.Get(), M3CWarnTool.WU_Arg); ShowArgFlag(M3CWarnTool.Get(), M3CWarnTool.WN_Arg); ShowArgFlag(M3CharTool.Get(), M3CharTool.TypesToChange_Arg); ShowArgFlag(M3CharTool.Get(), M3CharTool.StatsToConsider_Arg); ShowArgFlag(M3CharTool.Get(), M3CharTool.ExprsToReplace_Arg); ShowArgFlag(M3CharTool.Get(), M3CharTool.ExprsToConsider_Arg); ShowArgFlag(M3CharTool.Get(), M3CharTool.ExprsDistantlyRelated_Arg); ShowArgFlag(M3CharTool.Get(), M3CharTool.ConsiderAll_Arg); END ArgValues; PROCEDURE ShowArgFlag(t: M3Args.T; arg: TEXT) RAISES {}= BEGIN Command.Put(Fmt.F("%-24s %s\n", arg, Fmt.Bool(M3Args.GetFlag(t, arg)))); END ShowArgFlag; PROCEDURE ShowArgString(t: M3Args.T; arg: TEXT) RAISES {}= VAR av := M3Args.GetString(t, arg); tv: TEXT; BEGIN IF av = NIL THEN tv := "UNSET" ELSE tv := av END; Command.Put(Fmt.F("%-24s %s\n", arg, tv)); END ShowArgString; PROCEDURE ShowArgStringList(t: M3Args.T; arg: TEXT) RAISES {}= VAR av := M3Args.GetStringList(t, arg); tv: TEXT; BEGIN IF av = NIL THEN tv := "UNSET" ELSIF NUMBER(av^)=0 THEN tv := "\"\""; ELSE tv := av[0] END; Command.Put(Fmt.F("%-24s %s\n", arg, tv)); IF av # NIL THEN FOR i := 1 TO NUMBER(av^)-1 DO Command.Put(Fmt.F("%-24s %s\n", "", av[i])); END; (* for *) END; END ShowArgStringList; PROCEDURE Query() RAISES {}= BEGIN M3Query.Context(context_g, Command.RestOfLine()); END Query; PROCEDURE GC() RAISES {}= BEGIN M3CheckGC.CollectNow(); END GC; PROCEDURE NotifyGC() RAISES {}= BEGIN WITH b = ToggleFlag(M3ASTCacheTool.Handle(), M3ASTCacheTool.NotifyGC_Arg) DO M3ASTCacheTool.Notify(b); END; END NotifyGC; PROCEDURE IncreaseHeap() RAISES {}= VAR text: TEXT; increase: CARDINAL; BEGIN IF Command.GetArg(text) THEN IF TextTo.BigCard(text, increase) THEN EVAL M3ASTCacheTool.Increase(increase); ELSE Command.Put("illegal value, use 'n', 'nK' or 'nM'"); END; END; (* if *) END IncreaseHeap; PROCEDURE Target() RAISES {}= VAR text: TEXT; BEGIN IF Command.GetArg(text) THEN target_g := text; END; (* if *) END Target; PROCEDURE M3Make() RAISES {}= VAR cd := "(cd "; slash := "/"; m3make := "; m3make)"; dir := ".."; BEGIN IF Command.Argument(dir) THEN END; IF target_g = NIL THEN IF NOT EnvVar.Get("CPU_TYPE", target_g) THEN Command.Put("CPU_TYPE environment variable unset - do 'target dir' to set\n"); RETURN END; END; TRY UnixRun.ShellCommand(cd & dir & slash & target_g & m3make, NIL); EXCEPT | OSError.E(error) => Command.PutF("Failed to run command - %s\n", OSError.ToText(error)); END; END M3Make; PROCEDURE Shell() RAISES {}= VAR command := Command.RestOfLine(); BEGIN TRY UnixRun.ShellCommand(command, NIL); EXCEPT | OSError.E(error) => Command.PutF("Failed to run command - %s\n", OSError.ToText(error)); END; END Shell; PROCEDURE DoCompileInDir(dir: TEXT) RAISES {}= VAR cid := M3Args.GetStringList(M3DepDATool.Get(), M3DepDATool.CompileInDir_Arg); cid_num: CARDINAL; BEGIN IF dir = NIL THEN cid := NIL ELSE M3Path.SetReadOnly(M3Path.ElemFrom(dir), FALSE); IF cid = NIL THEN cid_num := 0 ELSE cid_num := NUMBER(cid^) END; WITH n_cid = NEW(REF ARRAY OF TEXT, cid_num+1) DO FOR j := 0 TO cid_num-1 DO n_cid[j] := cid[j]; END; (* for *) n_cid[cid_num] := dir; cid := n_cid; END; END; M3Args.SetStringList(M3DepDATool.Get(), M3DepDATool.CompileInDir_Arg, cid); END DoCompileInDir; PROCEDURE CompileInDir() RAISES {}= VAR text: TEXT := NIL; BEGIN EVAL Command.Argument(text); DoCompileInDir(text); ShowArgStringList(M3DepDATool.Get(), M3DepDATool.CompileInDir_Arg); END CompileInDir; PROCEDURE Dir() RAISES {}= VAR dir: TEXT := ""; BEGIN EVAL Command.Argument(dir); IF FileOp.Accessible(dir) THEN M3Path.AddExplicit(dir); ELSE Err.Print(Fmt.F("directory '%s' is inaccessible\n", dir), Err.Severity.Warning); END; (* if *) (*ListPath();*) END Dir; PROCEDURE DirC() RAISES {}= VAR dir: TEXT := ""; BEGIN EVAL Command.Argument(dir); IF FileOp.Accessible(dir) THEN M3Path.AddExplicit(dir); DoCompileInDir(dir); ELSE Err.Print(Fmt.F("directory '%s' is inaccessible\n", dir), Err.Severity.Warning); END; (*ListPath();*) END DirC; PROCEDURE FreezeM3Path() RAISES {}= PROCEDURE Append(elem: M3Path.Elem) RAISES {}= BEGIN IF elem.next # NIL THEN Append(elem.next); END; M3Path.AddExplicit(elem.text, elem.readOnly); END Append; BEGIN TRY VAR dirs := M3DepM3Path.Dirs(CheckM3Path(cur_m3path_g)); elem: M3Path.Elem := dirs.head; BEGIN M3Path.AddExplicit(NIL); (* reset *) Append(elem); END; EXCEPT NoM3Path => END; END FreezeM3Path; PROCEDURE ShowLocationModule() RAISES {}= VAR text: TEXT; BEGIN IF Command.GetArg(text) THEN ShowLocationUnit(M3CUnit.Type.Module, text); END; (* if *) END ShowLocationModule; PROCEDURE ShowLocationInterface() RAISES {}= VAR text: TEXT; BEGIN IF Command.GetArg(text) THEN ShowLocationUnit(M3CUnit.Type.Interface, text); END; (* if *) END ShowLocationInterface; PROCEDURE ShowLocationUnit(ut: M3CUnit.Type; name: TEXT) RAISES {}= BEGIN TRY EVAL CheckM3Path(cur_m3path_g) EXCEPT NoM3Path => RETURN END; VAR info := M3DepM3Path.InfoOf(cur_m3path_g, ut, name); tsText: TEXT := "time stamp information not available"; BEGIN WITH s = StdIO.Out() DO IF info.pathName = NIL THEN IO.PutF(s, "%s '%s' not found on search path\n", M3CUnit.TypeName(ut), name); ELSE IF info.timeStamp # NIL THEN tsText := TimeDate.ToText(info.timeStamp); END; IO.PutF(s, "%s %s\n", info.pathName, tsText); END; END; END; END ShowLocationUnit; BEGIN Command.Bind("Scan", Scan, "scan for changes and rebuild dependency graph"); Command.Bind("WriteM3Makefile", GenM3Make, "write m3makefile"); Command.Bind("ARchive", AR, "generate \'archive\' target in makefile"); Command.Bind("HeadersOnly", HeadersOnly, "toggle \'HeadersOnly\' flag"); Command.Bind("M3MakeFile", SetM3Makefile, "set makefile name"); Command.Bind("PrintUnits", SetPrintUnits, "toggle \'PrintUnits\' flag"); Command.Bind("NOFilterUnits", SetFilterUnits, "toggle \'NOFilterUnits\' flag"); Command.Bind("FilterUnitsExact", SetFilterUnitsExact, "toggle \'FilterUnitsExact\' flag"); Command.Bind("Verbose", SetVerbose, "toggle \'Verbose\' flag"); Command.Bind("TTimings", SetTTimings, "toggle \'TTimings\' flag"); Command.Bind("ListPath", ListPath, "display \'m3path\'"); Command.Bind("ListInterfaces", ListInterfaces, "list interfaces (in dir if given)"); Command.Bind("ListModules", ListModules, "list modules (in dir if given)"); Command.Bind("ListUnits", ListUnits, "list interfaces and modules (in dir if given)"); Command.Bind("ShowUsesInterface", ShowUsesInterface, "show the \'uses\' relation for given interface"); Command.Bind("ShowUsesModule", ShowUsesModule, "show the \'uses\' relation for given module"); Command.Bind("ShowDependsOn", ShowDependsOn, "show the \'depends-on\' relation for given module"); Command.Bind("WhoImports", WhoImports, "list importers of given interface"); Command.Bind("WhoeXports", WhoExports, "list exporters of given interface"); Command.Bind("WhoDependsOn", WhoDependsOn, "list modules that depend on given module"); Command.Bind("TypeHierarchy", TypeHierarchy, "show the (abstract) type hierarchy for given type"); Command.Bind("ConcreteTypeHierarchy", ConcreteTypeHierarchy, "show the complete type hierarchy for given type"); Command.Bind("CompileInterface", CompileInterfaces, "compile given interface"); Command.Bind("CompileModule", CompileModules, "compile given module"); Command.Bind("CompileAll", CompileAll, "compile all units not yet compiled"); Command.Bind("PreLink", PreLink, "apply pre-linker to main program"); Command.Bind("WarnExceptions", SetWarnExceptions, "toggle \'WarnExceptions\' flag"); Command.Bind("WarnUses", SetWarnUses, "toggle \'WarnUses\' flag"); Command.Bind("WarnReturns", SetWarnReturns, "toggle \'WarnReturns\' flag"); Command.Bind("WarnNarrows", SetWarnNarrows, "toggle \'WarnNarrows\' flag"); Command.Bind("WarnIgnoreFor", SetWarnIgnoreFor, "toggle \'WarnIgnoreFor\' flag"); Command.Bind("WarnAll", SetWarnAll, "toggle \'WarnAll\' flag"); Command.Bind("ArgValues", ArgValues, "show current values of arguments"); Command.Bind("QueryAst", Query, "QueryAst "); Command.Bind("GarbageCollect", GC, "force a garbage collection"); Command.Bind("NotifyGC", NotifyGC, "toggle 'NotifyGC' flag"); Command.Bind("IncreaseHeap", IncreaseHeap, "increase heap (AST cache)"); Command.Bind("Target", Target, "set target for 'm3make', e.g. 'mips'"); Command.Bind("M3Make", M3Make, "execute 'm3make' for current 'target'"); Command.Bind("SHell", Shell, "pass rest of line to Unix shell"); Command.Bind("CompileInDir", CompileInDir, "add directory to 'CompileInDir' list"); Command.Bind("Dir", Dir, "prepend given directory to search path"); Command.Bind("DirC", DirC, "Dir 'n' plus 'CompileInDir 'n'"); Command.Bind("ScanDirs", ScanDirs, "scan directories"); Command.Bind("ChangeDirStatus", ChangeDirStatus, "change directory status to 'R' or 'W'"); Command.Bind("Compile", Compile, "compile changed units"); Command.Bind("FreezeM3Path", FreezeM3Path, "freeze 'm3path'"); Command.Bind("ShowLocationInterface", ShowLocationInterface, "show location information on given interface"); Command.Bind("ShowLocationModule", ShowLocationModule, "show location information on given module"); Command.Bind("CWTypesToChange", SetCharTypesToChange, "toggle \'CWTypesToChange\' flag"); Command.Bind("CWStatsToConsider", SetCharStatsToConsider, "toggle \'CWStatsToConsider\' flag"); Command.Bind("CWExprsToReplace", SetCharExprsToReplace, "toggle \'CWExprsToReplace\' flag"); Command.Bind("CWExprsToConsider", SetCharExprsToConsider, "toggle \'CWExprsToConsider\' flag"); Command.Bind("CWExprsDistantlyRelated", SetCharExprsDistantlyRelated, "toggle \'CWExprsDistantlyRelated\' flag"); Command.Bind("CWConsiderAll", SetCharConsiderAll, "toggle \'CWConsiderAll\' flag"); END M3DepInteract.