diff --git a/debugger/breakpropertydlg.lfm b/debugger/breakpropertydlg.lfm index 4e2c5301b3..417ee04336 100644 --- a/debugger/breakpropertydlg.lfm +++ b/debugger/breakpropertydlg.lfm @@ -19,9 +19,9 @@ inherited BreakPropertyDlg: TBreakPropertyDlg AnchorSideTop.Control = edtFilename AnchorSideTop.Side = asrCenter Left = 6 - Height = 18 + Height = 14 Top = 10 - Width = 62 + Width = 55 BorderSpacing.Around = 6 Caption = 'Filename:' ParentColor = False @@ -31,21 +31,20 @@ inherited BreakPropertyDlg: TBreakPropertyDlg AnchorSideTop.Control = edtLine AnchorSideTop.Side = asrCenter Left = 6 - Height = 18 - Top = 43 - Width = 31 + Height = 14 + Top = 39 + Width = 28 BorderSpacing.Around = 6 Caption = 'Line:' ParentColor = False end object lblCondition: TLabel[2] AnchorSideLeft.Control = Owner - AnchorSideTop.Control = edtCondition AnchorSideTop.Side = asrCenter Left = 6 - Height = 18 + Height = 14 Top = 76 - Width = 65 + Width = 58 BorderSpacing.Around = 6 Caption = 'Condition:' ParentColor = False @@ -55,9 +54,9 @@ inherited BreakPropertyDlg: TBreakPropertyDlg AnchorSideTop.Control = edtCounter AnchorSideTop.Side = asrCenter Left = 6 - Height = 18 + Height = 14 Top = 109 - Width = 59 + Width = 51 BorderSpacing.Around = 6 Caption = 'Hitcount:' ParentColor = False @@ -67,9 +66,9 @@ inherited BreakPropertyDlg: TBreakPropertyDlg AnchorSideTop.Control = cmbGroup AnchorSideTop.Side = asrCenter Left = 6 - Height = 18 - Top = 176 - Width = 44 + Height = 14 + Top = 169 + Width = 40 BorderSpacing.Around = 6 Caption = 'Group:' ParentColor = False @@ -79,9 +78,9 @@ inherited BreakPropertyDlg: TBreakPropertyDlg AnchorSideTop.Control = edtAutocontinueMS AnchorSideTop.Side = asrCenter Left = 6 - Height = 18 - Top = 142 - Width = 124 + Height = 14 + Top = 138 + Width = 109 BorderSpacing.Around = 6 Caption = 'Auto continue after' ParentColor = False @@ -91,10 +90,10 @@ inherited BreakPropertyDlg: TBreakPropertyDlg AnchorSideLeft.Side = asrBottom AnchorSideTop.Control = lblAutoContinue AnchorSideTop.Side = asrCenter - Left = 208 - Height = 18 - Top = 142 - Width = 31 + Left = 193 + Height = 14 + Top = 138 + Width = 27 BorderSpacing.Left = 6 Caption = '(ms)' ParentColor = False @@ -105,58 +104,40 @@ inherited BreakPropertyDlg: TBreakPropertyDlg AnchorSideTop.Control = edtCounter AnchorSideTop.Side = asrBottom AnchorSideRight.Side = asrBottom - Left = 142 - Height = 27 - Top = 138 + Left = 127 + Height = 23 + Top = 134 Width = 60 BorderSpacing.Left = 6 BorderSpacing.Around = 6 - TabOrder = 4 + TabOrder = 3 Text = 'edtAutocontinueMS' end object edtCounter: TEdit[8] AnchorSideLeft.Control = lblAutoContinue AnchorSideLeft.Side = asrBottom - AnchorSideTop.Control = edtCondition AnchorSideTop.Side = asrBottom AnchorSideRight.Control = Owner AnchorSideRight.Side = asrBottom - Left = 142 - Height = 27 + Left = 127 + Height = 23 Top = 105 - Width = 295 - Anchors = [akTop, akLeft, akRight] - BorderSpacing.Left = 6 - BorderSpacing.Around = 6 - TabOrder = 3 - Text = 'edtCounter' - end - object edtCondition: TEdit[9] - AnchorSideLeft.Control = lblAutoContinue - AnchorSideLeft.Side = asrBottom - AnchorSideTop.Control = edtLine - AnchorSideTop.Side = asrBottom - AnchorSideRight.Control = Owner - AnchorSideRight.Side = asrBottom - Left = 142 - Height = 27 - Top = 72 - Width = 295 + Width = 310 Anchors = [akTop, akLeft, akRight] BorderSpacing.Left = 6 BorderSpacing.Around = 6 TabOrder = 2 - Text = 'edtCondition' + Text = 'edtCounter' end - object edtLine: TEdit[10] + object edtLine: TEdit[9] AnchorSideLeft.Control = lblAutoContinue AnchorSideLeft.Side = asrBottom AnchorSideTop.Control = edtFilename AnchorSideTop.Side = asrBottom AnchorSideRight.Side = asrBottom - Left = 142 - Height = 27 - Top = 39 + Left = 127 + Height = 23 + Top = 35 Width = 60 BorderSpacing.Left = 6 BorderSpacing.Around = 6 @@ -165,16 +146,16 @@ inherited BreakPropertyDlg: TBreakPropertyDlg TabOrder = 1 Text = 'edtLine' end - object edtFilename: TEdit[11] + object edtFilename: TEdit[10] AnchorSideLeft.Control = lblAutoContinue AnchorSideLeft.Side = asrBottom AnchorSideTop.Control = Owner AnchorSideRight.Control = Owner AnchorSideRight.Side = asrBottom - Left = 142 - Height = 27 + Left = 127 + Height = 23 Top = 6 - Width = 295 + Width = 310 Anchors = [akTop, akLeft, akRight] BorderSpacing.Left = 6 BorderSpacing.Around = 6 @@ -183,48 +164,48 @@ inherited BreakPropertyDlg: TBreakPropertyDlg TabOrder = 0 Text = 'edtFilename' end - object cmbGroup: TComboBox[12] + object cmbGroup: TComboBox[11] AnchorSideLeft.Control = lblAutoContinue AnchorSideLeft.Side = asrBottom AnchorSideTop.Control = edtAutocontinueMS AnchorSideTop.Side = asrBottom AnchorSideRight.Control = Owner AnchorSideRight.Side = asrBottom - Left = 142 - Height = 29 - Top = 171 - Width = 295 + Left = 127 + Height = 27 + Top = 163 + Width = 310 Anchors = [akTop, akLeft, akRight] BorderSpacing.Left = 6 BorderSpacing.Around = 6 ItemHeight = 0 - TabOrder = 5 + TabOrder = 4 Text = 'cmbGroup' end - object gbActions: TGroupBox[13] + object gbActions: TGroupBox[12] AnchorSideLeft.Control = Owner AnchorSideTop.Control = cmbGroup AnchorSideTop.Side = asrBottom AnchorSideRight.Control = Owner AnchorSideRight.Side = asrBottom Left = 6 - Height = 185 - Top = 206 + Height = 165 + Top = 196 Width = 431 Anchors = [akTop, akLeft, akRight] AutoSize = True BorderSpacing.Around = 6 Caption = 'Actions' - ClientHeight = 166 + ClientHeight = 150 ClientWidth = 427 - TabOrder = 6 + TabOrder = 5 object chkActionBreak: TCheckBox AnchorSideLeft.Control = gbActions AnchorSideTop.Control = gbActions Left = 6 Height = 22 Top = 6 - Width = 61 + Width = 57 BorderSpacing.Around = 6 Caption = 'Break' TabOrder = 0 @@ -235,8 +216,8 @@ inherited BreakPropertyDlg: TBreakPropertyDlg AnchorSideTop.Side = asrCenter Left = 6 Height = 22 - Top = 36 - Width = 110 + Top = 34 + Width = 101 BorderSpacing.Around = 6 Caption = 'Enable goups' TabOrder = 1 @@ -247,8 +228,8 @@ inherited BreakPropertyDlg: TBreakPropertyDlg AnchorSideTop.Side = asrCenter Left = 6 Height = 22 - Top = 69 - Width = 119 + Top = 63 + Width = 110 BorderSpacing.Around = 6 Caption = 'Disable groups' TabOrder = 2 @@ -259,10 +240,10 @@ inherited BreakPropertyDlg: TBreakPropertyDlg AnchorSideTop.Control = chkActionBreak AnchorSideTop.Side = asrBottom AnchorSideRight.Side = asrBottom - Left = 147 - Height = 27 + Left = 143 + Height = 23 Top = 34 - Width = 251 + Width = 255 Anchors = [akTop, akLeft, akRight] BorderSpacing.Left = 80 BorderSpacing.Top = 6 @@ -280,10 +261,10 @@ inherited BreakPropertyDlg: TBreakPropertyDlg AnchorSideTop.Control = edtEnableGroups AnchorSideTop.Side = asrBottom AnchorSideRight.Side = asrBottom - Left = 147 - Height = 27 - Top = 67 - Width = 251 + Left = 143 + Height = 23 + Top = 63 + Width = 255 Anchors = [akTop, akLeft, akRight] BorderSpacing.Left = 80 BorderSpacing.Top = 6 @@ -301,8 +282,8 @@ inherited BreakPropertyDlg: TBreakPropertyDlg AnchorSideTop.Side = asrCenter Left = 6 Height = 22 - Top = 102 - Width = 123 + Top = 92 + Width = 114 BorderSpacing.Around = 6 Caption = 'Eval expression' Enabled = False @@ -314,8 +295,8 @@ inherited BreakPropertyDlg: TBreakPropertyDlg AnchorSideTop.Side = asrCenter Left = 6 Height = 22 - Top = 135 - Width = 110 + Top = 121 + Width = 101 BorderSpacing.Around = 6 Caption = 'Log message' Enabled = False @@ -328,10 +309,10 @@ inherited BreakPropertyDlg: TBreakPropertyDlg AnchorSideTop.Side = asrBottom AnchorSideRight.Control = gbActions AnchorSideRight.Side = asrBottom - Left = 147 - Height = 27 - Top = 100 - Width = 274 + Left = 143 + Height = 23 + Top = 92 + Width = 278 Anchors = [akTop, akLeft, akRight] BorderSpacing.Left = 80 BorderSpacing.Top = 6 @@ -347,10 +328,10 @@ inherited BreakPropertyDlg: TBreakPropertyDlg AnchorSideTop.Side = asrBottom AnchorSideRight.Control = gbActions AnchorSideRight.Side = asrBottom - Left = 147 - Height = 27 - Top = 133 - Width = 274 + Left = 143 + Height = 23 + Top = 121 + Width = 278 Anchors = [akTop, akLeft, akRight] BorderSpacing.Left = 80 BorderSpacing.Top = 6 @@ -360,17 +341,35 @@ inherited BreakPropertyDlg: TBreakPropertyDlg TabOrder = 8 end end - object ButtonPanel: TButtonPanel[14] + object ButtonPanel: TButtonPanel[13] AnchorSideTop.Control = gbActions AnchorSideTop.Side = asrBottom AnchorSideRight.Side = asrBottom Left = 6 - Height = 32 - Top = 397 + Height = 62 + Top = 367 Width = 431 Anchors = [akTop, akLeft, akRight, akBottom] - TabOrder = 7 + TabOrder = 6 ShowButtons = [pbOK, pbCancel, pbHelp] ShowBevel = False end + object edtCondition: TComboBox[14] + AnchorSideLeft.Control = lblAutoContinue + AnchorSideLeft.Side = asrBottom + AnchorSideTop.Control = edtLine + AnchorSideTop.Side = asrBottom + AnchorSideRight.Control = Owner + AnchorSideRight.Side = asrBottom + Left = 127 + Height = 27 + Top = 64 + Width = 310 + Anchors = [akTop, akLeft, akRight] + BorderSpacing.Left = 6 + BorderSpacing.Around = 6 + ItemHeight = 0 + TabOrder = 7 + Text = 'edtCondition' + end end diff --git a/debugger/breakpropertydlg.pas b/debugger/breakpropertydlg.pas index a49a9c1903..6b17744fe0 100644 --- a/debugger/breakpropertydlg.pas +++ b/debugger/breakpropertydlg.pas @@ -7,7 +7,7 @@ interface uses Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls, StdCtrls, Buttons, DebuggerDlg, Debugger, ButtonPanel, EditBtn, - BaseDebugManager, IDEContextHelpEdit, LazarusIDEStrConsts; + BaseDebugManager, IDEContextHelpEdit, LazarusIDEStrConsts, InputHistory; type @@ -21,12 +21,12 @@ type chkLogMessage: TCheckBox; chkActionBreak: TCheckBox; cmbGroup: TComboBox; + edtCondition: TComboBox; edtEvalExpression: TEdit; edtLogMessage: TEdit; edtEnableGroups: TEditButton; edtDisableGroups: TEditButton; edtAutocontinueMS: TEdit; - edtCondition: TEdit; edtCounter: TEdit; edtFilename: TEdit; edtLine: TEdit; @@ -105,6 +105,8 @@ begin // if chkEvalExpression.Checked then Include(Actions, bpaEValExpression); // if chkLogMessage.Checked then Include(Actions, bpaLogMessage); FBreakpoint.Actions := Actions; + + InputHistories.HistoryLists.GetList('BreakPointExpression', True).Add(edtCondition.Text); end; procedure TBreakPropertyDlg.DoEndUpdate; @@ -162,6 +164,7 @@ begin chkDisableGroups.Caption := lisDisableGroup; chkEvalExpression.Caption := lisEvalExpression; chkLogMessage.Caption := lisLogMessage; + edtCondition.Items.Assign(InputHistories.HistoryLists.GetList('BreakPointExpression', True)); FBreakpoint := ABreakPoint; FBreakpointsNotification := TIDEBreakPointsNotification.Create; diff --git a/debugger/gdbmidebugger.pp b/debugger/gdbmidebugger.pp index 3e54bf52ae..2f65b7c197 100644 --- a/debugger/gdbmidebugger.pp +++ b/debugger/gdbmidebugger.pp @@ -153,6 +153,7 @@ type function GDBSourceAdress(const ASource: String; ALine, AColumn: Integer; out AAddr: TDbgPtr): Boolean; procedure CallStackSetCurrent(AIndex: Integer); + function ConvertPascalExpression(var AExpression: String): Boolean; // --- procedure ClearSourceInfo; procedure GDBStopCallback(const AResult: TGDBMIExecResult; const ATag: PtrInt); @@ -285,6 +286,7 @@ type TGDBMIBreakPoint = class(TDBGBreakPoint) private FBreakID: Integer; + FParsedExpression: String; procedure SetBreakPointCallback(const AResult: TGDBMIExecResult; const ATag: PtrInt); procedure SetBreakPoint; procedure ReleaseBreakPoint; @@ -2683,127 +2685,6 @@ begin end; function TGDBMIDebugger.GDBModify(const AExpression, ANewValue: String): Boolean; - function ConvertString(var AValue: String): Boolean; - var - R: String; - P: PChar; - InString, EndString, EndVal: Boolean; - CharVal: Byte; - n: Integer; - ValMode: Char; - begin - R := '"'; - Instring := False; - EndString := False; - EndVal := False; - ValMode := #0; - CharVal := 0; - P := @AValue[1]; - for n := 1 to Length(AVAlue) do - begin - if InString - then begin - case P^ of - '''': begin - InString := False; - EndString := True; - end; - #0..#31, - '"', - #128..#255: begin - R := R + '\' + OctStr(Ord(P^), 3); - end; - else - R := R + P^; - end; - Inc(P); - Continue; - end; - - - case P^ of - '''': begin - if EndString - then R := R + '\' + OctStr(Ord(''''), 3); - EndVal := True; - InString := True; - end; - '#': begin - if ValMode <> #0 - then begin - if not (ValMode in ['h', 'd', 'o', 'b']) then Exit(False); - R := R + '\' + OctStr(CharVal, 3); - end; - CharVal := 0; - ValMode := 'D'; - end; - '$', '&', '%': begin - if ValMode <> 'D' then Exit(False); - ValMode := P^; - end; - else - case ValMode of - 'D', 'd': begin - case P^ of - '0'..'9': CharVal := CharVal * 10 + Ord(P^) - Ord('0'); - else - Exit(False); - end; - ValMode := 'd'; - end; - '$', 'h': begin - case P^ of - '0'..'9': CharVal := CharVal * 16 + Ord(P^) - Ord('0'); - 'a'..'f': CharVal := CharVal * 16 + Ord(P^) - Ord('a'); - 'A'..'F': CharVal := CharVal * 16 + Ord(P^) - Ord('A'); - else - Exit(False); - end; - ValMode := 'h'; - end; - '&', 'o': begin - case P^ of - '0'..'7': CharVal := CharVal * 8 + Ord(P^) - Ord('0'); - else - Exit(False); - end; - ValMode := 'o'; - end; - '%', 'b': begin - case P^ of - '0': CharVal := CharVal shl 1; - '1': CharVal := CharVal shl 1 or 1; - else - Exit(False); - end; - ValMode := 'o'; - end; - else - Exit(False); - end; - end; - - if EndVal - then begin - case Valmode of - #0:; - 'h', 'd', 'o', 'b': begin - R := R + '\' + OctStr(CharVal, 3); - ValMode := #0; - end; - else - Exit(False); - end; - EndVal := False; - end; - - EndString := False; - Inc(p); - end; - AValue := R + '"'; - Result := True; - end; - var R: TGDBMIExecResult; S: String; @@ -2811,7 +2692,7 @@ begin S := Trim(ANewValue); if (S <> '') and (S[1] in ['''', '#']) then begin - if not ConvertString(S) then Exit(False); + if not ConvertPascalExpression(S) then Exit(False); end; Result := ExecuteCommand('-gdb-set var %s := %s', [AExpression, S], [cfIgnoreError, cfExternal], R) @@ -4028,6 +3909,157 @@ begin FSourceNames.Clear; end; +function TGDBMIDebugger.ConvertPascalExpression(var AExpression: String): Boolean; +var + R: String; + P: PChar; + InString, WasString, IsText, ValIsChar: Boolean; + n: Integer; + ValMode: Char; + Value: QWord; + + function AppendValue: Boolean; + var + S: String; + begin + if ValMode = #0 then Exit(True); + if not (ValMode in ['h', 'd', 'o', 'b']) then Exit(False); + + if ValIsChar + then begin + if not IsText + then begin + R := R + '"'; + IsText := True; + end; + R := R + '\' + OctStr(Value, 3); + ValIsChar := False; + end + else begin + if IsText + then begin + R := R + '"'; + IsText := False; + end; + Str(Value, S); + R := R + S; + end; + Result := True; + ValMode := #0; + end; + +begin + R := ''; + Instring := False; + WasString := False; + IsText := False; + ValIsChar := False; + ValMode := #0; + Value := 0; + + P := @AExpression[1]; + for n := 1 to Length(AExpression) do + begin + if InString + then begin + case P^ of + '''': begin + InString := False; + // delay setting terminating ", more characters defined through # may follow + WasString := True; + end; + #0..#31, + '"', '\', + #128..#255: begin + R := R + '\' + OctStr(Ord(P^), 3); + end; + else + R := R + P^; + end; + Inc(P); + Continue; + end; + + case P^ of + '''': begin + if WasString + then begin + R := R + '\' + OctStr(Ord(''''), 3) + end + else begin + if not AppendValue then Exit(False); + if not IsText + then R := R + '"'; + end; + IsText := True; + InString := True; + end; + '#': begin + if not AppendValue then Exit(False); + Value := 0; + ValMode := 'D'; + ValIsChar := True; + end; + '$', '&', '%': begin + if not (ValMode in [#0, 'D']) then Exit(False); + ValMode := P^; + end; + else + case ValMode of + 'D', 'd': begin + case P^ of + '0'..'9': Value := Value * 10 + Ord(P^) - Ord('0'); + else + Exit(False); + end; + ValMode := 'd'; + end; + '$', 'h': begin + case P^ of + '0'..'9': Value := Value * 16 + Ord(P^) - Ord('0'); + 'a'..'f': Value := Value * 16 + Ord(P^) - Ord('a'); + 'A'..'F': Value := Value * 16 + Ord(P^) - Ord('A'); + else + Exit(False); + end; + ValMode := 'h'; + end; + '&', 'o': begin + case P^ of + '0'..'7': Value := Value * 8 + Ord(P^) - Ord('0'); + else + Exit(False); + end; + ValMode := 'o'; + end; + '%', 'b': begin + case P^ of + '0': Value := Value shl 1; + '1': Value := Value shl 1 or 1; + else + Exit(False); + end; + ValMode := 'b'; + end; + else + if IsText + then begin + R := R + '"'; + IsText := False; + end; + R := R + P^; + end; + end; + WasString := False; + Inc(p); + end; + + if not AppendValue then Exit(False); + if IsText then R := R + '"'; + AExpression := R; + Result := True; +end; + procedure TGDBMIDebugger.SelectStackFrame(AIndex: Integer); begin ExecuteCommand('-stack-select-frame %d', [AIndex], [cfIgnoreError]); @@ -4427,7 +4459,13 @@ begin end; procedure TGDBMIBreakPoint.DoExpressionChange; +var + S: String; begin + S := Expression; + if TGDBMIDebugger(Debugger).ConvertPascalExpression(S) + then FParsedExpression := S + else FParsedExpression := Expression; UpdateExpression; inherited; end; @@ -4474,14 +4512,18 @@ begin ResultList := TGDBMINameValueList.Create(AResult, ['bkpt']); FBreakID := StrToIntDef(ResultList.Values['number'], 0); SetHitCount(StrToIntDef(ResultList.Values['times'], 0)); - if FBreakID <> 0 - then SetValid(vsValid) - else SetValid(vsInvalid); - UpdateExpression; + if FBreakID = 0 + then begin + ResultList.Free; + SetValid(vsInvalid); + Exit; + end; + + SetValid(vsValid); + if FParsedExpression <> '' then UpdateExpression; UpdateEnable; - if (FBreakID <> 0) - and Enabled + if Enabled and (TGDBMIDebugger(Debugger).FBreakAtMain = nil) then begin // Check if this BP is at the same location as the temp break @@ -4521,19 +4563,24 @@ const // Use shortstring as fix for fpc 1.9.5 [2004/07/15] CMD: array[Boolean] of ShortString = ('disable', 'enable'); begin - if (FBreakID = 0) - or (Debugger = nil) - then Exit; + if FBreakID = 0 then Exit; + if Debugger = nil then Exit; if Debugger.State = dsRun then TGDBMIDebugger(Debugger).GDBPause(True); - //writeln('TGDBMIBreakPoint.UpdateEnable Line=',Line,' Enabled=',Enabled,' InitialEnabled=',InitialEnabled); - TGDBMIDebugger(Debugger).ExecuteCommand('-break-%s %d', - [CMD[Enabled], FBreakID], []); + + TGDBMIDebugger(Debugger).ExecuteCommand('-break-%s %d', [CMD[Enabled], FBreakID], []); end; procedure TGDBMIBreakPoint.UpdateExpression; begin + if FBreakID = 0 then Exit; + if Debugger = nil then Exit; + + if Debugger.State = dsRun + then TGDBMIDebugger(Debugger).GDBPause(True); + + TGDBMIDebugger(Debugger).ExecuteCommand('-break-condition %d %s', [FBreakID, FParsedExpression], [cfIgnoreError, cfExternal]); end; { =========================================================================== }