m3tk/src/chartool/M3CharTool.m3


 Copyright (C) 1992, Digital Equipment Corporation 
 All rights reserved. 
 See the file COPYRIGHT for a full description. 

MODULE M3CharTool;

IMPORT AST, ASTWalk;
IMPORT M3Args, M3Context, M3CUnit, M3Conventions;
IMPORT M3AST_AS;
IMPORT M3AST_AS_F, M3AST_FE_F;
IMPORT M3CGo;
IMPORT M3Error;
IMPORT M3CharTypesToChange, M3CharStatsToConsider,
       M3CharExprsToReplace, M3CharExprsToConsider;

CONST Version = "Sep-28-92";

VAR tool_g: M3Args.T;

PROCEDURE Get (): M3Args.T RAISES {} =
  BEGIN
    RETURN tool_g;
  END Get;

TYPE
  Extension =
    M3CGo.Extension OBJECT OVERRIDES extend := Extend END;

TYPE
  ASTWalkClosure =
    ASTWalk.Closure OBJECT
      typesToChangeHandle  : M3CharTypesToChange.Handle   := NIL;
      statsToConsiderHandle: M3CharStatsToConsider.Handle := NIL;
      exprsToReplaceHandle : M3CharExprsToReplace.Handle  := NIL;
    OVERRIDES
      callback := Node; END;

PROCEDURE Init () RAISES {} =
  BEGIN
    M3CGo.AddExtension(NEW(Extension));
  END Init;

PROCEDURE Extend (<*UNUSED*> e      : M3CGo.Extension;
                  <*UNUSED*> context: M3Context.T;
                             cu     : M3AST_AS.Compilation_Unit;
                  <*UNUSED*> VAR (*inout*) phases: M3CUnit.Status; )
  RAISES {} =
  VAR
    exprsToConsider_Arg := M3Args.GetFlag(tool_g, ExprsToConsider_Arg);
    typesToChange_Arg := M3Args.GetFlag(tool_g, TypesToChange_Arg);
    statsToConsider_Arg := M3Args.GetFlag(tool_g, StatsToConsider_Arg);
    exprsToReplace_Arg := M3Args.GetFlag(tool_g, ExprsToReplace_Arg);
    exprsDistantlyRelated_Arg := M3Args.GetFlag(
                       tool_g, ExprsDistantlyRelated_Arg);
    all    := M3Args.GetFlag(tool_g, ConsiderAll_Arg);
    do_etc := all OR exprsToConsider_Arg;
    do_edr := all OR exprsDistantlyRelated_Arg;
    any := all OR exprsToConsider_Arg OR typesToChange_Arg OR
               statsToConsider_Arg OR exprsToReplace_Arg OR
               exprsDistantlyRelated_Arg;
  BEGIN
    IF M3Conventions.PrimarySource IN cu.fe_status
         AND M3CUnit.State.SemChecked IN cu.fe_status THEN
      IF any THEN
        IF cu.fe_status * M3CUnit.Errors = M3CUnit.Status{} THEN
          TYPECASE cu.as_root OF
           | NULL =>
             (* no tree to analyse *)

           | M3AST_AS.UNIT_GEN_DEF =>
             (* ignore generic definitions *)

          ELSE
            WITH cl = NEW(ASTWalkClosure) DO
              IF all OR typesToChange_Arg THEN
                cl.typesToChangeHandle :=
                  M3CharTypesToChange.NewHandle(); END;
              IF all OR statsToConsider_Arg THEN
                cl.statsToConsiderHandle :=
                  M3CharStatsToConsider.NewHandle(); END;
              IF all OR exprsToReplace_Arg THEN
                cl.exprsToReplaceHandle :=
                  M3CharExprsToReplace.NewHandle(); END;

              IF any THEN
                <*FATAL ANY*> BEGIN
                  ASTWalk.ModeVisitNodes(
                      cu, cl, ASTWalk.OnEntryAndExit);
                END;
              END;
            END (* with *);
            IF do_etc OR do_edr THEN
              <*FATAL ANY*> BEGIN
                ASTWalk.ModeVisitNodes(
                    cu, M3CharExprsToConsider.NewHandle(do_etc, do_edr),
                    ASTWalk.OnEntryAndExit);
              END;
            END (*if*);
          END; (* typecase *)
        ELSE
          M3Error.Warn(cu.as_root,
                       "'m3chartool' analysis suppressed due to errors");
        END;
      END;
    END;
  END Extend;

PROCEDURE Node (cl: ASTWalkClosure;
                n : AST.NODE;
                vm: ASTWalk.VisitMode) =
  BEGIN
    IF cl.typesToChangeHandle # NIL THEN
      M3CharTypesToChange.Node(cl.typesToChangeHandle, n, vm) END;
    IF cl.statsToConsiderHandle # NIL THEN
      M3CharStatsToConsider.Node(cl.statsToConsiderHandle, n, vm) END;
    IF cl.exprsToReplaceHandle # NIL THEN
      M3CharExprsToReplace.Node(cl.exprsToReplaceHandle, n, vm) END;
  END Node;

BEGIN
  tool_g :=
    M3Args.New(
      "m3char", "analyse code for CHAR size dependencies", Version);
  M3Args.RegisterFlag(
    tool_g, TypesToChange_Arg, "find types to change");
  M3Args.RegisterFlag(
    tool_g, StatsToConsider_Arg, "statements to think about");
  M3Args.RegisterFlag(
    tool_g, ExprsToReplace_Arg,
    "expressions requiring systematic replacement");
  M3Args.RegisterFlag(
    tool_g, ExprsToConsider_Arg, "expressions needing thought");
  M3Args.RegisterFlag(
    tool_g, ExprsDistantlyRelated_Arg,
    "expressions distantly related to CHAR");
  M3Args.RegisterFlag(
    tool_g, ConsiderAll_Arg, "consider all the above situations");
END M3CharTool.