IMPLEMENTATION MODULE CGMethods;

FROM ArrayList IMPORT ArrayList;
FROM YaflCfg IMPORT CurrentSpot, YaflCfg;
FROM YaflGC IMPORT YaflGC;
FROM Streams IMPORT StdOut;
FROM YaflDictionary IMPORT MethodReference;
FROM Conversions IMPORT IntConversions;
IMPORT SYSTEM;
FROM YaflAsGC IMPORT AssertionGC;
FROM YaflPredefined IMPORT PredefCreateMethod, PredefKillMethod, PredefCloneMethod;

------------------------------
-- C Code Generators
------------------------------
FROM CGCode          IMPORT CGcContext;
FROM CGDeclarations  IMPORT CSingleDataItemCodeGenerator;

FROM CGClass         IMPORT CClassDecl;
FROM CGPreconditions IMPORT CPreCondCodeGenerator,
                            CPostCondCodeGenerator;

------------------------------
-- Generic Code Generators
------------------------------
FROM YaflGMethods IMPORT MethDeclCodeGenerator;
FROM YaflGDeclarations IMPORT SingleDataItemCodeGenerator;
FROM YaflGPreconditions IMPORT PreCondCodeGenerator,
                              PostCondCodeGenerator;

------------------------------
-- Nom Terminals
------------------------------
FROM YaflMetImplementation IMPORT MethodImplementation;
FROM YaflType IMPORT Type;
FROM YaflClasses IMPORT ClassDeclaration, VirtualClassDecl;
FROM YaflModules IMPORT CompilationUnit;
FROM YaflPredefined IMPORT PredefItems;
FROM YaflCreator IMPORT Creators;
FROM YaflMethods IMPORT MethodDeclaration;


 ------------------------------ 

  CLASS CPredefMethCodeGenerator;
    INHERITS PredefMethCodeGenerator(CGcContext);
    
    METHOD GenerateAnchorDefinition;
      BEGIN 
      Ctx.MethDeclGenerateAnchorDefinition(THIS);
      END GenerateAnchorDefinition;

    METHOD GenerateAnchorBody;
      BEGIN 
      Ctx.MethDeclGenerateAnchorBody(THIS);
      END GenerateAnchorBody;

    METHOD GenerateMethodPointer;
      BEGIN 
      Ctx.MethDeclGenerateMethodPointer(THIS);
      END GenerateMethodPointer;

    METHOD GenerateAnchorId;
      BEGIN 
      Ctx.MethDeclGenerateAnchorId(THIS);
      END GenerateAnchorId;

    METHOD GenerateMethodRef;
      BEGIN 
      Ctx.MethDeclGenerateMethodRef(THIS);
      END GenerateMethodRef;

  END CPredefMethCodeGenerator;
  
------------------------------------------------------------   

  CLASS CMethDefCodeGenerator;
    INHERITS MethDefCodeGenerator(CGcContext);

    -- XXJC (d)
    VAR
      TheMetIGc: CMethImplCodeGenerator;

    METHOD SetImplementationGC(MetIGc: CMethImplCodeGenerator);
      BEGIN
      ASSERT TheMetIGc = VOID;
      TheMetIGc := MetIGc;
      END SetImplementationGC;

    METHOD ImplementationGC: CMethImplCodeGenerator;
      BEGIN
      RESULT := TheMetIGc;
      END ImplementationGC;
    -- END XXJC (d)

    METHOD GenerateAnchorDefinition;
      BEGIN
      Ctx.MethDeclGenerateAnchorDefinition(THIS);
      END GenerateAnchorDefinition;

    METHOD GenerateAnchorBody;
      BEGIN
      Ctx.MethDeclGenerateAnchorBody(THIS);
      END GenerateAnchorBody;

    METHOD GenerateMethodPointer;
      BEGIN
      Ctx.MethDeclGenerateMethodPointer(THIS);
      END GenerateMethodPointer;

    METHOD GenerateAnchorId;
      BEGIN
      Ctx.MethDeclGenerateAnchorId(THIS);
      END GenerateAnchorId;

    METHOD GenerateMethodRef;
      BEGIN
      Ctx.MethDeclGenerateMethodRef(THIS);
      END GenerateMethodRef;

    ----------------------------------------------- 
	-- The following code has been added by RJC for the
    -- pre and post conditions generation.
    -- It declares a METHOD_INFO structure for deferred methods.
    ----------------------------------------------- 

    METHOD Output: YaflGC;
      BEGIN
      ASSERT Ctx.Output <> VOID;
      RESULT := Ctx.Output;
      END Output;

    METHOD CPreCond(Gc: PreCondCodeGenerator): CPreCondCodeGenerator;
      BEGIN
      WHAT Gc OF 
        IN CPreCondCodeGenerator:
          RESULT := TAG;
          END;
        END;
      END CPreCond;

    METHOD CPostCond(Gc: PostCondCodeGenerator): CPostCondCodeGenerator;
      BEGIN
      WHAT Gc OF 
        IN CPostCondCodeGenerator:
          RESULT := TAG;
          END;
        END;
      END CPostCond;

    METHOD GenerateDbxExtRefVariable;
      BEGIN
      Ctx.MethDeclGenerateDbxExtRefVariable(THIS);
      END GenerateDbxExtRefVariable;

-- XXJC (d)

    -------------------------------------
    --  generate the text of the C function call that
    --  is pushing a new frame into the debugger list
    --  of calls (instances of methods);
    --  these frames are composed of a pointer to the dbx-method
    --  data structure corresponding to the YAFl method,
    --  a pointer to the context of this method and a
    --  pointer to the current object of this method;
    --  this text is generated inside and near the beginning of
    --  the code of the method but must be after the definition
    --  of the context local variable;
    --  this method has been made for the debugger so there
    --  is nothing now in the base method but we still
    --  call it,just to be sure;
    ---------------------------------------------------
      METHOD GenerateDbxMethodPrefix;
      VAR
        ModName,ClaName,MethName: ARRAY OF CHAR;
      BEGIN
      MethName := Obj.Id.Data;
      ClaName := Obj.Class.Id.Data;
      ModName := Obj.Class.Module.Id.Data;
      Output.IfDefined(Output.FullTraceModeLabel);
      Output.DbxPushCall;
      Output.LeftParent;
      Output.DbxMethodReference(ModName,ClaName,MethName);
      Output.Comma;
------------------------------------      
-- a method containing INLINE statements does not have a context
-- stucture so in this case we cannot push its address on the debugger stack      
------------------------------------      
--      IF NOT Obj.UsesInline THEN
--        Output.Ampersand; -- by reference
--        Output.Context;
--       ELSE
        Output.Null;
--        END;
      Output.Comma;
      Output.Ampersand; -- by reference
      Output.Yu("THIS");
      Output.RightParent;
      Output.SemiColon;
      Output.WriteLn;
      Output.EndIf;
      END GenerateDbxMethodPrefix;

    --------------------------------
    -- Generate the method registation for the debugger.
    -- Used for pre- and post- condition runtime errors.
    --------------------------------
    METHOD DbxEnterMethod;
      VAR
        Cl: ClassDeclaration;
        Mod: CompilationUnit;
      BEGIN
      Cl := Obj.Class;
      Mod := Cl.Module;
      IF YaflCfg.TraceModeLevel = 2 THEN
        GenerateDbxMethodPrefix;
        END;
      Output.EnterMethod;      
      Output.LeftParent;
      Ctx.CompilationUnitGenerateLiteral(Mod.Gc);
      Output.Comma;
      CClassDecl.GenerateLiteral(Cl.Gc);
      Output.Comma;
      Output.QuotedString (Obj.Id.Data, 
                           UseEsc := FALSE);
      Output.RightParent;                           
      Output.SemiColon;
      Output.WriteLn;
      END DbxEnterMethod;
-- END XXJC (d)

    REDEFINE METHOD GenerateDbxMethodCode;
      VAR
        ModName,ClaName,MethName : ARRAY OF CHAR;

      -----------------------------------
      -- Create a new method data structure into
      -- the debugging memory area, and assign
      -- the newly allocated data to a static
      -- variable (See Output4Ident below)
      -- visible from inside the current module.
      -----------------------------------
      METHOD GenerateMethodAdd;
        VAR
          TheType: Type;
          Cl: ClassDeclaration;
        BEGIN
        Output.DbxMethodReference(ModName,ClaName,MethName);
        Output.Becomes;
        Output.DbxAddMethod;
        Output.LeftParent;
        Output.RightParent;
        Output.SemiColon;
        Output.WriteLn;
        
        ------------------------------------------------------------------
        -- name field
        ------------------------------------------------------------------
        Output.DbxMethodReference(ModName,ClaName,MethName);
        Output.Arrow;
        Output.WriteString ('name');
        --Output.Name;
        Output.Becomes;
        Output.QuotedString(Obj.Id.Data,
                            UseEsc := FALSE);
        Output.SemiColon;
        Output.WriteLn;
        
        ------------------------------------------------------------------
        -- beginline field
        ------------------------------------------------------------------
        Output.DbxMethodReference(ModName,ClaName,MethName);
        Output.Arrow;
        Output.BeginLine;
        Output.Becomes;
        Output.WriteInt(Obj.LineNr, 0);
        Output.SemiColon;
        Output.WriteLn;
        ------------------------------------------------------------------
        -- endline field
        ------------------------------------------------------------------
        Output.DbxMethodReference(ModName,ClaName,MethName);
        Output.Arrow;
        Output.EndLine;
        Output.Becomes;
        Output.WriteInt(Obj.LineNr, 0);
        --Output.WriteInt(Obj.EndIdent.LineNr, 0);
        Output.SemiColon;
        Output.WriteLn;
        ------------------------------------------------------------------
        -- offset field
        ------------------------------------------------------------------
        Output.DbxMethodReference(ModName,ClaName,MethName);
        Output.Arrow;
        Output.OffsetField; -- CAUTION Offset already used for macro
        Output.Becomes;
        IF Obj.IsPredefined THEN
          IF Obj.IsCreate THEN
            Output.WriteString("sizeof(minimal_dual)-sizeof(int*)");
          ELSIF Obj.Id.Data = PredefItems.Clone.Id.Data THEN
            Output.WriteString("sizeof(minimal_dual)-2*sizeof(int*)");
          ELSIF Obj.Id.Data = PredefItems.Kill.Id.Data THEN
            Output.WriteString("sizeof(minimal_dual)-3*sizeof(int*)");
          ELSE
            Output.Zero;
            Output.Comment("predefined method");
  			END;
        ELSIF Obj.Redefine THEN
          Ctx.MethDeclGenerateDualOffsetValue(Obj.Redefined(TRUE).Gc);
        ELSIF NOT Obj.AppearsInDual THEN
          Output.Zero;
        ELSE
          Ctx.MethDeclGenerateDualOffsetValue(THIS);
          --Output.Offset;
          --Output.LeftParent;
          --Output.DualInstance(ModName, ClaName);
          --Output.Comma;
          --Output.MethodStructRef(ModName, ClaName, MethName);
          --Output.RightParent;
          END; -- IF
        Output.SemiColon;
        Output.WriteLn;

  	    TheType := Obj.Return;
        ------------------------------------------------------------------
        -- return_dual field
        ------------------------------------------------------------------
        Output.DbxMethodReference(ModName,ClaName,MethName);
        Output.Arrow;
        Output.ReturnDual;
        Output.Becomes;
        IF TheType <> VOID THEN
          Cl := TheType.SimpleType;
          Output.LeftParent;
          Output.MinimalDual;
          Output.Star;
          Output.RightParent;
          WHAT Cl OF
            IN VirtualClassDecl:
              Output.Ampersand;
              Output.VirtualDual;
              END; -- IN
           ELSE
            CClassDecl.GenerateDualRef(Cl.Gc);
            END; -- IF
         ELSE
          Output.Null;
          END; -- IF
        Output.SemiColon;
        Output.WriteLn;
        ------------------------------------------------------------------
        -- return_array_level field
        ------------------------------------------------------------------
        Output.DbxMethodReference(ModName,ClaName,MethName);
        Output.Arrow;
        Output.ReturnArrayLevel;
        Output.Becomes;
        IF TheType <> VOID THEN
          Output.WriteInt(TheType.ArrayLevel,0);
         ELSE
          Output.Zero;
          END; -- IF
        Output.SemiColon;
        Output.WriteLn;
        -- XXJC (d)
        -- Context Free Precondition.
        --Output.IfDefined(Output.FullTraceModeLabel);
        Output.IfDefined(Output.CheckPreCondLabel);
        Output.DbxMethodReference(ModName,ClaName,MethName);
        Output.Arrow;
        Output.PreContextFree;
        Output.Becomes;
        IF Obj.GetPreCondition <> VOID THEN
          Output.Ampersand;
          Output.ContextFreePreCondFName(ModName,ClaName,MethName);
        ELSE
          Output.Null;
          END;
        Output.SemiColon;
        Output.WriteLn;
        -- Context Dependent Precondition.
        Output.DbxMethodReference(ModName,ClaName,MethName);
        Output.Arrow;
        Output.PreContextDep;
        Output.Becomes;
        IF Obj.GetPreCondition <> VOID THEN
          Output.Ampersand;
          Output.ContextDepPreCondFName (ModName, ClaName, MethName);
        ELSE
          Output.Null;
          END;
        Output.SemiColon;
        Output.WriteLn;
        Output.EndIf;
        --Output.EndIf;
        -- PostCondition.
        --Output.IfDefined(Output.FullTraceModeLabel);
        Output.IfDefined(Output.CheckPostCondLabel);
        Output.DbxMethodReference(ModName,ClaName,MethName);
        Output.Arrow;
        Output.PostCondition;
        Output.Becomes;
        IF Obj.GetPostCondition <> VOID THEN
          Output.Ampersand;
          Output.PostConditionFName(ModName,ClaName,MethName);
        ELSE
          Output.Null;
          END;
        Output.SemiColon;
        Output.WriteLn;
        Output.DbxMethodReference(ModName,ClaName,MethName);
        Output.Arrow;
        Output.ComputeOld;
        Output.Becomes;
        IF Obj.GetPostCondition <> VOID THEN
          Output.Ampersand;
          Output.ComputeOldExprFName(ModName,ClaName,MethName);
        ELSE
          Output.Null;
          END;
        Output.SemiColon;
        Output.WriteLn;
        -- before having the right values for them, 
        -- we set this two fields to NULL
        --Output.DbxMethodReference(ModName,ClaName,MethName);
        --Output.Arrow;
        --Output.Entry;
        --Output.Becomes;
        --Output.Null;
        --Output.SemiColon;
        Output.WriteLn;
        Output.DbxMethodReference(ModName,ClaName,MethName);
        Output.Arrow;
        Output.Base;
        Output.Becomes;
        Output.Null;
        Output.SemiColon;
        Output.WriteLn;
        Output.EndIf;
        --Output.EndIf;
        -- END XXJC (d)
        END GenerateMethodAdd;
        
      -----------------------------------
      -- Generate the code used to insert the
      -- METHOD_INFO structure of this method in
      -- the chain of method implementation corresponding
      -- to the entry..
      -----------------------------------
      METHOD GenerateMethodChainInsert;
        BEGIN
        Output.Static;
        Output.Void;
        GenerateDbxMethodChainInsert;
        Output.IfDef;
        Output.Ansi;                        
        Output.LeftParent;
        Output.Void;
        Output.RightParent;
        Output.ElseDef;
        Output.LeftParent;
        Output.RightParent;
        Output.EndIf;
        Output.WriteLn;
        Output.Comment("MethodChainInsert");
        Output.LeftBrace;
        Output.WriteLn;

        -- Not needed anymore
        --Output.DbxMethodReference(ModName,ClaName,MethName);
        --Output.Arrow;
        --Output.Entry;
        --Output.Becomes;
        --Output.DbxMethodReference(ModName,ClaName,MethName);
        ----Output.Null;
        --Output.Comment("Deferred Method");
        --Output.SemiColon;
        --Output.WriteLn;
        
        Output.AttachRedefinedMethod;
        Output.LeftParent;
        Output.DbxMethodReference(ModName,ClaName,MethName);
        Output.RightParent;
        Output.SemiColon;
        Output.WriteLn;
        
        Output.RightBrace;
        Output.WriteLn;
        END GenerateMethodChainInsert;

      BEGIN
      ------------------------------------------------------
      -- generates method initialization function
      ------------------------------------------------------
-- ???
-- 
      ASSERT Obj.Deferred;
      CurrentSpot.PushCurrentMethod(Obj);
      MethName := Obj.Id.Data;
      ClaName := Obj.Class.Id.Data;
      ModName := Obj.Class.Module.Id.Data;
-- patched by bernard
-- useful not only for debugger now
      IF NOT Obj.Publish THEN
        Output.IfDefined(Output.FullTraceModeLabel);
        END; -- IF
      Ctx.MethDeclGenerateDbxReferenceVariable(THIS);
      -- XXJC (d)
      --Output.EndIf;
      GenerateExtAssertCode;
      --Output.IfDefined(Output.FullTraceModeLabel);
      -- END XXJC (d)
      Output.Static;
      Output.Void;
      GenerateDbxMethodInitialization;
      Output.IfDef;
      Output.Ansi;                        
      Output.LeftParent;
      Output.Void;
      Output.RightParent;
      Output.ElseDef;
      Output.LeftParent;
      Output.RightParent;
      Output.EndIf;
----------------------------------      
      Output.WriteLn;
      Output.LeftBrace;
      Output.WriteLn;

      GenerateMethodAdd;
      --GenerateMethodDeclsPassOne;
      --GenerateMethodDeclsPassTwo;
        
      Output.RightBrace;
      Output.WriteLn;
      GenerateMethodChainInsert;
-- patched by bernard
-- useful not only for debugger now
      IF NOT Obj.Publish THEN
        Output.EndIf;
        END; -- IF
      CurrentSpot.PopCurrentMethod;
      END GenerateDbxMethodCode;

    VAR
      DbxMethodNr,
      DbxMethodChainInsertNr: INTEGER;

    METHOD GenerateDbxMethodInitialization;
      BEGIN
      ASSERT Obj.Deferred;
      IF DbxMethodNr = 0 THEN
        DbxMethodNr := YaflCfg.UniqueNumber;
        END;
      Output.UniqueItem (DbxMethodNr);
      END GenerateDbxMethodInitialization;

    METHOD GenerateDbxMethodChainInsert;
      BEGIN
      ASSERT Obj.Deferred;
      IF DbxMethodChainInsertNr = 0 THEN
        DbxMethodChainInsertNr := YaflCfg.UniqueNumber;
        END;
      Output.UniqueItem (DbxMethodChainInsertNr);
      END GenerateDbxMethodChainInsert;
      
    METHOD GenerateExtAssertCode;
  -- XXXXXXXX   to be check for deferred method
      BEGIN
      ASSERT Obj.Deferred;
      -- generate code for the pre and post conditions.
      IF YaflCfg.VerboseLevel > 3 THEN
        StdOut.WriteLine("GenerateExtAssertCode");
        END;
	  IF Obj.GetPreCondition <> VOID THEN
	    CPreCond(Obj.GetPreCondition.Gc).GenerateContextFreeFunc(Obj);
	    CPreCond(Obj.GetPreCondition.Gc).GenerateContextDependentFunc(Obj);
	    END;
	  IF Obj.GetPostCondition <> VOID THEN
	    CPostCond(Obj.GetPostCondition.Gc).GenerateFunction(Obj);
	    CPostCond(Obj.GetPostCondition.Gc).GenerateOldExprInitFunc(Obj);
	    END; 
      END GenerateExtAssertCode;

    REDEFINE METHOD MustPushParamStackLevel: BOOLEAN;
      BEGIN
      RESULT := ((Obj.Formals <> VOID) AND (Obj.Formals.Size > 0)) 
                OR (Obj.Return <> VOID);
      END MustPushParamStackLevel;  
      
  END CMethDefCodeGenerator;
   
------------------------------------------------------------   

  CLASS CMethImplCodeGenerator;
    INHERITS MethImplCodeGenerator(CGcContext);
     
    METHOD Output: YaflGC;
      BEGIN
      ASSERT Ctx.Output <> VOID;
      RESULT := Ctx.Output;
      END Output;

    METHOD CPreCond(Gc: PreCondCodeGenerator): CPreCondCodeGenerator;
      BEGIN
      WHAT Gc OF 
        IN CPreCondCodeGenerator:
          RESULT := TAG;
          END;
        END;
      END CPreCond;

    METHOD CPostCond(Gc: PostCondCodeGenerator): CPostCondCodeGenerator;
      BEGIN
      WHAT Gc OF 
        IN CPostCondCodeGenerator:
          RESULT := TAG;
          END;
        END;
      END CPostCond;

    METHOD CSingleDataItem(Gc: SingleDataItemCodeGenerator): CSingleDataItemCodeGenerator;
      BEGIN
      WHAT Gc OF
        IN CSingleDataItemCodeGenerator:
          RESULT := TAG;
          END; 
        END; -- what
      END CSingleDataItem;

    METHOD CMethImpl(Gc: MethImplCodeGenerator): CMethImplCodeGenerator;
      BEGIN
      WHAT Gc OF
        IN CMethImplCodeGenerator:
          RESULT := TAG;
          END;
        END; -- what
      END CMethImpl;

    METHOD OutputOnceItems;
      BEGIN
      FOR m IN Obj.Methods DO
        WHAT m.Gc OF
          IN CMethImplCodeGenerator:
            TAG.OutputOnceItems;
            END;
          END; -- what
        END;
      FOR l IN Obj.Locals | l.Once DO
        CSingleDataItem(l.Gc).GenerateDeclaration(Zap := TRUE);
        END;
      IF Obj.UseStruct THEN
        GenerateStructDecl;
        END;
      END OutputOnceItems;

    METHOD GeneratePrefix;
      BEGIN
      END GeneratePrefix;

    METHOD GeneratePostfix;
      BEGIN
      END GeneratePostfix;

    METHOD GenerateLocals;
      BEGIN
      Output.WriteLn;
      FOR l IN Obj.Locals | NOT l.Once DO
        CSingleDataItem(l.Gc).GenerateDeclaration(Zap := TRUE);
        Output.WriteLn;
        END;
      END GenerateLocals;

    METHOD GenerateResult;
      BEGIN
      Obj.Return.Gc.GenerateCode;
      Output.Result;
      Output.Becomes;
      Output.LeftParent;
      Obj.Return.Gc.GenerateCode;
      Output.RightParent;
      Output.Zero;
      Output.SemiColon;
      Output.WriteLn;
      END GenerateResult;

    METHOD GenerateStructDecl;
      VAR
        Empty: BOOLEAN;
      BEGIN
      Empty := TRUE;
      Output.TypeDef;
      Output.Struct;
      Output.LeftBrace;
      Output.WriteLn;
      FOR f IN Obj.Formals DO
        CSingleDataItem(f.Gc).GenerateDeclaration(Zap := FALSE);
        END;
      Empty := Obj.Formals.Size = 0;
      FOR l IN Obj.Locals | NOT l.Once DO
        CSingleDataItem(l.Gc).GenerateDeclaration(Zap := FALSE);
        Empty := FALSE; 
        END;
      IF Obj.Return <> VOID THEN
        Empty := FALSE;
        Obj.Return.Gc.GenerateCode;
        Output.Result;
        Output.SemiColon;
        Output.WriteLn;
        END;
      Output.WriteLn;
      IF Empty THEN
        Output.ObjPtr;
        Output.UniqueItem (YaflCfg.UniqueNumber);
        Output.SemiColon;
        END;
      Output.RightBrace;
      Output.UniqueItem (Obj.StructNr);
      Output.SemiColon;
      Output.WriteLn;
---------------------------------------------------------------------------
-- CAUTION: the publish mechanism uses the same structures as the debugger
---------------------------------------------------------------------------
-- CAUTION: is is the DEFINITION that is tagged by the pragma IF one is present
---------------------------------------------------------------------------
      IF ((YaflCfg.TraceModeLevel = 2) AND NOT Obj.Deferred)
          OR Obj.Publish THEN
        GenerateDbxMethodDecl;
        END;
      END GenerateStructDecl;
      
    ----------------------------------------------------
    -- generates a prototype for the initialization function
    -- of the debugger method data structure;
    -- this is necessary as we can't be sure in wich order they
    -- will be generated and a method must be able to initialize
    -- its locals methods;
    -- we use this function as it generates code near the
    -- beginning of the file;
    -- it is ok to do so as we always force the use of a context
    -- structure when debugging so this method will always be called;
    ----------------------------------------------------
    METHOD GenerateDbxMethodDecl;
      BEGIN
      ASSERT NOT Obj.Deferred;
      Output.Static;
      Output.Void;
      GenerateDbxMethodInitialization;
      Output.IfDef;
      Output.Ansi;                        
      Output.LeftParent;
      Output.Void;
      Output.RightParent;
      Output.ElseDef;
      Output.LeftParent;
      Output.RightParent;
      Output.EndIf;
      Output.SemiColon;
      Output.WriteLn;
      END GenerateDbxMethodDecl;
      
    VAR
      DbxMethodNr,
      DbxMethodChainInsertNr: INTEGER;

    METHOD GenerateDbxMethodChainInsert;
      BEGIN
      IF DbxMethodChainInsertNr = 0 THEN
        DbxMethodChainInsertNr := YaflCfg.UniqueNumber;
        END;
      Output.UniqueItem (DbxMethodChainInsertNr);
      END GenerateDbxMethodChainInsert;
      
    METHOD GenerateDbxMethodInitialization;
      BEGIN
	  -- removed by rjc for pre- and post-conditions.
      --ASSERT NOT Obj.Deferred;
      IF DbxMethodNr = 0 THEN
        DbxMethodNr := YaflCfg.UniqueNumber;
        END;
      Output.UniqueItem (DbxMethodNr);
      END GenerateDbxMethodInitialization;

      
    METHOD GenerateLocalAnchors;
      BEGIN
      FOR m IN Obj.Methods DO
        CMethImpl(m.Gc).GenerateAnchorDefinition;
        CMethImpl(m.Gc).GenerateLocalAnchors;
        END;
      END GenerateLocalAnchors; 
      
    VAR
      Registered: ArrayList(SingleDataItem);

    METHOD Register (DataItem: SingleDataItem);
      BEGIN
      IF Registered = VOID THEN
        Registered.CREATE;
        END;
      Registered.Append (DataItem);  
      END Register;
      
    METHOD RegisterLocals;
      BEGIN
      FOR l IN Obj.Locals | l.NeedsOwnMarking DO
        Register (l);
        END;
      END RegisterLocals;

    METHOD InlinePreAndPost: BOOLEAN;
      BEGIN
      RESULT := NOT (Obj.NeedsSeparateAnchor OR Obj.Redefine)
                OR Obj.IsPredefined;
      END InlinePreAndPost;
      
    REDEFINE METHOD MustPushParamStackLevel: BOOLEAN;
      BEGIN
      RESULT := ((Obj.Formals <> VOID) AND (Obj.Formals.Size > 0)) 
                OR (Obj.Return <> VOID);
      END MustPushParamStackLevel;  

    REDEFINE METHOD GenerateCode;
      VAR
        Cl: ClassDeclaration;
        Mod: CompilationUnit;
        VBpVar, BpVar: INTEGER;
        UsesValueStack,
        RequiresRegistration: BOOLEAN;
      BEGIN
--      IF YaflCfg.PleaseOptimizeRemoveMethods THEN
--        IF Obj.IsLocal AND NOT Obj.Useful THEN
--          StdOut.WriteLine 
--             ("Warning : Generating code for unused local method: " 
--              + Obj.Id.Data + "[" + Obj.Class.Id.Data + "]");
--          END;
--        END;
      CurrentSpot.PushCurrentMethod (Obj);
      -- XXJC	(d)
      IF (Obj.Definition <> VOID) AND (Obj.Definition.Gc <> VOID) THEN
        WHAT Obj.Definition.Gc OF
          IN CMethDefCodeGenerator:
            TAG.SetImplementationGC(THIS);
            END;
          END;
        END;
      -- END XXJC	(d)
      IF YaflCfg.VerboseLevel > 1 THEN
        StdOut.WriteLine ("Generating code " + Obj.Class.Id.Data + "." + Obj.Id.Data);
        END;
---------------------------------------------------------------------------
-- CAUTION: the publish mechanism uses the same structures as the debugger
---------------------------------------------------------------------------
-- CAUTION: is is the DEFINITION that is tagged by the pragma IF one is present
---------------------------------------------------------------------------
      IF (YaflCfg.TraceModeLevel = 2) OR Obj.Publish THEN
        GenerateDbxMethodCode;
        END;
      ------------------------------------
      -- First, generate forward anchors for
      -- local methods.
      ------------------------------------
      IF NOT Obj.IsLocal THEN
        GenerateLocalAnchors;
        END;
      ------------------------------------
      -- Then, generate code for local methods
      ------------------------------------
      FOR p IN Obj.Methods | 
          NOT YaflCfg.PleaseOptimizeRemoveMethods OR p.Useful DO
        p.Gc.GenerateCode;
        END;
      -------------------------------------------
      -- Set the current method reference to this.
      -------------------------------------------
      Output.Comment (Obj.Id.Data);
      -------------------------------------------
      -- Check if this method must be accessed through
      -- a callback function
      -------------------------------------------
      IF Obj.CallBackName <> VOID THEN
        Ctx.MethDeclGenerateCallBack(THIS, Obj.CallBackName, 
                          WithBody := TRUE); 
        END;
      Cl := Obj.Class;
      Mod := Cl.Module;
      ------------------------------------------
      -- If the current method requires a
      -- separate anchor,
      -- generate a body function. Otherwise,
      -- the generated function serves as both
      -- anchor and body function.
      ------------------------------------------
      IF Obj.MergeAnchor THEN
        IF Obj.UseStaticAnchor THEN
          Output.Static;
          END;
        Ctx.MethDeclGenerateReturnType(THIS);
        CMethDecl.GenerateAnchorId(THIS);
       ELSE
        IF Obj.UseStaticBodyFunction THEN
          Output.Static;
          END;
        Ctx.MethDeclGenerateReturnType(THIS);
        GenerateMethodRef;
        END;
      ---------------------------------------
      -- Generate the formals, by using the
      -- corresponding macro to ensure it will
      -- work with both ANSI and K&R compilers.
      ---------------------------------------
      Ctx.MethDeclGenerateNativeFormals(THIS, WithThis := TRUE);
      Output.LeftBrace;
      IF Obj.UseStruct THEN
        Output.UniqueItem (Obj.StructNr);
        Output.Context;
        Output.SemiColon;
        Output.WriteLn;
       ELSE
        GenerateLocals;
        END;
      RegisterLocals;
      IF Obj.Return <> VOID THEN
        IF NOT Obj.UseStruct THEN
          GenerateResult;
          ---------------------------------------
          -- If UseStruct returns TRUE, the local
          -- variable RESULT is defined in the
          -- context structure.
          ---------------------------------------
          END;
        IF Obj.LocalResult.NeedsOwnMarking THEN
          Register (Obj.LocalResult);
          END;
        END;
      IF NOT Obj.IsLocal AND ((NOT Obj.Class.Once) OR Obj.Redefine) THEN
        -- Register (This);
        END;
      UsesValueStack := Obj.UsesValueStack;
      IF YaflCfg.PleaseGlobalOptimize THEN
        RequiresRegistration := (Registered <> VOID) AND
                      (Obj.Reference.AllocatingState = MethodReference.Allocates);
       ELSE            
        RequiresRegistration := (Obj.CallsOtherMethods OR UsesValueStack) AND
                                (Registered <> VOID);
        END;
      -------------------------
      -- If at least one item needs
      -- to be registered, a unique variable (BpVar) keeps
      -- the previous value of the d_stack pointer.
      -------------------------
      IF RequiresRegistration THEN
        BpVar := YaflCfg.UniqueNumber;
        Output.ObjPtr;
        Output.Star;
        Output.Star;
        Output.UniqueItem (BpVar);
        Output.SemiColon;
        Output.WriteLn;
        END;
      --------------------------------
      -- Generate a Casted THIS if the method we are
      -- trying to compile includes at least a single
      -- INLINE statement.
      --------------------------------
      IF Obj.UsesInline THEN
        Output.Class (Mod.Id.Data, Cl.Id.Data);
        Output.Star;
        Output.CastedThis;
        Output.Becomes;
        Output.LeftParent;
        Output.Class (Mod.Id.Data, Cl.Id.Data);
        Output.Star;
        Output.RightParent;
        Output.This;
        Output.SemiColon;
        Output.WriteLn;
        END;
      ------------------------------------
      -- The VBp Variable keeps the state of the
      -- value stack pointer, to be restored
      -- on method exit.
      ------------------------------------      
      IF UsesValueStack THEN
        VBpVar := YaflCfg.UniqueNumber;
        Output.ObjPtr;
        Output.Star;
        Output.UniqueItem (VBpVar);
        Output.SemiColon;
        Output.WriteLn; 
        Output.SaveVStack (VBpVar);
        END;           
      IF RequiresRegistration THEN
        ASSERT BpVar <> 0;
        Output.SaveDStack (BpVar);
        END;
      ------------------------------------
      -- Initialize the local & formal
      -- data structure if required.
      ------------------------------------
      IF Obj.UseStruct THEN
        Output.ZeroMem;
        Output.LeftParent;
        Output.Context;
        Output.RightParent;
        Output.SemiColon;
        Output.WriteLn;
        --------------------------------------------
        -- Assign formals into the context structure
        --------------------------------------------
        FOR f IN Obj.Formals DO
          Output.Context;
          Output.Dot;
          f.Gc.GenerateCode;
          Output.Becomes;
          f.Gc.GenerateCode;
          Output.SemiColon;
          Output.WriteLn;
          END;
        END;
      IF RequiresRegistration THEN
        Output.CheckDualOverflow;
        Output.LeftParent;
        Output.WriteInt (Registered.Size, 0);
        Output.Comma; 
        WHAT Obj.Class.Module OF
          IN CompilationUnit:
             Ctx.CompilationUnitGenerateLiteral(TAG.Gc);
             END;
          END;   
        Output.Comma;
        CClassDecl.GenerateLiteral(Obj.Class.Gc);
        Output.Comma;
        Output.QuotedString (Obj.Id.Data, FALSE);
        Output.RightParent;
        Output.SemiColon;
        Output.WriteLn;
        FOR l IN Registered DO
          Output.Reg;
          Output.LeftParent;
          Output.Ampersand;
          GenerateLocal(l);
          Output.RightParent;
          Output.SemiColon;
          Output.WriteLn;
          END;
        END;
      IF (YaflCfg.TraceModeLevel = 2) THEN
        GenerateDbxMethodPrefix;
        END;
      GeneratePrefix;
      Output.WriteLn;
      IF Obj.MergeAnchor AND NOT Obj.Class.Once AND NOT Obj.IsLocal THEN
        Output.IfDefined (YaflGC.CheckVoidObjectLabel);
        Ctx.MethDeclGenerateCheckVoidObj(THIS);
        Output.EndIf;
        END;
      Output.EnterMethod;      
      Output.LeftParent;
      Ctx.CompilationUnitGenerateLiteral(Mod.Gc);
      Output.Comma;
      CClassDecl.GenerateLiteral(Cl.Gc);
      Output.Comma;
      Output.QuotedString (Obj.Id.Data, 
                           UseEsc := FALSE);
      Output.RightParent;                           
      Output.SemiColon;
      Output.WriteLn;
      --XXJC (d)
      -- Handle the pre and post conditions.
      --IF NOT (Obj.NeedsSeparateAnchor OR Obj.Redefine) THEN
      IF InlinePreAndPost THEN
        --Output.IfDefined(Output.FullTraceModeLabel);
        Output.Comment("Eval PreCond: Push Params (in func)");
        IF (Obj.Formals <> VOID) AND (Obj.Formals.Size > 0) THEN
          Output.IfDefined(Output.CheckPreCondLabel);
          Ctx.MethAssertPushLevel;
          Ctx.MethAssertPushFormals(THIS, FALSE, FALSE);
          Output.EndIf;
        ELSE
          Output.Comment("Eval PreCond: NO Params");
          END;
        Output.IfDefined(Output.CheckPostCondLabel);
        --Ctx.MethAssertPushOldLevel;
        AssertionGC.CallToComputeOldExpressions(Output, Obj);
        Output.EndIf;
        Output.IfDefined(Output.CheckPreCondLabel);
        Output.Comment("Eval PreCond: call to evaluate");
        AssertionGC.CallToCheckPreConditions(Output, Obj);
        IF (Obj.Formals <> VOID) AND (Obj.Formals.Size > 0) THEN
          Ctx.MethAssertPopLevel;
          END;
        Output.EndIf;
        --Output.EndIf;
     -- ELSE
     --   StdOut.WriteLine("NOT Generate Pre in method: " + Obj.Id.Data);
        END;
      --END XXJC (d)
      -----------------------------
      -- Generate the actual code to be
      -- executed (It was abOut time)
      -----------------------------
      IF Obj.StmtList <> VOID THEN
        Obj.StmtList.Gc.GenerateCode;
        END;
      Output.ExitMethod;
      IF YaflCfg.TraceModeLevel = 2 THEN
        GenerateDbxMethodPostfix;
        END;
      GeneratePostfix;
      ------------------------------
      -- Restore the d_stack pointer if
      -- required
      ------------------------------
      IF RequiresRegistration THEN
        ASSERT BpVar <> 0;
        Output.RestoreDStack (BpVar);
        END;
      ------------------------------
      -- Restore the v_stack pointer
      ------------------------------
      IF UsesValueStack THEN
        Output.RestoreVStack (VBpVar);
        END;
      IF (Obj.Return <> VOID) AND (Obj.Return.UseObjPtr) THEN
        -------------------------------
        -- Keep track of the RESULT local, in order
        -- to make sure it won't be discarded
        -- by the garbage collector.
        -------------------------------
        Output.VReg;
        Output.LeftParent;
        GenerateLocal(Obj.LocalResult);
        Output.RightParent;
        Output.SemiColon;
        END;    
      -- XXJC (d)
--      IF NOT (Obj.NeedsSeparateAnchor OR Obj.Redefine) THEN
      IF InlinePreAndPost THEN
        --Output.IfDefined(Output.FullTraceModeLabel);
        Output.IfDefined(Output.CheckPostCondLabel);
        IF MustPushParamStackLevel THEN
          Output.Comment("Eval PostCond: Push Params");
          Ctx.MethAssertPushLevel;
          Ctx.MethAssertPushFormals(THIS, TRUE, FALSE);
        ELSE
          Output.Comment("Eval PostCond: NO Params");
          END;
        Output.Comment("Eval PostCond: call to evaluate");
        AssertionGC.CallToCheckPostConditions(Output, Obj);
        IF MustPushParamStackLevel THEN
          Ctx.MethAssertPopLevel;
          END;
        --Ctx.MethAssertPopOldLevel;
        Output.EndIf;
        --Output.EndIf;
        END;
      -- END XXJC (d)
      IF Obj.Return <> VOID THEN
        Output.WriteLn;
        Output.Return;
        GenerateLocal(Obj.LocalResult);
        Output.SemiColon;
        Output.WriteLn;
        END;
      Output.RightBrace;
      Output.WriteLn;
      CurrentSpot.PopCurrentMethod;
      END GenerateCode;    
      
-- XXJC (d)
    METHOD GenerateExtAssertCode;
      BEGIN
      -- generate code for the pre and post conditions.
      IF YaflCfg.VerboseLevel > 3 THEN
        StdOut.WriteLine("GenerateExtAssertCode");
        END;
      --IF YaflCfg.PleaseGeneratePreCondition THEN
        IF Obj.GetPreCondition <> VOID THEN
          CPreCond(Obj.GetPreCondition.Gc).GenerateContextFreeFunc(Obj);
          CPreCond(Obj.GetPreCondition.Gc).GenerateContextDependentFunc(Obj);
        ELSE
          IF (Obj.Definition <> VOID) 
            AND (Obj.Definition.GetPreCondition <> VOID) THEN
            CPreCond(Obj.Definition.GetPreCondition.Gc).
                                                  GenerateContextFreeFunc(Obj);
            CPreCond(Obj.Definition.GetPreCondition.Gc).
                                             GenerateContextDependentFunc(Obj);
            END;
          END;
        IF Obj.GetPostCondition <> VOID THEN
          DEBUG
            IF Obj.GetPostCondition.Conditions = VOID THEN
              Obj.Warning("PostCondition with void conditions");  
              END; 
            IF (Obj.GetPostCondition.Conditions <> VOID)
               AND (Obj.GetPostCondition.Conditions.Size = 0) THEN
              Obj.Warning("PostCondition without conditions");  
              END; 
            END; 
          CPostCond(Obj.GetPostCondition.Gc).GenerateFunction(Obj);
          CPostCond(Obj.GetPostCondition.Gc).GenerateOldExprInitFunc(Obj);
        ELSE
          IF (Obj.Definition <> VOID) 
            AND (Obj.Definition.GetPostCondition <> VOID) THEN
            CPostCond(Obj.Definition.GetPostCondition.Gc).GenerateFunction(Obj);
            CPostCond(Obj.Definition.GetPostCondition.Gc).
                                                   GenerateOldExprInitFunc(Obj);
            END;
          END; 
        --END;  
      END GenerateExtAssertCode;

    METHOD GenerateDbxExtRefVariable;
      BEGIN
      Ctx.MethDeclGenerateDbxExtRefVariable(THIS);
      END GenerateDbxExtRefVariable;

-- END XXJC (d)

-- XXJC (d)
    --------------------------------
    -- Generate the method registation for the debugger.
    -- Used for pre- and post- condition runtime errors.
    --------------------------------
    METHOD DbxEnterMethod;
      VAR
        Cl: ClassDeclaration;
        Mod: CompilationUnit;
      BEGIN
      Cl := Obj.Class;
      Mod := Cl.Module;
      IF YaflCfg.TraceModeLevel = 2 THEN
        GenerateDbxMethodPrefix;
        END;
      Output.EnterMethod;      
      Output.LeftParent;
      Ctx.CompilationUnitGenerateLiteral(Mod.Gc);
      Output.Comma;
      CClassDecl.GenerateLiteral(Cl.Gc);
      Output.Comma;
      Output.QuotedString (Obj.Id.Data, 
                           UseEsc := FALSE);
      Output.RightParent;                           
      Output.SemiColon;
      Output.WriteLn;
      END DbxEnterMethod;
-- END XXJC (d)


    REDEFINE METHOD GenerateDbxMethodCode;
      VAR
        ModName,ClaName,MethName : ARRAY OF CHAR;
        DumVarNr :INTEGER;

      METHOD GenerateDummyContext;
        BEGIN
        Output.UniqueItem(Obj.StructNr);
        Output.Space;
        DumVarNr := YaflCfg.UniqueNumber;
        Output.UniqueItem(DumVarNr);
        Output.SemiColon;
        Output.WriteLn;
        END GenerateDummyContext;

      -----------------------------------
      -- Create a new method data structure into
      -- the debugging memory area, and assign
      -- the newly allocated data to a static
      -- variable (See Output4Ident below)
      -- visible from inside the current module.
      -----------------------------------
      METHOD GenerateMethodAdd;
        VAR
          TheType: Type;
          Cl: ClassDeclaration;
        BEGIN
        Output.DbxMethodReference(ModName,ClaName,MethName);
        Output.Becomes;
        Output.DbxAddMethod;
        Output.LeftParent;
----        Output.QuotedString(MethName,
----                            UseEsc := FALSE);
----        Output.Comma;
----        Output.WriteInt(Obj.LineNr,0);
----        Output.Comma;
----        Output.WriteInt(Obj.EndIdent.LineNr,0);
        Output.RightParent;
        Output.SemiColon;
        Output.WriteLn;
        ------------------------------------------------------------------
        -- name field
        ------------------------------------------------------------------
        Output.DbxMethodReference(ModName,ClaName,MethName);
        Output.Arrow;
        Output.WriteString ('name');
        --Output.Name;
        Output.Becomes;
        Output.QuotedString(Obj.Id.Data,
                            UseEsc := FALSE);
        Output.SemiColon;
        Output.WriteLn;
        ------------------------------------------------------------------
        -- beginline field
        ------------------------------------------------------------------
        Output.DbxMethodReference(ModName,ClaName,MethName);
        Output.Arrow;
        Output.BeginLine;
        Output.Becomes;
        Output.WriteInt(Obj.LineNr, 0);
        Output.SemiColon;
        Output.WriteLn;
        ------------------------------------------------------------------
        -- endline field
        ------------------------------------------------------------------
        IF NOT Obj.Deferred THEN
          Output.DbxMethodReference(ModName,ClaName,MethName);
          Output.Arrow;
          Output.EndLine;
          Output.Becomes;
          Output.WriteInt(Obj.EndIdent.LineNr, 0);
          Output.SemiColon;
          Output.WriteLn;
          END;
        ------------------------------------------------------------------
        -- offset field
        ------------------------------------------------------------------
        Output.DbxMethodReference(ModName,ClaName,MethName);
        Output.Arrow;
        Output.OffsetField; -- CAUTION Offset already used for macro
        Output.Becomes;
        IF Obj.IsPredefined THEN
          IF Obj.IsCreate THEN
            Output.WriteString("sizeof(minimal_dual)-sizeof(int*)");
           ELSIF Obj.Id.Data = PredefItems.Clone.Id.Data THEN
            Output.WriteString("sizeof(minimal_dual)-2*sizeof(int*)");
           ELSIF Obj.Id.Data = PredefItems.Kill.Id.Data THEN
            Output.WriteString("sizeof(minimal_dual)-3*sizeof(int*)");
           ELSE
            Output.Zero;
            Output.Comment("predefined method");
  			END;
         ELSIF Obj.Redefine THEN
          IF Obj.Redefined(TRUE) <> VOID THEN
            Ctx.MethDeclGenerateDualOffsetValue(Obj.Redefined(TRUE).Gc);
           ELSE
            ASSERT Obj.Redefined(FALSE) = VOID;
            Output.Zero;
            Output.Comment("modified by Darius (13/7/98)");
            END;
         ELSIF NOT Obj.AppearsInDual THEN
          Output.Zero;
         ELSE
          Ctx.MethDeclGenerateDualOffsetValue(THIS);
          --Output.Offset;
          --Output.LeftParent;
          --Output.DualInstance(ModName, ClaName);
          --Output.Comma;
          --Output.MethodStructRef(ModName, ClaName, MethName);
          --Output.RightParent;
          END; -- IF
        Output.SemiColon;
        Output.WriteLn;

  	    TheType := Obj.Return;
        ------------------------------------------------------------------
        -- return_dual field
        ------------------------------------------------------------------
        Output.DbxMethodReference(ModName,ClaName,MethName);
        Output.Arrow;
        Output.ReturnDual;
        Output.Becomes;
        IF TheType <> VOID THEN
          Cl := TheType.SimpleType;
          Output.LeftParent;
          Output.MinimalDual;
          Output.Star;
          Output.RightParent;
          WHAT Cl OF
            IN VirtualClassDecl:
              Output.Ampersand;
              Output.VirtualDual;
              END; -- IN
           ELSE
            CClassDecl.GenerateDualRef(Cl.Gc);
            END; -- IF
         ELSE
          Output.Null;
          END; -- IF
        Output.SemiColon;
        Output.WriteLn;
        ------------------------------------------------------------------
        -- return_array_level field
        ------------------------------------------------------------------
        Output.DbxMethodReference(ModName,ClaName,MethName);
        Output.Arrow;
        Output.ReturnArrayLevel;
        Output.Becomes;
        IF TheType <> VOID THEN
          Output.WriteInt(TheType.ArrayLevel,0);
         ELSE
          Output.Zero;
          END; -- IF
        Output.SemiColon;
        Output.WriteLn;
        -- XXJC (d)
        -- Context Free Precondition.
        --Output.IfDefined(Output.FullTraceModeLabel);
        Output.IfDefined(Output.CheckPreCondLabel);
        Output.DbxMethodReference(ModName,ClaName,MethName);
        Output.Arrow;
        Output.PreContextFree;
        Output.Becomes;
        IF Obj.GetPreCondition <> VOID THEN
          Output.Ampersand;
          Output.ContextFreePreCondFName(ModName,ClaName,MethName);
        ELSE
          Output.Null;
          END;
        Output.SemiColon;
        Output.WriteLn;
        -- Context Dependent Precondition.
        Output.DbxMethodReference(ModName,ClaName,MethName);
        Output.Arrow;
        Output.PreContextDep;
        Output.Becomes;
        IF Obj.GetPreCondition <> VOID THEN
          Output.Ampersand;
          Output.ContextDepPreCondFName (ModName, ClaName, MethName);
        ELSE
          Output.Null;
          END;
        Output.SemiColon;
        Output.WriteLn;
        Output.EndIf;
        --Output.EndIf;
        -- PostCondition.
        --Output.IfDefined(Output.FullTraceModeLabel);
        Output.IfDefined(Output.CheckPostCondLabel);
        Output.DbxMethodReference(ModName,ClaName,MethName);
        Output.Arrow;
        Output.PostCondition;
        Output.Becomes;
        IF Obj.GetPostCondition <> VOID THEN
          Output.Ampersand;
          Output.PostConditionFName(ModName,ClaName,MethName);
        ELSE
          Output.Null;
          END;
        Output.SemiColon;
        Output.WriteLn;
        Output.DbxMethodReference(ModName,ClaName,MethName);
        Output.Arrow;
        Output.ComputeOld;
        Output.Becomes;
        IF Obj.GetPostCondition <> VOID THEN
          Output.Ampersand;
          Output.ComputeOldExprFName(ModName,ClaName,MethName);
        ELSE
          Output.Null;
          END;
        Output.SemiColon;
        Output.WriteLn;
        -- before having the right values for them, 
        -- we set this two fields to NULL
        --Output.DbxMethodReference(ModName,ClaName,MethName);
        --Output.Arrow;
        --Output.Entry;
        --Output.Becomes;
        --Output.Null;
        --Output.SemiColon;
        --Output.WriteLn;
        Output.DbxMethodReference(ModName,ClaName,MethName);
        Output.Arrow;
        Output.Base;
        Output.Becomes;
        Output.Null;
        Output.SemiColon;
        Output.WriteLn;
        Output.EndIf;
        --Output.EndIf;
        -- END XXJC (d)
        END GenerateMethodAdd;
        
      -----------------------------------
      -- Generate the code used to insert the
      -- METHOD_INFO structure of this method in
      -- the chain of method implementation corresponding
      -- to the entry..
      -----------------------------------
      METHOD GenerateMethodChainInsert;
        VAR
          Meth, CreateMeth: MethodDeclaration;
        BEGIN
        Output.Static;
        Output.Void;
        GenerateDbxMethodChainInsert;
        Output.IfDef;
        Output.Ansi;                        
        Output.LeftParent;
        Output.Void;
        Output.RightParent;
        Output.ElseDef;
        Output.LeftParent;
        Output.RightParent;
        Output.EndIf;
        Output.WriteLn;
        Output.Comment("MethodChainInsert");
        Output.LeftBrace;
        Output.WriteLn;
        
        -- not needed anymore (7/7/98)
        --Output.DbxMethodReference(ModName,ClaName,MethName);
        --Output.Arrow;
        --Output.Entry;
        --Output.Becomes;
        --Meth := Obj.Redefined(TRUE);
        --IF Meth <> VOID THEN
        --  IF Meth.IsPredefined THEN
        --    WHAT Meth OF
        --      IN PredefCloneMethod:
	    --        Output.LeftParent;
	    --        Output.DbxMethod;
	    --        Output.Space;
	    --        Output.Star;
	    --        Output.RightParent;
        --        Output.WriteInt(1,0);
        --        Output.Comment("CLONE");
        --        END; 
        --      IN PredefKillMethod:
	    --        Output.LeftParent;
	    --        Output.DbxMethod;
	    --        Output.Space;
	    --        Output.Star;
	    --        Output.RightParent;
        --        Output.WriteInt(2,0);
        --        Output.Comment("KILL");
        --        END; 
        --      IN PredefCreateMethod:
        --        CreateMeth := Obj;
        --        WHILE NOT CreateMeth.IsPredefined DO
        --          CreateMeth := CreateMeth.Redefined(FALSE);
        --          END;
        --        Output.DbxMethodReference(CreateMeth.Class.Module.Id.Data,
        --                                  CreateMeth.Class.Id.Data,
        --                                  CreateMeth.Id.Data);
        --        Output.Comment("Method does redefine (CREATE)");
        --        END; 
        --      END; 
        --  ELSE
        --    Output.DbxMethodReference(Meth.Class.Module.Id.Data,
        --                              Meth.Class.Id.Data,
        --                              Meth.Id.Data);
        --    Output.Comment("Method does redefine something interesting");
        --    END;                          
        --ELSE
        --  --Output.Null;
        --  Output.DbxMethodReference(ModName,ClaName,MethName);
        --  Output.Comment("Method does not redefine anything");
        --  END;
        --Output.SemiColon;
        --Output.WriteLn;
        
        --IF Obj.IsCreate THEN
        --  -- For the CREATE method, we already now the base method.
        --  Output.DbxMethodReference(ModName,ClaName,MethName);
        --  Output.Arrow;
        --  Output.Base;
        --  Output.Becomes;
        --  --Output.DbxMethodReference(ModName,ClaName,MethName);
        --  --Output.Arrow;
        --  --Output.Entry;
        --  Meth := Obj.Redefined(FALSE);
        --  IF Meth <> VOID THEN
        --    IF Meth.IsPredefined THEN
        --      WHAT Meth OF
        --        IN PredefCreateMethod:
        --          CreateMeth := Obj;
        --          WHILE NOT CreateMeth.IsPredefined DO
        --            CreateMeth := CreateMeth.Redefined(FALSE);
        --            END;
        --          Output.DbxMethodReference(CreateMeth.Class.Module.Id.Data,
        --                                    CreateMeth.Class.Id.Data,
        --                                    CreateMeth.Id.Data);
        --          Output.Comment("Method does redefine (CREATE)");
        --          END; 
        --        END; 
        --    ELSE
        --      ASSERT FALSE; 
        --      END;                          
        --  ELSE
        --    Output.WriteInt(0,0);
        --    Output.Comment("Method does not redefine anything (to check JC)");
        --    END;
        --  Output.SemiColon;
        --  Output.WriteLn;
        --ELSE
          -- we have to attach this method to its redefined and base versions.
          Output.AttachRedefinedMethod;
          Output.LeftParent;
          Output.DbxMethodReference(ModName,ClaName,MethName);
          Output.RightParent;
          Output.SemiColon;
          Output.WriteLn;
        --  END;
        
        Output.RightBrace;
        Output.WriteLn;
        END GenerateMethodChainInsert;

    ---------------------------------------------
    -- we generate the declarations of a method in two
    -- passes : the first one processes the locals of the
    -- method (that is,this,parameters,variables,and the eventual
    -- result) and the second one processes the eventual local 
    -- methods; we must do this to ensure that the locals will
    -- be correctly attached to their method by the sequence of
    -- initialisation calls (see the corresponding C code)
    --------------------------------------------------
    METHOD GenerateMethodDeclsPassOne;

      METHOD GenerateLocalAdd(LocName: ARRAY OF CHAR;
                              TheType: Type;
                              OnceInst: SingleDataItem);
        VAR
          Cl: ClassDeclaration;
        BEGIN
---------------------------------------------------------------------
-- the return value is not used yet;
---------------------------------------------------------------------
--        Output.DbxLocalReference(ModName, ClaName, MetName, LocName);
--        Output.Becomes;
---------------------------------------------------------------------
        Output.WriteString("dbx_add_local");
        Output.LeftParent;
        Output.QuotedString(LocName,UseEsc := FALSE);
        Output.Comma;
        Cl := TheType.SimpleType;
        Output.LeftParent;
        Output.MinimalDual;
        Output.Star;
        Output.RightParent;
        WHAT Cl OF
          IN VirtualClassDecl:
            Output.Ampersand;
            Output.VirtualDual;
            END;
         ELSE
          CClassDecl.GenerateDualRef(Cl.Gc);
          END;
        Output.Comma;
        Output.WriteInt(TheType.ArrayLevel,0);
        Output.Comma;
        IF OnceInst <> VOID THEN
          Output.Ampersand;
          OnceInst.Gc.GenerateCode;
          Output.Comma;
          Output.Zero;
         ELSE
          Output.Null;
          Output.Comma;
          Output.Offset;
          Output.LeftParent;
          Output.UniqueItem(DumVarNr);
          Output.Comma;
          Output.Yu(LocName);
          Output.RightParent;
          END;
        Output.RightParent;
        Output.SemiColon;
        Output.WriteLn;
        END GenerateLocalAdd;

      METHOD GenerateMethodFormalsAdd;
        BEGIN
        FOR i := 0 TO Obj.Formals.Size - 1 DO
          GenerateLocalAdd (LocName := Obj.Formals.Get(i).Id.Data,
                            TheType := Obj.Formals.Get(i).GetType,
                            OnceInst := VOID);
          END;
        END GenerateMethodFormalsAdd;

      METHOD GenerateMethodOthersAdd;
        VAR
          Loc: SingleDataItem;
        BEGIN
        FOR i := 0 TO Obj.Locals.Size - 1 DO
          Loc := Obj.Locals.Get(i);
          IF Loc.Once THEN
            GenerateLocalAdd(LocName := Loc.Id.Data,
                             TheType := Loc.GetType,
                             OnceInst := Loc);
           ELSE
            GenerateLocalAdd(LocName := Loc.Id.Data,
                             TheType := Loc.GetType,
                             OnceInst := VOID);
            END;
          END;
        END GenerateMethodOthersAdd;

      -----------------------------------------------
      -- we store THIS in the structures of the debugger
      -- as an ordinary local to simplify things,although
      -- it will be treated sligthly differently;    
      -- however we cannot use the method GenerateLocalAdd
      -- because THIS is neither once nor not once is
      -- the sense that data and offset are both undefined
      -- in the C data structure for the THIS local;
      ------------------------------------------------
      METHOD GenerateMethodThisAdd;
        BEGIN
        Output.DbxAddLocal; -- caution:named elsewhere
        Output.LeftParent;
        Output.QuotedString("THIS",UseEsc := FALSE);
        Output.Comma;
        CClassDecl.GenerateMinDualRef(Obj.Class.Gc);
        Output.Comma;
        Output.WriteInt(0,0); -- array level always zero
        Output.Comma;
        Output.Null; -- never once
        Output.Comma;
        Output.Zero; -- offset always zero;
        Output.RightParent;
        Output.SemiColon;
        Output.WriteLn; 
        END GenerateMethodThisAdd;
        
      METHOD GenerateMethodResultAdd;
        BEGIN
        IF Obj.Return <> VOID THEN
          GenerateLocalAdd(LocName := "RESULT",
                           TheType := Obj.Return,
                           OnceInst := VOID);
          END;
        END GenerateMethodResultAdd ;

       BEGIN
-----------------------------------       
-- CAUTION: patched by bernard
-- the Publish mechanism only works without parameters for the time being
-- so local variables structures are not useful
-----------------------------------       
       IF YaflCfg.TraceModeLevel = 2 THEN
         GenerateMethodThisAdd;
-----------------------------------       
-- a method containing INLINE statements does not have a context structure
-- so in this case parameters and locals other than THIS cannot be 
-- made available with the current registration scheme
-----------------------------------       
         IF NOT Obj.UsesInline THEN
           GenerateMethodFormalsAdd;
           GenerateMethodOthersAdd;
           GenerateMethodResultAdd;
           END;
         END;
       END GenerateMethodDeclsPassOne;

      METHOD GenerateMethodDeclsPassTwo;
        
        METHOD GenerateMethodInit(Meth: MethodImplementation);
          BEGIN
          ASSERT NOT Meth.Deferred;
          CMethImpl(Meth.Gc).GenerateDbxMethodInitialization;
          -- naive naming for local methods
          -- assuming no name conflicts
          Output.LeftParent;
          Output.RightParent;
          Output.SemiColon;
          Output.WriteLn;
          END GenerateMethodInit;

                  
        METHOD GenerateDownLevel;
          BEGIN
          Output.DbxDownLevel;
          Output.LeftParent;
          Output.RightParent;
          Output.SemiColon;
          Output.WriteLn;
          END GenerateDownLevel;
        
        METHOD GenerateUpLevel;
          BEGIN
          Output.DbxUpLevel;
          Output.LeftParent;
          Output.RightParent;
          Output.SemiColon;
          Output.WriteLn;
          END GenerateUpLevel;
                
        BEGIN
        GenerateDownLevel;
        FOR m IN Obj.Methods DO
          GenerateMethodInit(m);
          END;
        GenerateUpLevel;
        END GenerateMethodDeclsPassTwo;


      BEGIN
      ------------------------------------------------------
      -- generates method initialization function
      ------------------------------------------------------
	  -- removed by rjc for pre- and post-conditions.
	  -- ASSERT NOT Obj.Deferred;
      MethName := Obj.Id.Data;
      ClaName := Obj.Class.Id.Data;
      ModName := Obj.Class.Module.Id.Data;
-- patched by bernard
-- useful not only for the debugger now
      IF NOT Obj.Publish THEN
        Output.IfDefined(Output.FullTraceModeLabel);
        END;
      Ctx.MethDeclGenerateDbxReferenceVariable(THIS);
      -- XXJC (d)
-- patched by bernard
-- useful not only for the debugger now
      IF NOT Obj.Publish THEN
        Output.EndIf;
        END;
      GenerateExtAssertCode;
-- patched by bernard
-- useful not only for the debugger now
      IF NOT Obj.Publish THEN
        Output.IfDefined(Output.FullTraceModeLabel);
        END; -- IF
      -- END XXJC (d)
      Output.Static;
      Output.Void;
      GenerateDbxMethodInitialization;
      Output.IfDef;
      Output.Ansi;                        
      Output.LeftParent;
      Output.Void;
      Output.RightParent;
      Output.ElseDef;
      Output.LeftParent;
      Output.RightParent;
      Output.EndIf;
----------------------------------      
      Output.WriteLn;
      Output.LeftBrace;
      Output.WriteLn;
----------------------------------      
-- a method containing INLINE statements does not have a context
-- structure so in this case we cannot declare a dummy context      
----------------------------------      
-- CAUTION: patched by bernard
-- the Publish mechanism only works without parameters for the time being
-- so local variables structures are not useful
-- this structure is only used for computing the offset of these local variables
-- structures
----------------------------------      
      IF YaflCfg.TraceModeLevel = 2 THEN
        IF NOT Obj.UsesInline THEN
          GenerateDummyContext;
          END;
        END;
      -- XXJC  
      GenerateMethodAdd;
      -- END XXJC
      IF NOT Obj.Deferred THEN
        GenerateMethodDeclsPassOne;
        GenerateMethodDeclsPassTwo;
        END;
      Output.RightBrace;
      Output.WriteLn;
      GenerateMethodChainInsert;
-- patched by bernard
-- useful not only for the debugger now
      IF NOT Obj.Publish THEN
        Output.EndIf;
        END;
      END GenerateDbxMethodCode;

    -------------------------------------
    --  generate the text of the C function call that
    --  is pushing a new frame into the debugger list
    --  of calls (instances of methods);
    --  these frames are composed of a pointer to the dbx-method
    --  data structure corresponding to the YAFl method,
    --  a pointer to the context of this method and a
    --  pointer to the current object of this method;
    --  this text is generated inside and near the beginning of
    --  the code of the method but must be after the definition
    --  of the context local variable;
    --  this method has been made for the debugger so there
    --  is nothing now in the base method but we still
    --  call it,just to be sure;
    ---------------------------------------------------
      METHOD GenerateDbxMethodPrefix;
      VAR
        ModName,ClaName,MethName: ARRAY OF CHAR;
      BEGIN
      MethName := Obj.Id.Data;
      ClaName := Obj.Class.Id.Data;
      ModName := Obj.Class.Module.Id.Data;
      Output.IfDefined(Output.FullTraceModeLabel);
      Output.DbxPushCall;
      Output.LeftParent;
      Output.DbxMethodReference(ModName,ClaName,MethName);
      Output.Comma;
------------------------------------      
-- a method containing INLINE statements does not have a context
-- stucture so in this case we cannot push its address on the debugger stack      
------------------------------------      
      IF NOT Obj.UsesInline THEN
        Output.Ampersand; -- by reference
        Output.Context;
       ELSE
        Output.Null;
        END;
      Output.Comma;
      Output.Ampersand; -- by reference
      Output.Yu("THIS");
      Output.RightParent;
      Output.SemiColon;
      Output.WriteLn;
      Output.EndIf;
      END GenerateDbxMethodPrefix;

    ----------------------------------------------
    -- generates the text of the C function call that
    -- is removing the top frame of the debugger list
    -- of calls(instances of methods);
    -- this text is generated near the end of the code of
    -- the method;
    -- same remark as in GeneratePrefix concerning the
    -- base method;
    -------------------------------------------------
    METHOD GenerateDbxMethodPostfix;
      BEGIN
      Output.IfDefined(Output.FullTraceModeLabel);
-- generates an additional trace step just before the end of the function;
-- this is required in the debugger because one must be able to see the
-- variables just before returning from the function;      
      Output.TraceStep(Obj.EndIdent.LineNr);
      Output.DbxPopCall;
      Output.LeftParent;
      Output.RightParent;
      Output.SemiColon;
      Output.WriteLn;
      Output.EndIf;
      END GenerateDbxMethodPostfix;

    METHOD GenerateAnchorId;
      BEGIN
      IF NOT YaflCfg.PleaseGlobalOptimize THEN
        IF Obj.UseStaticAnchor THEN
          Output.UniqueWithSuffix (Obj.GetAnchorNumber, Obj.Id.Data);
          Output.WriteChar (' ');
         ELSE
          Ctx.MethDeclGenerateAnchorId(THIS); --BASE;
          END;
       ELSE
        IF Obj.IsCreate THEN
          CClassDecl.GenerateCreateAnchorId(Obj.Class.Gc);
         ELSE
          Output.Anchor (Obj.Class.Module.Id.Data, Obj.Class.Id.Data, Obj.Id.Data);
          END;
        END;
      END GenerateAnchorId;

    METHOD GenerateLocal(DataItem: SingleDataItem);
      BEGIN
      IF Obj.UseStruct AND (DataItem <> Obj.This) AND (DataItem <> Obj.TagDecl) THEN
        IF Obj = CurrentSpot.CurrentMethod THEN
          Output.Context;
          Output.Dot;
         ELSE
          Output.UniqueItem (Obj.ContextNr);
          Output.Arrow;
          END;
        END;
      ASSERT DataItem <> VOID;
      DataItem.Gc.GenerateCode;
      END GenerateLocal;
      
    -----------------------------------
    -- Generate the name of the method :
    --    * YG_xxx    if MergeAnchor
    --    * YM_xxx    otherwise
    -----------------------------------
    METHOD GenerateMethodRef;
      BEGIN         
      IF Obj.MergeAnchor AND YaflCfg.PleaseGlobalOptimize THEN
        GenerateAnchorId;
       ELSE
        Ctx.MethDeclGenerateMethodRef(THIS); --BASE;
        END;      
      END GenerateMethodRef;
                 
    METHOD GenerateMethodDefinition;
      BEGIN                        
      IF NOT Obj.MergeAnchor THEN
        Ctx.MethDeclGenerateReturnType(THIS);
        GenerateMethodRef;
        Ctx.MethDeclGenerateAnchorFormals(THIS);
        Output.SemiColon;
        Output.WriteLn;
        END;
      END GenerateMethodDefinition;

    METHOD GenerateAnchorDefinition;
      BEGIN
      Ctx.MethDeclGenerateAnchorDefinition(THIS);
      END GenerateAnchorDefinition;

    METHOD GenerateAnchorBody;
      BEGIN
      Ctx.MethDeclGenerateAnchorBody(THIS);
      END GenerateAnchorBody;

    METHOD GenerateMethodPointer;
      BEGIN
      Ctx.MethDeclGenerateMethodPointer(THIS);
      END GenerateMethodPointer;

  END CMethImplCodeGenerator;
  
-------------------------------------------------------  

  ONCE CLASS CMethDecl; 
 
    METHOD GenerateMethodRef(Gc: MethDeclCodeGenerator);
      BEGIN
      WHAT Gc OF
         IN CPredefMethCodeGenerator:
            TAG.GenerateMethodRef;
            END;
         IN CMethDefCodeGenerator:
            TAG.GenerateMethodRef;
            END;
         IN CMethImplCodeGenerator:
            TAG.GenerateMethodRef;
            END;
         END; -- what 
      END GenerateMethodRef; 

    METHOD GenerateAnchorDefinition(Gc: MethDeclCodeGenerator);
      BEGIN
      WHAT Gc OF
         IN CPredefMethCodeGenerator:
            TAG.GenerateAnchorDefinition;
            END;
         IN CMethDefCodeGenerator:
            TAG.GenerateAnchorDefinition;
            END;
         IN CMethImplCodeGenerator:
            TAG.GenerateAnchorDefinition;
            END;
         END; -- what
      END GenerateAnchorDefinition;

    METHOD GenerateAnchorId(Gc: MethDeclCodeGenerator);
      BEGIN
      WHAT Gc OF
         IN CPredefMethCodeGenerator:
            TAG.GenerateAnchorId;
            END;
         IN CMethDefCodeGenerator:
            TAG.GenerateAnchorId;
            END;
         IN CMethImplCodeGenerator:
            TAG.GenerateAnchorId;
            END;
         END; -- what
      END GenerateAnchorId;
   
    METHOD GenerateAnchorBody(Gc: MethDeclCodeGenerator);
      BEGIN
      WHAT Gc OF
         IN CPredefMethCodeGenerator:
            TAG.GenerateAnchorBody;
            END;
         IN CMethDefCodeGenerator:
            TAG.GenerateAnchorBody;
            END;
         IN CMethImplCodeGenerator:
            TAG.GenerateAnchorBody;
            END;
         END; -- what
      END GenerateAnchorBody; 
    
    METHOD GenerateMethodPointer(Gc: MethDeclCodeGenerator);
      BEGIN
      WHAT Gc OF
         IN CPredefMethCodeGenerator:
            TAG.GenerateMethodPointer;
            END;
         IN CMethDefCodeGenerator:
            TAG.GenerateMethodPointer;
            END;
         IN CMethImplCodeGenerator:
            TAG.GenerateMethodPointer;
            END;
         END; -- what
      END GenerateMethodPointer;

  END CMethDecl;

END CGMethods;
