From a67dccae5be9d53c27ed058a439fdb50f0f19510 Mon Sep 17 00:00:00 2001 From: FellippeHeitor Date: Thu, 16 Sep 2021 22:49:43 -0300 Subject: [PATCH] Allows setting watchpoints regardless of scope. Adds "Clear Watchpoint" functionality. Allows watching more than one array index/element. --- internal/support/vwatch/vwatch.bm | 59 ++++++++++++++++++++----------- source/ide/ide_methods.bas | 38 ++++++++++++++------ 2 files changed, 66 insertions(+), 31 deletions(-) diff --git a/internal/support/vwatch/vwatch.bm b/internal/support/vwatch/vwatch.bm index fab2b9df6..e6d3a957a 100644 --- a/internal/support/vwatch/vwatch.bm +++ b/internal/support/vwatch/vwatch.bm @@ -5,7 +5,7 @@ SUB vwatch (globalVariables AS _OFFSET, localVariables AS _OFFSET) STATIC AS LONG vw_runToLine, vw_originalVarLineNumber STATIC AS _BYTE vw_pauseMode, vw_stepOver, vw_bypass, vw_setNextLine, vw_hwndSent STATIC AS _OFFSET vw_ideHwnd - STATIC vw_buffer$, vw_globalWatchpoints$, vw_localWatchpoints$ + STATIC vw_buffer$, vw_globalWatchpoints$, vw_localWatchpoints$, vw_lastWatchpoint$ DIM AS LONG vw_i, vw_j, vw_tempIndex, vw_localIndex, vw_varSize, vw_cmdSize DIM AS LONG vw_arrayElementSize, vw_element, vw_elementOffset, vw_storage, vw_blockSize DIM AS LONG vw_arrayDimension, vw_arrayTotalDimensions, vw_arrayIndex, vw_realArrayIndex @@ -304,7 +304,7 @@ SUB vwatch (globalVariables AS _OFFSET, localVariables AS _OFFSET) IF vw_scope$ = LEFT$(vwatch_stack(vwatch_sublevel), INSTR(vwatch_stack(vwatch_sublevel), ",") - 1) THEN vw_address = _OFFSET(localVariables) + LEN(vw_address) * vw_localIndex ELSE - IF vw_checkingWatchpoints THEN RETURN + IF vw_checkingWatchpoints THEN vw_varType$ = "": RETURN GOTO cmdProcessingDone END IF END IF @@ -316,7 +316,7 @@ SUB vwatch (globalVariables AS _OFFSET, localVariables AS _OFFSET) IF vw_originalVarLineNumber > 0 THEN 'prevent fetching array data before DIM line IF vwatch_linenumber <= vw_originalVarLineNumber THEN - IF vw_checkingWatchpoints THEN RETURN + IF vw_checkingWatchpoints THEN vw_varType$ = "": RETURN GOTO cmdProcessingDone END IF END IF @@ -329,7 +329,7 @@ SUB vwatch (globalVariables AS _OFFSET, localVariables AS _OFFSET) vw_uBound = check_ubound%&(vw_address, vw_arrayDimension, vw_arrayTotalDimensions) vw_arrayIndex = CVL(MID$(vw_arrayIndexes$, vw_arrayDimension * 4 - 3, 4)) IF vw_arrayIndex < vw_lBound OR vw_arrayIndex > vw_uBound THEN - IF vw_checkingWatchpoints THEN RETURN + IF vw_checkingWatchpoints THEN vw_varType$ = "": RETURN GOTO cmdProcessingDone END IF @@ -545,7 +545,17 @@ SUB vwatch (globalVariables AS _OFFSET, localVariables AS _OFFSET) 'vw_address now points to the actual data vw_m = _MEM(vw_address, vw_varSize) _MEMPUT vw_m, vw_m.OFFSET, vw_value$ + CASE "clear last watchpoint" + IF LEFT$(vw_lastWatchpoint$, 1) = "g" THEN + vw_cmd$ = "clear global watchpoint" + ELSE + vw_cmd$ = "clear local watchpoint" + END IF + vw_value$ = MID$(vw_lastWatchpoint$, 2) + vw_getBytesPosition& = 1 + GOTO WatchpointCommands CASE "set global watchpoint", "set local watchpoint", "clear global watchpoint", "clear local watchpoint" + WatchpointCommands: vw_getBytes& = 4: GOSUB GetBytes: vw_tempIndex = CVL(vw_valueBytes$) vw_getBytes& = 1: GOSUB GetBytes: vw_isArray = _CV(_BYTE, vw_valueBytes$) vw_getBytes& = 4: GOSUB GetBytes: vw_originalVarLineNumber = CVL(vw_valueBytes$) @@ -553,7 +563,7 @@ SUB vwatch (globalVariables AS _OFFSET, localVariables AS _OFFSET) vw_getBytes& = 4: GOSUB GetBytes: vw_arrayTotalDimensions = CVL(vw_valueBytes$) vw_getBytes& = vw_arrayTotalDimensions: GOSUB GetBytes: vw_arrayIndexes$ = vw_valueBytes$ - vw_temp$ = LEFT$(vw_value$, vw_arrayTotalDimensions + 37) + vw_temp$ = LEFT$(vw_value$, vw_arrayTotalDimensions + 33) vw_arrayTotalDimensions = vw_arrayTotalDimensions \ 4 vw_getBytes& = 4: GOSUB GetBytes: vw_arrayElementSize = CVL(vw_valueBytes$) @@ -575,24 +585,29 @@ SUB vwatch (globalVariables AS _OFFSET, localVariables AS _OFFSET) IF INSTR(vw_cmd$, " global ") THEN vw_buf$ = vw_globalWatchpoints$ ELSE - vw_scope$ = LEFT$(vwatch_stack(vwatch_sublevel), INSTR(vwatch_stack(vwatch_sublevel), ",") - 1) - vw_value$ = vw_value$ + MKI$(LEN(vw_scope$)) + vw_scope$ vw_buf$ = vw_localWatchpoints$ END IF - vw_i = INSTR(vw_buf$, vw_temp$) + vw_i = 0 + vw_i = INSTR(vw_i + 1, vw_buf$, MKL$(-1)) + DO WHILE vw_i + IF MID$(vw_buf$, vw_i + 8, LEN(vw_temp$)) = vw_temp$ THEN EXIT DO + vw_i = INSTR(vw_i + 1, vw_buf$, MKL$(-1)) + LOOP + IF vw_i > 0 THEN 'remove existing watchpoint for the same variable/index/element - vw_j = CVL(MID$(vw_buf$, vw_i - 4, 4)) - vw_buf$ = LEFT$(vw_buf$, vw_i - 5) + MID$(vw_buf$, vw_i + vw_j) + vw_j = CVL(MID$(vw_buf$, vw_i + 4, 4)) + templen = LEN(vw_buf$) + vw_buf$ = LEFT$(vw_buf$, vw_i - 1) + MID$(vw_buf$, vw_i + vw_j + 8) END IF IF LEFT$(vw_cmd$, 4) = "set " THEN - vw_value$ = MKI$(LEN(vw_wpExpression$)) + vw_wpExpression$ + vw_value$ - vw_buf$ = vw_buf$ + MKL$(LEN(vw_value$)) + vw_value$ + vw_value$ = vw_value$ + MKL$(LEN(vw_wpExpression$)) + vw_buf$ = vw_buf$ + MKL$(-1) + MKL$(LEN(vw_value$)) + vw_value$ END IF - IF vw_cmd$ = "set global watchpoint" THEN + IF INSTR(vw_cmd$, " global ") THEN vw_globalWatchpoints$ = vw_buf$ ELSE vw_localWatchpoints$ = vw_buf$ @@ -689,9 +704,9 @@ SUB vwatch (globalVariables AS _OFFSET, localVariables AS _OFFSET) DIM vw_wpTemp$, vw_v1$, vw_v2$ FOR vw_wpi = 1 TO 2 IF vw_wpi = 1 AND LEN(vw_globalWatchpoints$) > 0 THEN - vw_wpTemp$ = vw_globalWatchpoints$ + vw_wpTemp$ = MID$(vw_globalWatchpoints$, 5) ELSEIF vw_wpi = 2 AND LEN(vw_localWatchpoints$) > 0 THEN - vw_wpTemp$ = vw_localWatchpoints$ + vw_wpTemp$ = MID$(vw_localWatchpoints$, 5) ELSE _CONTINUE END IF @@ -699,16 +714,15 @@ SUB vwatch (globalVariables AS _OFFSET, localVariables AS _OFFSET) DO WHILE LEN(vw_wpTemp$) vw_wpj = CVL(LEFT$(vw_wpTemp$, 4)) vw_value$ = MID$(vw_wpTemp$, 5, vw_wpj) - vw_wpTemp$ = MID$(vw_wpTemp$, 5 + vw_wpj) + vw_wpTemp$ = MID$(vw_wpTemp$, 9 + vw_wpj) IF vw_wpi = 1 THEN vw_cmd$ = "get global var" ELSE vw_cmd$ = "get local var" - vw_getBytesPosition& = 1 - vw_getBytes& = 2: GOSUB GetBytes: vw_i = CVI(vw_valueBytes$) - vw_getBytes& = vw_i: GOSUB GetBytes: vw_wpExpression$ = vw_valueBytes$ - vw_value$ = MID$(vw_value$, 3 + LEN(vw_wpExpression$)) + vw_i = CVL(RIGHT$(vw_value$, 4)) + vw_wpExpression$ = MID$(vw_value$, LEN(vw_value$) - (4 + vw_i) + 1, vw_i) vw_getBytesPosition& = 1 GOSUB getGlobalLocal + IF vw_varType$ = "" THEN _CONTINUE IF INSTR(vw_varType$, "STRING") THEN IF LEFT$(vw_wpExpression$, 1) = "=" THEN @@ -755,6 +769,11 @@ SUB vwatch (globalVariables AS _OFFSET, localVariables AS _OFFSET) WatchPointBreak: 'send watchpoint info and pause + IF INSTR(vw_cmd$, "global") THEN + vw_lastWatchpoint$ = "g" + vw_value$ + ELSE + vw_lastWatchpoint$ = "l" + vw_value$ + END IF vw_checkingWatchpoints = 2 RETURN diff --git a/source/ide/ide_methods.bas b/source/ide/ide_methods.bas index 07f3e255b..7f4d9d76b 100644 --- a/source/ide/ide_methods.bas +++ b/source/ide/ide_methods.bas @@ -7156,6 +7156,7 @@ SUB DebugMode cmd$ = "set local address:" END IF + findVarSize: tempVarType$ = varType$ fixedVarSize& = 0 IF INSTR(varType$, "STRING *") THEN @@ -7232,6 +7233,8 @@ SUB DebugMode END IF END SELECT + IF returnAction = 2 OR returnAction = 3 THEN RETURN + cmd$ = cmd$ + MKL$(tempIndex&) cmd$ = cmd$ + _MK$(_BYTE, tempIsArray& <> 0) cmd$ = cmd$ + MKL$(0) @@ -7290,6 +7293,9 @@ SUB DebugMode cmd$ = temp$ + "local watchpoint:" END IF + temp$ = value$ + GOSUB findVarSize + cmd$ = cmd$ + MKL$(tempIndex&) cmd$ = cmd$ + _MK$(_BYTE, tempIsArray& <> 0) cmd$ = cmd$ + MKL$(usedVariableList(tempIndex&).linenumber) @@ -7303,7 +7309,7 @@ SUB DebugMode cmd$ = cmd$ + MKL$(tempStorage&) cmd$ = cmd$ + MKI$(LEN(tempScope$)) + tempScope$ cmd$ = cmd$ + MKI$(LEN(varType$)) + varType$ - cmd$ = cmd$ + MKI$(LEN(value$)) + value$ + cmd$ = cmd$ + MKI$(LEN(temp$)) + temp$ GOSUB SendCommand PCOPY 3, 0: SCREEN , , 3, 0 @@ -7524,7 +7530,11 @@ SUB DebugMode tempIndex& = CVL(GetBytes$(value$, 4)) i = CVI(GetBytes$(value$, 2)) temp$ = usedVariableList(tempIndex&).name + GetBytes$(value$, i) - result = idemessagebox("Watchpoint condition met", temp$, "#Continue;#Clear Watchpoint") + result = idemessagebox("Watchpoint condition met", temp$, "#OK;#Clear Watchpoint") + IF result = 2 THEN + cmd$ = "clear last watchpoint" + GOSUB SendCommand + END IF value$ = RIGHT$(value$, 4) END IF l = CVL(value$) @@ -8016,7 +8026,7 @@ FUNCTION idevariablewatchbox$(currentScope$, filter$, selectVar, returnAction) dialogWidth = 6 + maxModuleNameLen + maxVarLen + maxTypeLen IF IdeDebugMode > 0 THEN dialogWidth = dialogWidth + 40 'make room for "= values" - IF dialogWidth < 60 THEN dialogWidth = 60 + IF dialogWidth < 65 THEN dialogWidth = 65 IF dialogWidth > idewx - 8 THEN dialogWidth = idewx - 8 idepar p, dialogWidth, dialogHeight, "Add Watch - Variable List" @@ -8190,8 +8200,8 @@ FUNCTION idevariablewatchbox$(currentScope$, filter$, selectVar, returnAction) IF y >= 1 AND y <= totalVisibleVariables THEN tempIndex& = varDlgList(y).index - IF usedVariableList(tempIndex&).subfunc = currentScope$ OR usedVariableList(tempIndex&).subfunc = "" THEN - 'scope is valid + IF (focus = 5 AND (usedVariableList(tempIndex&).subfunc = currentScope$ OR usedVariableList(tempIndex&).subfunc = "")) OR focus = 6 THEN + 'scope is valid (or we're setting a watchpoint) tempArrayIndex& = 0 tempArrayIndexes$ = MKL$(0) tempStorage& = 0 @@ -8200,6 +8210,7 @@ FUNCTION idevariablewatchbox$(currentScope$, filter$, selectVar, returnAction) IF usedVariableList(tempIndex&).isarray THEN setArrayRange3: v$ = ideinputbox$(dlgTitle$, dlgPrompt$, temp$, "01234567890,", 45, 0, ok) + _KEYCLEAR IF ok THEN IF LEN(v$) > 0 THEN WHILE RIGHT$(v$, 1) = ",": v$ = LEFT$(v$, LEN(v$) - 1): WEND @@ -8207,6 +8218,7 @@ FUNCTION idevariablewatchbox$(currentScope$, filter$, selectVar, returnAction) i = countelements(temp$) IF i <> ABS(ids(usedVariableList(tempIndex&).id).arrayelements) THEN result = idemessagebox("Error", "Array has" + STR$(ABS(ids(usedVariableList(tempIndex&).id).arrayelements)) + " dimension(s).", "#OK") + _KEYCLEAR temp$ = _TRIM$(v$) GOTO setArrayRange3 END IF @@ -8253,6 +8265,7 @@ FUNCTION idevariablewatchbox$(currentScope$, filter$, selectVar, returnAction) LOOP PCOPY 0, 4 v$ = ideelementwatchbox$(usedVariableList(tempIndex&).name + ".", elementIndexes$, 0, -1, ok) + _KEYCLEAR PCOPY 2, 0 PCOPY 2, 1 SCREEN , , 1, 0 @@ -8277,6 +8290,7 @@ FUNCTION idevariablewatchbox$(currentScope$, filter$, selectVar, returnAction) IF numelements(temp$) <> 1 THEN 'shouldn't ever happen result = idemessagebox("Error", "Only one UDT element can be selected at a time", "#OK") + _KEYCLEAR _CONTINUE END IF @@ -8290,6 +8304,7 @@ FUNCTION idevariablewatchbox$(currentScope$, filter$, selectVar, returnAction) 'shouldn't ever happen Error_Happened = 0 result = idemessagebox("Error", Error_Message, "#OK") + _KEYCLEAR _CONTINUE ELSE typ = typ - ISUDT @@ -8333,6 +8348,7 @@ FUNCTION idevariablewatchbox$(currentScope$, filter$, selectVar, returnAction) ELSE 'shouldn't ever happen result = idemessagebox("Error", "Cannot select full UDT", "#OK") + _KEYCLEAR GOTO dlgLoop END IF END SELECT @@ -8369,6 +8385,7 @@ FUNCTION idevariablewatchbox$(currentScope$, filter$, selectVar, returnAction) END IF getNewValueInput: v$ = ideinputbox$(dlgTitle$, dlgPrompt2$, a2$, "", thisWidth, 0, ok) + _KEYCLEAR IF ok THEN IF focus = 6 THEN 'validate condition string first @@ -8389,11 +8406,13 @@ FUNCTION idevariablewatchbox$(currentScope$, filter$, selectVar, returnAction) CASE ">" IF op2$ = "<" OR op2$ = ">" THEN result = idemessagebox(dlgTitle$, "Invalid expression.\nYou can use =, <>, >, >=, < and <=", "#OK") + _KEYCLEAR GOTO getNewValueInput END IF CASE "<" CASE ELSE result = idemessagebox(dlgTitle$, "Invalid expression.\nYou can use =, <>, >, >=, < and <=", "#OK") + _KEYCLEAR GOTO getNewValueInput END SELECT END IF @@ -8408,12 +8427,7 @@ FUNCTION idevariablewatchbox$(currentScope$, filter$, selectVar, returnAction) cmd$ = cmd$ + MKL$(usedVariableList(tempIndex&).arrayElementSize) cmd$ = cmd$ + MKL$(tempIsUDT&) cmd$ = cmd$ + MKL$(tempElement&) - IF tempElement& THEN - tempElementOffset& = CVL(MID$(usedVariableList(tempIndex&).elementOffset, tempElement& * 4 - 3, 4)) - ELSE - tempElementOffset& = 0 - END IF - cmd$ = cmd$ + MKL$(tempElementOffset&) + cmd$ = cmd$ + tempElementOffset$ cmd$ = cmd$ + MKL$(varSize&) cmd$ = cmd$ + MKL$(tempStorage&) cmd$ = cmd$ + MKI$(LEN(usedVariableList(tempIndex&).subfunc)) @@ -8429,9 +8443,11 @@ FUNCTION idevariablewatchbox$(currentScope$, filter$, selectVar, returnAction) EXIT FUNCTION ELSE result = idemessagebox(dlgTitle$, "Variable is out of scope.", "#OK") + _KEYCLEAR END IF ELSE result = idemessagebox(dlgTitle$, "Select a variable first.", "#OK") + _KEYCLEAR END IF focus = filterBox _CONTINUE