IMPLEMENTATION MODULE YaflGC;

FROM Conversions IMPORT IntConversions;
FROM Directories IMPORT Operations;
FROM Streams IMPORT Stream, StdOut, InputStream;
IMPORT String;
IMPORT SYSTEM;
FROM YaflCfg IMPORT YaflCfg, CurrentSpot;
FROM YaflError IMPORT MainErrorHandler;
FROM YaflPredefined IMPORT PredefItems;
FROM YaflWorlds IMPORT World;
FROM Ycc IMPORT Yc;
FROM YaflClasses IMPORT ClassDeclaration;
FROM YaflModules IMPORT ImplementationModule;

  CLASS VersionedOutputStream;
    INHERITS OutputStream;
    
    VAR
      VersionedFile: BOOLEAN;
      TempFileName, RealFileName: ARRAY OF CHAR;
    
    METHOD AttemptCreate (FName,
                          TempFName: ARRAY OF CHAR);
      BEGIN
      ASSERT NOT VersionedFile;
      VersionedFile := TRUE;
      RealFileName := FName;
      TempFileName := TempFName;
      Create (TempFileName, WriteAccess);
      END AttemptCreate;
      
    METHOD Compare (FName1, FName2: ARRAY OF CHAR): BOOLEAN;
      VAR
        File1, File2: InputStream;
        Buffer1: ONCE ARRAY OF CHAR;
        Buffer2: ONCE ARRAY OF CHAR;
        Read1, Read2, i: INTEGER;
        Continue: BOOLEAN;
      CONST
        BufferSize = 1024;
      BEGIN
      IF Buffer1 = VOID THEN
        ASSERT Buffer2 = VOID;
        Buffer1.CREATE (BufferSize);
        Buffer2.CREATE (BufferSize);
        END;
      File1.CREATE;
      File2.CREATE;
      File1.Open (FName1, Stream.ReadAccess);
      IF File1.ErrorCode = Stream.NoError THEN
        File2.Open (FName2, Stream.ReadAccess);
        IF File2.ErrorCode = Stream.NoError THEN
          Continue := TRUE;
          -------------------------------
          -- Skip the first line, so that the comment
          -- which merely indicates the compiler's version
          -- is not taken into account.
          -------------------------------
          VOID := File1.ReadLine;
          VOID := File2.ReadLine;
          WHILE Continue DO
            Read1 := File1.ReadBuffer (Buffer1, BufferSize);
            Read2 := File2.ReadBuffer (Buffer2, BufferSize);
            IF Read1 = Read2 THEN
              i := String.LimitedCompare (Buffer1, Buffer2, Read1);
              IF i = String.Equal THEN
                IF Read1 <> BufferSize THEN
                  RESULT := TRUE;
                  Continue := FALSE;
                  END;
               ELSE
                Continue := FALSE;
                END;
             ELSE
              Continue := FALSE;
              END;
            END;
          File2.Close;
          END;
        File1.Close;
        END;
      END Compare;

    REDEFINE METHOD Close;
      BEGIN
      BASE;
      IF VersionedFile THEN
        IF NOT String.Equals (TempFileName, RealFileName) THEN
          IF NOT Compare(TempFileName, RealFileName) THEN
            Operations.Delete (RealFileName);
            VOID := Operations.Rename (TempFileName, RealFileName);
           ELSE
            Operations.Delete (TempFileName);
            END;
          END;
        VersionedFile := FALSE;
        END;
      END Close;
    
  END VersionedOutputStream;
  -------------------------------------------
  CLASS YaflGC;
    INHERITS VersionedOutputStream;

    CONST
      MaxWidth = 68;
    VAR
      ColNr: INTEGER;
      PleaseCut: BOOLEAN;
      GenLines: INTEGER;

      
      IfNDefString, IfDefString, NewStringString,
      EndIfString, FirstSigString, ElseDefString,
      LastSigString, UFirstSigString, ULastSigString, DefineString, UndefineString,
      InclString, 
      MethodInfoString, LocalInfoString, SetLineString,
      FailWhatString, FailCaseString, FailAssertString, FailVoidString,
      FailUndefMethodString, FailBadClassString, EnterMethodString,
      ExitMethodString, IsInString, AnsiString,

      StructString, TypeDefString, ForString, WhileString, ElseString,
      VoidString, SizeOfString, ExternString, ReturnString, StaticString,
      CaseString, SwitchString, DefaultString, JumpString, BreakString,
      ConstString, MallocString,

      RegisterModuleString, ProfileLinesString,

      MarkArrayString, ReqMarkString, OnceTabString, OnceInstanceString,
      AssignObjPtrString, PreContextFreeString, 
      PreContextDepString, PostFuncString, 
      
      ------------------------------------
      -- Strings which are used for conditionnal
      -- compilation purposes
      ------------------------------------
      FullTraceModeLabelString,      
      DebugModeLabelString,
      TraceModeLabelString,
      ProfileModeLabelString,
      ForceStructLabelString,
      CheckDualLabelString,
      CheckVoidMethodLabelString,
      CheckVoidObjectLabelString,
      CheckArrayLabelString,
      CheckWhatLabelString,
      CheckCaseLabelString,
      CheckDebugLabelString,
      CheckAssertLabelString,
      CheckVersionLabelString,
      NeedAddMethRefLabelString,

      ObjPtrString, YIntString,
      IntString, CharString, DualString, TagString,
      ResultString, ThisString, CastedThisString,
      HeaderString, HighString, UnivCloneString,
      UnivKillString,
      UnivSliceString, UnivConcatString, ArrayElementString, CloneFuncString,
      KillFuncString,
      ReAllocString, AllocString, EnterPoolString, ElementSizeString, 
      DualSizeString,
      ClassNameString,
      ModuleNameString, 
      BeginLineString,
      EndLineString,
      OncePtrString,
      CurrentModuleNameString, 
      UnsignedString, UnsignedIntString,
      OrigMethCountString, InhMethCountString, MoISInitString,
      InheritedString, MarkFuncString,
      OffsetString,
      OffsetFieldString,
      ReturnDualString,
      ReturnArrayLevelString,
      AlignString,
      DefaultCloneString, RegString,
      VRegString, FlyVRegString,
      RegisterClassString, 
      SaveDStackString, 
      SaveVStackString, 
      RestoreDStackString, 
      RestoreVStackString, 
      CheckDualOverflowString,
      CheckVersionString,
      ContextString, YArgsString, YFormalsString, ToUpperString,
      ToLowerString, ZeroMemString, MemsetString,

--      PushIntString, PushRealString, PushCharString,
--      PushBooleanString, PushObjPtrString, PopIntString,
--      PopRealString, PopCharString, PopBooleanString,
--      PopObjPtrString, 
--      NameString,
      LineCountString,
      SourceFileNameString, LineNumbersString,
      FirstClassString, LastClassString, SourceLinesString,

      
      TrueString, FalseString, ModuleDualString,
      
      DbxString, AddString, ClassString, LocalString,
      MethodString, DownString, UpString, LevelString,
      PushString, PopString, YaflString, InitString, 
      BeginString, ModuleString, FieldString, CallString,
      AppendString, DistanceString, ParallelDualString,
      AddMethodRefString, ComputeOldString,
      
      MethodRefString,
      IntFuncString, CharFuncString, DoubleFuncString,
      BooleanFuncString, ObjPtrFuncString, VoidFuncString, 
      CurrentString,
      
-- XXJC (d)
      -----------------------------------------------------
      -- string added by rjc for pre- and post- conditions
      -----------------------------------------------------
      AssertionStackPushIntString,
      AssertionStackPushObjString,
      AssertionStackPushCharString,
      AssertionStackPushRealString,
      AssertionStackPopIntString,
      AssertionStackPopObjString,
      AssertionStackPopCharString,
      AssertionStackPopRealString,
      AssertionStackGetIntString,
      AssertionStackGetObjString,
      AssertionStackGetCharString,
      AssertionStackGetRealString,
      AssertionParamStackNameString,
      OldStackNameString,
      CheckPreConditionString,
      CheckPostConditionsString,
      ComputeOldExpressionsString,
      AssertionStackPushLevelString,
      AssertionStackPopLevelString,
      CheckLoopInvariantLabelString,
      CheckClassInvariantLabelString,
      CheckPostCondLabelString,
      CheckPreCondLabelString,
      CheckContextFreePreCondLabelString,
      CheckContextDepPreCondLabelString,
      AttachRedefinedMethodString,
      BaseMethodString,
      EntryString,
      SetBitString : ONCE ARRAY OF CHAR;
-- END XXJC (d)

      TheMaxStringLen: INTEGER;

      theYaflIdentifier: YaflIdentifier;

    REDEFINE METHOD CREATE;
      BEGIN
      BASE;
      theYaflIdentifier.CREATE;
      IF IfNDefString = VOID THEN
        InitStrings;
        ASSERT IfNDefString <> VOID;
        END;
      TheMaxStringLen := YaflCfg.MaxStringLen;
      ASSERT TheMaxStringLen >= 40;
      END CREATE;

    METHOD Cut;
      BEGIN
      PleaseCut := TRUE;
      END Cut;

    METHOD NoCut;
      BEGIN
      PleaseCut := FALSE;
      END NoCut;

    METHOD Need(Len: INTEGER);
      BEGIN
      IF PleaseCut AND (ColNr + Len > MaxWidth) THEN
        WriteLn;
        Tab;
        END;
      END Need;

    REDEFINE METHOD WriteChar(Ch: CHAR);
      BEGIN
      BASE (Ch);
      ColNr := ColNr + 1;
      END WriteChar;
      
    REDEFINE METHOD WriteString(a: ARRAY OF CHAR);
      BEGIN
      Need (a.SIZE);
      BASE(a);
      ColNr := ColNr + a.SIZE;
      END WriteString;
      
    REDEFINE METHOD WriteLn;
      BEGIN
      IF ColNr <> 0 THEN
        BASE;
        ColNr := 0;
        GenLines := GenLines + 1;
        END;
      END WriteLn;
      
    METHOD GeneratedLines: INTEGER;
      BEGIN
      RESULT := GenLines;
      END GeneratedLines;

    METHOD Tab;
      BEGIN
      WriteChar (SYSTEM.CHR(SYSTEM.Tab));
      END Tab;

    METHOD Space;
      BEGIN
      WriteChar (' ');
      END Space;

    METHOD Zero;
      BEGIN
      WriteChar ('0');
      END Zero;
      
    METHOD One;
      BEGIN
      WriteChar ('1');
      END One;

    METHOD Becomes;
      BEGIN
      WriteChar ('=');
      END Becomes;

    METHOD Star;
      BEGIN
      WriteChar ('*');
      END Star;

    METHOD Arobas;
      BEGIN
      WriteChar ('@');
      END Arobas;

    METHOD Plus;
      BEGIN
      WriteChar ('+');
      END Plus;

    METHOD Minus;
      BEGIN
      WriteChar ('-');
      END Minus;

    METHOD Slash;
      BEGIN
      WriteChar ('/');
      END Slash;

    METHOD Mod;
      BEGIN
      WriteChar ('%');
      END Mod;

    METHOD SelfStar;
      BEGIN
      Need(4);
      WriteChar ('*');
      WriteChar ('=');
      END SelfStar;

    METHOD SelfPlus;
      BEGIN
      Need(4);
      WriteChar ('+');
      WriteChar ('=');
      END SelfPlus;

    METHOD SelfMinus;
      BEGIN
      Need(4);
      WriteChar ('-');
      WriteChar ('=');
      END SelfMinus;

    METHOD SelfSlash;
      BEGIN
      Need(4);
      WriteChar ('/');
      WriteChar ('=');
      END SelfSlash;

    METHOD SelfMod;
      BEGIN
      Need(4);
      WriteChar ('%');
      WriteChar ('=');
      END SelfMod;

    METHOD Not;
      BEGIN
      WriteChar ('!');
      END Not;

    METHOD Greater;
      BEGIN
      WriteChar ('>');
      END Greater;

    METHOD Smaller;
      BEGIN
      WriteChar ('<');
      END Smaller;

    METHOD Equal;
      BEGIN
      WriteChar ('=');
      WriteChar ('=');
      END Equal;

    METHOD NonEqual;
      BEGIN
      WriteChar ('!');
      WriteChar ('=');
      END NonEqual;

    METHOD And;
      BEGIN
      WriteChar ('&');
      WriteChar ('&');
      END And;

    METHOD Or;
      BEGIN
      WriteChar ('|');
      WriteChar ('|');
      END Or;

    METHOD GreaterEqual;
      BEGIN
      WriteChar ('>');
      WriteChar ('=');
      END GreaterEqual;

    METHOD SmallerEqual;
      BEGIN
      WriteChar ('<');
      WriteChar ('=');
      END SmallerEqual;

    METHOD Arrow;
      BEGIN
      WriteChar ('-');
      WriteChar ('>');
      END Arrow;

    METHOD Increment;
      BEGIN
      WriteChar ('+');
      WriteChar ('+');
      END Increment;

    METHOD Decrement;
      BEGIN
      WriteChar ('-');
      WriteChar ('-');
      END Decrement;

    METHOD IncVar;
      BEGIN
      WriteChar ('+');
      WriteChar ('=');
      END IncVar;

    METHOD True;
      BEGIN
      WriteString(TrueString);
      END True;

    METHOD False;
      BEGIN
      WriteString(FalseString);
      END False;
      
    METHOD BitAnd;
      BEGIN
      WriteChar ('&');
      END BitAnd;
      
    METHOD BitOr; 
      BEGIN
      WriteChar ('|');
      END BitOr; 
      
    METHOD BitXor;
      BEGIN
      WriteChar ('&');
      WriteChar ('~');
      END BitXor;
      
    METHOD BitNot;
      BEGIN
      WriteChar ('~');
      END BitNot;
      
    METHOD LeftShift;
      BEGIN
      WriteChar ('<');
      WriteChar ('<');
      END LeftShift;
      
    METHOD RightShift;
      BEGIN
      WriteChar ('>');
      WriteChar ('>');
      END RightShift;

    METHOD Comma;
      BEGIN
      Need(0);
      WriteChar (',');
      END Comma;

    METHOD Dot;
      BEGIN
      WriteChar ('.');
      END Dot;

    METHOD Ampersand;
      BEGIN
      WriteChar ('&');
      END Ampersand;

    METHOD SemiColon;
      BEGIN
      WriteChar (';');
      END SemiColon;

    METHOD Colon;
      BEGIN
      WriteChar (':');
      END Colon;

    METHOD QuestionMark;
      BEGIN
      WriteChar ('?');
      END QuestionMark;

    METHOD LeftBracket;
      BEGIN
      Need(0);
      WriteChar ('[');
      END LeftBracket;

    METHOD RightBracket;
      BEGIN
      Need(0);
      WriteChar (']');
      END RightBracket;

    METHOD LeftBrace;
      BEGIN
      WriteChar ('{');
      END LeftBrace;

    METHOD RightBrace;
      BEGIN
      WriteChar ('}');
      END RightBrace;

    METHOD LeftParent;
      BEGIN
      WriteChar ('(');
      END LeftParent;

    METHOD LeftParents(Count: INTEGER);
      BEGIN
      FOR i := 1 TO Count DO
        WriteChar ('(');
        END;
      END LeftParents;

    METHOD RightParent;
      BEGIN
      WriteChar (')');
      END RightParent;

    METHOD RightParents(Count: INTEGER);
      BEGIN
      FOR i := 1 TO Count DO
        WriteChar (')');
        END;
      END RightParents;

    METHOD Comment (a: ARRAY OF CHAR);
      BEGIN
      WriteChar ('/');
      WriteChar ('*');
      Tab;
      Tab;
      WriteString (a);
      Tab;
      Tab;
      WriteChar ('*');
      WriteChar ('/');
      WriteLn;
      END Comment;

    METHOD HGuard (Module: ARRAY OF CHAR);
      BEGIN
      WriteString (Module);
      WriteChar ('_');
      WriteChar ('H');
      END HGuard;
      
    METHOD Current;
      BEGIN  
      WriteString(CurrentString);
      END Current;  

    METHOD IntegerFunc;
      BEGIN         
      WriteString(IntFuncString);
      END IntegerFunc;
      
    METHOD BooleanFunc;
      BEGIN
      WriteString(BooleanFuncString);
      END BooleanFunc;
      
    METHOD CharFunc;
      BEGIN
      WriteString(CharFuncString);
      END CharFunc;
      
    METHOD RealFunc;
      BEGIN
      WriteString(DoubleFuncString);
      END RealFunc;
      
    METHOD VoidFunc;
      BEGIN
      WriteString(VoidFuncString);
      END VoidFunc;
      
    METHOD ObjPtrFunc;
      BEGIN
      WriteString(ObjPtrFuncString);
      END ObjPtrFunc;
      
    
    CONST
      HExt = YaflCfg.HeaderExt;
      CExt = YaflCfg.IntermediateExt;
      MExt = "met";
      QuoteChar = '"';

    METHOD Quote;
      BEGIN
      WriteChar (QuoteChar);
      END Quote;
      
    METHOD Underscore;
      BEGIN
      WriteChar ('_');
      END Underscore;  

    METHOD QuotedString (a: ARRAY OF CHAR;
                         UseEsc: BOOLEAN);
      BEGIN
      Need (a.SIZE * 2);    
      WriteQuotedString (a, UseEsc);
      Need(10);
      END QuotedString;

    METHOD LiteralChar (Ch: CHAR);
      BEGIN
      Need(6);
      IF Ch = SYSTEM.CHR(SYSTEM.Tab) THEN
        WriteChar ("'");
        WriteChar ("\");
        WriteChar ("t");
        WriteChar ("'");
       ELSIF Ch = SYSTEM.CHR(SYSTEM.NewLine) THEN
        WriteChar ("'");
        WriteChar ("\");
        WriteChar ("n");
        WriteChar ("'");
       ELSE
        CASE Ch OF
          'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
          'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
          'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
          'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
          '0' TO '9', 
          '!', '@', '#', '$', '%', '&', '*', '(', ')', '/',
          '[', '{', ']', '}', '|', '?', '.', ',', '<', '>',
          '+', '-', '_', '=', ' ', ';', ':' :
            WriteChar ("'");
            WriteChar (Ch);
            WriteChar ("'");
            END;
          "'", '"', '\':
            WriteChar ("'");
            WriteChar ("\");
            WriteChar (Ch);
            WriteChar ("'");
            END;          
         ELSE
          WriteInt (SYSTEM.ORD(Ch), 0);
          END;
        END;
      END LiteralChar;

   METHOD WriteQuotedString (a: ARRAY OF CHAR;
                              UseEsc: BOOLEAN);
      VAR
        Ch: CHAR;
      CONST
        BackSlash = '\';
      BEGIN
      NoCut;
      IF UseEsc AND
         ((String.Pos (a, QuoteChar) < a.SIZE) OR
          (String.Pos (a, BackSlash) < a.SIZE)) THEN
        Quote;
        FOR i := 0 TO a.SIZE - 1 DO
          Ch := a[i];
          IF (Ch = QuoteChar) OR (Ch = BackSlash) THEN
            WriteChar (BackSlash);
            END;
          WriteChar (Ch);
          END;
        Quote;
       ELSE
        Quote;
        WriteString (a);
        Quote;
        END;
      Cut;
      END WriteQuotedString;
      
    METHOD NewString (a: ARRAY OF CHAR);
      VAR
        Middle: INTEGER;
      BEGIN
      IF a.SIZE > TheMaxStringLen THEN
        Middle := a.SIZE / 2;
        UnivConcat (Arity := 2);
        LeftParent; 
        NewString (a.SLICE (0, Middle));
        Comma;
        NewString (a.SLICE (Middle, a.SIZE - Middle));
        RightParent;
       ELSE 
        WriteString (NewStringString);
        LeftParent;
        QuotedString (a, TRUE);
        RightParent;
        END;
      END NewString;

    METHOD SystemInclude (FName: ARRAY OF CHAR);
      BEGIN                    
      WriteLn;
      WriteString (InclString);
      Smaller;
      WriteString (FName);
      Greater;
      WriteLn;
      END SystemInclude;

    METHOD UserInclude (FName: ARRAY OF CHAR);
      BEGIN                    
      WriteLn;
      WriteString (InclString);
      WriteQuotedString (FName, UseEsc := FALSE);
      WriteLn;
      END UserInclude;

    METHOD PragmaInclude (FName: ARRAY OF CHAR);
      BEGIN                    
      WriteLn;
      WriteString (InclString);
      WriteString (FName);
      WriteLn;
      END PragmaInclude;

    METHOD Dual;
      BEGIN
      WriteString (DualString);
      END Dual;

    METHOD DefaultClone;
      BEGIN
      WriteString (DefaultCloneString);
      END DefaultClone;

    METHOD Reg;
      BEGIN
      WriteString (RegString);
      END Reg;
      
    METHOD VReg;
      BEGIN
      WriteString (VRegString);
      END VReg;

    METHOD FlyVReg;
      BEGIN
      WriteString (FlyVRegString);
      END FlyVReg;

    METHOD RegisterClass;
      BEGIN
      WriteString (RegisterClassString);
      END RegisterClass;

    METHOD This;
      BEGIN
      WriteString (ThisString);
      END This;

    METHOD CastedThis;
      BEGIN
      WriteString (CastedThisString);
      END CastedThis;

    METHOD Result;
      BEGIN
      WriteString (ResultString);
      END Result;

    METHOD Tag;
      BEGIN
      WriteString (TagString);
      END Tag;

    METHOD Header;
      BEGIN
      WriteString (HeaderString);
      END Header;

    METHOD Define;
      BEGIN
      WriteLn;
      WriteString (DefineString);
      END Define;

    METHOD Undefine;
      BEGIN
      WriteLn;
      WriteString (UndefineString);
      END Undefine;

    METHOD IfDef;
      BEGIN
      WriteLn;
      WriteString(IfDefString);
      END IfDef;

    METHOD IfNDef;
      BEGIN
      WriteLn;
      WriteString(IfNDefString);
      END IfNDef;

    METHOD ElseDef;
      BEGIN
      WriteLn;
      WriteString(ElseDefString);
      WriteLn;
      END ElseDef;             
      
    METHOD BreakDefine;
      BEGIN
      WriteChar ('\');
      WriteLn;
      END BreakDefine;
      
    METHOD EndIf;
      BEGIN
      WriteLn;
      WriteString(EndIfString);
      WriteLn;
      END EndIf;


    METHOD SizeOf;
      BEGIN
      WriteString (SizeOfString);
      END SizeOf;

    METHOD Extern;
      BEGIN
      WriteString (ExternString);
      END Extern;

    METHOD Static;
      BEGIN
      WriteString (StaticString);
      END Static;

    METHOD Return;
      BEGIN
      WriteString (ReturnString);
      END Return;

    METHOD DefineJumpTarget (LabelNr: INTEGER);
      BEGIN
      UniqueItem (LabelNr);
      Colon;
      SemiColon;
      WriteLn;
      END DefineJumpTarget;

    METHOD Jump(LabelNr: INTEGER);  -- Goto exists already as a method
      BEGIN
      WriteString (JumpString);
      UniqueItem (LabelNr);
      SemiColon;
      WriteLn;
      END Jump;

    METHOD Break;
      BEGIN
      WriteString (BreakString);
      END Break;

    METHOD Const;
      BEGIN     
      WriteString (ConstString);        
      END Const;

    METHOD Malloc;
      BEGIN
      WriteString (MallocString);
      END Malloc;

    -- Returns TRUE if the two file are considered the same
    METHOD OpenHeaderFile (Mod: CompilationUnit;
                           Number: INTEGER);
      VAR
        FName, TempFName, BaseName: ARRAY OF CHAR;
        TheWorld: World;
      BEGIN
      ASSERT (Number=1) OR (Number=2);
      TheWorld := Mod.GetWorld;   
      BaseName := Mod.Id.Data;
      FName := TheWorld.BuildTargetFName (BaseName, 
                               HExt + IntConversions.IntToString (Number, 0));
      TempFName := TheWorld.BuildTempFName (BaseName, 
                               HExt + IntConversions.IntToString (Number, 0));
      AttemptCreate (FName, TempFName);
      IF (ErrorCode = Stream.NoError) THEN
        Comment (FName + " Version: " + Yc.Version);
        PleaseCut := TRUE;
       ELSE
        MainErrorHandler.SetError (0, 0, "Cannot create file[1]: " + 
                                FName);
        END;
      END OpenHeaderFile;
      
    METHOD OpenBodyFile (Mod: CompilationUnit);
      VAR
        BaseName, 
        FName: ARRAY OF CHAR;
      BEGIN
      BaseName := Mod.Id.Data;
      PleaseCut := TRUE;
      FName := Mod.GetWorld.BuildTargetFName (BaseName, CExt);
      Create (FName, Stream.WriteAccess);
      IF ErrorCode = Stream.NoError THEN
        Comment (FName + " Version: " + Yc.Version);
       ELSE     
        MainErrorHandler.SetError (0, 0, "Cannot create file[2]: " 
                                + FName);
        END;
      END OpenBodyFile;

    METHOD OpenMetricsFile (Mod: CompilationUnit);
      VAR
        BaseName,
        FName: ARRAY OF CHAR;
      BEGIN                                     
      BaseName := Mod.Id.Data;
      PleaseCut := TRUE;
      FName := Mod.GetWorld.BuildTargetFName (BaseName, MExt);
      Create (FName, Stream.WriteAccess);
      IF ErrorCode = Stream.NoError THEN
        Comment (FName + " Version: " + Yc.Version);
       ELSE     
        MainErrorHandler.SetError (0, 0, "Cannot create file[2]: " 
                                + FName);
        END;
      END OpenMetricsFile;

--

    METHOD ModuleDual;
      BEGIN
      WriteString(ModuleDualString);
      END ModuleDual;

    METHOD ModuleDualRef (Mod: ARRAY OF CHAR);
      BEGIN
      ASSERT Mod <> VOID;
      WriteString(theYaflIdentifier.ModuleDualRef(Mod));
      Space;
      END ModuleDualRef;

    METHOD ModuleLinesRef(Mod: ARRAY OF CHAR);
      BEGIN
      ASSERT Mod <> VOID;
      WriteString(theYaflIdentifier.ModuleLinesRef(Mod));
      Space;
      END ModuleLinesRef;

    METHOD ModuleProfileRef(Mod: ARRAY OF CHAR);
      BEGIN
      ASSERT Mod <> VOID;
      WriteString(theYaflIdentifier.ModuleProfileRef(Mod));
      Space;
      END ModuleProfileRef;
      
    METHOD MethodRef;
      BEGIN
      WriteString(MethodRefString);
      Space;
      END MethodRef;
      
    METHOD MethodStructRef (Module, Class, Meth: ARRAY OF CHAR);
      BEGIN
      WriteString( theYaflIdentifier.MethodStructRef(Module,Class,Meth));
      Space;
      END MethodStructRef;

--

    METHOD Anchor (Module, Class, Meth: ARRAY OF CHAR);
      BEGIN
      ASSERT Meth <> PredefItems.Create.Id.Data;
      WriteString(theYaflIdentifier.Anchor(Module, Class, Meth));
      Space;
      END Anchor;
      
    METHOD CreateAnchor (Module, Class: ARRAY OF CHAR);
      BEGIN
      WriteString(theYaflIdentifier.CreateAnchor (Module, Class));
      Space;
      END CreateAnchor;

    METHOD Yu (Ident: ARRAY OF CHAR);
      BEGIN
      WriteString(theYaflIdentifier.Yu(Ident));
      Space;
      END Yu;

    METHOD OnceClassInstance (Module, Class: ARRAY OF CHAR);
      BEGIN
      WriteString(theYaflIdentifier.OnceClassInstance(Module, Class));
      Space;
      END OnceClassInstance;

    METHOD UniqueItem (ItemNr: INTEGER);
      BEGIN
      WriteString(theYaflIdentifier.UniqueItem (ItemNr));
      Space;
      END UniqueItem;
      
    METHOD UniqueWithSuffix (ItemNr: INTEGER;
                             Suffix: ARRAY OF CHAR);
      BEGIN
      WriteString(theYaflIdentifier.UniqueWithSuffix(ItemNr,Suffix));
      Space;
      END UniqueWithSuffix;                             

    METHOD Class (Module, Cl: ARRAY OF CHAR);
      BEGIN
      WriteString(theYaflIdentifier.Class(Module, Cl));
      Space;
      END Class;
      
    METHOD VersionKey (Module, Key: ARRAY OF CHAR);
      BEGIN
      WriteString(theYaflIdentifier.VersionKey(Module, Key));
      Space;
      END VersionKey;
      
    METHOD Additive (Module, Class: ARRAY OF CHAR);
      BEGIN
      WriteString(theYaflIdentifier.Additive (Module, Class));      
      Space;
      END Additive;

    METHOD AdditiveSize (Module, Class: ARRAY OF CHAR);
      BEGIN
      WriteString(theYaflIdentifier.AdditiveSize (Module, Class));
      Space;
      END AdditiveSize;

    METHOD AdditiveDual (Module, Class: ARRAY OF CHAR);
      BEGIN
      WriteString(theYaflIdentifier.AdditiveDual (Module, Class));
      Space;
      END AdditiveDual;

    METHOD AdditiveDualSize (Module, Class: ARRAY OF CHAR);
      BEGIN
      WriteString(theYaflIdentifier.AdditiveDualSize (Module, Class));
      Space;
      END AdditiveDualSize;

    METHOD Module (ModuleName: ARRAY OF CHAR);
      BEGIN
      WriteString(theYaflIdentifier.Module (ModuleName));
      Space;
      END Module;

    METHOD DualType (Module, Class: ARRAY OF CHAR);
      BEGIN
      WriteString(theYaflIdentifier.DualType (Module, Class));
      Space;
      END DualType;

    METHOD DualInstance (Module, Class: ARRAY OF CHAR);
      BEGIN
      WriteString(theYaflIdentifier.DualInstance (Module, Class));
      Space;
      END DualInstance;
      
    METHOD ConstructFunc (Module, Class: ARRAY OF CHAR);
      BEGIN
      WriteString(theYaflIdentifier.ConstructFunc (Module, Class));
      Space;
      END ConstructFunc;

    METHOD PredefinedDual (TypeName: ARRAY OF CHAR);
      BEGIN
      WriteString(theYaflIdentifier.PredefinedDual (TypeName));
      Space;
      END PredefinedDual;

    METHOD ParallelDualId (Module, Class: ARRAY OF CHAR);
      BEGIN
      WriteString(theYaflIdentifier.ParallelDualId (Module, Class));
      Space;
      END ParallelDualId;

--    METHOD Name;
--      BEGIN
--      WriteString(NameString);
--      END Name;

    METHOD LineCount;
      BEGIN
      WriteString(LineCountString);
      END LineCount;

    METHOD SourceFileName;
      BEGIN
      WriteString(SourceFileNameString);
      END SourceFileName;
 
    METHOD LineNumbers;
      BEGIN
      WriteString(LineNumbersString);
      END LineNumbers;

    METHOD FirstClass;
      BEGIN
      WriteString(FirstClassString);
      END FirstClass;

    METHOD LastClass;
      BEGIN
      WriteString(LastClassString);
      END LastClass;

    METHOD SourceLines;
      BEGIN
      WriteString(SourceLinesString);
      END SourceLines;

    METHOD AddMethod;
      BEGIN
      WriteString(AddString);
      Underscore;
      WriteString(MethodString);
      END AddMethod;  

    METHOD AddField;
      BEGIN
      WriteString(AddString);
      Underscore;
      WriteString(FieldString);
      END AddField;  

    METHOD DbxClass;
      BEGIN
      WriteString(DbxString);
      Underscore;
      WriteString(ClassString);
      END DbxClass;  

    METHOD DbxAddClass;
      BEGIN
      WriteString(DbxString);
      Underscore;
      WriteString(AddString);
      Underscore;
      WriteString(ClassString);
      END DbxAddClass;  

    METHOD DbxAddLocal;
      BEGIN
      WriteString(DbxString);
      Underscore;
      WriteString(AddString);
      Underscore;
      WriteString(LocalString);
      END DbxAddLocal;  

    METHOD DbxAddMethod;
      BEGIN
      WriteString(DbxString);
      Underscore;
      WriteString(AddString);
      Underscore;
      WriteString(MethodString);
      END DbxAddMethod;  

    METHOD DbxMethod;
      BEGIN
      WriteString(DbxString);
      Underscore;
      WriteString(MethodString);
      END DbxMethod;  

    METHOD DbxDownLevel;
      BEGIN
      WriteString(DbxString);
      Underscore;
      WriteString(DownString);
      Underscore;
      WriteString(LevelString);
      END DbxDownLevel;  

    METHOD DbxUpLevel;
      BEGIN
      WriteString(DbxString);
      Underscore;
      WriteString(UpString);
      Underscore;
      WriteString(LevelString);
      END DbxUpLevel;  

    METHOD DbxPushCall;
      BEGIN
      WriteString(DbxString);
      Underscore;
      WriteString(PushString);
      Underscore;
      WriteString(CallString);
      END DbxPushCall;  

    METHOD DbxPopCall;
      BEGIN
      WriteString(DbxString);
      Underscore;
      WriteString(PopString);
      Underscore;
      WriteString(CallString);
      END DbxPopCall;  

    METHOD DbxYaflInit;
      BEGIN
      WriteString(DbxString);
      Underscore;
      WriteString(YaflString);
      Underscore;
      WriteString(InitString);
      END DbxYaflInit;  

    METHOD DbxYaflBegin;
      BEGIN
      WriteString(DbxString);
      Underscore;
      WriteString(YaflString);
      Underscore;
      WriteString(BeginString);
      END DbxYaflBegin;  

    METHOD DbxModule;
      BEGIN
      WriteString(DbxString);
      Underscore;
      WriteString(ModuleString);
      END DbxModule;  

    METHOD DbxAddModule;
      BEGIN
      WriteString(DbxString);
      Underscore;
      WriteString(AddString);
      Underscore;
      WriteString(ModuleString);
      END DbxAddModule;

    METHOD Distance;
      BEGIN
      WriteString(DistanceString);
      END Distance;

    METHOD ParallelDual;
      BEGIN
      WriteString(ParallelDualString);
      END ParallelDual;

    METHOD AddMethodRef;
      BEGIN
      WriteString(AddMethodRefString);
      END AddMethodRef;

    METHOD ComputeOld;
      BEGIN
      WriteString(ComputeOldString);
      END ComputeOld;
     
    METHOD VirtualDual;
      BEGIN
      WriteString(theYaflIdentifier.VirtualDual);
      END VirtualDual;

    METHOD RegisterModule;
      BEGIN
      WriteString(RegisterModuleString);
      END RegisterModule;
      
    METHOD ProfileLines;
      BEGIN
      WriteString(ProfileLinesString);
      END ProfileLines;
      
    METHOD ModuleLiteral(Module: ARRAY OF CHAR);
      BEGIN
      WriteString(theYaflIdentifier.ModuleLiteral(Module));
      Space;
      END ModuleLiteral;
      
    METHOD ClassLiteral (Module, Class: ARRAY OF CHAR);
      BEGIN
      WriteString(theYaflIdentifier.ClassLiteral (Module, Class));
      Space;
      END ClassLiteral;
      
    METHOD ModuleInitialization (Module: ARRAY OF CHAR);
      BEGIN
      WriteString(theYaflIdentifier.ModuleInitialization(Module));
      Space;
      END ModuleInitialization;

    METHOD ClassInitialization (Module, Class: ARRAY OF CHAR);
      BEGIN
      WriteString(theYaflIdentifier.ClassInitialization (Module, Class));
      Space;
      END ClassInitialization;

    METHOD ClassDualInitialization (Module, Class: ARRAY OF CHAR);
      BEGIN
      WriteString(theYaflIdentifier.ClassDualInitialization(Module,Class));
      Space;
      END ClassDualInitialization;
      
    -- for fields data
    METHOD ClassFieldsInsertion (Module,Class: ARRAY OF CHAR);
      BEGIN
      WriteString(theYaflIdentifier.ClassFieldsInsertion (Module,Class));
      Space;
      END ClassFieldsInsertion;

    -- for the debugger     
    METHOD DbxModuleInitialization (Module: ARRAY OF CHAR);
      BEGIN
      WriteString(theYaflIdentifier.DbxModuleInitialization (Module));
      Space;
      END DbxModuleInitialization;
      
    METHOD DbxModuleReference (Module: ARRAY OF CHAR);
      BEGIN
      WriteString(theYaflIdentifier.DbxModuleReference (Module));
      Space;
      END DbxModuleReference;
      
    METHOD DbxClassInitialization (Module, Class: ARRAY OF CHAR);
      BEGIN
      WriteString(theYaflIdentifier.DbxClassInitialization (Module, Class));
      Space;
      END DbxClassInitialization;
      
    METHOD DbxClassReference (Module, Class: ARRAY OF CHAR);
      BEGIN
      WriteString(theYaflIdentifier.DbxClassReference (Module, Class));
      Space;
      END DbxClassReference;
      
    METHOD DbxMethodReference (Module, Class, Method: ARRAY OF CHAR);
      BEGIN
      WriteString(theYaflIdentifier.DbxMethodReference (Module,Class,Method));
      Space;
      END DbxMethodReference;

    METHOD DbxFieldReference(Module, Class, Field: ARRAY OF CHAR);
      BEGIN
      WriteString(theYaflIdentifier.DbxFieldReference(Module, Class, Field));
      Space;
      END DbxFieldReference;

    METHOD DbxLocalReference(Module, Class, Method, Local: ARRAY OF CHAR);
      BEGIN
      WriteString(theYaflIdentifier.DbxLocalReference(Module, Class, 
                                                      Method, Local));
      Space;
      END DbxLocalReference;
          
    METHOD ClassCreate (Module, Class: ARRAY OF CHAR);
      BEGIN
      WriteString(theYaflIdentifier.ClassCreate (Module, Class));
      Space;
      END ClassCreate;

    METHOD FirstSignature (UpperCase: BOOLEAN);
      BEGIN
      IF UpperCase THEN
        WriteString (UFirstSigString);
       ELSE
        WriteString (FirstSigString);
        END;
      END FirstSignature;

    METHOD LastSignature (UpperCase: BOOLEAN);
      BEGIN
      IF UpperCase THEN
        WriteString (ULastSigString);
       ELSE
        WriteString (LastSigString);
        END;
      END LastSignature;

    METHOD Allocate (Module, Class: ARRAY OF CHAR);
      ----------------------------------------------
      -- y_alloc((yint)0,0,(obj_ptr)&DUAL)
      ----------------------------------------------
      BEGIN
      WriteString (AllocString);
      LeftParents(2);
      WriteString (YIntString);
      RightParent;
      WriteChar ('0');
      Comma;
      WriteChar ('0');
      Comma;
      LeftParent;
      WriteString (ObjPtrString);
      RightParent;
      Ampersand;
      DualInstance (Module, Class);
      RightParent;
      END Allocate;

    METHOD IsIn;
      BEGIN
      WriteString (IsInString);
      END IsIn;

    METHOD IncludeRuntime;
      BEGIN                     
      IF YaflCfg.TargetPlatform = SYSTEM.Mvs THEN
        WriteLine ('#include <yaflusr.h>');
        WriteLine ('#include <yaflrnt.h>');
       ELSE
        WriteLine ('#include <yafl_usr.h>');
        WriteLine ('#include <yafl_rnt.h>');
        END;
      END IncludeRuntime;

    METHOD IncludeDbxRuntime;
      BEGIN                     
      IF YaflCfg.TargetPlatform = SYSTEM.Mvs THEN
        WriteLine ('#include <dbxrnt.h>');
       ELSE
        WriteLine ('#include <dbx_rnt.h>');
        END;
      END IncludeDbxRuntime;

    METHOD TraceStep (LineNumber: INTEGER);
      BEGIN
      WriteString (SetLineString);
      LeftParent;
      WriteInt (LineNumber, 0);
      RightParent;
      SemiColon;
      END TraceStep;

    ---------------------------------------------
    -- The various fail conditions
    ---------------------------------------------
    METHOD FailWhat (ModuleName: ARRAY OF CHAR;
                     LineNumber: INTEGER;
                     VarNr: INTEGER);
      BEGIN
      WriteString (FailWhatString);
      LeftParent;
      QuotedString (ModuleName, FALSE);
      Comma;
      WriteInt (LineNumber, 0);
      Comma;
      IF VarNr <> 0 THEN
        UniqueItem (VarNr);
       ELSE
        LeftParent;
        ObjPtr;
        RightParent;
        Zero;
        END;
      RightParent;
      SemiColon;
      END FailWhat;

    METHOD FailCase (ModuleName: ARRAY OF CHAR;
                     LineNumber: INTEGER;
                     DiscVar: INTEGER);
      BEGIN
      WriteString (FailCaseString);
      LeftParent;
      QuotedString (ModuleName, FALSE);
      Comma;
      WriteInt (LineNumber, 0);
      Comma;
      UniqueItem (DiscVar);
      RightParent;
      SemiColon;
      END FailCase;

    METHOD FailAssert (ModuleName: ARRAY OF CHAR;
                       LineNumber: INTEGER);
      BEGIN
      WriteString (FailAssertString);
      LeftParent;
      QuotedString (ModuleName, FALSE);
      Comma;
      WriteInt (LineNumber, 0);
      RightParent;
      SemiColon;
      END FailAssert;

    METHOD FailVoidMethod;
      BEGIN
      WriteString (FailVoidString);
      END FailVoidMethod;

    METHOD FailUndefMethod (ModuleName,
                            ClassName,
                            MethodName: ARRAY OF CHAR);
      BEGIN
      WriteString (FailUndefMethodString);
      LeftParent;
      QuotedString (ModuleName, FALSE);
      Comma;
      QuotedString (ClassName, FALSE);
      Comma;
      QuotedString (MethodName, FALSE);
      Comma;
      This;
      RightParent;
      SemiColon;
      END FailUndefMethod;

    METHOD FailBadClass (ModuleName,
                         ClassName,
                         MethodName: ARRAY OF CHAR);
      BEGIN
      WriteString (FailBadClassString);
      LeftParent;
      QuotedString (ModuleName, FALSE);
      Comma;
      QuotedString (ClassName, FALSE);
      Comma;
      QuotedString (MethodName, FALSE);
      RightParent;
      SemiColon;
      END FailBadClass;

    METHOD EnterMethod;
      BEGIN           
      WriteLn;
      WriteString (EnterMethodString);
      END EnterMethod;

    METHOD ExitMethod;
      BEGIN
      WriteString (ExitMethodString);
      SemiColon;
      WriteLn;
      END ExitMethod;

    ---------------------------------------------
    -- Reserved words generation method
    ---------------------------------------------
    METHOD TypeDef;
      BEGIN
      WriteString (TypeDefString);
      END TypeDef;

    METHOD Struct;
      BEGIN
      WriteString (StructString);
      END Struct;

    METHOD While;
      BEGIN
      WriteString (WhileString);
      END While;

    METHOD For;
      BEGIN
      WriteString (ForString);
      END For;

    METHOD If;
      BEGIN
      WriteChar ('i');
      WriteChar ('f');
      END If;

    METHOD Else;
      BEGIN
      WriteString (ElseString);
      END Else;

    METHOD Switch;
      BEGIN
      WriteString (SwitchString);
      END Switch;

    METHOD Case;
      BEGIN
      WriteString (CaseString);
      END Case;

    METHOD Default;
      BEGIN
      WriteString (DefaultString);
      END Default;

    METHOD Void;
      BEGIN
      WriteString (VoidString);
      END Void;

    METHOD ObjPtr;
      BEGIN
      WriteString (ObjPtrString);
      END ObjPtr;

    METHOD Char;
      BEGIN
      WriteString (CharString);
      END Char;

    METHOD Int;
      BEGIN
      WriteString (IntString);
      END Int;

    METHOD Unsigned;
      BEGIN
      WriteString (UnsignedString);
      END Unsigned;

    METHOD UnsignedInt;
      BEGIN
      WriteString (UnsignedIntString);
      END UnsignedInt;
        
    METHOD High;
      BEGIN
      WriteString (HighString);
      END High;

    METHOD Ansi;
      BEGIN
      WriteString (AnsiString);
      WriteLn;
      END Ansi;

    METHOD UnivClone;
      BEGIN
      WriteString (UnivCloneString);
      END UnivClone;

    METHOD UnivKill;
      BEGIN
      WriteString (UnivKillString);
      END UnivKill;

    METHOD UnivSlice;
      BEGIN
      WriteString (UnivSliceString);
      END UnivSlice;

    METHOD UnivConcat(Arity: INTEGER);
      BEGIN
      Need(12);
      WriteString (UnivConcatString);
      ASSERT Arity < 9;
      IF Arity > 2 THEN
        WriteChar (SYSTEM.CHR(Arity + SYSTEM.ORD('0')));
        END;
      END UnivConcat;

    METHOD ArrayElement;
      BEGIN
      WriteString (ArrayElementString);
      END ArrayElement;

    METHOD Alloc;
      BEGIN
      WriteString (AllocString);
      END Alloc;

    METHOD ReAlloc;
      BEGIN
      WriteString (ReAllocString);
      END ReAlloc;

    METHOD EnterPool;
      BEGIN
      WriteString (EnterPoolString);
      END EnterPool;

    METHOD MinimalDual;
      BEGIN
      WriteString(theYaflIdentifier.MinimalDual);
      Space;
      -- WriteString (MinimalDualString);
      END MinimalDual;

    METHOD FieldInfo;
      BEGIN      
      WriteString(theYaflIdentifier.FieldInfo);
      END FieldInfo;

    METHOD MethodInfo;
      BEGIN
      WriteString(MethodInfoString);
      END MethodInfo;

    METHOD LocalInfo;
      BEGIN
      WriteString(LocalInfoString);
      END LocalInfo;

    METHOD CloneFunc;
      BEGIN
      WriteString (CloneFuncString);
      END CloneFunc;

    METHOD KillFunc;
      BEGIN
      WriteString (KillFuncString);
      END KillFunc;

    METHOD ElementSize;
      BEGIN
      WriteString (ElementSizeString);
      END ElementSize;

    METHOD DualSize;
      BEGIN
      WriteString (DualSizeString);
      END DualSize;

    METHOD ClassName;
      BEGIN
      WriteString (ClassNameString);
      END ClassName;
      
    METHOD ModuleName;
      BEGIN
      WriteString (ModuleNameString);
      END ModuleName;

    METHOD BeginLine;
      BEGIN
      WriteString(BeginLineString);
      END BeginLine;

    METHOD EndLine;
      BEGIN
      WriteString(EndLineString);
      END EndLine;

    METHOD OncePtr;
      BEGIN
      WriteString(OncePtrString);
      END OncePtr;

    METHOD CurrentModuleName;
      BEGIN
      WriteString (CurrentModuleNameString);
      END CurrentModuleName;

    METHOD Inherited;
      BEGIN
      WriteString (InheritedString);
      END Inherited;

    METHOD OrigMethCount;
      BEGIN
      WriteString (OrigMethCountString);
      END OrigMethCount;

    METHOD InhMethCount;
      BEGIN
      WriteString (InhMethCountString);
      END InhMethCount;

    METHOD MoISInit;
      BEGIN
      WriteString (MoISInitString);
      END MoISInit;

    METHOD Align;
      BEGIN
      WriteString (AlignString);
      END Align;

    METHOD MarkFunc;
      BEGIN
      WriteString (MarkFuncString);
      END MarkFunc;
      
    METHOD Offset;
      BEGIN
      WriteString (OffsetString);
      END Offset;

    METHOD OffsetField;
      BEGIN
      WriteString (OffsetFieldString);
      END OffsetField;

    METHOD ReturnDual;
      BEGIN
      WriteString (ReturnDualString);
      END ReturnDual;

    METHOD ReturnArrayLevel;
      BEGIN
      WriteString (ReturnArrayLevelString);
      END ReturnArrayLevel;

    METHOD CheckVersion;
      BEGIN
      WriteString (CheckVersionString);
      END CheckVersion;
      
    METHOD MarkArray;
      BEGIN
      WriteString (MarkArrayString);
      END MarkArray;
      
    METHOD ReqMark;
      BEGIN       
      WriteString (ReqMarkString);
      END ReqMark;
      
    METHOD OnceTab;
      BEGIN
      WriteString (OnceTabString);
      END OnceTab;

    METHOD OnceInstance;
      BEGIN
      WriteString (OnceInstanceString);
      END OnceInstance;
      
    METHOD SaveDStack(VarNr: INTEGER);
      BEGIN       
      WriteLn;
      WriteString(SaveDStackString);
      LeftParent;
      UniqueItem (VarNr);
      RightParent;
      WriteLn;
      END SaveDStack;
      
    METHOD RestoreDStack(VarNr: INTEGER);
      BEGIN
      WriteLn;
      WriteString(RestoreDStackString);
      LeftParent;
      UniqueItem (VarNr);
      RightParent;
      WriteLn;
      END RestoreDStack;
      
    METHOD SaveVStack(VarNr: INTEGER);
      BEGIN
      WriteLn;
      WriteString(SaveVStackString);
      LeftParent;
      UniqueItem (VarNr);
      RightParent;
      WriteLn;
      END SaveVStack;
      
    METHOD RestoreVStack(VarNr: INTEGER);
      BEGIN
      WriteLn;
      WriteString(RestoreVStackString);
      LeftParent;
      UniqueItem (VarNr);
      RightParent;
      WriteLn;
      END RestoreVStack;

    METHOD CheckDualOverflow;
      BEGIN
      WriteString (CheckDualOverflowString);
      END CheckDualOverflow;

    METHOD ZeroMem;
      BEGIN
      WriteString (ZeroMemString);
      END ZeroMem;

    METHOD Memset;
      BEGIN
      WriteString (MemsetString);
      END Memset;

    METHOD Context;
      BEGIN
      WriteString (ContextString);
      END Context;
      
    METHOD YArgs;
      BEGIN
      Need(8);
      WriteString (YArgsString);
      END YArgs;
      
    METHOD ToUpper;
      BEGIN
      Need(12);
      WriteString (ToUpperString);
      END ToUpper;
      
    METHOD ToLower;
      BEGIN
      Need(12);
      WriteString (ToLowerString);
      END ToLower;
      
    METHOD YFormals(Arity: INTEGER);
      BEGIN
      ASSERT Arity >= 0;
      ASSERT Arity <= 64;
      Need(12);
      WriteString (YFormalsString);
      WriteInt (Arity * 2, 0);
      END YFormals;
  -----------------------------------------------
  -- useful things for the debugger
  -----------------------------------------------
    METHOD BoolValue(Value : BOOLEAN);
      BEGIN
      IF Value THEN
        WriteChar("1");
       ELSE
        WriteChar("0");
        END;
      END BoolValue;

    METHOD Null;
      BEGIN
      LeftParent;
      ObjPtr;
      RightParent;
      WriteChar("0");
      END Null;
      
    METHOD OutputLabel (Label: INTEGER);
      BEGIN
      ASSERT Label >= FirstLabel;
      ASSERT Label <= LastLabel;
      CASE Label OF
        FullTraceModeLabel:
          WriteString(FullTraceModeLabelString);
          END;      
        DebugModeLabel:
          WriteString(DebugModeLabelString);
          END;
        ProfileModeLabel:
          WriteString(ProfileModeLabelString);
          END;
        TraceModeLabel:
          WriteString(TraceModeLabelString);
          END;
        ForceStructLabel:
          WriteString(ForceStructLabelString);
          END;
        CheckDualLabel:
          WriteString(CheckDualLabelString);
          END;
        CheckVoidMethodLabel:
          WriteString(CheckVoidMethodLabelString);
          END;
        CheckVoidObjectLabel:
          WriteString(CheckVoidObjectLabelString);
          END;
        CheckArrayLabel:
          WriteString(CheckArrayLabelString);
          END;
        CheckWhatLabel:
          WriteString(CheckWhatLabelString);
          END;
        CheckCaseLabel:
          WriteString(CheckCaseLabelString);
          END;
        CheckDebugLabel:
          WriteString(CheckDebugLabelString);
          END;
        CheckAssertLabel:
          WriteString(CheckAssertLabelString);
          END;
        CheckVersionLabel:
          WriteString(CheckVersionLabelString);
          END;
        NeedAddMethRefLabel:
          WriteString(NeedAddMethRefLabelString);
          END;
        CheckLoopInvariantLabel:
          WriteString(CheckLoopInvariantLabelString);
          END;
        CheckClassInvariantLabel:
          WriteString(CheckClassInvariantLabelString);
          END;
        CheckPostCondLabel:
          WriteString(CheckPostCondLabelString);
          END;
        CheckPreCondLabel:
          WriteString(CheckPreCondLabelString);
          END;
        CheckContextFreePreCondLabel:
          WriteString(CheckContextFreePreCondLabelString);
          END;
        CheckContextDepPreCondLabel:
          WriteString(CheckContextDepPreCondLabelString);
          END;
        END; -- Case.           
      END OutputLabel;
      
    METHOD DefineLabel (Label: INTEGER);
      BEGIN
      Define;
      OutputLabel (Label);
      WriteChar (' ');
      WriteChar ('1');
      WriteLn;
      END DefineLabel;
      
-- XXJC (d)      
    METHOD CheckPreCondition;
      BEGIN
      WriteString(CheckPreConditionString);
      END CheckPreCondition;

    METHOD CheckPostConditions;
      BEGIN
      WriteString(CheckPostConditionsString);
      END CheckPostConditions;

    METHOD ComputeOldExpressions;
      BEGIN
      WriteString(ComputeOldExpressionsString);
      END ComputeOldExpressions;

    METHOD AssertionStackPushInt;
      BEGIN
      WriteString(AssertionStackPushIntString);
      END AssertionStackPushInt;
      
    METHOD AssertionStackPushObj;
      BEGIN
      WriteString(AssertionStackPushObjString);
      END AssertionStackPushObj;
      
    METHOD AssertionStackPushChar;
      BEGIN
      WriteString(AssertionStackPushCharString);
      END AssertionStackPushChar;
      
    METHOD AssertionStackPushReal;
      BEGIN
      WriteString(AssertionStackPushRealString);
      END AssertionStackPushReal;
      
    METHOD AssertionStackPopInt;
      BEGIN
      WriteString(AssertionStackPopIntString);
      END AssertionStackPopInt;
      
    METHOD AssertionStackPopObj;
      BEGIN
      WriteString(AssertionStackPopObjString);
      END AssertionStackPopObj;
      
    METHOD AssertionStackPopChar;
      BEGIN
      WriteString(AssertionStackPopCharString);
      END AssertionStackPopChar;
      
    METHOD AssertionStackPopReal;
      BEGIN
      WriteString(AssertionStackPopRealString);
      END AssertionStackPopReal;
      
    METHOD AssertionStackGetInt;
      BEGIN
      WriteString(AssertionStackGetIntString);
      END AssertionStackGetInt;
      
    METHOD AssertionStackGetObj;
      BEGIN
      WriteString(AssertionStackGetObjString);
      END AssertionStackGetObj;
      
    METHOD AssertionStackGetChar;
      BEGIN
      WriteString(AssertionStackGetCharString);
      END AssertionStackGetChar;
      
    METHOD AssertionStackGetReal;
      BEGIN
      WriteString(AssertionStackGetRealString);
      END AssertionStackGetReal;
      
    METHOD OldStackName;
      BEGIN
      WriteString(OldStackNameString);
      END OldStackName;
      
    METHOD AssertionStackName;
      BEGIN
      WriteString(AssertionParamStackNameString);
      END AssertionStackName;

    METHOD AssertionStackPushLevel;
      BEGIN
      WriteString(AssertionStackPushLevelString);
      END AssertionStackPushLevel;

    METHOD AssertionStackPopLevel;
      BEGIN
      WriteString(AssertionStackPopLevelString);
      END AssertionStackPopLevel;

    METHOD ContextFreePreCondFName(Module, Class, Method: ARRAY OF CHAR);
      BEGIN
      WriteString(theYaflIdentifier.ContextFreePreCondFuncName(Module, 
                                                   Class, Method));
      END ContextFreePreCondFName;
      
    METHOD ContextDepPreCondFName(Module, 
                                           Class, 
                                           Method: ARRAY OF CHAR);
      BEGIN
      WriteString(theYaflIdentifier.ContextDependentPreCondFuncName(Module,
                                           Class, Method));
      END ContextDepPreCondFName;
      
    METHOD PostConditionFName(Module, Class, Method: ARRAY OF CHAR);
      BEGIN
      WriteString(theYaflIdentifier.PostConditionFunctionName(Module, 
                                                              Class, Method));
      END PostConditionFName;

    METHOD ComputeOldExprFName(Module, Class, Method: ARRAY OF CHAR);
      BEGIN
      WriteString(theYaflIdentifier.ComputeOldFunctionName(Module, 
                                                           Class, Method));
      END ComputeOldExprFName;
      
    METHOD MethodChainInitialisation(Module, Class: ARRAY OF CHAR);
      BEGIN
      WriteString(theYaflIdentifier.MethodChainInitialisation(Module, Class));
      END MethodChainInitialisation;

    METHOD AttachRedefinedMethod;   
      BEGIN
      WriteString(AttachRedefinedMethodString);
      END AttachRedefinedMethod;
      
    METHOD Entry;
      BEGIN
      WriteString(EntryString);
      END Entry;  
      
    METHOD Base;
      BEGIN
      WriteString(BaseMethodString);
      END Base;  
      
    METHOD SetBit;
      BEGIN
      WriteString(SetBitString);
      END SetBit;  
-- END XXJC (d)
      
    METHOD AssignObjPtr;
      BEGIN
      WriteString (AssignObjPtrString);
      END AssignObjPtr;

-- XXJC (d)
    METHOD PreContextFree;
      BEGIN
      WriteString (PreContextFreeString);
      END PreContextFree;
      
    METHOD PreContextDep;
      BEGIN
      WriteString (PreContextDepString);
      END PreContextDep;
      
    METHOD PostCondition;
      BEGIN
      WriteString (PostFuncString);
      END PostCondition;
-- END XXJC (d)
      
    METHOD IfDefined (Label: INTEGER);
      BEGIN
      IfDef;
      OutputLabel (Label);
      WriteLn;
      END IfDefined;
      
    METHOD IfNDefined (Label: INTEGER);
      BEGIN
      IfNDef;
      OutputLabel (Label);
      WriteLn;
      END IfNDefined;
      
    METHOD InitStrings;
      BEGIN

      IfNDefString :=                   "#ifndef ";
      IfDefString :=                    "#ifdef ";
      AnsiString :=                     "YAFL_ANSI";
      EndIfString :=                    "#endif";
      ElseDefString :=                  "#else";
      FirstSigString :=                 "first_sig";
      LastSigString :=                  "last_sig";
      UFirstSigString :=                "FIRST_SIG";
      ULastSigString :=                 "LAST_SIG";
      DefineString :=                   "#define ";
      UndefineString :=                 "#undef ";
      InclString :=                     "#include ";
      LastSigString :=                  "last_sig";
      MethodInfoString :=               "METHOD_INFO";
      LocalInfoString :=                "LOCAL_INFO";
      NewStringString :=                "new_string";
      SetLineString :=                  "SET_LINE";
      FailWhatString :=                 "fail_what";
      FailCaseString :=                 "fail_case";
      FailAssertString :=               "fail_assert";
      FailVoidString :=                 "fail_void_obj";
      FailUndefMethodString :=          "fail_void_mth";
      FailBadClassString :=             "fail_bad_class";
      EnterMethodString :=              "ENTER_METHOD";
      ExitMethodString :=               "EXIT_METHOD";
      AllocString :=                    "y_alloc";
      ReAllocString :=                  "y_realloc";
      IsInString :=                     "is_in";
                                       
      StructString :=                   "struct ";
      TypeDefString :=                  "typedef ";
      WhileString :=                    "while";
      ForString :=                      "for";
      ElseString :=                     "else ";
      VoidString :=                     "void ";
      SizeOfString :=                   "sizeof ";
      ExternString :=                   "extern ";
      StaticString :=                   "static ";
      ReturnString :=                   "return ";
      SwitchString :=                   "switch ";
      CaseString :=                     "case ";
      DefaultString :=                  "default ";
      JumpString :=                     "goto ";
      BreakString :=                    "break";
      ConstString :=                    "const ";
      MallocString :=                   "malloc ";
                                       
      ObjPtrString :=                   "obj_ptr ";
      CharString :=                     "char ";
      IntString :=                      "int ";
      YIntString :=                     "yint ";
      UnsignedString :=                 "unsigned ";
      UnsignedIntString :=              "yuint ";
      ThisString :=                     "Y_THIS";
      CastedThisString :=               "THIS";
      ResultString :=                   "Y_RESULT";
      TagString :=                      "Y_TAG";
      HeaderString :=                   "header";
      DualString :=                     "dual";
      HighString :=                     "HIGH";
      UnivCloneString :=                "univ_clone";
      UnivKillString :=                 "univ_kill";
      UnivSliceString :=                "univ_slice";
      UnivConcatString :=               "univ_concat";
      ArrayElementString :=             "ARRAY_ELEMENT";
      EnterPoolString :=                "enter_pool";
      CloneFuncString :=                "clone_func";
      KillFuncString :=                 "kill_func";
      ElementSizeString :=              "elem_size";
      DualSizeString :=                 "dual_size";
      ClassNameString :=                "class_name";
      ModuleNameString :=               "module_name";
      BeginLineString :=                "beginline";
      EndLineString :=                  "endline";
      OncePtrString :=                  "once_ptr";
      CurrentModuleNameString :=        "Y_CURRENT_MODULE";
      InheritedString :=                "inherited";
      OrigMethCountString :=            "orig_meth_count";
      InhMethCountString :=             "inh_meth_count";
      MoISInitString :=                 "mois_init";
      AlignString :=                    "ALIGN";
      MarkFuncString :=                 "mark_func";
      OffsetString :=                   "OFFSET";
      OffsetFieldString :=              "offset";
      ReturnDualString :=               "return_dual";
      ReturnArrayLevelString :=         "return_array_level";
      DefaultCloneString :=             "default_clone";
      RegString :=                      "REG";
      FlyVRegString :=                  "FLYVREG";
      VRegString :=                     "VREG";
      RegisterClassString :=            "register_class";
      SaveDStackString :=               "SAVE_DSTACK";
      SaveVStackString :=               "SAVE_VSTACK";
      RestoreDStackString :=            "RESTORE_DSTACK";
      RestoreVStackString :=            "RESTORE_VSTACK";
      CheckDualOverflowString :=        "CHECK_DUAL_OVFL";
      CheckVersionString :=             "CHECK_VERSION";
      ZeroMemString :=                  "ZERO";
      MemsetString :=                   "y_memset";
      ContextString :=                  "CONTEXT";
      YArgsString :=                    "YARGS";
      ToUpperString :=                  "toupper";
      ToLowerString :=                  "tolower";
      YFormalsString :=                 "YPARAMS";
      MarkArrayString :=                "mark_tab";
      ReqMarkString :=                  "requires_marking";
      OnceTabString :=                  "once_tab";
      OnceInstanceString :=             "once_inst";
      AssignObjPtrString :=             "ASSIGN_OBJ_PTR";
      PreContextFreeString :=           "pre_context_free";
      PreContextDepString :=            "pre_context_dep";
      PostFuncString :=                 "post_func";
      RegisterModuleString :=           "register_module";
      ProfileLinesString :=             "y_profile_lines";
                                       
      MethodRefString :=                "method_ref "; 
      CurrentString :=                  "current";
      IntFuncString :=                  "int_func";
      BooleanFuncString :=              "boolean_func";
      CharFuncString :=                 "char_func";
      DoubleFuncString :=               "double_func";
      ObjPtrFuncString :=               "obj_ptr_func";
      VoidFuncString :=                 "void_func";
--      NameString :=                     "name";
      LineCountString :=                "line_count";
      SourceFileNameString :=           "source_file_name";
      LineNumbersString :=              "line_numbers";
      FirstClassString :=               "first_class";
      LastClassString :=                "last_class";
      SourceLinesString :=               "Y_SOURCE_LINES";
                                       
      TrueString :=                     "TRUE";
      FalseString :=                    "FALSE";
      ModuleDualString :=               "module_dual";
                                       
      DbxString :=                      "dbx";
      AddString :=                      "add";
      ClassString :=                    "class";
      LocalString :=                    "local";
      MethodString :=                   "method";
      DownString :=                     "down";
      UpString :=                       "up";
      LevelString :=                    "level";
      PushString :=                     "push";
      PopString :=                      "pop";
      YaflString :=                     "yafl";
      InitString :=                     "init";
      BeginString :=                    "begin";
      ModuleString :=                   "module";
      FieldString :=                    "field";
      CallString :=                     "call";
      AppendString :=                   "append";
      DistanceString :=                 "DISTANCE";
      ParallelDualString :=             "parallel_dual";
      AddMethodRefString :=             "add_method_ref ";
      ComputeOldString :=               "compute_old";      
               
      FullTraceModeLabelString :=       "YFULL_DEBUG_MODE";  
      DebugModeLabelString :=           "YDEBUG_MODE";
      ProfileModeLabelString :=         "YPROFILE_MODE";
      TraceModeLabelString :=           "YTRACE_MODE";
      ForceStructLabelString :=         "YFORCE_STRUCT";
      CheckDualLabelString :=           "YCHECK_DUAL";
      CheckVoidMethodLabelString :=     "YCHECK_VOID_METH";
      CheckVoidObjectLabelString :=     "YCHECK_VOID_OBJ";
      CheckArrayLabelString :=          "YCHECK_ARRAY";
      CheckCaseLabelString :=           "YCHECK_CASE";
      CheckWhatLabelString :=           "YCHECK_WHAT";
      CheckDebugLabelString :=          "YCHECK_DEBUG";
      CheckAssertLabelString :=         "YCHECK_ASSERT";
      CheckVersionLabelString :=        "YCHECK_VERSION";
      NeedAddMethRefLabelString :=      "NEED_ADD_METH_REF";
      
      AssertionStackPushIntString    := "assert_stack_push_int";
      AssertionStackPushObjString    := "assert_stack_push_obj";
      AssertionStackPushCharString   := "assert_stack_push_char";
      AssertionStackPushRealString   := "assert_stack_push_double";
      AssertionStackPopIntString     := "assert_stack_pop_int";
      AssertionStackPopObjString     := "assert_stack_pop_obj";
      AssertionStackPopCharString    := "assert_stack_pop_char";
      AssertionStackPopRealString    := "assert_stack_pop_double";
      AssertionStackGetIntString     := "assert_stack_get_int";
      AssertionStackGetObjString     := "assert_stack_get_obj";
      AssertionStackGetCharString    := "assert_stack_get_char";
      AssertionStackGetRealString    := "assert_stack_get_double";
      AssertionStackPushLevelString  := "assert_stack_push_level";
      AssertionStackPopLevelString   := "assert_stack_pop_level";
      AssertionParamStackNameString  := "param_stack";
      OldStackNameString             := "old_stack";
      CheckPreConditionString        := "check_pre_cond";
      CheckPostConditionsString      := "check_post_conditions";
      ComputeOldExpressionsString    := "compute_old_expressions";
      ComputeOldString               := "compute_old";      
      AttachRedefinedMethodString    := "attach_redefined_method";
      BaseMethodString               := "base";
      EntryString                    := "entry";
      SetBitString                   := "SET_BIT";
      
      CheckLoopInvariantLabelString      := "YCHECK_LOOP_INVARIANT";
      CheckClassInvariantLabelString     := "YCHECK_CLASS_INVARIANT";
      CheckPostCondLabelString           := "YCHECK_POST_CONDITION";
      CheckPreCondLabelString            := "YCHECK_PRE_CONDITION";
      CheckContextFreePreCondLabelString := "YCHECK_CF_PRE_CONDITION";
      CheckContextDepPreCondLabelString  := "YCHECK_CD_PRE_CONDITION";
      
      END InitStrings;
      
  END YaflGC;

  CLASS YaflIdentifier;

    REDEFINE METHOD CREATE;
      BEGIN
      IF MethodPrefix = VOID THEN
        InitStrings;
        ASSERT MethodPrefix <> VOID;
        END;
      TheInternalMaxIdentLen := YaflCfg.InternalMaxIdentLen;
      TheExternalMaxIdentLen := YaflCfg.ExternalMaxIdentLen;
      ASSERT TheInternalMaxIdentLen >= 8;
      ASSERT TheExternalMaxIdentLen >= 8;
      END CREATE;
  
  VAR
      MethodPrefix, AnchorPrefix, CreateAnchorPrefix,
      YuPrefix, ModuleDualPrefix, ModuleLinesPrefix,
      ModuleProfilePrefix,
      ClassPrefix, VersionPrefix,
      AdditivePrefix, AdditiveSizePrefix,
      AdditiveDualPrefix, AdditiveDualSizePrefix, ModuleNamePrefix,
      DualTypePrefix, DualInstancePrefix,
      ModuleLiteralPrefix, ClassLiteralPrefix,
      ModuleInitializationPrefix, ClassInitializationPrefix,
      ClassDualInitializationPrefix, ClassCreatePrefix,
      ConstructFuncPrefix, MinimalDualString, FieldInfoString,

      ClassFieldsInsertionPrefix, -- for fields data
      
      ParallelDualPrefix,
      
      DbxModuleInitializationPrefix, DbxModuleReferencePrefix, -- for
      DbxClassInitializationPrefix,  DbxClassReferencePrefix,  -- the
      DbxMethodReferencePrefix, -- debugger 
      DbxFieldReferencePrefix,
      DbxLocalReferencePrefix,

      VirtualDualNameString,

      ContextFreePreCondFuncPrefix,
      ContextDependentPreCondFuncPrefix,
      ComputeOldFunctionPrefix,
      PostConditionFunctionPrefix,
      DbxMethodChainInitPrefix:          ONCE ARRAY OF CHAR;

      TheInternalMaxIdentLen, 
      TheExternalMaxIdentLen : INTEGER;

    METHOD InitStrings;
      BEGIN
      MethodPrefix :=                  "YM_";
      AnchorPrefix :=                  "YG_";
      CreateAnchorPrefix :=            "YH_";
      YuPrefix :=                      "Y_";
      ClassPrefix :=                   "YC_";
      VersionPrefix :=                 "YV_";
      AdditivePrefix :=                "YTB_";
      AdditiveSizePrefix :=            "YTS_";
      AdditiveDualPrefix :=            "YDB_";
      AdditiveDualSizePrefix :=        "YDS_";
      ModuleNamePrefix :=              "YU_";
      ModuleDualPrefix :=              "YMD_";
      ModuleLinesPrefix :=             "YML_";
      ModuleProfilePrefix :=           "YMP_";
      DualTypePrefix :=                "YT_";
      DualInstancePrefix :=            "YD_";
      ModuleInitializationPrefix :=    "YIM_";
      ModuleLiteralPrefix :=           "YNM_";
      ClassLiteralPrefix :=            "YNC_";
      ClassInitializationPrefix :=     "YIC_";
      ClassDualInitializationPrefix := "YID_";
      ClassCreatePrefix :=             "YIR_";
      ConstructFuncPrefix :=           "YIP_";
      ParallelDualPrefix :=            "YPD_";
          
      ClassFieldsInsertionPrefix        := "YIF_"; -- for fields data
      DbxModuleInitializationPrefix     := "XIMO_"; -- for the debugger
      DbxModuleReferencePrefix          := "XRMO_";
      DbxClassInitializationPrefix      := "XIC_"; 
      DbxClassReferencePrefix           := "XRC_";
      DbxMethodReferencePrefix          := "XRME_"; 
      DbxFieldReferencePrefix           := "XRF_";
      DbxLocalReferencePrefix           := "XRL_";
      
      ContextFreePreCondFuncPrefix       := "AFPF_"; -- for the pre- and post- 
      ContextDependentPreCondFuncPrefix  := "ADPF_"; -- conditions. 
      PostConditionFunctionPrefix        := "APOF_"; 
      ComputeOldFunctionPrefix           := "ACOF_"; 
      DbxMethodChainInitPrefix           := "XIMM_";

      VirtualDualNameString              := "VIRT";

      MinimalDualString                  := "minimal_dual";
      FieldInfoString                    := "FIELD_INFO";
 
    END InitStrings;

    METHOD Hash (Src: ARRAY OF CHAR;
                 Seed: INTEGER): INTEGER;
      VAR
         Treble: INTEGER;
      BEGIN
      ASSERT Src <> VOID;
      RESULT := 1797*1797;
      Treble := Seed;
      FOR i := 0 TO Src.SIZE - 1 DO
        RESULT := RESULT + Treble + 
                  (RESULT * RESULT * Treble * (SYSTEM.ORD(Src[i]) + i));
        Treble := Treble + 7;
        END;
      IF RESULT < 0 THEN
        RESULT := - RESULT;
        END;
      RESULT := RESULT MOD 800000000;
      END Hash;

    METHOD OutputLongIdent (Src: ARRAY OF CHAR;
                            MaxIdentLen: INTEGER): ARRAY OF CHAR;
      VAR
        Nr: ARRAY OF CHAR;
        i, Seed: INTEGER;         
        LetterDigits: ONCE ARRAY OF CHAR;
      CONST
        NrLen = 8;     
        BrutalThreshold = 10;
      BEGIN  
      IF MaxIdentLen < BrutalThreshold THEN
        IF LetterDigits = VOID THEN
          LetterDigits := 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
          ASSERT LetterDigits.SIZE = 26;
          END;                                         
        Nr := LetterDigits.SLICE (Hash(Src, 7) MOD 26, 1);
        Seed := 7;
        WHILE (Nr.SIZE < MaxIdentLen) DO
          Nr := Nr + IntConversions.IntToAnyString (Hash(Src,Seed), 0,
                                     Base := IntConversions.MaxBase);
          Seed := Seed + 17;                                     
          END;
        RESULT:= (Nr.SLICE (0, MaxIdentLen));
       ELSE
        -- Need (MaxIdentLen + 5);   -- 5 more, just in case
        Nr := IntConversions.IntToHexString(Hash(Src, 7), NrLen);
        ASSERT Nr.SIZE = NrLen;
        WHILE Nr[i] = ' ' DO
          ASSERT i < NrLen;
          Nr[i] := '0';
          i := i + 1;
          END;
        RESULT:= RESULT + (Src.SLICE (0, MaxIdentLen - NrLen)) + Nr;
        END;
      END OutputLongIdent;
      
    METHOD MaxIdentLen (Internal: BOOLEAN): INTEGER;
      BEGIN
      IF Internal THEN
        RESULT := TheInternalMaxIdentLen;
       ELSE
        RESULT := TheExternalMaxIdentLen;
        END;
      END MaxIdentLen;

    METHOD Output2Ident (One, Two: ARRAY OF CHAR;
                         Internal: BOOLEAN): ARRAY OF CHAR;
      VAR
        MaxLen: INTEGER;                         
      BEGIN
      ASSERT One <> VOID;
      ASSERT Two <> VOID;
      MaxLen := MaxIdentLen (Internal);
      IF One.SIZE + Two.SIZE > MaxLen THEN
        RESULT:=OutputLongIdent (One + Two, MaxLen);
      ELSE
      --  Need (One.SIZE + Two.SIZE);
        RESULT:= One + Two;
        END;
      -- RESULT:= RESULT + (' ');
      END Output2Ident;

    METHOD Output3Ident (One, Two, Three: ARRAY OF CHAR;
                         Internal: BOOLEAN): ARRAY OF CHAR;
      VAR
        MaxLen: INTEGER;
      BEGIN
      ASSERT One <> VOID;
      ASSERT Two <> VOID;
      ASSERT Three <> VOID;
      MaxLen := MaxIdentLen (Internal);
      IF One.SIZE + Two.SIZE + Three.SIZE > MaxLen THEN
        RESULT:=OutputLongIdent (One + Two + Three, MaxLen);
      ELSE
        -- Need (One.SIZE + Two.SIZE + Three.SIZE);
        RESULT:= One + Two + Three;
        END;
      -- WriteChar (' ');
      END Output3Ident;

    METHOD Output4Ident (One, Two, Three, Four: ARRAY OF CHAR;
                         Internal: BOOLEAN): ARRAY OF CHAR ;
      VAR
        MaxLen: INTEGER;
      BEGIN
      ASSERT One <> VOID;
      ASSERT Two <> VOID;
      ASSERT Three <> VOID;
      ASSERT Four <> VOID;
      MaxLen := MaxIdentLen (Internal);
      IF One.SIZE + Two.SIZE + Three.SIZE + Four.SIZE > MaxLen THEN
        RESULT:=OutputLongIdent (One + Two + Three + Four, MaxLen);
       ELSE
        -- Need (One.SIZE + Two.SIZE + Three.SIZE + Four.SIZE);
        RESULT:= One + Two + Three + Four;
        END;
      -- WriteChar (' ');
      END Output4Ident;
      
    METHOD Output5Ident (One, Two, Three, Four, Five: ARRAY OF CHAR;
                         Internal: BOOLEAN): ARRAY OF CHAR;
      VAR
        MaxLen: INTEGER;
      BEGIN
      ASSERT One <> VOID;
      ASSERT Two <> VOID;
      ASSERT Three <> VOID;
      ASSERT Four <> VOID;
      ASSERT Five <> VOID;                
      MaxLen := MaxIdentLen (Internal);
      IF One.SIZE + Two.SIZE + Three.SIZE + Four.SIZE + Five.SIZE 
                         > MaxLen THEN
        RESULT:=OutputLongIdent (One + Two + Three + Four + Five, MaxLen);
       ELSE
        -- Need (One.SIZE + Two.SIZE + Three.SIZE + Four.SIZE + Five.SIZE);
        RESULT:= One + Two + Three + Four + Five;
        END;
      -- WriteChar (' ');
      END Output5Ident;

    METHOD ModuleDualRef (Mod: ARRAY OF CHAR): ARRAY OF CHAR;
      BEGIN
      ASSERT Mod <> VOID;
      RESULT:=Output2Ident (ModuleDualPrefix, Mod, Internal := TRUE);
      END ModuleDualRef;

    METHOD ModuleLinesRef(Mod: ARRAY OF CHAR): ARRAY OF CHAR;
      BEGIN
      ASSERT Mod <> VOID;
      RESULT:=Output2Ident (ModuleLinesPrefix, Mod, Internal := TRUE);
      END ModuleLinesRef;

    METHOD ModuleProfileRef(Mod: ARRAY OF CHAR): ARRAY OF CHAR;
      BEGIN
      ASSERT Mod <> VOID;
      RESULT:=Output2Ident (ModuleProfilePrefix, Mod, Internal := TRUE);
      END ModuleProfileRef;

   METHOD MethodStructRef (Module, Class, Meth: ARRAY OF CHAR): ARRAY OF CHAR;
      BEGIN
      RESULT:=Output4Ident (MethodPrefix, Meth, Class, Module,
                    Internal := FALSE);
      END MethodStructRef;
   
    METHOD Anchor (Module, Class, Meth: ARRAY OF CHAR): ARRAY OF CHAR;
      BEGIN
      ASSERT Meth <> PredefItems.Create.Id.Data;
      RESULT:=Output4Ident (AnchorPrefix, Meth, Class, Module,
                    Internal := FALSE);
      END Anchor;
      
    METHOD CreateAnchor (Module, Class: ARRAY OF CHAR): ARRAY OF CHAR;
      BEGIN
      RESULT:=Output3Ident (CreateAnchorPrefix, Class, Module,
                            Internal := FALSE);
      END CreateAnchor;

    METHOD Yu (Ident: ARRAY OF CHAR): ARRAY OF CHAR;
      BEGIN
      RESULT:=Output2Ident (YuPrefix, Ident, Internal := TRUE);
      END Yu;

    METHOD OnceClassInstance (Module, Class: ARRAY OF CHAR): ARRAY OF CHAR;
      BEGIN
      RESULT:=Output3Ident (YuPrefix, Class, Module, Internal := FALSE);
      END OnceClassInstance;

    METHOD UniqueItem (ItemNr: INTEGER): ARRAY OF CHAR;
      BEGIN
      -- Need (10);
      RESULT:=YuPrefix + IntConversions.IntToString (ItemNr, 0);
      -- WriteChar (' ');
      END UniqueItem;
      
    METHOD UniqueWithSuffix (ItemNr: INTEGER;
                             Suffix: ARRAY OF CHAR): ARRAY OF CHAR;
      BEGIN
      -- Need(Suffix.SIZE + 10);
      RESULT:=YuPrefix + IntConversions.IntToString(ItemNr, 0) + Suffix;      
      END UniqueWithSuffix;                             

    METHOD Class (Module, Cl: ARRAY OF CHAR): ARRAY OF CHAR;
      BEGIN
      RESULT:=Output3Ident (ClassPrefix, Cl, Module, Internal := TRUE);
      END Class;
      
    METHOD VersionKey (Module, Key: ARRAY OF CHAR): ARRAY OF CHAR;
      BEGIN
      RESULT:=Output3Ident (VersionPrefix, Module, Key, Internal := FALSE);
      END VersionKey;
      
    METHOD Additive (Module, Class: ARRAY OF CHAR): ARRAY OF CHAR;
      BEGIN
      RESULT:=Output3Ident (AdditivePrefix, Class, Module, Internal := TRUE);
      END Additive;

    METHOD AdditiveSize (Module, Class: ARRAY OF CHAR): ARRAY OF CHAR;
      BEGIN
      RESULT:=Output3Ident (AdditiveSizePrefix, Class, Module, Internal := TRUE);
      END AdditiveSize;

    METHOD AdditiveDual (Module, Class: ARRAY OF CHAR): ARRAY OF CHAR;
      BEGIN
      RESULT:=Output3Ident (AdditiveDualPrefix, Class, Module, Internal := TRUE);
      END AdditiveDual;

    METHOD AdditiveDualSize (Module, Class: ARRAY OF CHAR): ARRAY OF CHAR;
      BEGIN
      RESULT:=Output3Ident (AdditiveDualSizePrefix, Class, Module, Internal := TRUE);
      END AdditiveDualSize;

    METHOD Module (ModuleName: ARRAY OF CHAR): ARRAY OF CHAR;
      BEGIN
      RESULT:=Output2Ident (ModuleNamePrefix, ModuleName, Internal := FALSE);
      END Module;

    METHOD DualType (Module, Class: ARRAY OF CHAR): ARRAY OF CHAR;
      BEGIN
      RESULT:=Output3Ident (DualTypePrefix, Class, Module, Internal := TRUE);
      END DualType;

    METHOD DualInstance (Module, Class: ARRAY OF CHAR): ARRAY OF CHAR;
      BEGIN
      RESULT:=Output3Ident (DualInstancePrefix, Class, Module, Internal := FALSE);
      END DualInstance;
      
    METHOD ConstructFunc (Module, Class: ARRAY OF CHAR): ARRAY OF CHAR;
      BEGIN
      RESULT:=Output3Ident (ConstructFuncPrefix, Class, Module, Internal := FALSE);
      END ConstructFunc;

    METHOD PredefinedDual (TypeName: ARRAY OF CHAR): ARRAY OF CHAR;
      BEGIN
      RESULT:=Output2Ident (DualInstancePrefix, TypeName, Internal := FALSE);
      END PredefinedDual;

    METHOD ParallelDualId (Module, Class: ARRAY OF CHAR): ARRAY OF CHAR;
      BEGIN
      RESULT:=Output3Ident(ParallelDualPrefix, Class, Module, Internal := FALSE);
      END ParallelDualId;

    METHOD VirtualDual: ARRAY OF CHAR;
      BEGIN
      RESULT:=Output2Ident (DualInstancePrefix, VirtualDualNameString,
                            Internal := FALSE);
      END VirtualDual;
     
    METHOD ModuleLiteral(Module: ARRAY OF CHAR): ARRAY OF CHAR;
      BEGIN
      RESULT:=Output2Ident (ModuleLiteralPrefix, Module, 
                            Internal := FALSE);
      END ModuleLiteral;

    METHOD ClassLiteral (Module, Class: ARRAY OF CHAR): ARRAY OF CHAR;
      BEGIN
      RESULT:=Output3Ident (ClassLiteralPrefix, Module, Class,
                            Internal := FALSE);
      END ClassLiteral;
      
    METHOD ModuleInitialization (Module: ARRAY OF CHAR): ARRAY OF CHAR;
      BEGIN
      RESULT:=Output2Ident (ModuleInitializationPrefix, Module, 
                    Internal := FALSE);
      END ModuleInitialization;

    METHOD ClassInitialization (Module, Class: ARRAY OF CHAR): ARRAY OF CHAR;
      BEGIN
      RESULT:=Output3Ident (ClassInitializationPrefix, Class, Module,
                    Internal := FALSE);
      END ClassInitialization;

    METHOD ClassDualInitialization (Module, Class: ARRAY OF CHAR): ARRAY OF CHAR;
      BEGIN
      RESULT:=Output3Ident (ClassDualInitializationPrefix, Class, Module,
                    Internal := FALSE);
      END ClassDualInitialization;
      
    -- for fields data
    METHOD ClassFieldsInsertion (Module,Class: ARRAY OF CHAR): ARRAY OF CHAR;
      BEGIN
      RESULT:=Output3Ident (ClassFieldsInsertionPrefix, Class, Module, 
                    Internal := FALSE);
      END ClassFieldsInsertion;

    -- for the debugger     
    METHOD DbxModuleInitialization (Module: ARRAY OF CHAR): ARRAY OF CHAR;
      BEGIN
      RESULT:=Output2Ident (DbxModuleInitializationPrefix, Module,
                    Internal := FALSE);
      END DbxModuleInitialization;
      
    METHOD DbxModuleReference (Module: ARRAY OF CHAR): ARRAY OF CHAR;
      BEGIN
      RESULT:=Output2Ident (DbxModuleReferencePrefix, Module,
                    Internal := FALSE);
      END DbxModuleReference;
      
    METHOD DbxClassInitialization (Module, Class: ARRAY OF CHAR): ARRAY OF CHAR;
      BEGIN
      RESULT:=Output3Ident (DbxClassInitializationPrefix, Class, Module,
                    Internal := FALSE);
      END DbxClassInitialization;
      
    METHOD DbxClassReference (Module, Class: ARRAY OF CHAR): ARRAY OF CHAR;
      BEGIN
      RESULT:=Output3Ident (DbxClassReferencePrefix, Class, Module,
                    Internal := FALSE);
      END DbxClassReference;
      
    METHOD DbxMethodReference (Module, Class, Method: ARRAY OF CHAR): ARRAY OF CHAR;
      BEGIN
      RESULT:=Output4Ident (DbxMethodReferencePrefix, Method, Class, Module,
                    Internal := FALSE);
      END DbxMethodReference;

    METHOD DbxFieldReference(Module, Class, Field: ARRAY OF CHAR): ARRAY OF CHAR;
      BEGIN
      RESULT:=Output4Ident (DbxFieldReferencePrefix, Field, Class, Module,
                    Internal := FALSE);
      END DbxFieldReference;

    METHOD DbxLocalReference(Module, Class, Method, Local: ARRAY OF CHAR): ARRAY OF CHAR;
      BEGIN
      RESULT:=Output5Ident (DbxLocalReferencePrefix, Local, Method, Class, Module,
                    Internal := FALSE);
      END DbxLocalReference;
          
    METHOD ClassCreate (Module, Class: ARRAY OF CHAR): ARRAY OF CHAR;
      BEGIN
      RESULT:=Output3Ident (ClassCreatePrefix, Class, Module, Internal := FALSE);
      END ClassCreate;

-------
      
    METHOD ContextFreePreCondFuncName(Module, Class, Method: ARRAY OF CHAR)
                                           : ARRAY OF CHAR;
      BEGIN
      RESULT:=Output4Ident(ContextFreePreCondFuncPrefix, Module, Class, Method,
                   Internal := FALSE);
      END ContextFreePreCondFuncName;
      
    METHOD ContextDependentPreCondFuncName(Module, 
                                           Class, 
                                           Method: ARRAY OF CHAR)
                                           : ARRAY OF CHAR;
      BEGIN
      RESULT:=Output4Ident(ContextDependentPreCondFuncPrefix, 
                   Module, Class, Method,
                   Internal := FALSE);
      END ContextDependentPreCondFuncName;
      
    METHOD PostConditionFunctionName(Module, Class, Method: ARRAY OF CHAR)
                                    : ARRAY OF CHAR;
      BEGIN
      RESULT:=Output4Ident(PostConditionFunctionPrefix, Module, Class, Method, 
                   Internal := FALSE);
      END PostConditionFunctionName;
 
    METHOD ComputeOldFunctionName(Module, Class, Method: ARRAY OF CHAR)
                                    : ARRAY OF CHAR;
      BEGIN
      RESULT:=Output4Ident(ComputeOldFunctionPrefix, Module, Class, Method, 
                   Internal := FALSE);
      END ComputeOldFunctionName;

    METHOD MethodChainInitialisation(Module, Class: ARRAY OF CHAR)
                                     : ARRAY OF CHAR;
      BEGIN
      RESULT:=Output3Ident(DbxMethodChainInitPrefix, Module, Class, 
                   Internal := FALSE);
      END MethodChainInitialisation;
 
     METHOD MinimalDual: ARRAY OF CHAR;
       BEGIN
       RESULT:=MinimalDualString;
       END MinimalDual;

     METHOD FieldInfo: ARRAY OF CHAR;
       BEGIN
       RESULT:=FieldInfoString;
       END FieldInfo;
   
  END YaflIdentifier;

END YaflGC;
