home *** CD-ROM | disk | FTP | other *** search
/ Chip 2002 November / Chip_2002-11_cd1.bin / zkuste / delphi / kompon / d456 / CAJSCRPT.ZIP / ifps3 / ifps3debug.pas < prev    next >
Pascal/Delphi Source File  |  2002-07-24  |  14KB  |  525 lines

  1. unit ifps3debug;
  2. {
  3.  
  4. Innerfuse Pascal Script III
  5. Copyright (C) 2000-2002 by Carlo Kok (ck@carlo-kok.com)
  6.  
  7. }
  8. {$I ifps3_def.inc}
  9. interface
  10. uses
  11.   ifps3, ifps3utl;
  12.  
  13. type
  14.   {The current debugging mode}
  15.   TDebugMode = (dmRun, dmStepOver, dmStepInto, dmPaused);
  16.   {The TIFPSCustomDebugExec class is used to load and use compiler debug information}
  17.   TIFPSCustomDebugExec = class(TIFPSExec)
  18.   protected
  19.     FDebugDataForProcs: TIfList;
  20.     FLastProc: PIFProcRec;
  21.     FCurrentDebugProc: Pointer;
  22.     FProcNames: TIFStringList;
  23.     FGlobalVarNames: TIfStringList;
  24.     FCurrentSourcePos: Cardinal;
  25.     function GetCurrentProcParams: TIfStringList;
  26.     function GetCurrentProcVars: TIfStringList;
  27.   protected
  28.     procedure ClearDebug; virtual;
  29.   public
  30.     {The current proc no}
  31.     function GetCurrentProcNo: Cardinal;
  32.     {Get the current position}
  33.     function GetCurrentPosition: Cardinal;
  34.     {Translate a position to a real position}
  35.     function TranslatePosition(Proc, Position: Cardinal): Cardinal;
  36.     {Load debug data in the scriptengine}
  37.     procedure LoadDebugData(const Data: string);
  38.     {Clear the debugdata and the current script}
  39.     procedure Clear; override;
  40.     {Contains the names of the global variables}
  41.     property GlobalVarNames: TIfStringList read FGlobalVarNames;
  42.     {Contains the names of the procedures}
  43.     property ProcNames: TIfStringList read FProcNames;
  44.     {The variables in the current proc (could be nil)}
  45.     property CurrentProcVars: TIfStringList read GetCurrentProcVars;
  46.     {The paramters of the current proc (could be nil)}
  47.     property CurrentProcParams: TIfStringList read GetCurrentProcParams;
  48.     {Get global variable no I}
  49.     function GetGlobalVar(I: Cardinal): PIfVariant;
  50.     {Get Proc variable no I}
  51.     function GetProcVar(I: Cardinal): PIfVariant;
  52.     {Get proc param no I}
  53.     function GetProcParam(I: Cardinal): PIfVariant;
  54.     {Create an instance of the debugger}
  55.     constructor Create;
  56.     {destroy the current instance of the debugger}
  57.     destructor Destroy; override;
  58.   end;
  59.   TIFPSDebugExec = class;
  60.   {see TIFPSDebugExec.OnSourceLine}
  61.   TOnSourceLine = procedure (Sender: TIFPSDebugExec; Position: Cardinal);
  62.   {see TIFPSDebugExec.OnIdleCall}
  63.   TOnIdleCall = procedure (Sender: TIFPSDebugExec);
  64.   {The TIFPSCustomDebugExec class is used to load and use compiler debug information}
  65.   TIFPSDebugExec = class(TIFPSCustomDebugExec)
  66.   private
  67.     FDebugMode: TDebugMode;
  68.     FStepOverStackBase: Cardinal;
  69.     FOnIdleCall: TOnIdleCall;
  70.     FOnSourceLine: TOnSourceLine;
  71.   protected
  72.     procedure SourceChanged;
  73.     procedure ClearDebug; override;
  74.     procedure RunLine; override;
  75.   public
  76.     function LoadData(const s: string): Boolean; override;
  77.     procedure Pause; override;
  78.     procedure Run;
  79.     procedure StepInto;
  80.     procedure StepOver;
  81.     procedure Stop; override;
  82.     {Contains the current debugmode}
  83.     property DebugMode: TDebugMode read FDebugMode;
  84.     {OnSourceLine is called after passing each source line}
  85.     property OnSourceLine: TOnSourceLine read FOnSourceLine write FOnSourceLine;
  86.     {OnIdleCall is called when the script is paused}
  87.     property OnIdleCall: TOnIdleCall read FOnIdleCall write FOnIdleCall;
  88.   end;
  89.  
  90. implementation
  91.  
  92. type
  93.   PPositionData = ^TPositionData;
  94.   TPositionData = packed record
  95.     Position,
  96.     SourcePosition: Cardinal;
  97.   end;
  98.   PFunctionInfo = ^TFunctionInfo;
  99.   TFunctionInfo = packed record
  100.     Func: PIFProcRec;
  101.     FParamNames: TIfStringList;
  102.     FVariableNames: TIfStringList;
  103.     FPositionTable: TIfList;
  104.   end;
  105.  
  106. { TIFPSCustomDebugExec }
  107.  
  108. procedure TIFPSCustomDebugExec.Clear;
  109. begin
  110.   inherited Clear;
  111.   if FGlobalVarNames <> nil then ClearDebug;
  112. end;
  113.  
  114. procedure TIFPSCustomDebugExec.ClearDebug;
  115. var
  116.   i, j: Longint;
  117.   p: PFunctionInfo;
  118. begin
  119.   FCurrentDebugProc := nil;
  120.   FLastProc := nil;
  121.   FProcNames.Clear;
  122.   FGlobalVarNames.Clear;
  123.   FCurrentSourcePos := Cardinal(-1);
  124.   for i := 0 to FDebugDataForProcs.Count -1 do
  125.   begin
  126.     p := FDebugDataForProcs.GetItem(I);
  127.     for j := 0 to p^.FPositionTable.Count -1 do
  128.     begin
  129.       Dispose(PPositionData(P^.FPositionTable.GetItem(J)));
  130.     end;
  131.     p^.FPositionTable.Free;
  132.     p^.FParamNames.Free;
  133.     p^.FVariableNames.Free;
  134.     Dispose(p);
  135.   end;
  136.   FDebugDataForProcs.Clear;
  137. end;
  138.  
  139. constructor TIFPSCustomDebugExec.Create;
  140. begin
  141.   inherited Create;
  142.   FCurrentSourcePos := Cardinal(-1);
  143.   FDebugDataForProcs := TIfList.Create;
  144.   FLastProc := nil;
  145.   FCurrentDebugProc := nil;
  146.   FProcNames := TIFStringList.Create;
  147.   FGlobalVarNames := TIfStringList.Create;
  148. end;
  149.  
  150. destructor TIFPSCustomDebugExec.Destroy;
  151. begin
  152.   Clear;
  153.   FDebugDataForProcs.Free;
  154.   FProcNames.Free;
  155.   FGlobalVarNames.Free;
  156.   FGlobalVarNames := nil;
  157.   inherited Destroy;
  158. end;
  159.  
  160. function TIFPSCustomDebugExec.GetCurrentPosition: Cardinal;
  161. begin
  162.   Result := TranslatePosition(GetCurrentProcNo, 0);
  163. end;
  164.  
  165. function TIFPSCustomDebugExec.GetCurrentProcNo: Cardinal;
  166. var
  167.   i: Longint;
  168. begin
  169.   for i := 0 to FProcs.Count -1 do
  170.   begin
  171.     if FProcs.GetItem(i) = FCurrProc then
  172.     begin
  173.       Result := I;
  174.       Exit;
  175.     end;
  176.   end;
  177.   Result := Cardinal(-1);
  178. end;
  179.  
  180. function TIFPSCustomDebugExec.GetCurrentProcParams: TIfStringList;
  181. begin
  182.   if FCurrentDebugProc <> nil then
  183.   begin
  184.     Result := PFunctionInfo(FCurrentDebugProc)^.FParamNames;
  185.   end else Result := nil;
  186. end;
  187.  
  188. function TIFPSCustomDebugExec.GetCurrentProcVars: TIfStringList;
  189. begin
  190.   if FCurrentDebugProc <> nil then
  191.   begin
  192.     Result := PFunctionInfo(FCurrentDebugProc)^.FVariableNames;
  193.   end else Result := nil;
  194. end;
  195.  
  196. function TIFPSCustomDebugExec.GetGlobalVar(I: Cardinal): PIfVariant;
  197. begin
  198.   Result := FGlobalVars.GetItem(I);
  199. end;
  200.  
  201. function TIFPSCustomDebugExec.GetProcParam(I: Cardinal): PIfVariant;
  202. begin
  203.   Result := FStack.GetItem(Cardinal(Longint(FCurrStackBase) - Longint(I) - 1));
  204. end;
  205.  
  206. function TIFPSCustomDebugExec.GetProcVar(I: Cardinal): PIfVariant;
  207. begin
  208.   Result := FStack.GetItem(Cardinal(Longint(FCurrStackBase) + Longint(I) + 1));
  209. end;
  210.  
  211. function GetProcDebugInfo(FProcs: TIFList; Proc: PIFProcRec): PFunctionInfo;
  212. var
  213.   i: Longint;
  214.   c: PFunctionInfo;
  215. begin
  216.   if Proc = nil then
  217.   begin
  218.     Result := nil;
  219.     exit;
  220.   end;
  221.   for i := 0 to FProcs.Count -1 do
  222.   begin
  223.     c := FProcs.GetItem(I);
  224.     if c^.Func = Proc then
  225.     begin
  226.       Result := c;
  227.       exit;
  228.     end;
  229.   end;
  230.   new(c);
  231.   c^.Func := Proc;
  232.   c^.FPositionTable := TIfList.Create;
  233.   c^.FVariableNames := TIfStringList.Create;
  234.   c^.FParamNames := TIfStringList.Create;
  235.   FProcs.Add(c);
  236.   REsult := c;
  237. end;
  238.  
  239. procedure TIFPSCustomDebugExec.LoadDebugData(const Data: string);
  240. var
  241.   CP, I: Longint;
  242.   c: char;
  243.   CurrProcNo, LastProcNo: Cardinal;
  244.   LastProc: PFunctionInfo;
  245.   NewLoc: PPositionData;
  246. begin
  247.   ClearDebug;
  248.   if FStatus = isNotLoaded then exit;
  249.   CP := 1;
  250.   LastProcNo := Cardinal(-1);
  251.   LastProc := nil;
  252.   while CP <= length(Data) do
  253.   begin
  254.     c := Data[CP];
  255.     inc(cp);
  256.     case c of
  257.       #0:
  258.         begin
  259.           i := cp;
  260.           if i > length(data) then exit;
  261.           while Data[i] <> #0 do
  262.           begin
  263.             if Data[i] = #1 then
  264.             begin
  265.               FProcNames.Add(Copy(Data, cp, i-cp));
  266.               cp := I + 1;
  267.             end;
  268.             inc(I);
  269.             if I > length(data) then exit;
  270.           end;
  271.           cp := i + 1;
  272.         end;
  273.       #1:
  274.         begin
  275.           i := cp;
  276.           if i > length(data) then exit;
  277.           while Data[i] <> #0 do
  278.           begin
  279.             if Data[i] = #1 then
  280.             begin
  281.               FGlobalVarNames.Add(Copy(Data, cp, i-cp));
  282.               cp := I + 1;
  283.             end;
  284.             inc(I);
  285.             if I > length(data) then exit;
  286.           end;
  287.           cp := i + 1;
  288.         end;
  289.       #2:
  290.         begin
  291.           if cp + 4 > Length(data) then exit;
  292.           CurrProcNo := Cardinal((@Data[cp])^);
  293.           if CurrProcNo = Cardinal(-1) then Exit;
  294.           if CurrProcNo <> LastProcNo then
  295.           begin
  296.             LastProcNo := CurrProcNo;
  297.             LastProc := GetProcDebugInfo(FDebugDataForProcs, FProcs.GetItem(CurrProcNo));
  298.             if LastProc = nil then exit;
  299.           end;
  300.           inc(cp, 4);
  301.  
  302.           i := cp;
  303.           if i > length(data) then exit;
  304.           while Data[i] <> #0 do
  305.           begin
  306.             if Data[i] = #1 then
  307.             begin
  308.               LastProc^.FParamNames.Add(Copy(Data, cp, i-cp));
  309.               cp := I + 1;
  310.             end;
  311.             inc(I);
  312.             if I > length(data) then exit;
  313.           end;
  314.           cp := i + 1;
  315.         end;
  316.       #3:
  317.         begin
  318.           if cp + 4 > Length(data) then exit;
  319.           CurrProcNo := Cardinal((@Data[cp])^);
  320.           if CurrProcNo = Cardinal(-1) then Exit;
  321.           if CurrProcNo <> LastProcNo then
  322.           begin
  323.             LastProcNo := CurrProcNo;
  324.             LastProc := GetProcDebugInfo(FDebugDataForProcs, FProcs.GetItem(CurrProcNo));
  325.             if LastProc = nil then exit;
  326.           end;
  327.           inc(cp, 4);
  328.  
  329.           i := cp;
  330.           if i > length(data) then exit;
  331.           while Data[i] <> #0 do
  332.           begin
  333.             if Data[i] = #1 then
  334.             begin
  335.               LastProc^.FVariableNames.Add(Copy(Data, cp, i-cp));
  336.               cp := I + 1;
  337.             end;
  338.             inc(I);
  339.             if I > length(data) then exit;
  340.           end;
  341.           cp := i + 1;
  342.         end;
  343.       #4:
  344.         begin
  345.           if cp + 4 > Length(data) then exit;
  346.           CurrProcNo := Cardinal((@Data[cp])^);
  347.           if CurrProcNo = Cardinal(-1) then Exit;
  348.           if CurrProcNo <> LastProcNo then
  349.           begin
  350.             LastProcNo := CurrProcNo;
  351.             LastProc := GetProcDebugInfo(FDebugDataForProcs, FProcs.GetItem(CurrProcNo));
  352.             if LastProc = nil then exit;
  353.           end;
  354.           inc(cp, 4);
  355.           if cp + 8 > Length(data) then exit;
  356.           new(NewLoc);
  357.           NewLoc^.Position := Cardinal((@Data[Cp])^);
  358.           NewLoc^.SourcePosition := Cardinal((@Data[Cp+4])^);
  359.           inc(cp, 8);
  360.           LastProc^.FPositionTable.Add(NewLoc);
  361.         end;
  362.       else
  363.         begin
  364.           ClearDebug;
  365.           Exit;
  366.         end;
  367.     end;
  368.  
  369.   end;
  370. end;
  371.  
  372.  
  373.  
  374.  
  375.  
  376.  
  377. function TIFPSCustomDebugExec.TranslatePosition(Proc, Position: Cardinal): Cardinal;
  378. // Made by Martijn Laan (mlaan@wintax.nl)
  379. var
  380.   i: LongInt;
  381.   fi: PFunctionInfo;
  382.   pt: TIfList;
  383.   r: PPositionData;
  384.   LastSourcePosition: Cardinal;
  385.   pp: PIFProcRec;
  386. begin
  387.   fi := nil;
  388.   pp := FProcs.GetItem(Proc);
  389.   for i := 0 to FDebugDataForProcs.Count -1 do
  390.   begin
  391.     fi := FDebugDataForProcs.GetItem(i);
  392.     if fi^.Func = pp then
  393.       Break;
  394.     fi := nil;
  395.   end;
  396.   LastSourcePosition := 0;
  397.   if fi <> nil then begin
  398.     pt := fi^.FPositionTable;
  399.     for i := 0 to pt.Count -1 do
  400.     begin
  401.       r := pt.GetItem(I);
  402.       if r^.Position >= Position then
  403.       begin
  404.         if r^.Position = Position then
  405.           Result := r^.SourcePosition
  406.         else
  407.           Result := LastSourcePosition;
  408.         exit;
  409.       end else
  410.         LastSourcePosition := r^.SourcePosition;
  411.     end;
  412.   end;
  413.   Result := LastSourcePosition;
  414. end;
  415.  
  416. { TIFPSDebugExec }
  417. procedure TIFPSDebugExec.ClearDebug;
  418. begin
  419.   inherited;
  420.   FDebugMode := dmRun;
  421. end;
  422.  
  423. function TIFPSDebugExec.LoadData(const s: string): Boolean;
  424. begin
  425.   Result := inherited LoadData(s);
  426.   FDebugMode := dmRun;
  427. end;
  428.  
  429. procedure TIFPSDebugExec.RunLine;
  430. var
  431.   i: Longint;
  432.   pt: TIfList;
  433.   r: PPositionData;
  434. begin
  435.   inherited RunLine;
  436.   if FCurrProc <> FLastProc then
  437.   begin
  438.     FLastProc := FCurrProc;
  439.     FCurrentDebugProc := nil;
  440.     for i := 0 to FDebugDataForProcs.Count -1 do
  441.     begin
  442.       if PFunctionInfo(FDebugDataForProcs.GetItem(I))^.Func = FLastProc then
  443.       begin
  444.         FCurrentDebugProc := FDebugDataForProcs.GetItem(I);
  445.         break;
  446.       end;
  447.     end;
  448.   end;
  449.   if FCurrentDebugProc <> nil then
  450.   begin
  451.     pt := PFunctionInfo(FCurrentDebugProc)^.FPositionTable;
  452.     for i := 0 to pt.Count -1 do
  453.     begin
  454.       r := pt.GetItem(I);
  455.       if r^.Position = FCurrentPosition then
  456.       begin
  457.         FCurrentSourcePos := r^.SourcePosition;
  458.         SourceChanged;
  459.         break;
  460.       end;
  461.     end;
  462.   end else
  463.   begin
  464.     FCurrentSourcePos := Cardinal(-1);
  465.   end;
  466.   while FDebugMode = dmPaused do
  467.   begin
  468.     if @FOnIdleCall <> nil then
  469.     begin
  470.       FOnIdleCall(Self);
  471.     end else break; // endless loop
  472.   end;
  473. end;
  474.  
  475.  
  476. procedure TIFPSDebugExec.SourceChanged;
  477. begin
  478.   case FDebugMode of
  479.     dmStepInto:
  480.       begin
  481.         FDebugMode := dmPaused;
  482.       end;
  483.     dmStepOver:
  484.       begin
  485.         if FCurrStackBase <= FStepOverStackBase then
  486.         begin
  487.           FDebugMode := dmPaused;
  488.         end;
  489.       end;
  490.   end;
  491.   if @FOnSourceLine <> nil then
  492.     FOnSourceLine(Self, FCurrentSourcePos);
  493. end;
  494.  
  495.  
  496. procedure TIFPSDebugExec.Pause;
  497. begin
  498.   FDebugMode := dmPaused;
  499. end;
  500.  
  501. procedure TIFPSDebugExec.Stop;
  502. begin
  503.   FDebugMode := dmRun;
  504.   inherited Stop;
  505. end;
  506.  
  507. procedure TIFPSDebugExec.Run;
  508. begin
  509.   FDebugMode := dmRun;
  510. end;
  511.  
  512. procedure TIFPSDebugExec.StepInto;
  513. begin
  514.   FDebugMode := dmStepInto;
  515. end;
  516.  
  517. procedure TIFPSDebugExec.StepOver;
  518. begin
  519.   FDebugMode := dmStepOver;
  520.   FStepOverStackBase := FCurrStackBase;
  521. end;
  522.  
  523.  
  524. end.
  525.