From 482250533847640bb98500e04ba6af3bb968228a Mon Sep 17 00:00:00 2001 From: Johnny Chen Date: Mon, 25 Jul 2011 19:32:35 +0000 Subject: Provide an add-on API to SBValue class by post-processing to provide a way to iterate through an SBValue instance by treating it as the head of a linked list. API program must provide two args to the linked_list_iter() method: the first being the child member name which points to the next item on the list and the second being a Python function which an SBValue (for the next item) and returns True if end of list is reached, otherwise it returns False. For example, suppose we have the following sample program. #include class Task { public: int id; Task *next; Task(int i, Task *n): id(i), next(n) {} }; int main (int argc, char const *argv[]) { Task *task_head = new Task(-1, NULL); Task *task1 = new Task(1, NULL); Task *task2 = new Task(2, NULL); Task *task3 = new Task(3, NULL); // Orphaned. Task *task4 = new Task(4, NULL); Task *task5 = new Task(5, NULL); task_head->next = task1; task1->next = task2; task2->next = task4; task4->next = task5; int total = 0; // Break at this line Task *t = task_head; while (t != NULL) { if (t->id >= 0) ++total; t = t->next; } printf("We have a total number of %d tasks\n", total); return 0; } The test program produces the following output while exercising the linked_list_iter() SBVAlue API: task_head: TypeName -> Task * ByteSize -> 8 NumChildren -> 2 Value -> 0x0000000106400380 ValueType -> local_variable Summary -> None IsPointerType -> True Location -> 0x00007fff65f06e60 (Task *) next = 0x0000000106400390 (int) id = 1 (Task *) next = 0x00000001064003a0 (Task *) next = 0x00000001064003a0 (int) id = 2 (Task *) next = 0x00000001064003c0 (Task *) next = 0x00000001064003c0 (int) id = 4 (Task *) next = 0x00000001064003d0 (Task *) next = 0x00000001064003d0 (int) id = 5 (Task *) next = 0x0000000000000000 llvm-svn: 135938 --- lldb/scripts/Python/modify-python-lldb.py | 61 +++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) (limited to 'lldb/scripts/Python/modify-python-lldb.py') diff --git a/lldb/scripts/Python/modify-python-lldb.py b/lldb/scripts/Python/modify-python-lldb.py index 789e2e7..6b44f26 100644 --- a/lldb/scripts/Python/modify-python-lldb.py +++ b/lldb/scripts/Python/modify-python-lldb.py @@ -82,6 +82,63 @@ def lldb_iter(obj, getsize, getelem): # ============================================================================== ''' +# +# linked_list_iter() is a special purpose iterator to treat the SBValue as a +# list data structure, where you specify the child member name which points to +# the next item on the list and you specify the end-of-list function which takes +# an SBValue and returns True if EOL is reached and False if not. +# +linked_list_iter_def = ''' + # ================================================== + # Iterator for lldb.SBValue treated as a linked list + # ================================================== + def linked_list_iter(self, next_item_name, end_of_list): + """A generator adaptor to support iteration for SBValue as a linked list. + + For example, + + # Test function to determine end of list. + def eol(val): + if not val: + return True + try: + # Test the semantics of the item we got. + id = val.GetChildMemberWithName("id") + if int(id.GetValue()) > 0: + return False + except: + pass + + # If we fall through to here. It could be that exception + # occurred or the "id" child member does not qualify as a + # valid item. Return True for EOL. + return True + + # Get Frame #0. + ... + + # Get variable 'task_head'. + task_head = frame0.FindVariable('task_head') + ... + + for t in task_head.linked_list_iter('next', eol): + print t + """ + try: + item = self.GetChildMemberWithName(next_item_name) + while item: + yield item + # Prepare for the next iteration. + item = item.GetChildMemberWithName(next_item_name) + if end_of_list(item): + break + except: + # Exception occurred. Stop the generator. + pass + + return +''' + # This supports the iteration protocol. iter_def = " def __iter__(self): return lldb_iter(self, '%s', '%s')" module_iter = " def module_iter(self): return lldb_iter(self, '%s', '%s')" @@ -266,6 +323,10 @@ for line in content.splitlines(): new_content.add_line(eq_def % (cls, list_to_frag(e[cls]))) new_content.add_line(ne_def) + # This special purpose iterator is for SBValue only!!! + if cls == "SBValue": + new_content.add_line(linked_list_iter_def) + # Next state will be NORMAL. state = NORMAL -- cgit v1.1