stubgen/src/StubGenTool.m3


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

MODULE StubGenTool;

IMPORT ASTWalk;
IMPORT M3Context, M3CId, M3CUnit, M3Conventions, M3CConcTypeSpec, M3AST_AS;
IMPORT M3CGo;
IMPORT M3Args, M3CFETool;
IMPORT M3AST_AS_F, M3AST_SM_F, M3AST_FE_F;
IMPORT AstToType, StubUtils, Protocol, Type;
IMPORT Atom, Stdio, Text;

CONST Version = "1-Oct-96";

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

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

PROCEDURE GetArgs(tool: M3Args.T)=
  VAR strings, intfs, newarg: REF ARRAY OF TEXT;
      n, m, nextArg := 0;
      found: BOOLEAN;
      perfMon: BOOLEAN;
  BEGIN
    IF M3Args.GetFlag(tool, StubGen_V1_Arg) THEN Protocol.version := 1; END;
    IF M3Args.GetFlag(tool, StubGen_V2_Arg) THEN Protocol.version := 2; END;
    perfMon := M3Args.GetFlag(tool, StubGenPerf_Arg);
    StubUtils.SetPerfMon(perfMon);
    strings := M3Args.GetStringList(tool, StubGenTypes_Arg);
    stubTypes := GetQidList(strings);
    strings := M3Args.GetStringList(tool, StubGenExists_Arg);
    useTypes := GetQidList(strings);
    IF stubTypes # NIL THEN
      intfs := NEW(REF ARRAY OF TEXT, NUMBER(stubTypes^));
      FOR i := 0 TO LAST(stubTypes^) DO
        IF stubTypes[i] # NIL AND stubTypes[i].intf # NIL THEN
          intfs[n] := Atom.ToText(stubTypes[i].intf);
          found := FALSE;
          FOR j := 0 TO n-1 DO
            IF Text.Equal(intfs[j], intfs[n]) THEN found := TRUE; END;
          END;
          IF NOT found THEN INC(n) END;
        END;
      END;
      m := n;
      strings := M3Args.GetStringList(tool, M3CFETool.Interfaces_Arg);
      IF strings = NIL THEN
        newarg := NEW(REF ARRAY OF TEXT, n);
        nextArg := 0;
      ELSE
        FOR i := 0 TO n-1 DO
          found := FALSE;
          FOR j := 0 TO LAST(strings^) DO
            IF Text.Equal(intfs[i], strings[j]) THEN
              found := TRUE;
            END;
          END;
          IF found THEN DEC(m); intfs[i] := NIL END;
        END;
        IF m > 0 THEN
          newarg := NEW(REF ARRAY OF TEXT, m+NUMBER(strings^));
          FOR i := 0 TO LAST(strings^) DO
            newarg[i] := strings[i];
          END;
          nextArg := LAST(strings^)+1;
        END;
      END;
      IF m > 0 THEN
        FOR i := 0 TO n-1 DO
          IF intfs[i] # NIL THEN
            newarg[nextArg] := intfs[i];
            INC(nextArg);
          END;
        END;
        M3Args.SetStringList(tool, M3CFETool.Interfaces_Arg, newarg);
      END;
    END;
    strings := M3Args.GetStringList(tool, M3CFETool.Interfaces_Arg);
  END GetArgs;

PROCEDURE GetQidList(strings: REF ARRAY OF TEXT): REF ARRAY OF Type.Qid =
  VAR qids: REF ARRAY OF Type.Qid;
      dotpos: INTEGER;
  BEGIN
    IF strings = NIL THEN RETURN NIL END;
    qids := NEW(REF ARRAY OF Type.Qid, NUMBER(strings^));
    FOR i := 0 TO LAST(strings^) DO
      dotpos := Text.FindChar(strings[i], '.');
      IF dotpos < 1 THEN
        StubUtils.Message(
            "Invalid argument \"" & strings[i] &"\".  " &
            "Should be qualified id.");
      ELSE
        qids[i] := NEW(Type.Qid,
                       intf := Atom.FromText(Text.Sub(strings[i], 0, dotpos)),
                       item := Atom.FromText(Text.Sub(strings[i], dotpos+1,
                                          LAST(INTEGER))));
      END
    END;
    RETURN qids;
  END GetQidList;

PROCEDURE StubGen(<*UNUSED*> e      : Extension;
                             context: M3Context.T;
                             cu     : M3AST_AS.Compilation_Unit;
                  <*UNUSED*> VAR (*inout*) phases: M3CUnit.Status)=
  BEGIN
    IF M3Args.Find(tool_g) THEN
      IF M3Args.GetFlag(tool_g, StubGen_Arg) THEN
        IF M3Conventions.PrimarySource IN cu.fe_status AND
           (M3CUnit.Errors * cu.fe_status = M3CUnit.Status{}) THEN
          Set(context, cu);
        END;
      END;
    END;
  END StubGen;

PROCEDURE Set(context: M3Context.T; cu: M3AST_AS.Compilation_Unit)=
  VAR intfname := M3CId.ToText(cu.as_root.as_id.lx_symrep);
      handle: AstToType.Handle;
  BEGIN
    StubUtils.Message("Processing interface " & intfname);
    handle := AstToType.NewHandle(Stdio.stdout, intfname, context);
    IF handle=NIL THEN RETURN END; (* No NetObj.T in context *)
    (* some cases we dont want to handle, plus making sure we
       deal with generic instantiations. *)
    TYPECASE cu.as_root OF
    | NULL => RETURN
    | M3AST_AS.UNIT_GEN_DEF =>
        (* parsing is ok, but no semantic analysis *)
    | M3AST_AS.UNIT_GEN_INS(ui) =>
        WITH cu_ins = ui.sm_ins_comp_unit DO
          IF cu_ins # NIL THEN
            Set(context, cu_ins);
          END;
        END;
        RETURN
    | M3AST_AS.UNIT_NORMAL =>
        IF cu = M3Context.Standard() THEN RETURN END;
    ELSE StubUtils.Die("StubGenTool.Set: unknown AST root type");
    END;

    (* No reason to look at MODULEs *)
    TYPECASE cu.as_root OF
    | M3AST_AS.Module, M3AST_AS.Module_gen_ins, M3AST_AS.Module_gen_def =>
        RETURN
    ELSE (* continue *)
    END;
    M3CConcTypeSpec.SetCurrentReveal(cu, ASTWalk.VisitMode.Entry);
    ASTWalk.VisitNodes(cu, handle);   <* NOWARN *>
    M3CConcTypeSpec.SetCurrentReveal(cu, ASTWalk.VisitMode.Exit);
  END Set;

BEGIN
  tool_g := M3Args.New("stubs",
               "Generate stubs for network objects", Version,
               master := TRUE);
  M3Args.RegisterFlag(tool_g, StubGen_Arg, "stub generate");
  M3Args.RegisterFlag(tool_g, StubGen_V1_Arg, "protocol version 1");
  M3Args.RegisterFlag(tool_g, StubGen_V2_Arg, "protocol version 2");
  M3Args.RegisterStringList(tool_g, StubGenTypes_Arg, "list of types");
  M3Args.RegisterStringList(tool_g, StubGenExists_Arg,
                            "list of existing types");
  M3Args.RegisterFlag(tool_g, StubGenPerf_Arg, "performance monitoring");
END StubGenTool.

interface StubGenTool is in:


interface AstToType is in:


interface Protocol is in:


interface Type is in: