Browse Source

Merge branch 'stepout' into main

Martijn Laan 5 years ago
parent
commit
4ac0f00e6a

+ 1 - 1
Components/UniPs

@@ -1 +1 @@
-Subproject commit d48b2cb5e9dadffe80f1bc8f13f33b9579ecc402
+Subproject commit 652d9075eef8726da69355fc7a5ea8fdbf5b3f08

+ 9 - 4
ISHelp/isx.xml

@@ -731,17 +731,22 @@ external 'ADllFunc@files:A.dll,B.dll stdcall loadwithalteredsearchpath'; //A.dll
 
 <dt><i>Run To Cursor</i> (F4)</dt>
 <dd>
-<p>Runs or unpauses Setup until it reaches the line of the cursor, then pauses.</p>
+<p>Runs or unpauses Setup until it reaches the line of the cursor, then pauses it.</p>
 </dd>
 
 <dt><i>Step Into</i> (F7)</dt>
 <dd>
-<p>Runs or unpauses Setup until it reaches the next line, then pauses. By continually pressing F7 you can follow the entire execution flow of Setup.</p>
+<p>Runs or unpauses Setup until it reaches the next line, then pauses it. By continually pressing F7 you can follow the entire execution flow of Setup.</p>
 </dd>
 
 <dt><i>Step Over</i> (F8)</dt>
 <dd>
-<p>Runs or unpauses Setup until it reaches the next line, then pauses. Lines inside functions calls are skipped.</p>
+<p>Runs or unpauses Setup until it reaches the next line, then pauses it. Lines inside functions calls are skipped.</p>
+</dd>
+
+<dt><i>Step Out</i> (Shift+F8)</dt>
+<dd>
+<p>Unpauses Setup until it reaches the end of the current function, then pauses it on the next line.</p>
 </dd>
 
 <dt><i>Toggle Breakpoint</i> (F5)</dt>
@@ -762,7 +767,7 @@ external 'ADllFunc@files:A.dll,B.dll stdcall loadwithalteredsearchpath'; //A.dll
 
 <p>Lines which can be paused on are marked by a gray square in the gutter. The square turns green the first time Setup reaches the line.</p>
 
-<p>Besides lines in the Pascal script, lines in some other sections can also be paused on, again shown by a gray square in the gutter. For example, toggling a breakpoint on a line in the [Files] section will pause Setup when that file is about to be processed.</p>
+<p>Besides lines in the Pascal script, lines in some other sections can also be paused on, again shown by a gray square in the gutter. For example, toggling a breakpoint on a line in the [Files] section will pause Setup when that file is about to be processed. On such lines <i>Step Over</i> and <i>Step Out</i> both act as <i>Step Into</i>.</p>
 
 </body>
 </topic>

+ 5 - 0
Projects/CompForm.dfm

@@ -547,6 +547,11 @@ object CompileForm: TCompileForm
         ShortCut = 119
         OnClick = RStepOverClick
       end
+      object RStepOut: TMenuItem
+        Caption = 'Step Out'
+        ShortCut = 8311
+        OnClick = RStepOutClick
+      end
       object RToggleBreakPoint: TMenuItem
         Caption = 'Toggle &Breakpoint'
         ShortCut = 116

+ 43 - 15
Projects/CompForm.pas

@@ -38,7 +38,7 @@ type
   TDebugEntryArray = array[0..0] of TDebugEntry;
   PVariableDebugEntryArray = ^TVariableDebugEntryArray;
   TVariableDebugEntryArray = array[0..0] of TVariableDebugEntry;
-  TStepMode = (smRun, smStepInto, smStepOver, smRunToCursor);
+  TStepMode = (smRun, smStepInto, smStepOver, smStepOut, smRunToCursor);
   TDebugTarget = (dtSetup, dtUninstall);
 
 const
@@ -185,6 +185,7 @@ type
     HMailingList: TMenuItem;
     MemosTabSet: TNewTabSet; { First tab is the main memo, last tab is the preprocessor output memo }
     FSaveAll: TMenuItem;
+    RStepOut: TMenuItem;
     procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
     procedure FExitClick(Sender: TObject);
     procedure FOpenMainFileClick(Sender: TObject);
@@ -272,6 +273,7 @@ type
     procedure TInsertMsgBoxClick(Sender: TObject);
     procedure MemosTabSetClick(Sender: TObject);
     procedure FSaveAllClick(Sender: TObject);
+    procedure RStepOutClick(Sender: TObject);
   private
     { Private declarations }
     FMemos: TList<TCompScintEdit>;                      { FMemos[0] is the main memo and FMemos[1] the preprocessor output memo - also see MemosTabSet comment above }
@@ -332,7 +334,7 @@ type
     FLoadingIncludedFiles: Boolean;
     FDebugging: Boolean;
     FStepMode: TStepMode;
-    FPaused: Boolean;
+    FPaused, FPausedAtCodeLine: Boolean;
     FRunToCursorPoint: TDebugEntry;
     FReplyString: String;
     FDebuggerException: String;
@@ -437,7 +439,8 @@ type
     procedure WMDebuggerHello(var Message: TMessage); message WM_Debugger_Hello;
     procedure WMDebuggerGoodbye(var Message: TMessage); message WM_Debugger_Goodbye;
     procedure WMDebuggerQueryVersion(var Message: TMessage); message WM_Debugger_QueryVersion;
-    procedure GetMemoAndLineNumberFromEntry(Kind, Index: Integer; var Memo: TCompScintFileEdit; var LineNumber: Integer);
+    procedure GetMemoAndDebugEntryFromMessage(Kind, Index: Integer; var Memo: TCompScintFileEdit;
+      var DebugEntry: PDebugEntry);
     procedure DebuggerStepped(var Message: TMessage; const Intermediate: Boolean);
     procedure WMDebuggerStepped(var Message: TMessage); message WM_Debugger_Stepped;
     procedure WMDebuggerSteppedIntermediate(var Message: TMessage); message WM_Debugger_SteppedIntermediate;
@@ -3205,7 +3208,7 @@ begin
   DebuggingStopped(True);
 end;
 
-procedure TCompileForm.GetMemoAndLineNumberFromEntry(Kind, Index: Integer; var Memo: TCompScintFileEdit; var LineNumber: Integer);
+procedure TCompileForm.GetMemoAndDebugEntryFromMessage(Kind, Index: Integer; var Memo: TCompScintFileEdit; var DebugEntry: PDebugEntry);
 
   function GetMemoFromDebugEntryFileIndex(const FileIndex: Integer): TCompScintFileEdit;
   var
@@ -3229,12 +3232,12 @@ begin
   for I := 0 to FDebugEntriesCount-1 do begin
     if (FDebugEntries[I].Kind = Kind) and (FDebugEntries[I].Index = Index) then begin
       Memo := GetMemoFromDebugEntryFileIndex(FDebugEntries[I].FileIndex);
-      LineNumber := FDebugEntries[I].LineNumber;
+      DebugEntry := @FDebugEntries[I];
       Exit;
     end;
   end;
   Memo := nil;
-  LineNumber := -1;
+  DebugEntry := nil;
 end;
 
 procedure TCompileForm.BringToForeground;
@@ -3261,10 +3264,16 @@ end;
 procedure TCompileForm.DebuggerStepped(var Message: TMessage; const Intermediate: Boolean);
 var
   Memo: TCompScintFileEdit;
+  DebugEntry: PDebugEntry;
   LineNumber: Integer;
 begin
-  GetMemoAndLineNumberFromEntry(Message.WParam, Message.LParam, Memo, LineNumber);
-  if (Memo = nil) or (LineNumber < 0) then
+  GetMemoAndDebugEntryFromMessage(Message.WParam, Message.LParam, Memo, DebugEntry);
+  if (Memo = nil) or (DebugEntry = nil) then
+    Exit;
+
+  LineNumber := DebugEntry.LineNumber;
+
+  if LineNumber = -1 then { UninstExe has a DebugEntry but not a line number }
     Exit;
 
   if (LineNumber < Memo.LineStateCount) and
@@ -3273,12 +3282,14 @@ begin
     UpdateLineMarkers(Memo, LineNumber);
   end;
 
-  if (FStepMode = smStepInto) or
-     ((FStepMode = smStepOver) and not Intermediate) or
-     ((FStepMode = smRunToCursor) and
-      (FRunToCursorPoint.Kind = Integer(Message.WParam)) and
-      (FRunToCursorPoint.Index = Message.LParam)) or
-     (Memo.BreakPoints.IndexOf(LineNumber) <> -1) then begin
+  if (FStepMode = smStepOut) and DebugEntry.StepOutMarker then
+    FStepMode := smStepInto { Pause on next line }
+  else if (FStepMode = smStepInto) or
+          ((FStepMode = smStepOver) and not Intermediate) or
+          ((FStepMode = smRunToCursor) and
+          (FRunToCursorPoint.Kind = Integer(Message.WParam)) and
+          (FRunToCursorPoint.Index = Message.LParam)) or
+          (Memo.BreakPoints.IndexOf(LineNumber) <> -1) then begin
     MoveCaretAndActivateMemo(Memo, LineNumber, True);
     HideError;
     SetStepLine(Memo, LineNumber);
@@ -3286,6 +3297,7 @@ begin
     { Tell Setup to pause }
     Message.Result := 1;
     FPaused := True;
+    FPausedAtCodeLine := DebugEntry.Kind = Ord(deCodeLine);
     UpdateRunMenu;
     UpdateCaption;
   end;
@@ -3304,11 +3316,17 @@ end;
 procedure TCompileForm.WMDebuggerException(var Message: TMessage);
 var
   Memo: TCompScintFileEdit;
+  DebugEntry: PDebugEntry;
   LineNumber: Integer;
   S: String;
 begin
   if FOptions.PauseOnDebuggerExceptions then begin
-    GetMemoAndLineNumberFromEntry(Message.WParam, Message.LParam, Memo, LineNumber);
+    GetMemoAndDebugEntryFromMessage(Message.WParam, Message.LParam, Memo, DebugEntry);
+
+    if DebugEntry <> nil then
+      LineNumber := DebugEntry.LineNumber
+    else
+      LineNumber := -1;
 
     if (Memo <> nil) and (LineNumber >= 0) then begin
       MoveCaretAndActivateMemo(Memo, LineNumber, True);
@@ -3320,6 +3338,7 @@ begin
     { Tell Setup to pause }
     Message.Result := 1;
     FPaused := True;
+    FPausedAtCodeLine := (DebugEntry <> nil) and (DebugEntry.Kind = Ord(deCodeLine));
     UpdateRunMenu;
     UpdateCaption;
 
@@ -3638,6 +3657,7 @@ begin
   RRunToCursor.Enabled := RRun.Enabled and (FActiveMemo is TCompScintFileEdit);
   RStepInto.Enabled := RRun.Enabled;
   RStepOver.Enabled := RRun.Enabled;
+  RStepOut.Enabled := FPaused;
   RToggleBreakPoint.Enabled := FActiveMemo is TCompScintFileEdit;
   RTerminate.Enabled := FDebugging and (FDebugClientWnd <> 0);
   TerminateButton.Enabled := RTerminate.Enabled;
@@ -3955,6 +3975,14 @@ begin
   Go(smStepInto);
 end;
 
+procedure TCompileForm.RStepOutClick(Sender: TObject);
+begin
+  if FPausedAtCodeLine then
+    Go(smStepOut)
+  else
+    Go(smStepInto);
+end;
+
 procedure TCompileForm.RStepOverClick(Sender: TObject);
 begin
   Go(smStepOver);

+ 6 - 5
Projects/Compile.pas

@@ -345,7 +345,7 @@ type
     procedure EnumCodeProc(const Line: PChar; const Ext: Integer);
     procedure ReadCode;
     procedure CodeCompilerOnLineToLineInfo(const Line: LongInt; var Filename: String; var FileLine: LongInt);
-    procedure CodeCompilerOnUsedLine(const Filename: String; const Line, Position: LongInt);
+    procedure CodeCompilerOnUsedLine(const Filename: String; const Line, Position: LongInt; const IsProcExit: Boolean);
     procedure CodeCompilerOnUsedVariable(const Filename: String; const Line, Col, Param1, Param2, Param3: LongInt; const Param4: AnsiString);
     procedure CodeCompilerOnError(const Msg: String; const ErrorFilename: String; const ErrorLine: LongInt);
     procedure CodeCompilerOnWarning(const Msg: String);
@@ -356,7 +356,7 @@ type
     procedure ShiftDebugEntryIndexes(AKind: TDebugEntryKind);
     procedure Sign(AExeFilename: String);
     procedure SignCommand(const AName, ACommand, AParams, AExeFilename: String; const RetryCount, RetryDelay, MinimumTimeBetween: Integer; const RunMinimized: Boolean);
-    procedure WriteDebugEntry(Kind: TDebugEntryKind; Index: Integer);
+    procedure WriteDebugEntry(Kind: TDebugEntryKind; Index: Integer; StepOutMarker: Boolean = False);
     procedure WriteCompiledCodeText(const CompiledCodeText: Ansistring);
     procedure WriteCompiledCodeDebugInfo(const CompiledCodeDebugInfo: AnsiString);
     function CreateMemoryStreamsFromFiles(const ADirectiveName, AFiles: String): TList;
@@ -1717,7 +1717,7 @@ begin
   Result := PrevFileIndex;
 end;
 
-procedure TSetupCompiler.WriteDebugEntry(Kind: TDebugEntryKind; Index: Integer);
+procedure TSetupCompiler.WriteDebugEntry(Kind: TDebugEntryKind; Index: Integer; StepOutMarker: Boolean = False);
 var
   Rec: TDebugEntry;
 begin
@@ -1725,6 +1725,7 @@ begin
   Rec.LineNumber := LineNumber;
   Rec.Kind := Ord(Kind);
   Rec.Index := Index;
+  Rec.StepOutMarker := StepOutMarker;
   DebugInfo.WriteBuffer(Rec, SizeOf(Rec));
   Inc(DebugEntryCount);
 end;
@@ -7278,7 +7279,7 @@ begin
   end;
 end;
 
-procedure TSetupCompiler.CodeCompilerOnUsedLine(const Filename: String; const Line, Position: LongInt);
+procedure TSetupCompiler.CodeCompilerOnUsedLine(const Filename: String; const Line, Position: LongInt; const IsProcExit: Boolean);
 var
   OldLineFilename: String;
   OldLineNumber: Integer;
@@ -7288,7 +7289,7 @@ begin
   try
     LineFilename := Filename;
     LineNumber := Line;
-    WriteDebugEntry(deCodeLine, Position);
+    WriteDebugEntry(deCodeLine, Position, IsProcExit);
   finally
     LineFilename := OldLineFilename;
     LineNumber := OldLineNumber;

+ 1 - 0
Projects/DebugStruct.pas

@@ -85,6 +85,7 @@ type
     LineNumber: Integer; { Starts at 1 - decreased by one by the Compiler IDE on receive }
     Kind: Integer;       { TDebugEntryKind }
     Index: Integer;
+    StepOutMarker: Boolean;
   end;
 
   { TVariableDebugEntrys associate [Code] section variable references with line

+ 1 - 0
Projects/ISPP/IsppPreprocess.pas

@@ -276,6 +276,7 @@ begin
         Result := ispeSilentAbort
       else
       begin
+        Preprocessor.GetNextOutputLineReset;
         while Preprocessor.GetNextOutputLine(LineFilename, LineNumber, LineText) do
           Params.LineOutProc(Params.CompilerData, PChar(LineFilename),
             LineNumber, PChar(LineText));

+ 4 - 4
Projects/ScriptCompiler.pas

@@ -16,7 +16,7 @@ uses
 
 type
   TScriptCompilerOnLineToLineInfo = procedure(const Line: LongInt; var Filename: String; var FileLine: LongInt) of object;
-  TScriptCompilerOnUsedLine = procedure(const Filename: String; const Line, Position: LongInt) of object;
+  TScriptCompilerOnUsedLine = procedure(const Filename: String; const Line, Position: LongInt; const IsProcExit: Boolean) of object;
   TScriptCompilerOnUsedVariable = procedure(const Filename: String; const Line, Col, Param1, Param2, Param3: LongInt; const Param4: AnsiString) of object;
   TScriptCompilerOnError = procedure(const Msg: String; const ErrorFilename: String; const ErrorLine: LongInt) of object;
   TScriptCompilerOnWarning = procedure(const Msg: String) of object;
@@ -257,7 +257,7 @@ begin
   end;
 end;
 
-function PSPascalCompilerOnWriteLine(Sender: TPSPascalCompiler; Position: Cardinal): Boolean;
+function PSPascalCompilerOnWriteLine2(Sender: TPSPascalCompiler; Position: Cardinal; IsProcExit: Boolean): Boolean;
 var
   ScriptCompiler: TScriptCompiler;
   Filename: String;
@@ -272,7 +272,7 @@ begin
       Filename := '';
       if Assigned(ScriptCompiler.FOnLineToLineInfo) then
         ScriptCompiler.FOnLineToLineInfo(Line, Filename, Line);
-      ScriptCompiler.FOnUsedLine(Filename, Line, Position);
+      ScriptCompiler.FOnUsedLine(Filename, Line, Position, IsProcExit);
       Result := True;
     end else
       Result := False;
@@ -494,7 +494,7 @@ begin
     PSPascalCompiler.OnBeforeOutput := PSPascalCompilerOnBeforeOutput;
     DefaultCC := ClStdCall;
     FUsedLines.Clear();
-    PSPascalCompiler.OnWriteLine := PSPascalCompilerOnWriteLine;
+    PSPascalCompiler.OnWriteLine2 := PSPascalCompilerOnWriteLine2;
     PSPascalCompiler.OnUseVariable := PSPascalCompilerOnUseVariable;
     PSPascalCompiler.OnUseRegProc := PSPascalCompilerOnUseRegProc;
 

+ 1 - 0
whatsnew.htm

@@ -48,6 +48,7 @@ For conditions of distribution and use, see <a href="https://jrsoftware.org/file
   <li>Added new topic to the help file explaining the various <a href="https://jrsoftware.org/ishelp/index.php?topic=scriptdebug">integrated debugger menu items</a> in the <i>Run</i> menu which can be used to debug your [Code] section.</li>
   <li><a href="https://i.imgur.com/wHoJ3FG.png">Improved highlighting</a> for the [CustomMessages] and [Messages] sections.</li>
   <li>Added new <a href="https://i.imgur.com/c9wGM3M.png">MessageBox Designer</a> menu item to the <i>Tools</i> menu to design and insert <tt>MsgBox</tt> or <tt>TaskDialogMsgBox</tt> calls for the [Code] section.</li>
+  <li>Added new <i>Step Out</i> menu item to the <i>Run</i> menu to unpause Setup until it reaches the end of the current function, then pause it on the next line.</li>
   <li>Added buttons to the Welcome dialog to <a href="https://jrsoftware.org/isdonate.php">Donate</a> to support Inno Setup (Thank you!) and to <a href="https://jrsoftware.org/ismail.php">Subscribe</a> to the Inno Setup Mailing List to be notified by e-mail of new Inno Setup releases.</li>
   <li>The Run Parameters dialog now shows a list of most recently used parameters.</li>
 </ul>