Commit 6107fdc2 authored by hjk's avatar hjk

Debugger: Add "composite" watchers

Multiple expressions can be separated by semicolon,
and arrays allow index ranges given as [a..b] or
with strides [a.(s).b].

Change-Id: I0b7b4ee500a5f6f5027d777b0a1e8ee5a28a7cd5
Reviewed-by: default avatarChristian Stenger <christian.stenger@digia.com>
parent abe4bff8
......@@ -31,6 +31,7 @@ import os
import struct
import sys
import base64
import re
if sys.version_info[0] >= 3:
xrange = range
......@@ -1328,6 +1329,84 @@ class DumperBase:
code = "I" if self.ptrSize() == 4 else "Q"
return struct.unpack_from(code, bytes, offset)[0]
# Parses a..b and a.(s).b
def parseRange(self, exp):
match = re.search("\[(.+?)\.(\(.+?\))?\.(.+?)\]", exp)
if match:
a = match.group(1)
s = match.group(2)
b = match.group(3)
try:
step = toInteger(s[1:len(s)-1]) if s else 1
template = exp[:match.start(1)] + '%s' + exp[match.end(3):]
return True, toInteger(a), step, toInteger(b) + 1, template
except:
pass
return False, 0, 1, 1, exp
def handleWatch(self, origexp, exp, iname):
exp = str(exp).strip()
escapedExp = self.hexencode(exp)
#warn("HANDLING WATCH %s -> %s, INAME: '%s'" % (origexp, exp, iname))
# Grouped items separated by semicolon
if exp.find(";") >= 0:
exps = exp.split(';')
n = len(exps)
with TopLevelItem(self, iname):
self.put('iname="%s",' % iname)
#self.put('wname="%s",' % escapedExp)
self.put('name="%s",' % exp)
self.put('exp="%s",' % exp)
self.putItemCount(n)
self.putNoType()
for i in xrange(n):
self.handleWatch(exps[i], exps[i], "%s.%d" % (iname, i))
return
# Special array index: e.g a[1..199] or a[1.(3).199] for stride 3.
isRange, begin, step, end, template = self.parseRange(exp)
if isRange:
#warn("RANGE: %s %s %s in %s" % (begin, step, end, template))
r = range(begin, end, step)
n = len(r)
with TopLevelItem(self, iname):
self.put('iname="%s",' % iname)
#self.put('wname="%s",' % escapedExp)
self.put('name="%s",' % exp)
self.put('exp="%s",' % exp)
self.putItemCount(n)
self.putNoType()
with Children(self, n):
for i in r:
e = template % i
self.handleWatch(e, e, "%s.%s" % (iname, i))
return
# Fall back to less special syntax
#return self.handleWatch(origexp, exp, iname)
with TopLevelItem(self, iname):
self.put('iname="%s",' % iname)
self.put('name="%s",' % exp)
self.put('wname="%s",' % escapedExp)
if len(exp) == 0: # The <Edit> case
self.putValue(" ")
self.putNoType()
self.putNumChild(0)
else:
try:
value = self.parseAndEvaluate(exp)
self.putItem(value)
except RuntimeError:
self.currentType = " "
self.currentValue = "<no such value>"
self.currentChildNumChild = -1
self.currentNumChild = 0
self.putNumChild(0)
# Some "Enums"
# Encodings. Keep that synchronized with DebuggerEncoding in debuggerprotocol.h
......
......@@ -492,7 +492,7 @@ class Dumper(DumperBase):
if len(watchers) > 0:
for watcher in watchers.split("##"):
(exp, iname) = watcher.split("#")
self.handleWatch(exp, iname)
self.handleWatch(exp, exp, iname)
#print('data=[' + locals + sep + watchers + ']\n')
......@@ -720,52 +720,6 @@ class Dumper(DumperBase):
msg = msg[0:-1]
return int(msg)
def handleWatch(self, exp, iname):
exp = str(exp)
escapedExp = self.hexencode(exp);
#warn("HANDLING WATCH %s, INAME: '%s'" % (exp, iname))
if exp.startswith("[") and exp.endswith("]"):
#warn("EVAL: EXP: %s" % exp)
with TopLevelItem(self, iname):
self.put('iname="%s",' % iname)
self.put('wname="%s",' % escapedExp)
try:
list = eval(exp)
self.putValue("")
self.putNoType()
self.putNumChild(len(list))
# This is a list of expressions to evaluate
with Children(self, len(list)):
itemNumber = 0
for item in list:
self.handleWatch(item, "%s.%d" % (iname, itemNumber))
itemNumber += 1
except RuntimeError as error:
warn("EVAL: ERROR CAUGHT %s" % error)
self.putValue("<syntax error>")
self.putNoType()
self.putNumChild(0)
self.put("children=[],")
return
with TopLevelItem(self, iname):
self.put('iname="%s",' % iname)
self.put('wname="%s",' % escapedExp)
if len(exp) == 0: # The <Edit> case
self.putValue(" ")
self.putNoType()
self.putNumChild(0)
else:
try:
value = self.parseAndEvaluate(exp)
self.putItem(value)
except RuntimeError:
self.currentType = " "
self.currentValue = "<no such value>"
self.currentChildNumChild = -1
self.currentNumChild = 0
self.putNumChild(0)
def intType(self):
self.cachedIntType = self.lookupType('int')
self.intType = lambda: self.cachedIntType
......
......@@ -1153,19 +1153,7 @@ class Dumper(DumperBase):
# could be 'watch.0' or 'tooltip.deadbead'
(base, component) = iname.split('.')
exp = self.hexdecode(watcher['exp'])
if exp == "":
self.put('type="",value="",exp=""')
continue
options = lldb.SBExpressionOptions()
value = self.target.EvaluateExpression(exp, options)
#value = self.target.EvaluateExpression(iname, exp)
self.currentIName = base
with SubItem(self, component):
self.put('exp="%s",' % exp)
self.put('wname="%s",' % self.hexencode(exp))
self.put('iname="%s",' % iname)
self.putItem(value)
self.handleWatch(exp, exp, iname)
self.put(']')
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment