diff -rupN src/gdb/data-directory/Makefile.in src_grep/gdb/data-directory/Makefile.in --- src/gdb/data-directory/Makefile.in 2011-08-17 16:11:20.000000000 +0530 +++ src_grep/gdb/data-directory/Makefile.in 2011-12-11 17:38:40.851766467 +0530 @@ -58,7 +58,8 @@ PYTHON_FILES = \ gdb/prompt.py \ gdb/command/__init__.py \ gdb/command/pretty_printers.py \ - gdb/command/prompt.py + gdb/command/prompt.py \ + gdb/command/grep.py FLAGS_TO_PASS = \ "prefix=$(prefix)" \ diff -rupN src/gdb/python/lib/gdb/command/grep.py src_grep/gdb/python/lib/gdb/command/grep.py --- src/gdb/python/lib/gdb/command/grep.py 1970-01-01 05:30:00.000000000 +0530 +++ src_grep/gdb/python/lib/gdb/command/grep.py 2012-01-02 10:20:07.565936926 +0530 @@ -0,0 +1,430 @@ +# GDB 'grep' command. +# Copyright (C) 2012 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +"""Implementation of the GDB 'grep' command using the GDB Python API""" + +from collections import deque +import gdb +import re + +class GrepBase(object): + """A base class for classes which can grep through values of a particular + type. See below for implementation of the different sub classes. + """ + + def grep(self, regex, name, path, value, grep_field, grep_value): + """The method which should perform the actual grep action. + The sub classes should override this method to reflect the type specfic + grep operation. + + Arguments: + regex: The regular expression to match names. + name: The name which has to be matched with the regular expression. + path: The path (as in the expression) to the current value. + value: The value to be grepped. + grep_field: A boolean value to indicate whether the field name + should be matched or not. + grep_value: A boolean value to indicate whether the value should be + matched or not. + """ + print "Cannot yet grep through values of type %s." % str(value.type) + + +class GrepScalar(GrepBase): + """A class to grep through values which are of a scalar type.""" + + def __init__(self, grep_command): + """ + Arguments: + grep_command: The command object which wants to do the grep + operation. + """ + self._grep_command = grep_command + + def grep(self, regex, name, path, value, grep_field, grep_value): + """ The method which greps through values which are of a scalar type. + See GrepBase.grep for more information. + """ + if ((grep_field and re.search(regex, name)) or + (grep_value and re.search(regex, str(value)))): + print "%s = (%s) %s" % (path, str(value.type), str(value)) + + +class GrepPointer(GrepBase): + """A class to grep through values which are of a pointer type.""" + + def __init__(self, grep_command): + """ + Arguments: + grep_command: The command object which wants to do the grep + operation. + """ + self._grep_command = grep_command + + def grep(self, regex, name, path, value, grep_field, grep_value): + """ The method which greps through values which are of a pointer type. + See GrepBase.grep for more information. + """ + if str(value.type.target().unqualified()) == "char": + try: + str_val = value.string() + if ((grep_field and re.search(regex, name)) or + (grep_value and re.search(regex, str_val))): + print "%s = (%s) \"%s\"" % (path, str(value.type), str_val) + return + except: + pass + + if grep_field and re.search(regex, name): + print "%s = (%s) %s" % (path, str(value.type), str(value)) + + deref_value = None + try: + deref_value = value.dereference() + str(deref_value) + except RuntimeError: + return + + self._grep_command.grep( + regex, name, "(*%s)" % path, deref_value, grep_field, grep_value) + + +class GrepArray(GrepBase): + """A class to grep through values which are of an array type.""" + + def __init__(self, grep_command): + """ + Arguments: + grep_command: The command object which wants to do the grep + operation. + """ + self._grep_command = grep_command + + def grep(self, regex, name, path, value, grep_field, grep_value): + """ The method which greps through values which are of an array type. + See GrepBase.grep for more information. + """ + if grep_field and re.search(regex, name): + print ("%s = " % + (path, str(value.type.target()))) + + if grep_value: + array_range = value.type.range() + for index in range(array_range[0], array_range[1] + 1): + self._grep_command.grep(regex, + name, + "%s[%d]" % (path, index), + value[index], + False, + True) + + +class GrepStruct(GrepBase): + """A class to grep through values which are of a struct type.""" + + def __init__(self, grep_command): + """ + Arguments: + grep_command: The command object which wants to do the grep + operation. + """ + self._grep_command = grep_command + + def grep(self, regex, name, path, value, grep_field, grep_value): + """ The method which greps through values which are of a struct type. + See GrepBase.grep for more information. + """ + if grep_field and re.search(regex, name): + print "%s = " % (path, str(value.type)) + + for field in value.type.fields(): + self._grep_command.grep(regex, + field.name, + "%s.%s" % (path, field.name), + value[field.name], + grep_field, + grep_value) + + +class GrepUnion(GrepBase): + """A class to grep through values which are of a union type.""" + + def __init__(self, grep_command): + """ + Arguments: + grep_command: The command object which wants to do the grep + operation. + """ + self._grep_command = grep_command + self._field_selector_list = [ ] + + def register_field_selector(self, selector): + """Method with which one can register a field selector. + + Arguments: + selector: The field selector. It should support a method with the + following signature: + get_field_name_matcher(value) + The argument 'value' is the union value which has to be + grepped. The method should return a regular expression + with which the field names of the union are matched. The + grep method greps through a field of the union only if + there is a match. + See the class AllFieldsSelector below as an example. + """ + self._field_selector_list.append(selector) + + def grep(self, regex, name, path, value, grep_field, grep_value): + """ The method which greps through values which are of a union type. + See GrepBase.grep for more information. + """ + if grep_field and re.search(regex, name): + print "%s = " % (path, str(value.type)) + + for field_selector in self._field_selector_list: + field_matcher = field_selector.get_field_name_matcher(value) + if field_matcher: + for field in value.type.fields(): + if re.search(field_matcher, field.name): + self._grep_command.grep(regex, + field.name, + "%s.%s" % (path, field.name), + value[field.name], + grep_field, + grep_value) + return + + +class GrepTypedef(GrepBase): + """A class to grep through values which are of a typedef type.""" + + def __init__(self, grep_command): + """ + Arguments: + grep_command: The command object which wants to do the grep + operation. + """ + self._grep_command = grep_command + + def grep(self, regex, name, path, value, grep_field, grep_value): + """ The method which greps through values which are of a typdef type. + See GrepBase.grep for more information. + """ + base_type_value = value.cast(value.type.strip_typedefs()) + self._grep_command.grep( + regex, name, path, base_type_value, grep_field, grep_value) + + +class GrepUtils(object): + """A class of utilities for implementing 'grep' and it's sub commands.""" + + @staticmethod + def parse_arg_str(arg_str): + """A function to help parse the arguments to 'grep' and its sub + commands. + + Arguments: + arg_str: The argument string as passed to the 'grep' or its sub + commands. + + Returns: + A 3-tuple of the form (regex, expr, value) where + i. regex is the regular expression passed to the command, + ii. expr is the expression whose value has to be 'grepped' with the + regex, + iii. value is the value of the expression. + + Raises: + gdb.GdbError if insufficient arguments are provided in the argument + string, or if the expression given in the argument string does not + evaluate to any value in the current context. + """ + args = gdb.string_to_argv(arg_str) + if len(args) < 2: + raise gdb.GdbError( + "ERROR: 'grep' and its sub commands need two arguments.") + + regex = args[0] + expr = "" + for i in range(1, len(args) - 1): + expr += args[i] + " " + expr += args[len(args) - 1] + + value = None + try: + value = gdb.parse_and_eval(expr) + except: + raise gdb.GdbError( + "ERROR: '%s' does not evaluate to any value in the current " + "context." % expr) + + return (regex, expr, value) + + +class GrepCommand(gdb.Command): + """Command to 'grep' for field names and values in expressions. + + Usage: grep [OPTION] REGEX EXPR + + OPTION - An optional argument which can be either 'field' or 'value'. + If it is 'value', then only values are matched with the REGEX. If it + is 'field', then only field names are matched with the REGEX. + + REGEX - A regular expression in double quotes if it contains spaces. + EXPR - A valid expression in the current scope. + + The command looks for values (of scalar, enum and string types) and field + names matching with the REGEX. It scans through the value of EXPR top-down + to look for matches. "Top-down" here means starting from the EXPR itself, to + the names and values of the fields (if any) of the type of the EXPR value, + and right down to the leaf scalar field names and values of these fields. + """ + + def __init__(self): + super(GrepCommand, self).__init__(name = "grep", + command_class = gdb.COMMAND_DATA, + prefix = True) + self.init_env() + + def init_env(self): + """Initializes the internal environment of the command.""" + self._type_to_greper_map = self._get_type_to_greper_map() + self._bfs_queue = deque([ ]) + + def register_union_field_selector(self, field_selector): + """Registers a field selector with the union grepper. + See GrepUnion.register_field_selector for more information. + """ + self._type_to_greper_map[gdb.TYPE_CODE_UNION].register_field_selector( + field_selector) + + def _get_type_to_greper_map(self): + """An internal method which returns type code to grepper map.""" + return { + gdb.TYPE_CODE_PTR : GrepPointer(self), + gdb.TYPE_CODE_ARRAY : GrepArray(self), + gdb.TYPE_CODE_STRUCT : GrepStruct(self), + gdb.TYPE_CODE_UNION : GrepUnion(self), + gdb.TYPE_CODE_ENUM : GrepScalar(self), + gdb.TYPE_CODE_INT : GrepScalar(self), + gdb.TYPE_CODE_FLT : GrepScalar(self), + gdb.TYPE_CODE_CHAR : GrepScalar(self), + gdb.TYPE_CODE_BOOL : GrepScalar(self), + gdb.TYPE_CODE_TYPEDEF : GrepTypedef(self) + } + + def grep(self, regex, name, path, value, grep_field, grep_value): + """The function to request the 'grep' for a value or a field. + + NOTE: One should invoke the 'start' function to beging the search. + """ + self._bfs_queue.append( + (regex, name, path, value, grep_field, grep_value)) + + def start(self): + """The function which starts the search once a 'grep' has been requested. + + It does something useful if invoked only after making a request with the + 'grep' function. + """ + while len(self._bfs_queue) > 0: + (regex, name, path, value, grep_field, grep_value) = ( + self._bfs_queue[0]) + + type_code = value.type.code + if type_code in self._type_to_greper_map: + greper = self._type_to_greper_map[type_code] + greper.grep(regex, name, path, value, grep_field, grep_value) + + self._bfs_queue.popleft() + + def invoke(self, arg_str, from_tty): + (regex, expr, value) = GrepUtils.parse_arg_str(arg_str) + self.grep(regex, expr, expr, value, True, True) + self.start() + + +class GrepFieldCommand(GrepCommand): + """Command to 'grep' for field names in expressions. + + Usage: grep field REGEX EXPR + + REGEX is a regular expression in double quotes if it contains spaces. + EXPR is a valid expression in the current scope. + + The command looks for field names matching with the REGEX. It scans through + the value of EXPR top-down to look for matches. "Top-down" here means + starting from the EXPR itself, to the names of the fields (if any) of the + type of the EXPR value, and right down to the leaf scalar field names of + these fields. + """ + + def __init__(self): + super(GrepCommand, self).__init__(name = "grep field", + command_class = gdb.COMMAND_DATA) + self.init_env() + + def invoke(self, arg_str, from_tty): + (regex, expr, value) = GrepUtils.parse_arg_str(arg_str) + self.grep(regex, expr, expr, value, True, False) + self.start() + + +class GrepValueCommand(GrepCommand): + """Command to 'grep' for field values in expressions. + + Usage: grep value REGEX EXPR + + REGEX is a regular expression in double quotes if it contains spaces. + EXPR is a valid expression in the current scope. + + The command looks for values (of scalar, enum and string fields) matching + with the REGEX. It scans through the value of EXPR top-down + to look for matches. "Top-down" here means starting from the EXPR itself, to + the values of the fields (if any) of the type of the EXPR value, and right + down to the values of the leaf scalar fields of these fields. + """ + + def __init__(self): + super(GrepCommand, self).__init__(name = "grep value", + command_class = gdb.COMMAND_DATA) + self.init_env() + + def invoke(self, arg_str, from_tty): + (regex, expr, value) = GrepUtils.parse_arg_str(arg_str) + self.grep(regex, expr, expr, value, False, True) + self.start() + + +gc = GrepCommand() +gfc = GrepFieldCommand() +gvc = GrepValueCommand() + +class AllFieldsSelector(object): + """A union field selector which selects all fields. + It is defined here as an example and for testing purposes. + + See GrepUnion.register_field_selector for more information. + """ + + def get_field_name_matcher(self, value): + """Returns an all matching regular expression.""" + return ".*" + +def register_union_field_selector(field_selector): + gc.register_union_field_selector(field_selector) + gfc.register_union_field_selector(field_selector) + gvc.register_union_field_selector(field_selector) diff -rupN src/gdb/testsuite/gdb.python/Makefile.in src_grep/gdb/testsuite/gdb.python/Makefile.in --- src/gdb/testsuite/gdb.python/Makefile.in 2011-05-16 19:26:40.000000000 +0530 +++ src_grep/gdb/testsuite/gdb.python/Makefile.in 2011-12-11 17:40:06.341794630 +0530 @@ -4,7 +4,8 @@ srcdir = @srcdir@ EXECUTABLES = py-type py-value py-prettyprint py-template py-block \ py-symbol py-mi py-breakpoint py-inferior py-infthread \ py-shared python lib-types py-events py-evthreads py-frame \ - py-mi py-pp-maint py-progspace py-section-script py-objfile + py-mi py-pp-maint py-progspace py-section-script py-objfile \ + py-grep MISCELLANEOUS = py-shared-sl.sl diff -rupN src/gdb/testsuite/gdb.python/py-grep.c src_grep/gdb/testsuite/gdb.python/py-grep.c --- src/gdb/testsuite/gdb.python/py-grep.c 1970-01-01 05:30:00.000000000 +0530 +++ src_grep/gdb/testsuite/gdb.python/py-grep.c 2011-12-31 11:29:58.342047729 +0530 @@ -0,0 +1,79 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2012 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +struct SimpleStruct +{ + int int_val; + double double_val; +}; + +struct ComplexStruct_1 +{ + struct SimpleStruct ss; + char* str_val; +}; + +struct ComplexStruct_2 +{ + struct ComplexStruct_1 cs1; + int int_array[10]; + int* int_ptr; +}; + +union UnionOfStructs +{ + struct SimpleStruct ss; + struct ComplexStruct_1 cs1; + struct ComplexStruct_2 cs2; +}; + +typedef union UnionOfStructs TheType; + +int +main (void) +{ + int i; + char* str_val = "I am a string"; + char char_array[] = + { 'n', 'o', 't', ' ' , 'a' , ' ', 's', 't', 'r', 'i', 'n', 'g' }; + + char* ptr_to_char_array = char_array; + + struct SimpleStruct ss; + ss.int_val = 10; + ss.double_val = 1.11; + + struct ComplexStruct_1 cs1; + cs1.ss = ss; + cs1.str_val = "embedded string value"; + + struct ComplexStruct_2 cs2; + cs2.cs1 = cs1; + cs2.int_ptr = &i; + for (i = 0; i < 10; i++) + { + cs2.int_array[i] = i; + } + + union UnionOfStructs us; + us.cs2 = cs2; + + TheType* tt = &us; + + return 0; /* Break here. */ +} diff -rupN src/gdb/testsuite/gdb.python/py-grep.exp src_grep/gdb/testsuite/gdb.python/py-grep.exp --- src/gdb/testsuite/gdb.python/py-grep.exp 1970-01-01 05:30:00.000000000 +0530 +++ src_grep/gdb/testsuite/gdb.python/py-grep.exp 2011-12-31 11:30:19.782050107 +0530 @@ -0,0 +1,85 @@ +# Copyright (C) 2012 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# This file is part of the GDB testsuite. It tests the command 'grep' +# which is implemented using the GDB-Python API. + +load_lib gdb-python.exp + +set testfile "py-grep" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} +if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile}] } { + return -1 +} + +# Skip all tests if Python scripting is not enabled. +if { [skip_python_tests] } { continue } + +if ![runto_main] { + return -1 +} + +gdb_breakpoint [gdb_get_line_number "Break here."] +gdb_continue_to_breakpoint "Break here" ".*Break here.*" + +gdb_test "python gdb.command.grep.register_union_field_selector(gdb.command.grep.AllFieldsSelector())" "" + +gdb_test "grep i i" "i = \\(int\\) 10" + +gdb_test "grep str str_val" "str_val = \\(char \\*\\) \"I am a string\"" + +gdb_test "grep s char_array" "char_array\\\[6\\\] = \\(char\\) 115 's'" + +gdb_test "grep not ptr_to_char_array" "ptr_to_char_array = \\(char \\*\\) \"not a string\"" + +set ss_int "ss\\.int_val = \\(int\\) 10" +set ss_double "ss\\.double_val = \\(double\\) 1\\.1.*" +gdb_test "grep \"val\" ss" "(($ss_int\[\\n\\r\]*)|($ss_double\[\\n\\r\]*))+" + +gdb_test "grep value \"^10$\" ss" "$ss_int" + +set cs1_ss_int "cs1\\.$ss_int" +set cs1_ss_double "cs1\\.$ss_double" +set cs1_str "cs1\\.str_val = \\(char \\*\\) \"embedded string value\"" +gdb_test "grep field val cs1" "(($cs1_ss_int\[\\n\\r\]*)|($cs1_ss_double\[\\n\\r\]*)|($cs1_str\[\\n\\r\]*))+" +gdb_test "grep value val cs1" "$cs1_str" + +set cs2_cs1_ss_int "cs2\\.$cs1_ss_int" +set cs2_int_ptr "\\*\\(cs2\\.int_ptr\\) = \\(int\\) 10" +gdb_test "grep \"^10$\" cs2" "(($cs2_cs1_ss_int\[\\n\\r\]*)|($cs2_int_ptr\[\\n\\r\]*))+" +gdb_test "grep \"^9$\" cs2" "cs2\\.int_array\\\[9\\\] = \\(int\\) 9" + +set us_val1 "us\\.$ss_int" +set us_val2 "us\\.$ss_double" +set us_val3 "us\\.$cs1_str" +set us_val4 "us\\.$cs1_ss_int" +set us_val5 "us\\.$cs1_ss_double" +set us_val6 "us\\.cs2\\.$cs1_str" +set us_val7 "us\\.cs2\\.$cs1_ss_int" +set us_val8 "us\\.cs2\\.$cs1_ss_double" +gdb_test "grep field val us" "(($us_val1\[\\n\\r\]*)|($us_val2\[\\n\\r\]*)|($us_val3\[\\n\\r\]*)|($us_val4\[\\n\\r\]*)|($us_val5\[\\n\\r\]*)|($us_val6\[\\n\\r\]*)|($us_val7\[\\n\\r\]*)|($us_val8\[\\n\\r\]*))+" +gdb_test "grep value val us" "(($us_val3\[\\n\\r\]*)|($us_val6\[\\n\\r\]*))+" + +set tt_val1 "\\(\\*tt\\)\\.$ss_int" +set tt_val2 "\\(\\*tt\\)\\.$ss_double" +set tt_val3 "\\(\\*tt\\)\\.$cs1_str" +set tt_val4 "\\(\\*tt\\)\\.$cs1_ss_int" +set tt_val5 "\\(\\*tt\\)\\.$cs1_ss_double" +set tt_val6 "\\(\\*tt\\)\\.cs2\\.$cs1_str" +set tt_val7 "\\(\\*tt\\)\\.cs2\\.$cs1_ss_int" +set tt_val8 "\\(\\*tt\\)\\.cs2\\.$cs1_ss_double" +gdb_test "grep field val tt" "(($tt_val1\[\\n\\r\]*)|($tt_val2\[\\n\\r\]*)|($tt_val3\[\\n\\r\]*)|($tt_val4\[\\n\\r\]*)|($tt_val5\[\\n\\r\]*)|($tt_val6\[\\n\\r\]*)|($tt_val7\[\\n\\r\]*)|($tt_val8\[\\n\\r\]*))+" +gdb_test "grep value val tt" "(($tt_val3\[\\n\\r\]*)|($tt_val6\[\\n\\r\]*))+"