IMPLEMENTATION MODULE Trace;

FROM Conversions IMPORT IntConversions;

INLINE
  %#undef SET_LINE
  %#undef ENTER_METHOD
  %#undef EXIT_METHOD
  %
  %#define SET_LINE(x)
  %#define ENTER_METHOD(x,y,z)
  %#define EXIT_METHOD
  END;

  CLASS TraceEntry;
    VAR
      TheModule,
      TheClass,
      TheMethod: ARRAY OF CHAR;
      TheLineNr: INTEGER;
      
    METHOD Module: ARRAY OF CHAR;
      BEGIN
      RESULT := TheModule;
      END Module;
      
    METHOD Class: ARRAY OF CHAR;
      BEGIN
      RESULT := TheClass;
      END Class;
      
    METHOD Method: ARRAY OF CHAR;
      BEGIN
      RESULT := TheMethod;
      END Method;
      
    METHOD LineNr: INTEGER;
      BEGIN
      RESULT := TheLineNr;
      END LineNr;
      
    REDEFINE METHOD CREATE (Module, Class, Method: ARRAY OF CHAR;
                            LineNr: INTEGER);
      BEGIN
      TheModule := Module;
      TheClass := Class;
      TheMethod := Method;
      TheLineNr := LineNr;
      END CREATE;                            
      
    METHOD Image: ARRAY OF CHAR;
      BEGIN
      RESULT := Module + "." + Class + "." + Method;
      IF RESULT.SIZE MOD 2 <> 0 THEN
        RESULT := RESULT + " ";
        END;
      WHILE RESULT.SIZE < 66 DO
        RESULT := RESULT + " ." ;
        END;
      RESULT := RESULT + IntConversions.IntToString (LineNr, 5);
      END Image;
      
  END TraceEntry;
----------------------------------------  
  CLASS CallStack;
    INHERITS List(TraceEntry);
    
    VAR
      TheCurrentLine: INTEGER;
      TheErrorCode: INTEGER;
      
    METHOD ErrorCode: INTEGER;
      BEGIN
      RESULT := TheErrorCode;
      END ErrorCode;
      
    METHOD CurrentLine: INTEGER;
      BEGIN
      RESULT := TheCurrentLine;
      END CurrentLine;
    
    REDEFINE METHOD CREATE;
      VAR
        Cl, Mod, Meth: ARRAY OF CHAR;
        LineNr, ECode: INTEGER;
        TEntry: TraceEntry;
      BEGIN
      BASE;
      INLINE
        %{
        %  int i, top;
        %  entry_type *p;
        %  obj_ptr *vv_stack;
        %  extern int yafl_error_code, yafl_err_line_nr;
        %  extern int trace_entries YARGS((void));
        %  extern entry_type * get_trace_entry YARGS((int sp));
        %                    
        %  vv_stack = v_stack;
        %  top = trace_entries();
        %  for (i=0; i < top; i++)
        %    {
        %      v_stack = vv_stack;
        %      p = get_trace_entry(i);
        %      Y_Cl = new_string (p->mod);
        %      Y_Mod = new_string(p->cl);
        %      Y_Meth = new_string(p->mth);
        %      Y_LineNr = p->line_nr;
        %
        END;
      TEntry.CREATE (Cl, Mod, Meth, LineNr);
      Append (TEntry);
      INLINE
        %      
        %    }
        %
        %  Y_LineNr = yafl_err_line_nr;
        %  Y_ECode = yafl_error_code;
        %}
        END;
      TheErrorCode := ECode;
      TheCurrentLine := LineNr;
      END CREATE;
      
    METHOD Dump (Out: OutputStream);
      BEGIN
      Out.WriteString ("Error code: ");
      Out.WriteInt (ErrorCode, 0);
      Out.WriteString ("  Line number: ");
      Out.WriteInt (CurrentLine, 0);
      Out.WriteLn;
      FOR i := Size-1 TO 0 BY -1 DO
        Out.WriteLine (Get(i).Image);
        END;
      END Dump;
      
  END CallStack;
                                     
END Trace;
