From a37e3801d8675ae16ef8f42ab06622dea8d1e5c3 Mon Sep 17 00:00:00 2001 From: FellippeHeitor Date: Wed, 8 Sep 2021 22:47:31 -0300 Subject: [PATCH] Adds support to watching arrays with multiple dimensions. --- internal/support/vwatch/vwatch.bm | 37 +++++-- source/ide/ide_methods.bas | 177 +++++++++++++++++++++++------- 2 files changed, 163 insertions(+), 51 deletions(-) diff --git a/internal/support/vwatch/vwatch.bm b/internal/support/vwatch/vwatch.bm index 0d3314ab8..36efc6bed 100644 --- a/internal/support/vwatch/vwatch.bm +++ b/internal/support/vwatch/vwatch.bm @@ -2,18 +2,19 @@ $CHECKING:OFF SUB vwatch (globalVariables AS _OFFSET, localVariables AS _OFFSET) STATIC AS LONG vw_ideHost, vw_breakpointCount, vw_skipCount, vw_timeout, vw_startLevel, vw_lastLine - STATIC AS LONG vw_runToLine, vw_arrayIndex, vw_originalVarLineNumber + 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$ DIM AS LONG vw_i, vw_tempIndex, vw_localIndex, vw_varSize, vw_cmdSize - DIM AS LONG vw_arrayElementSize, vw_element, vw_elementOffset, vw_storage - DIM AS LONG vw_arrayDimension, vw_arrayTotalDimensions + DIM AS LONG vw_arrayElementSize, vw_element, vw_elementOffset, vw_storage, vw_blockSize + DIM AS LONG vw_arrayDimension, vw_arrayTotalDimensions, vw_arrayIndex, vw_realArrayIndex DIM AS _OFFSET vw_address, vw_lBound, vw_uBound DIM AS _MEM vw_m, vw_m2 DIM AS _BYTE vw_isArray, vw_isUDT DIM vw_start!, vw_temp$, vw_cmd$, vw_value$, vw_k&, vw_buf$, vw_scope$, vw_varType$ DIM vw_prevValue$, vw_getBytes&, vw_getBytesPosition&, vw_valueBytes$, vw_dummy%& + DIM vw_arrayIndexes$ DECLARE LIBRARY SUB vwatch_stoptimers ALIAS stop_timers @@ -261,7 +262,9 @@ SUB vwatch (globalVariables AS _OFFSET, localVariables AS _OFFSET) vw_getBytes& = 1: GOSUB GetBytes: vw_isArray = _CV(_BYTE, vw_valueBytes$) vw_getBytes& = 4: GOSUB GetBytes: vw_originalVarLineNumber = CVL(vw_valueBytes$) vw_getBytes& = 4: GOSUB GetBytes: vw_localIndex = CVL(vw_valueBytes$) - vw_getBytes& = 4: GOSUB GetBytes: vw_arrayIndex = CVL(vw_valueBytes$) + vw_getBytes& = 4: GOSUB GetBytes: vw_arrayTotalDimensions = CVL(vw_valueBytes$) + vw_getBytes& = vw_arrayTotalDimensions: GOSUB GetBytes: vw_arrayIndexes$ = vw_valueBytes$ + vw_arrayTotalDimensions = vw_arrayTotalDimensions \ 4 vw_getBytes& = 4: GOSUB GetBytes: vw_arrayElementSize = CVL(vw_valueBytes$) vw_getBytes& = 4: GOSUB GetBytes: vw_element = CVL(vw_valueBytes$) vw_getBytes& = 4: GOSUB GetBytes: vw_elementOffset = CVL(vw_valueBytes$) @@ -293,12 +296,22 @@ SUB vwatch (globalVariables AS _OFFSET, localVariables AS _OFFSET) 'prevent fetching array data before DIM line IF vwatch_linenumber <= vw_originalVarLineNumber THEN GOTO cmdProcessingDone END IF - vw_lBound = check_lbound%&(vw_address, vw_arrayDimension, vw_arrayTotalDimensions) - vw_uBound = check_ubound%&(vw_address, vw_arrayDimension, vw_arrayTotalDimensions) - IF vw_arrayIndex < vw_lBound OR vw_arrayIndex > vw_uBound THEN - GOTO cmdProcessingDone - END IF + vw_realArrayIndex = 0 + vw_blockSize = 1 + + FOR vw_arrayDimension = 1 TO vw_arrayTotalDimensions + vw_lBound = check_lbound%&(vw_address, vw_arrayDimension, vw_arrayTotalDimensions) + 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 + GOTO cmdProcessingDone + END IF + + vw_arrayIndex = (vw_arrayIndex - VAL(STR$(vw_lBound))) * vw_blockSize + vw_realArrayIndex = vw_realArrayIndex + vw_arrayIndex + vw_blockSize = vw_blockSize * VAL(STR$(vw_uBound - vw_lBound + 1)) + NEXT 'get the address of where this array's data is stored vw_buf$ = SPACE$(LEN(vw_dummy%&)) @@ -321,9 +334,9 @@ SUB vwatch (globalVariables AS _OFFSET, localVariables AS _OFFSET) END IF 'this is where we calculate the actual array index position in memory IF vw_arrayElementSize = 0 THEN - vw_address = vw_address + ((vw_arrayIndex - vw_lBound) * vw_varSize) + vw_address = vw_address + (vw_realArrayIndex * vw_varSize) ELSE - vw_address = vw_address + ((vw_arrayIndex - vw_lBound) * vw_arrayElementSize) + vw_address = vw_address + (vw_realArrayIndex * vw_arrayElementSize) END IF END IF @@ -538,6 +551,7 @@ SUB vwatch (globalVariables AS _OFFSET, localVariables AS _OFFSET) ELSE vw_cmd$ = "": vw_value$ = "" END IF + vw_prevValue$ = "" RETURN SendCallStack: @@ -566,6 +580,7 @@ SUB vwatch (globalVariables AS _OFFSET, localVariables AS _OFFSET) vw_prevValue$ = vw_value$ vw_getBytesPosition& = 1 END IF + IF vw_getBytes& = 0 THEN vw_valueBytes$ = "": RETURN vw_valueBytes$ = MID$(vw_value$, vw_getBytesPosition&, vw_getBytes&) vw_getBytesPosition& = vw_getBytesPosition& + vw_getBytes& RETURN diff --git a/source/ide/ide_methods.bas b/source/ide/ide_methods.bas index 60ccafa3f..c158d42b2 100644 --- a/source/ide/ide_methods.bas +++ b/source/ide/ide_methods.bas @@ -7399,14 +7399,20 @@ SUB DebugMode 'request variables addresses IF LEN(variableWatchList$) THEN requestVariableValues: - temp$ = MID$(variableWatchList$, 9) - DO WHILE LEN(temp$) - tempIndex& = CVL(LEFT$(temp$, 4)) - tempArrayIndex& = CVL(MID$(temp$, 5, 4)) - tempElement& = CVL(MID$(temp$, 9, 4)) - tempElementOffset& = CVL(MID$(temp$, 13, 4)) - tempStorage& = CVL(MID$(temp$, 17, 4)) - temp$ = MID$(temp$, 25) + temp$ = GetBytes$("", 0) 'reset buffer + temp$ = MID$(variableWatchList$, 9) 'skip longest var name and total visible vars + DO + temp2$ = GetBytes$(temp$, 4) + IF temp2$ <> MKL$(-1) THEN EXIT DO 'no more variables in list + tempIndex& = CVL(GetBytes$(temp$, 4)) + tempArrayIndexes$ = GetBytes$(temp$, 4) + i = CVL(tempArrayIndexes$) + IF i > 0 THEN + tempArrayIndexes$ = tempArrayIndexes$ + GetBytes$(temp$, i) + END IF + tempElement& = CVL(GetBytes$(temp$, 4)) + tempElementOffset& = CVL(GetBytes$(temp$, 4)) + tempStorage& = CVL(GetBytes$(temp$, 4)) IF LEN(usedVariableList(tempIndex&).subfunc) = 0 THEN cmd$ = "get global var:" ELSE @@ -7418,7 +7424,7 @@ SUB DebugMode cmd$ = cmd$ + _MK$(_BYTE, usedVariableList(tempIndex&).isarray) cmd$ = cmd$ + MKL$(usedVariableList(tempIndex&).linenumber) cmd$ = cmd$ + MKL$(usedVariableList(tempIndex&).localIndex) - cmd$ = cmd$ + MKL$(tempArrayIndex&) + cmd$ = cmd$ + tempArrayIndexes$ cmd$ = cmd$ + MKL$(usedVariableList(tempIndex&).arrayElementSize) cmd$ = cmd$ + MKL$(tempElement&) IF tempElement& THEN @@ -7662,7 +7668,7 @@ SUB showvWatchPanel (this AS vWatchPanelType, currentScope$, totalVisibleVariabl 'new setup previousVariableWatchList$ = variableWatchList$ longestVarName = CVL(LEFT$(variableWatchList$, 4)) - totalVisibleVariables = (LEN(variableWatchList$) - 4) \ 20 + totalVisibleVariables = CVL(MID$(variableWatchList$, 5, 4)) this.h = totalVisibleVariables + 2 IF this.h > idewy - 10 THEN this.h = idewy - 10 IF this.h < 5 THEN this.h = 5 @@ -7697,14 +7703,18 @@ SUB showvWatchPanel (this AS vWatchPanelType, currentScope$, totalVisibleVariabl i = 0 this.contentWidth = 0 IF this.hPos = 0 THEN this.hPos = 1 + temp$ = GetBytes$("", 0) 'reset buffer temp$ = MID$(variableWatchList$, 9) - DO WHILE LEN(temp$) - tempIndex& = CVL(LEFT$(temp$, 4)) - tempArrayIndex& = CVL(MID$(temp$, 5, 4)) - tempElement& = CVL(MID$(temp$, 9, 4)) - tempElementOffset& = CVL(MID$(temp$, 13, 4)) - tempStorage& = CVL(MID$(temp$, 17, 4)) - temp$ = MID$(temp$, 25) + DO + temp2$ = GetBytes$(temp$, 4) + IF temp2$ <> MKL$(-1) THEN EXIT DO 'no more variables in list + tempIndex& = CVL(GetBytes$(temp$, 4)) + tempTotalArrayIndexes& = CVL(GetBytes$(temp$, 4)) + tempArrayIndexes$ = GetBytes$(temp$, tempTotalArrayIndexes&) + tempElement& = CVL(GetBytes$(temp$, 4)) + tempElementOffset& = CVL(GetBytes$(temp$, 4)) + tempStorage& = CVL(GetBytes$(temp$, 4)) + i = i + 1 IF this.firstVisible > i AND WatchListToConsole = 0 THEN _CONTINUE y = y + 1 @@ -7712,8 +7722,13 @@ SUB showvWatchPanel (this AS vWatchPanelType, currentScope$, totalVisibleVariabl thisName$ = usedVariableList(tempIndex&).name IF usedVariableList(tempIndex&).isarray THEN - thisName$ = LEFT$(thisName$, LEN(thisName$) - 1) + _ - LTRIM$(STR$(tempArrayIndex&)) + ")" + thisName$ = LEFT$(thisName$, LEN(thisName$) - 1) + tempTotalArrayIndexes& = tempTotalArrayIndexes& \ 4 + FOR j = 1 TO tempTotalArrayIndexes& + thisName$ = thisName$ + LTRIM$(STR$(CVL(MID$(tempArrayIndexes$, j * 4 - 3, 4)))) + IF j < tempTotalArrayIndexes& THEN thisName$ = thisName$ + ", " + NEXT + thisName$ = thisName$ + ")" END IF IF tempElement& THEN tempElementList$ = MID$(usedVariableList(tempIndex&).elements, 5) @@ -8199,12 +8214,13 @@ FUNCTION idevariablewatchbox$(currentScope$, filter$, selectVar, returnAction) variableWatchList$ = "" longestVarName = 0 nextvWatchDataSlot = 0 + totalVisibleVariables = 0 FOR y = 1 TO totalVariablesCreated IF usedVariableList(y).includedLine THEN _CONTINUE 'don't deal with variables in $INCLUDEs IF usedVariableList(y).watch THEN thisLen = LEN(usedVariableList(y).name) IF usedVariableList(y).isarray THEN - thisLen = thisLen + LEN(STR$(CVL(RIGHT$(usedVariableList(y).indexes, 4)))) - 1 + thisLen = thisLen + LEN(usedVariableList(y).watchRange) END IF IF LEN(usedVariableList(y).elements) THEN @@ -8213,28 +8229,39 @@ FUNCTION idevariablewatchbox$(currentScope$, filter$, selectVar, returnAction) IF thisLen > longestVarName THEN longestVarName = thisLen - IF variableWatchList$ = "" THEN variableWatchList$ = SPACE$(4) + IF variableWatchList$ = "" THEN variableWatchList$ = SPACE$(8) MID$(variableWatchList$, 1, 4) = MKL$(longestVarName) END IF IF usedVariableList(y).isarray <> 0 AND LEN(usedVariableList(y).elements) = 0 THEN 'array of native data type - temp$ = usedVariableList(y).indexes - DO WHILE LEN(temp$) + temp$ = GetBytes$("", 0) + temp$ = expandArray$(usedVariableList(y).indexes, "") + DO + temp2$ = GetBytes$(temp$, 4) + IF LEN(temp2$) <> 4 THEN EXIT DO 'no more items + length = CVL(temp2$) + temp2$ = MKL$(length) + GetBytes$(temp$, length) nextvWatchDataSlot = nextvWatchDataSlot + 1 WHILE nextvWatchDataSlot > UBOUND(vWatchReceivedData$) REDIM _PRESERVE vWatchReceivedData$(1 TO UBOUND(vWatchReceivedData$) + 999) WEND - variableWatchList$ = variableWatchList$ + MKL$(-1) + MKL$(y) + LEFT$(temp$, 4) + MKL$(0) + MKL$(0) + MKL$(nextvWatchDataSlot) + variableWatchList$ = variableWatchList$ + MKL$(-1) + MKL$(y) + temp2$ + MKL$(0) + MKL$(0) + MKL$(nextvWatchDataSlot) + totalVisibleVariables = totalVisibleVariables + 1 usedVariableList(y).storage = usedVariableList(y).storage + MKL$(nextvWatchDataSlot) vWatchReceivedData$(nextvWatchDataSlot) = "" - temp$ = MID$(temp$, 5) LOOP ELSEIF usedVariableList(y).isarray <> 0 AND LEN(usedVariableList(y).elements) > 0 THEN 'array of UDT - temp$ = usedVariableList(y).indexes - DO WHILE LEN(temp$) - thisTempElement$ = MKL$(-1) + MKL$(y) + LEFT$(temp$, 4) + temp$ = GetBytes$("", 0) + temp$ = expandArray$(usedVariableList(y).indexes, "") + DO + temp2$ = GetBytes$(temp$, 4) + IF LEN(temp2$) <> 4 THEN EXIT DO 'no more items + length = CVL(temp2$) + temp2$ = MKL$(length) + GetBytes$(temp$, length) + + thisTempElement$ = MKL$(-1) + MKL$(y) + temp2$ thisElementList$ = MID$(usedVariableList(y).elements, 5) i = 0 DO @@ -8248,10 +8275,10 @@ FUNCTION idevariablewatchbox$(currentScope$, filter$, selectVar, returnAction) WEND tempElementOffset& = CVL(MID$(usedVariableList(y).elementOffset, i * 4 - 3, 4)) variableWatchList$ = variableWatchList$ + thisTempElement$ + MKL$(i) + MKL$(tempElementOffset&) + MKL$(nextvWatchDataSlot) + totalVisibleVariables = totalVisibleVariables + 1 usedVariableList(y).storage = usedVariableList(y).storage + MKL$(nextvWatchDataSlot) vWatchReceivedData$(nextvWatchDataSlot) = "" LOOP - temp$ = MID$(temp$, 5) LOOP ELSEIF usedVariableList(y).isarray = 0 AND LEN(usedVariableList(y).elements) > 0 THEN 'single variable of UDT @@ -8269,6 +8296,7 @@ FUNCTION idevariablewatchbox$(currentScope$, filter$, selectVar, returnAction) WEND tempElementOffset& = CVL(MID$(usedVariableList(y).elementOffset, i * 4 - 3, 4)) variableWatchList$ = variableWatchList$ + thisTempElement$ + MKL$(i) + MKL$(tempElementOffset&) + MKL$(nextvWatchDataSlot) + totalVisibleVariables = totalVisibleVariables + 1 usedVariableList(y).storage = usedVariableList(y).storage + MKL$(nextvWatchDataSlot) vWatchReceivedData$(nextvWatchDataSlot) = "" LOOP @@ -8279,10 +8307,12 @@ FUNCTION idevariablewatchbox$(currentScope$, filter$, selectVar, returnAction) REDIM _PRESERVE vWatchReceivedData$(1 TO UBOUND(vWatchReceivedData$) + 999) WEND variableWatchList$ = variableWatchList$ + MKL$(-1) + MKL$(y) + MKL$(0) + MKL$(0) + MKL$(0) + MKL$(nextvWatchDataSlot) + totalVisibleVariables = totalVisibleVariables + 1 usedVariableList(y).storage = MKL$(nextvWatchDataSlot) END IF END IF NEXT + IF LEN(variableWatchList$) THEN MID$(variableWatchList$, 5, 4) = MKL$(totalVisibleVariables) IF mousedown THEN DO GetInput @@ -8322,17 +8352,38 @@ FUNCTION idevariablewatchbox$(currentScope$, filter$, selectVar, returnAction) IF LEN(usedVariableList(varDlgList(y).index).indexes) THEN temp$ = usedVariableList(varDlgList(y).index).watchRange END IF - - v$ = ideinputbox$("Watch Array", "#Indexes to watch", temp$, "01234567890,-", 45, 0, ok) + setArrayRange2: + v$ = ideinputbox$("Watch Array", "#Indexes" + tempPrompt$, temp$, "01234567890,-; TOto", 45, 0, ok) IF ok THEN IF LEN(v$) > 0 THEN - temp$ = parseRange$(v$) - usedVariableList(varDlgList(y).index).indexes = temp$ - temp$ = formatRange$(temp$) - usedVariableList(varDlgList(y).index).watchRange = temp$ - ELSE + v$ = UCASE$(v$) + v$ = StrReplace$(v$, " TO ", "-") + WHILE RIGHT$(v$, 1) = ",": v$ = LEFT$(v$, LEN(v$) - 1): WEND + temp$ = lineformat$(v$) + i = countelements(temp$) + IF i <> ABS(ids(usedVariableList(varDlgList(y).index).id).arrayelements) THEN + result = idemessagebox("Error", "Array has" + STR$(ABS(ids(usedVariableList(varDlgList(y).index).id).arrayelements)) + " dimension(s).", "#OK") + temp$ = v$ + GOTO setArrayRange2 + END IF usedVariableList(varDlgList(y).index).indexes = "" usedVariableList(varDlgList(y).index).watchRange = "" + WHILE i + foundComma = INSTR(v$, ",") + IF foundComma THEN + temp$ = LEFT$(v$, foundComma - 1) + v$ = MID$(v$, foundComma + 1) + ELSE + temp$ = v$ + END IF + temp$ = parseRange$(temp$) + usedVariableList(varDlgList(y).index).indexes = usedVariableList(varDlgList(y).index).indexes + MKL$(LEN(temp$)) + temp$ + temp$ = formatRange$(temp$) + usedVariableList(varDlgList(y).index).watchRange = usedVariableList(varDlgList(y).index).watchRange + temp$ + i = i - 1 + IF i THEN usedVariableList(varDlgList(y).index).watchRange = usedVariableList(varDlgList(y).index).watchRange + "," + WEND + ELSE usedVariableList(varDlgList(y).index).watch = 0 GOSUB buildList idetxt(o(varListBox).txt) = l$ @@ -8344,6 +8395,7 @@ FUNCTION idevariablewatchbox$(currentScope$, filter$, selectVar, returnAction) usedVariableList(varDlgList(y).index).watch = 0 GOTO unWatch END IF + END IF varType$ = usedVariableList(varDlgList(y).index).varType @@ -9064,10 +9116,10 @@ FUNCTION formatRange$(__text$) v2 = v ELSE IF v2 = -1 THEN - a2$ = a2$ + LTRIM$(STR$(v1)) + "," + a2$ = a2$ + LTRIM$(STR$(v1)) + ";" v1 = v ELSE - a2$ = a2$ + LTRIM$(STR$(v1)) + "-" + LTRIM$(STR$(v2)) + "," + a2$ = a2$ + LTRIM$(STR$(v1)) + "-" + LTRIM$(STR$(v2)) + ";" v1 = v v2 = -1 END IF @@ -9079,6 +9131,37 @@ FUNCTION formatRange$(__text$) formatRange$ = a2$ END FUNCTION +FUNCTION expandArray$ (__indexes$, __path$) + STATIC thisLevel AS LONG, returnValue$ + + IF thisLevel = 0 THEN + returnValue$ = "" + END IF + + thisLevel = thisLevel + 1 + + totalIndexes = CVL(LEFT$(__indexes$, 4)) + indexes$ = MID$(__indexes$, 5, totalIndexes) + remainingIndexes$ = MID$(__indexes$, 5 + totalIndexes) + totalIndexes = totalIndexes \ 4 + + FOR i = 1 TO totalIndexes + temp$ = __path$ + MID$(indexes$, i * 4 - 3, 4) + IF LEN(remainingIndexes$) THEN + temp$ = expandArray$(remainingIndexes$, temp$) + END IF + IF LEN(temp$) THEN + returnValue$ = returnValue$ + MKL$(LEN(temp$)) + temp$ + END IF + NEXT + + thisLevel = thisLevel - 1 + + IF thisLevel = 0 THEN + expandArray$ = returnValue$ + END IF +END FUNCTION + FUNCTION parseRange$(__text$) '__text$ must contain a valid numeric string (####), 'a valid interval (####-####) or comma-separated values. @@ -9090,7 +9173,7 @@ FUNCTION parseRange$(__text$) DIM zeroIncluded AS _BYTE Filter$ = _TRIM$(__text$) - j = INSTR(Filter$, "-") + INSTR(Filter$, ",") + j = INSTR(Filter$, "-") + INSTR(Filter$, ";") temp$ = SPACE$(1000) IF j = 0 THEN 'Single number passed @@ -9102,7 +9185,7 @@ FUNCTION parseRange$(__text$) FOR j = 1 TO LEN(Filter$) v = ASC(Filter$, j) SELECT CASE v - CASE 44 'comma + CASE 59 '; Reading = 1 GOSUB parseIt CASE 45 'hyphen @@ -18658,3 +18741,17 @@ SUB printWrapStatus (x AS INTEGER, y AS INTEGER, initialX AS INTEGER, __text$) RETURN END SUB +FUNCTION GetBytes$(__value$, numberOfBytes&) + STATIC prevValue$, getBytesPosition& + + value$ = __value$ + IF value$ <> prevValue$ THEN + prevValue$ = value$ + getBytesPosition& = 1 + END IF + + IF numberOfBytes& = 0 THEN EXIT FUNCTION + + GetBytes$ = MID$(value$, getBytesPosition&, numberOfBytes&) + getBytesPosition& = getBytesPosition& + numberOfBytes& +END FUNCTION