Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoraleherbau2011-04-05 10:13:09 +0000
committeraleherbau2011-04-05 10:13:09 +0000
commit559ca401ad7f4f02875edeefaf2b56dc79702000 (patch)
treef171952d1d842e357bda44a10dd23828e4b16eef /python/src
parent311c18e8e00e5d080d22bd2525dd46f94e1b0ab4 (diff)
downloadorg.eclipse.tcf-559ca401ad7f4f02875edeefaf2b56dc79702000.tar.gz
org.eclipse.tcf-559ca401ad7f4f02875edeefaf2b56dc79702000.tar.xz
org.eclipse.tcf-559ca401ad7f4f02875edeefaf2b56dc79702000.zip
Implemented registers service proxy
Diffstat (limited to 'python/src')
-rw-r--r--python/src/tcf/channel/__init__.py16
-rw-r--r--python/src/tcf/services/__init__.py5
-rw-r--r--python/src/tcf/services/breakpoints.py6
-rw-r--r--python/src/tcf/services/locator.py6
-rw-r--r--python/src/tcf/services/registers.py469
-rw-r--r--python/src/tcf/services/remote/RegistersProxy.py170
-rw-r--r--python/src/tcf/services/remote/RunControlProxy.py3
-rw-r--r--python/src/tcf/services/runcontrol.py3
-rw-r--r--python/src/tcf/services/stacktrace.py5
-rw-r--r--python/src/tcf/services/symbols.py3
-rw-r--r--python/src/tcf/shell.py10
-rw-r--r--python/src/tcf/tests/BasicTests.py39
12 files changed, 704 insertions, 31 deletions
diff --git a/python/src/tcf/channel/__init__.py b/python/src/tcf/channel/__init__.py
index 1a96a3b7d..0b81bbc73 100644
--- a/python/src/tcf/channel/__init__.py
+++ b/python/src/tcf/channel/__init__.py
@@ -118,7 +118,7 @@ def toJSONSequence(args):
return None
buf = cStringIO.StringIO()
for arg in args:
- json.dump(arg, buf, separators=(',', ':'))
+ json.dump(arg, buf, separators=(',', ':'), cls=TCFJSONEncoder)
buf.write('\0')
return buf.getvalue()
@@ -135,11 +135,19 @@ def fromJSONSequence(bytes):
objects.append(None)
return objects
-_ByteArrayType = type(bytearray())
def toByteArray(data):
if data is None: return None
t = type(data)
- if t is _ByteArrayType: return data
+ if t is bytearray: return data
if t is types.StringType:
return binascii.a2b_base64(data)
- raise exceptions.Exception()
+ raise exceptions.TypeError(str(t))
+
+class TCFJSONEncoder(json.JSONEncoder):
+ def default(self, o):
+ if isinstance(o, bytearray):
+ return binascii.b2a_base64(o)
+ elif hasattr('__iter__', o):
+ return tuple(o)
+ else:
+ json.JSONEncoder.default(self, o)
diff --git a/python/src/tcf/services/__init__.py b/python/src/tcf/services/__init__.py
index 349a2b52a..bb5c30618 100644
--- a/python/src/tcf/services/__init__.py
+++ b/python/src/tcf/services/__init__.py
@@ -35,8 +35,9 @@ def removeServiceProvider(provider):
def onChannelCreated(channel, services_by_name):
with _lock:
- zero_copy = ZeroCopy()
- services_by_name[zero_copy.getName()] = zero_copy
+ # TODO ZeroCopy support is incomplete
+# zero_copy = ZeroCopy()
+# services_by_name[zero_copy.getName()] = zero_copy
for provider in _providers:
try:
arr = provider.getLocalService(channel)
diff --git a/python/src/tcf/services/breakpoints.py b/python/src/tcf/services/breakpoints.py
index 97ee9b2c8..05481d0b4 100644
--- a/python/src/tcf/services/breakpoints.py
+++ b/python/src/tcf/services/breakpoints.py
@@ -9,9 +9,6 @@
# * Wind River Systems - initial API and implementation
# *******************************************************************************
-import exceptions
-from tcf import services
-
"""
Breakpoint is represented by unique identifier and set of properties.
Breakpoint identifier (String id) needs to be unique across all hosts and targets.
@@ -26,6 +23,9 @@ persistent and represent user input, breakpoint status reflects dynamic target a
about breakpoint current state, like actual addresses where breakpoint is planted or planting errors.
"""
+import exceptions
+from tcf import services
+
# Service name.
NAME = "Breakpoints"
diff --git a/python/src/tcf/services/locator.py b/python/src/tcf/services/locator.py
index 5c7f69c65..3ddaa6afe 100644
--- a/python/src/tcf/services/locator.py
+++ b/python/src/tcf/services/locator.py
@@ -9,9 +9,6 @@
# * Wind River Systems - initial API and implementation
# *******************************************************************************
-import exceptions
-from tcf import services, protocol, channel
-
"""
Locator service uses transport layer to search for peers and to collect data about
peer's attributes and capabilities (services). Discovery mechanism depends on transport protocol
@@ -23,6 +20,9 @@ Clients should use protocol.getLocator() to obtain local instance of locator,
then locator.getPeers() can be used to get list of available peers (hosts and targets).
"""
+import exceptions
+from tcf import services, protocol, channel
+
# Peer data retention period in milliseconds.
DATA_RETENTION_PERIOD = 60 * 1000;
diff --git a/python/src/tcf/services/registers.py b/python/src/tcf/services/registers.py
new file mode 100644
index 000000000..a350753d5
--- /dev/null
+++ b/python/src/tcf/services/registers.py
@@ -0,0 +1,469 @@
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+"""
+Registers service provides access to target CPU register values and properties.
+"""
+
+import exceptions
+from tcf import services
+
+NAME = "Registers"
+
+# Context property names.
+PROP_ID = "ID" # String, ID of the context
+PROP_PARENT_ID = "ParentID" # String, ID of a parent context
+PROP_PROCESS_ID = "ProcessID" # String, process ID
+PROP_NAME = "Name" # String, context name
+PROP_DESCRIPTION = "Description" # String, context description
+PROP_SIZE = "Size" # Number, context size in bytes. Byte arrays in get/set commands should be same size
+PROP_READBLE = "Readable" # Boolean, true if context value can be read
+PROP_READ_ONCE = "ReadOnce" # Boolean, true if reading the context (register) destroys its current value
+PROP_WRITEABLE = "Writeable" # Boolean, true if context value can be written
+PROP_WRITE_ONCE = "WriteOnce" # Boolean, true if register value can not be overwritten - every write counts
+PROP_SIDE_EFFECTS = "SideEffects" # Boolean, true if writing the context can change values of other registers
+PROP_VOLATILE = "Volatile" # Boolean, true if the register value can change even when target is stopped
+PROP_FLOAT = "Float" # Boolean, true if the register value is a floating-point value
+PROP_BIG_ENDIAN = "BigEndian" # Boolean, true if big endian
+PROP_LEFT_TO_RIGHT = "LeftToRight" # Boolean, true if the lowest numbered bit should be shown to user as the left-most bit
+PROP_FIST_BIT = "FirstBit" # Number, bit numbering base (0 or 1) to use when showing bits to user
+PROP_BITS = "Bits" # Number, if context is a bit field, contains the field bit numbers in the parent context
+PROP_VALUES = "Values" # Array of Map, predefined names (mnemonics) for some of context values
+PROP_MEMORY_ADDRESS = "MemoryAddress" # Number, the address of a memory mapped register
+PROP_MEMORY_CONTEXT = "MemoryContext" # String, the context ID of a memory context in which a memory mapped register is located
+PROP_CAN_SEARCH = "CanSearch" # Array of String, a list of attribute names which can be searched for starting on this context
+PROP_ROLE = "Role" # String, the role the register plays in a program execution
+
+# Values of context property "Role".
+ROLE_PC = "PC" # Program counter. Defines instruction to execute next
+ROLE_SP = "SP" # Register defining the current stack pointer location
+ROLE_FP = "FP" # Register defining the current frame pointer location
+ROLE_RET = "RET" # Register used to store the return address for calls
+ROLE_CORE = "CORE" # Indicates register or register groups which belong to the core state
+
+# Search filter properties.
+SEARCH_NAME = "Name" # The name of the property this filter applies too
+SEARCH_EQUAL_VALUE = "EqualValue" # The value which is searched for
+
+
+class RegistersContext(object):
+ """
+ RegistersContext objects represent register groups, registers and bit fields.
+ """
+ def __init__(self, props):
+ self._props = props or {}
+
+ def __str__(self):
+ return "[Registers Context %s]" % self._props
+
+ def getProperties(self):
+ """
+ Get context properties. See PROP_* definitions for property names.
+ Context properties are read only, clients should not try to modify them.
+ @return Map of context properties.
+ """
+ return self._props
+
+ def getID(self):
+ """
+ Get Context ID.
+ @return context ID.
+ """
+ return self._props.get(PROP_ID)
+
+ def getParentID(self):
+ """
+ Get parent context ID.
+ @return parent context ID.
+ """
+ return self._props.get(PROP_PARENT_ID)
+
+ def getProcessID(self):
+ """
+ Get process ID, if applicable.
+ @return process ID.
+ """
+ return self._props.get(PROP_PROCESS_ID)
+
+ def getName(self):
+ """
+ Get context (register, register group, bit field) name.
+ @return context name.
+ """
+ return self._props.get(PROP_NAME)
+
+ def getDescription(self):
+ """
+ Get context description.
+ @return context description.
+ """
+ return self._props.get(PROP_DESCRIPTION)
+
+ def getSize(self):
+ """
+ Get context size in bytes.
+ Byte arrays in get()/set() methods should be same size.
+ Hardware register can be smaller then this size, for example in case
+ when register size is not an even number of bytes. In such case implementation
+ should add/remove padding that consist of necessary number of zero bits.
+ @return context size in bytes.
+ """
+ return self._props.get(PROP_SIZE, 0)
+
+ def isReadable(self):
+ """
+ Check if context value can be read.
+ @return true if can read value of the context.
+ """
+ return self._props.get(PROP_READBLE)
+
+ def isReadOnce(self):
+ """
+ Check if reading the context (register) destroys its current value -
+ it can be read only once.
+ @return true if read-once register.
+ """
+ return self._props.get(PROP_READ_ONCE)
+
+ def isWriteable(self):
+ """
+ Check if context value can be written.
+ @return true if can write value of the context.
+ """
+ return self._props.get(PROP_WRITEABLE)
+
+ def isWriteOnce(self):
+ """
+ Check if register value can not be overwritten - every write counts.
+ @return true if write-once register.
+ """
+ return self._props.get(PROP_WRITE_ONCE)
+
+ def hasSideEffects(self):
+ """
+ Check if writing the context can change values of other registers.
+ @return true if has side effects.
+ """
+ return self._props.get(PROP_SIDE_EFFECTS)
+
+ def isVolatile(self):
+ """
+ Check if the register value can change even when target is stopped.
+ @return true if the register value can change at any time.
+ """
+ return self._props.get(PROP_VOLATILE)
+
+ def isFloat(self):
+ """
+ Check if the register value is a floating-point value.
+ @return true if a floating-point register.
+ """
+ return self._props.get(PROP_FLOAT)
+
+ def isBigEndian(self):
+ """
+ Check endianness of the context.
+ Big endian means decreasing numeric significance with increasing bit number.
+ The endianness is used to encode and decode values of get, getm, set and setm commands.
+ @return true if big endian.
+ """
+ return self._props.get(PROP_BIG_ENDIAN)
+
+ def isLeftToRight(self):
+ """
+ Check if the lowest numbered bit (i.e. bit #0 or bit #1 depending on
+ getFirstBitNumber() value) should be shown to user as the left-most bit or
+ the right-most bit.
+ @return true if the first bit is left-most bit.
+ """
+ return self._props.get(PROP_LEFT_TO_RIGHT)
+
+ def getFirstBitNumber(self):
+ """
+ If the context has bit field children, bit positions of the fields
+ can be zero-based or 1-based.
+ @return first bit position - 0 or 1.
+ """
+ return self._props.get(PROP_FIST_BIT, 0)
+
+ def getBitNumbers(self):
+ """
+ If context is a bit field, get the field bit numbers in parent context.
+ @return array of bit numbers.
+ """
+ return self._props.get(PROP_BITS)
+
+ def getNamedValues(self):
+ """
+ A context can have predefined names (mnemonics) for some its values.
+ This method returns a list of such named values.
+ @return array of named values or None.
+ """
+ return self._props.get(PROP_VALUES)
+
+ def getMemoryAddress(self):
+ """
+ Get the address of a memory mapped register.
+ @return address.
+ """
+ return self._props.get(PROP_MEMORY_ADDRESS)
+
+ def getMemoryContext(self):
+ """
+ Get the context ID of a memory context in which a memory mapped register is located.
+ @return memory context ID.
+ """
+ return self._props.get(PROP_MEMORY_CONTEXT)
+
+ def canSearch(self):
+ """
+ Get a list of property names which can be searched for starting on this context
+ @return collection of property names.
+ """
+ return self._props.get(PROP_CAN_SEARCH)
+
+ def getRole(self):
+ """
+ Get the role the register plays in a program execution.
+ @return role name.
+ """
+ return self._props.get(PROP_ROLE)
+
+ def get(self, done):
+ """
+ Read value of the context.
+ @param done - call back object.
+ @return - pending command handle.
+ """
+ raise exceptions.NotImplementedError("Abstract method")
+
+ def set(self, value, done):
+ """
+ Set value of the context.
+ @param value - value to write into the context.
+ @param done - call back object.
+ @return - pending command handle.
+ """
+ raise exceptions.NotImplementedError("Abstract method")
+
+ def search(self, filter, done):
+ """
+ Search register contexts that passes given search filter.
+ Search is only supported for properties listed in the "CanSearch" property.
+ @param filter - properties bag that defines search filter.
+ @param done - call back object.
+ @return - pending command handle.
+ """
+ raise exceptions.NotImplementedError("Abstract method")
+
+
+class RegistersService(services.Service):
+ def getName(self):
+ return NAME
+
+ def getContext(self, id, done):
+ """
+ Retrieve context info for given context ID.
+
+ @param id - context ID.
+ @param done - call back interface called when operation is completed.
+ """
+ raise exceptions.NotImplementedError("Abstract method")
+
+ def getChildren(self, parent_context_id, done):
+ """
+ Retrieve contexts available for registers commands.
+ A context corresponds to an execution thread, stack frame, registers group, etc.
+ A context can belong to a parent context. Contexts hierarchy can be simple
+ plain list or it can form a tree. It is up to target agent developers to choose
+ layout that is most descriptive for a given target. Context IDs are valid across
+ all services. In other words, all services access same hierarchy of contexts,
+ with same IDs, however, each service accesses its own subset of context's
+ attributes and functionality, which is relevant to that service.
+
+ @param parent_context_id - parent context ID. Can be None -
+ to retrieve top level of the hierarchy, or one of context IDs retrieved
+ by previous getChildren commands.
+ @param done - call back interface called when operation is completed.
+ """
+ raise exceptions.NotImplementedError("Abstract method")
+
+ def getm(self, locs, done):
+ """
+ Read values of multiple locations in registers.
+ @param locs - array of data locations.
+ @param done - call back object.
+ @return - pending command handle.
+ """
+ raise exceptions.NotImplementedError("Abstract method")
+
+ def setm(self, locs, value, done):
+ """
+ Set values of multiple locations in registers.
+ @param locs - array of data locations.
+ @param value - value to write into the context.
+ @param done - call back object.
+ @return - pending command handle.
+ """
+ raise exceptions.NotImplementedError("Abstract method")
+
+ def addListener(self, listener):
+ """
+ Add registers service event listener.
+ @param listener - event listener implementation.
+ """
+ raise exceptions.NotImplementedError("Abstract method")
+
+ def removeListener(self, listener):
+ """
+ Remove registers service event listener.
+ @param listener - event listener implementation.
+ """
+ raise exceptions.NotImplementedError("Abstract method")
+
+
+class NamedValue(object):
+ """
+ A register context can have predefined names (mnemonics) for some its values.
+ NamedValue objects represent such values.
+ """
+ def __init__(self, value, name, description):
+ self.value = value
+ self.name = name
+ self.description = description
+
+ def getValue(self):
+ """
+ Get value associated with the name.
+ @return the value as an array of bytes.
+ """
+ return self.value
+
+ def getName(self):
+ """
+ Get name (mnemonic) of the value.
+ @return value name.
+ """
+ return self.name
+
+ def getDescription(self):
+ """
+ Get human readable description of the value.
+ @return value description.
+ """
+ return self.description
+
+class DoneGet(object):
+ """
+ 'get' command call back interface.
+ """
+ def doneGet(self, token, error, value):
+ """
+ Called when value retrieval is done.
+ @param token - command handle
+ @param error - error description if operation failed, None if succeeded.
+ @param value - context value as array of bytes.
+ """
+ pass
+
+class DoneSet(object):
+ """
+ 'set' command call back interface.
+ """
+ def doneSet(self, token, error):
+ """
+ Called when value setting is done.
+ @param token - command handle.
+ @param error - error description if operation failed, None if succeeded.
+ """
+ pass
+
+class DoneSearch(object):
+ """
+ 'search' command call back interface.
+ """
+ def doneSearch(self, token, error, paths):
+ """
+ Called when context search is done.
+ @param token - command handle.
+ @param error - error description if operation failed, None if succeeded.
+ @param paths - array of paths to each context with properties matching the filter
+ """
+ pass
+
+class DoneGetContext(object):
+ def doneGetContext(self, token, error, context):
+ """
+ Called when context data retrieval is done.
+ @param token - command handle
+ @param error - error description if operation failed, None if succeeded.
+ @param context - context data.
+ """
+ pass
+
+class DoneGetChildren(object):
+ """
+ Client call back interface for getChildren().
+ """
+ def doneGetChildren(self, token, error, context_ids):
+ """
+ Called when context list retrieval is done.
+ @param token - command handle
+ @param error - error description if operation failed, None if succeeded.
+ @param context_ids - array of available context IDs.
+ """
+ pass
+
+
+class RegistersListener(object):
+ """
+ Registers event listener is notified when registers context hierarchy
+ changes, and when a register is modified by the service commands.
+ """
+
+ def contextChanged(self):
+ """
+ Called when register context properties changed.
+ Most targets have static set of registers and register properties.
+ Such targets never generate this event. However, some targets,
+ for example, JTAG probes, allow user to modify register definitions.
+ Clients should flush all cached register context data.
+ """
+ pass
+
+ def registerChanged(self, id):
+ """
+ Called when register content was changed and clients
+ need to update themselves. Clients, at least, should invalidate
+ corresponding cached registers data.
+ Not every change is notified - it is not possible,
+ only those, which are not caused by normal execution of the debuggee.
+ At least, changes caused by "set" command should be notified.
+ @param id - register context ID.
+ """
+ pass
+
+
+class Location(object):
+ """
+ Class Location represents value location in register context
+ """
+ def __init__(self, id, offs, size):
+ # Register context ID
+ self.id = id
+ # offset in the context, in bytes
+ self.offs = offs
+ # value size in bytes
+ self.size = size
+ def __iter__(self):
+ yield self.id
+ yield self.offs
+ yield self.size
diff --git a/python/src/tcf/services/remote/RegistersProxy.py b/python/src/tcf/services/remote/RegistersProxy.py
new file mode 100644
index 000000000..d75605cd9
--- /dev/null
+++ b/python/src/tcf/services/remote/RegistersProxy.py
@@ -0,0 +1,170 @@
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+import exceptions
+from tcf import channel
+from tcf.services import registers
+from tcf.channel import toByteArray
+from tcf.channel.Command import Command
+
+class Context(registers.RegistersContext):
+ def __init__(self, service, props):
+ super(Context, self).__init__(props)
+ self.service = service
+
+ def getNamedValues(self):
+ return _toValuesArray(self._props.get(registers.PROP_VALUES))
+
+ def get(self, done):
+ service = self.service
+ id = self.getID()
+ class GetCommand(Command):
+ def __init__(self):
+ super(GetCommand, self).__init__(service.channel, service, "get", (id,))
+ def done(self, error, args):
+ val = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ val = toByteArray(args[1])
+ done.doneGet(self.token, error, val)
+ return GetCommand().token
+
+ def set(self, value, done):
+ service = self.service
+ id = self.getID()
+ binary = bytearray(value)
+ class SetCommand(Command):
+ def __init__(self):
+ super(SetCommand, self).__init__(service.channel, service, "set", (id, binary))
+ def done(self, error, args):
+ if not error:
+ assert len(args) == 1
+ error = self.toError(args[0])
+ done.doneSet(self.token, error)
+ return SetCommand().token
+
+ def search(self, filter, done):
+ service = self.service
+ id = self.getID()
+ class SearchCommand(Command):
+ def __init__(self):
+ super(SearchCommand, self).__init__(service.channel, service, "search", (id, filter))
+ def done(self, error, args):
+ paths = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ paths = args[1]
+ done.doneSearch(self.token, error, paths)
+ return SearchCommand().token
+
+class RegistersProxy(registers.RegistersService):
+ def __init__(self, channel):
+ self.channel = channel
+ self.listeners = {}
+
+ def getChildren(self, parent_context_id, done):
+ service = self
+ class GetChildrenCommand(Command):
+ def __init__(self):
+ super(GetChildrenCommand, self).__init__(service.channel, service, "getChildren", (parent_context_id,))
+ def done(self, error, args):
+ contexts = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ contexts = args[1]
+ done.doneGetChildren(self.token, error, contexts)
+ return GetChildrenCommand().token
+
+ def getContext(self, id, done):
+ service = self
+ class GetContextCommand(Command):
+ def __init__(self):
+ super(GetContextCommand, self).__init__(service.channel, service, "getContext", (id,))
+ def done(self, error, args):
+ ctx = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ if args[1]: ctx = Context(service, args[1])
+ done.doneGetContext(self.token, error, ctx)
+ return GetContextCommand().token
+
+ def getm(self, locs, done):
+ service = self
+ class GetMCommand(Command):
+ def __init__(self):
+ super(GetMCommand, self).__init__(service.channel, service, "getm", (locs,))
+ def done(self, error, args):
+ val = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ val = toByteArray(args[1])
+ done.doneGet(self.token, error, val)
+ return GetMCommand().token
+
+ def setm(self, locs, value, done):
+ service = self
+ binary = bytearray(value)
+ class SetMCommand(Command):
+ def __init__(self):
+ super(SetMCommand, self).__init__(service.channel, service, "setm", (locs, binary))
+ def done(self, error, args):
+ if not error:
+ assert len(args) == 1
+ error = self.toError(args[0])
+ done.doneSet(self.token, error)
+ return SetMCommand().token
+
+ def addListener(self, listener):
+ l = ChannelEventListener(self, listener)
+ self.channel.addEventListener(self, l)
+ self.listeners[listener] = l
+
+ def removeListener(self, listener):
+ l = self.listeners.get(listener)
+ if l:
+ del self.listeners[listener]
+ self.channel.removeEventListener(self, l)
+
+class NamedValueInfo(registers.NamedValue):
+ def __init__(self, m):
+ desc = m.get("Description")
+ name = m.get("Name")
+ value = toByteArray(m.get("Value"))
+ super(NamedValueInfo, self).__init__(value, name, desc)
+
+def _toValuesArray(o):
+ if o is None: return None
+ arr = []
+ for m in o:
+ arr.append(NamedValueInfo(m))
+ return arr
+
+class ChannelEventListener(channel.EventListener):
+ def __init__(self, service, listener):
+ self.service = service
+ self.listener = listener
+ def event(self, name, data):
+ try:
+ args = channel.fromJSONSequence(data)
+ if name == "contextChanged":
+ self.listener.contextChanged()
+ elif name == "registerChanged":
+ assert len(args) == 1
+ self.listener.registerChanged(args[0])
+ else:
+ raise IOError("Registers service: unknown event: " + name);
+ except exceptions.Exception as x:
+ self.service.channel.terminate(x)
diff --git a/python/src/tcf/services/remote/RunControlProxy.py b/python/src/tcf/services/remote/RunControlProxy.py
index 6b1103542..e9b53226e 100644
--- a/python/src/tcf/services/remote/RunControlProxy.py
+++ b/python/src/tcf/services/remote/RunControlProxy.py
@@ -67,9 +67,6 @@ class RunContext(runcontrol.RunControlContext):
done.doneCommand(self.token, error)
return RCCommand(cmd, args).token
- def __str__(self):
- return "[Run Control Context %s]" % str(self._props)
-
class ChannelEventListener(channel.EventListener):
def __init__(self, service, listener):
diff --git a/python/src/tcf/services/runcontrol.py b/python/src/tcf/services/runcontrol.py
index 085f5e28f..a80585d1c 100644
--- a/python/src/tcf/services/runcontrol.py
+++ b/python/src/tcf/services/runcontrol.py
@@ -248,6 +248,9 @@ class RunControlContext(object):
"""
def __init__(self, props):
self._props = props or {}
+
+ def __str__(self):
+ return "[Run Control Context %s]" % self._props
def getProperties(self):
"""
diff --git a/python/src/tcf/services/stacktrace.py b/python/src/tcf/services/stacktrace.py
index ae8a6d5cf..1cb47b363 100644
--- a/python/src/tcf/services/stacktrace.py
+++ b/python/src/tcf/services/stacktrace.py
@@ -92,7 +92,10 @@ class StackTraceContext(object):
"""
def __init__(self, props):
self._props = props or {}
-
+
+ def __str__(self):
+ return "[Stack Trace Context %s]" % self._props
+
def getID(self):
"""
Get Context ID.
diff --git a/python/src/tcf/services/symbols.py b/python/src/tcf/services/symbols.py
index 3976956d3..ccf77de22 100644
--- a/python/src/tcf/services/symbols.py
+++ b/python/src/tcf/services/symbols.py
@@ -78,6 +78,9 @@ class Symbol(object):
def __init__(self, props):
self._props = props or {}
+ def __str__(self):
+ return "[Symbol Context %s]" % self._props
+
def getID(self):
"""
Get symbol ID.
diff --git a/python/src/tcf/shell.py b/python/src/tcf/shell.py
index 3a6dfc7c5..8d2b5ae28 100644
--- a/python/src/tcf/shell.py
+++ b/python/src/tcf/shell.py
@@ -9,11 +9,6 @@
# * Wind River Systems - initial API and implementation
# *******************************************************************************
-import code, sys
-import tcf
-from tcf.util import sync, event
-from tcf import protocol, channel
-
"""
Simple interactive shell for TCF. This is basically a Python interpreter with a few
TCF extensions.
@@ -33,6 +28,11 @@ Commands:
- Stop recording for service or for all services
"""
+import code, sys
+import tcf
+from tcf.util import sync, event
+from tcf import protocol, channel
+
class Shell(code.InteractiveConsole, protocol.ChannelOpenListener, channel.ChannelListener):
def __init__(self):
locals = {
diff --git a/python/src/tcf/tests/BasicTests.py b/python/src/tcf/tests/BasicTests.py
index b4da8fbac..757b0ca4b 100644
--- a/python/src/tcf/tests/BasicTests.py
+++ b/python/src/tcf/tests/BasicTests.py
@@ -14,6 +14,7 @@ import tcf
from tcf import protocol, channel
from tcf.util import sync
+__TRACE = False
class TraceListener(channel.TraceListener):
def onMessageReceived(self, type, token, service, name, data):
print "<<<", type, token, service, name, data
@@ -28,7 +29,7 @@ def test():
protocol.startEventQueue()
c = tcf.connect("TCP:127.0.0.1:1534")
assert c.state == channel.STATE_OPEN
- #protocol.invokeLater(c.addTraceListener, TraceListener())
+ if __TRACE: protocol.invokeLater(c.addTraceListener, TraceListener())
def r2():
print "services=", c.getRemoteServices()
protocol.invokeLater(r2)
@@ -36,6 +37,7 @@ def test():
testRunControl(c)
testBreakpoints(c)
testSymbols(c)
+ testRegisters(c)
testSyncCommands(c)
testEvents(c)
testDataCache(c)
@@ -57,10 +59,7 @@ def testRunControl(c):
if error:
protocol.log("Error from RunControl.getContext", error)
else:
- print "ID: ", context.getID()
- print "Name: ", context.getName()
- print "Parent: ", context.getParentID()
- print "IsContainer: ", context.isContainer()
+ print context
class DoneGetState(runcontrol.DoneGetState):
def doneGetState(self, token, error, suspended, pc, reason, params):
pending.remove(token)
@@ -200,7 +199,7 @@ def testStackTrace(c, ctx_id):
return
if ctxs:
for ctx in ctxs:
- print ctx.getProperties()
+ print ctx
stack.getContext(ctx_ids, DoneGetContext())
stack.getChildren(ctx_id, DoneGetChildren())
@@ -214,13 +213,11 @@ def testSymbols(c):
protocol.log("Error from Symbols.list", error)
return
class DoneGetContext(symbols.DoneGetContext):
- def doneGetContext(self, token, error, ctxs):
+ def doneGetContext(self, token, error, ctx):
if error:
protocol.log("Error from Symbols.getContext", error)
return
- if ctxs:
- for ctx in ctxs:
- print ctx.getProperties()
+ print ctx
if ctx_ids:
for ctx_id in ctx_ids:
syms.getContext(ctx_id, DoneGetContext())
@@ -228,6 +225,28 @@ def testSymbols(c):
for ctx_id in _suspended:
protocol.invokeLater(symTest, ctx_id)
+def testRegisters(c):
+ from tcf.services import registers
+ def regTest(ctx_id):
+ regs = c.getRemoteService(registers.NAME)
+ class DoneGetChildren(registers.DoneGetChildren):
+ def doneGetChildren(self, token, error, ctx_ids):
+ if error:
+ protocol.log("Error from Registers.getChildren", error)
+ return
+ class DoneGetContext(registers.DoneGetContext):
+ def doneGetContext(self, token, error, ctx):
+ if error:
+ protocol.log("Error from Registers.getContext", error)
+ return
+ print ctx
+ if ctx_ids:
+ for ctx_id in ctx_ids:
+ regs.getContext(ctx_id, DoneGetContext())
+ regs.getChildren(ctx_id, DoneGetChildren())
+ for ctx_id in _suspended:
+ protocol.invokeLater(regTest, ctx_id)
+
def testSyncCommands(c):
# simplified command execution
ctl = sync.CommandControl(c)

Back to the top