Change `GDBRegisterWithValue >> #value` to return numeric value
...rather than string. In case of 'composite' registers (such as
FPRs that can hold both IEEE 754 float and double values or vector
registers) it returns a dictionary with components.
--- a/GDBMIParser.st Fri Sep 10 20:25:06 2021 +0100
+++ b/GDBMIParser.st Fri Sep 10 22:12:22 2021 +0100
@@ -269,6 +269,56 @@
"Created: / 18-06-2014 / 07:17:34 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
+parseInteger
+ ^ self parseIntegerAndText: false
+
+ "Created: / 10-09-2021 / 14:36:11 / Jan Vrany <jan.vrany@labware.com>"
+ "Modified: / 10-09-2021 / 22:03:27 / Jan Vrany <jan.vrany@labware.com>"
+!
+
+parseIntegerAndText: returnAlsoString
+ "Parse decimal, hex or octal integer and return
+ either the integer value (if `returnAlsoString` is `false`)
+ or pair #(<value> <text>) where <text> is the literal string
+ if (if `returnAlsoString` is `true`).
+
+ The next character in input is known to be a digit.
+ "
+ | c v s |
+
+ c := self next.
+ returnAlsoString ifTrue:[
+ s := String new writeStream.
+ s nextPut: c.
+ ].
+ (c == $0 and:[ self peek == $x ]) ifTrue:[
+ "/ Find 0x prefix, parse hex number (address or alike)
+ returnAlsoString ifTrue:[ s nextPut: self peek].
+ self next. "/ eat $x
+ v := 0.
+ [ c := self peek.
+ c notNil and:[ c isHexDigit] ] whileTrue:[
+ returnAlsoString ifTrue:[ s nextPut: self peek].
+ self next.
+ v := (v << 4) + (c digitValue).
+ ].
+ ] ifFalse:[
+ "/ Parse decimal number
+ v := c digitValue.
+ [ c := self peek.
+ c notNil and:[ c isDigit] ] whileTrue:[
+ returnAlsoString ifTrue:[ s nextPut: self peek].
+ self next.
+ v := (v * 10) + (c digitValue).
+ ].
+ ].
+ ^ returnAlsoString
+ ifTrue:[ Array with: v with: s contents ]
+ ifFalse:[ v ].
+
+ "Created: / 10-09-2021 / 22:02:26 / Jan Vrany <jan.vrany@labware.com>"
+!
+
parseNl
| c |
@@ -732,6 +782,34 @@
"Created: / 30-05-2014 / 10:36:04 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
+parseInteger
+ "Parse input containing (MI) printed register value"
+ | c v |
+
+ c := self next.
+ (c == $0 and:[ self peek == $x ]) ifTrue:[
+ "/ Find 0x prefix, parse hex number (address or alike)
+ self next. "/ eat $x
+ v := 0.
+ [ c := self peek.
+ c notNil and:[ c isHexDigit] ] whileTrue:[
+ self next.
+ v := (v << 4) + (c digitValue).
+ ].
+ ] ifFalse:[
+ "/ Parse decimal number
+ v := c digitValue.
+ [ c := self peek.
+ c notNil and:[ c isDigit] ] whileTrue:[
+ self next.
+ v := (v * 10) + (c digitValue).
+ ].
+ ].
+ ^ v
+
+ "Created: / 10-09-2021 / 14:36:11 / Jan Vrany <jan.vrany@labware.com>"
+!
+
parseList
"
list → '[]' | '[' value ( ',' value )* ']' | '[' result ( ',' result )* ']'
@@ -801,13 +879,19 @@
dict := Dictionary new.
self peek ~~ $} ifTrue:[
name := self parseVariable.
+ self skipSeparators.
self expect: $=.
+ self skipSeparators.
value := self parseValue.
+ self skipSeparators.
dict at: name put: value.
[ self peek == $, ] whileTrue:[
self next.
+ self skipSeparators.
name := self parseVariable.
+ self skipSeparators.
self expect: $=.
+ self skipSeparators.
value := self parseValue.
dict at: name put: value.
].
@@ -816,25 +900,30 @@
"Created: / 14-06-2014 / 02:19:56 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 06-07-2017 / 08:25:32 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified: / 10-09-2021 / 14:50:55 / Jan Vrany <jan.vrany@labware.com>"
!
parseValue
"
- value → const | tuple | list
+ value → const | tuple | list | integer
"
self peek == $" ifTrue:[
- ^ self parseConst
+ ^ self parseConst
].
self peek == ${ ifTrue:[
- ^ self parseTuple.
+ ^ self parseTuple.
].
self peek == $[ ifTrue:[
- ^ self parseList
+ ^ self parseList
+ ].
+ self peek isDigit ifTrue: [
+ ^ self parseInteger
].
self error:'Invalid value'
"Created: / 30-05-2014 / 10:31:12 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified: / 10-09-2021 / 14:35:02 / Jan Vrany <jan.vrany@labware.com>"
! !
!GDBMIParser methodsFor:'parsing-values-typed'!
@@ -946,36 +1035,22 @@
| c v |
self expect: $".
- c := self next.
- v := 0.
- c isDigit ifTrue:[
- (c == $0 and:[ self peek == $x ]) ifTrue:[
- "/ Find 0x prefix, parse hex number (address or alike)
- self next. "/ eat $x
- c := self next.
- [ c isHexDigit ] whileTrue:[
- v := (v << 4) + (c digitValue).
- c := self next.
- ].
- ] ifFalse:[
- "/ Parse decimal number
- [ c isDigit ] whileTrue:[
- v := (v * 10) + (c digitValue).
- c := self next.
- ].
- ].
- c == $" ifTrue:[
- ^ v
+ self peek isDigit ifTrue:[
+ v := self parseIntegerAndText: true.
+ self peek == $" ifTrue:[
+ self next. "/ eat $"
+ ^ v first
] ifFalse:[
- ^ self parseCStringRest:v printString , c
+ ^ self parseCStringRest:v second
].
].
- ^ self parseCStringRest: c asString
+ ^ self parseCStringRest: ''
].
^ self parseValue
"Created: / 18-06-2014 / 07:39:22 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 03-07-2018 / 14:50:15 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified: / 10-09-2021 / 22:07:34 / Jan Vrany <jan.vrany@labware.com>"
!
parseValueAsListElementDescribedBy:descriptor
--- a/GDBRegisterWithValue.st Fri Sep 10 20:25:06 2021 +0100
+++ b/GDBRegisterWithValue.st Fri Sep 10 22:12:22 2021 +0100
@@ -89,10 +89,35 @@
!
value
- changed value.
+ "Return the value of the register. The returned value is either
+
+ * an integer in case the register is integer register - GPRs and so on)
+ * a dictionary in case of 'composite' registers - for example a value
+ of FPR might be returned as '{float = 0xABCDDCBA, double = 0xA...B}'
+ Similarly for vector registers (SSE / SSE2 regs on x86, VSRs on POWER)
+ "
+ ^ (GDBMIParser on: self valueString) parseValue
+
+ "Modified: / 27-09-2018 / 15:26:50 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified: / 10-09-2021 / 14:58:56 / Jan Vrany <jan.vrany@labware.com>"
+ "Modified (comment): / 10-09-2021 / 20:00:13 / Jan Vrany <jan.vrany@labware.com>"
+!
+
+valueString
+ value isNil ifTrue: [
+ | result registers |
+ result := debugger send: (GDBMI_data_list_register_values new arguments: (Array with: '--thread' with: frame thread id with: '--frame' with: frame level with: 'r' with: register number)).
+ registers := result propertyAt: #'register-values'.
+ self assert: registers size == 1.
+ self assert: registers first register = register number.
+ value := registers first valueString.
+ ] ifFalse: [
+ changed value.
+ ].
^ value
- "Modified: / 27-09-2018 / 15:26:50 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Created: / 10-09-2021 / 14:14:14 / Jan Vrany <jan.vrany@labware.com>"
+ "Modified: / 10-09-2021 / 15:58:15 / Jan Vrany <jan.vrany@labware.com>"
! !
!GDBRegisterWithValue methodsFor:'initialization'!
--- a/tests/GDBMIParserTests.st Fri Sep 10 20:25:06 2021 +0100
+++ b/tests/GDBMIParserTests.st Fri Sep 10 22:12:22 2021 +0100
@@ -1,7 +1,7 @@
"
jv:libgdbs - GNU Debugger Interface Library
Copyright (C) 2015-now Jan Vrany
-Copyright (C) 2020 LabWare
+Copyright (C) 2020-2021 LabWare
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -34,7 +34,7 @@
"
jv:libgdbs - GNU Debugger Interface Library
Copyright (C) 2015-now Jan Vrany
-Copyright (C) 2020 LabWare
+Copyright (C) 2020-2021 LabWare
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -790,6 +790,54 @@
"Created: / 06-07-2017 / 08:21:39 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
+!GDBMIParserTests methodsFor:'tests - values - registers'!
+
+test_registers_01
+ | value |
+
+ value := (GDBMIParser on:'0x00000000000717fc') parseValue.
+ self assert:value isInteger.
+ self assert:value = 16r00000000000717fc
+
+ "Created: / 10-09-2021 / 14:28:27 / Jan Vrany <jan.vrany@labware.com>"
+!
+
+test_registers_02
+ | value |
+
+ value := (GDBMIParser on:'{float = 0x00000000, double = 0x0000000000000000}') parseValue.
+ self assert:value isDictionary.
+ self assert:(value includesKey: 'float').
+ self assert:(value at: 'float') = 0.
+ self assert:(value includesKey: 'double').
+ self assert:(value at: 'double') = 0.
+
+ "Created: / 10-09-2021 / 14:31:00 / Jan Vrany <jan.vrany@labware.com>"
+!
+
+test_registers_03
+ | value |
+
+ value := (GDBMIParser on:'{x = 00000000, y = 1}') parseValue.
+ self assert:value isDictionary.
+ self assert:(value includesKey: 'x').
+ self assert:(value at: 'x') = 0.
+ self assert:(value includesKey: 'y').
+ self assert:(value at: 'y') = 1.
+
+ "Created: / 10-09-2021 / 14:52:54 / Jan Vrany <jan.vrany@labware.com>"
+!
+
+test_registers_04
+ | value |
+
+ value := (GDBMIParser on:'10') parseValue.
+ self assert:value isInteger.
+ self assert:value = 10
+
+ "Created: / 10-09-2021 / 14:56:17 / Jan Vrany <jan.vrany@labware.com>"
+! !
+
!GDBMIParserTests methodsFor:'tests - values - typed'!
test_typed_boolean