1# Copyright (C) 2008-2015 Free Software Foundation, Inc. 2 3# This program is free software; you can redistribute it and/or modify 4# it under the terms of the GNU General Public License as published by 5# the Free Software Foundation; either version 3 of the License, or 6# (at your option) any later version. 7# 8# This program is distributed in the hope that it will be useful, 9# but WITHOUT ANY WARRANTY; without even the implied warranty of 10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11# GNU General Public License for more details. 12# 13# You should have received a copy of the GNU General Public License 14# along with this program. If not, see <http://www.gnu.org/licenses/>. 15 16# This file is part of the GDB testsuite. It tests python pretty 17# printers. 18 19import re 20import gdb 21 22def _iterator (pointer, len): 23 start = pointer 24 end = pointer + len 25 while pointer != end: 26 yield ('[%d]' % int (pointer - start), pointer.dereference()) 27 pointer += 1 28 29# Same as _iterator but can be told to raise an exception. 30def _iterator_except (pointer, len): 31 start = pointer 32 end = pointer + len 33 while pointer != end: 34 if exception_flag: 35 raise gdb.MemoryError ('hi bob') 36 yield ('[%d]' % int (pointer - start), pointer.dereference()) 37 pointer += 1 38 39# Test returning a Value from a printer. 40class string_print (object): 41 def __init__(self, val): 42 self.val = val 43 44 def to_string(self): 45 return self.val['whybother']['contents'] 46 47# Test a class-based printer. 48class ContainerPrinter (object): 49 50 def __init__(self, val): 51 self.val = val 52 53 def to_string(self): 54 return 'container %s with %d elements' % (self.val['name'], self.val['len']) 55 56 def children(self): 57 return _iterator(self.val['elements'], self.val['len']) 58 59# Treats a container as array. 60class ArrayPrinter (object): 61 def __init__(self, val): 62 self.val = val 63 64 def to_string(self): 65 return 'array %s with %d elements' % (self.val['name'], self.val['len']) 66 67 def children(self): 68 return _iterator(self.val['elements'], self.val['len']) 69 70 def display_hint (self): 71 return 'array' 72 73# Flag to make NoStringContainerPrinter throw an exception. 74exception_flag = False 75 76# Test a printer where to_string is None 77class NoStringContainerPrinter (object): 78 def __init__(self, val): 79 self.val = val 80 81 def to_string(self): 82 return None 83 84 def children(self): 85 return _iterator_except (self.val['elements'], self.val['len']) 86 87class pp_s (object): 88 def __init__(self, val): 89 self.val = val 90 91 def to_string(self): 92 a = self.val["a"] 93 b = self.val["b"] 94 if a.address != b: 95 raise Exception("&a(%s) != b(%s)" % (str(a.address), str(b))) 96 return " a=<" + str(self.val["a"]) + "> b=<" + str(self.val["b"]) + ">" 97 98class pp_ss (object): 99 def __init__(self, val): 100 self.val = val 101 102 def to_string(self): 103 return "a=<" + str(self.val["a"]) + "> b=<" + str(self.val["b"]) + ">" 104 105class pp_sss (object): 106 def __init__(self, val): 107 self.val = val 108 109 def to_string(self): 110 return "a=<" + str(self.val['a']) + "> b=<" + str(self.val["b"]) + ">" 111 112class pp_multiple_virtual (object): 113 def __init__ (self, val): 114 self.val = val 115 116 def to_string (self): 117 return "pp value variable is: " + str (self.val['value']) 118 119class pp_vbase1 (object): 120 def __init__ (self, val): 121 self.val = val 122 123 def to_string (self): 124 return "pp class name: " + self.val.type.tag 125 126class pp_nullstr (object): 127 def __init__(self, val): 128 self.val = val 129 130 def to_string(self): 131 return self.val['s'].string(gdb.target_charset()) 132 133class pp_ns (object): 134 "Print a std::basic_string of some kind" 135 136 def __init__(self, val): 137 self.val = val 138 139 def to_string(self): 140 len = self.val['length'] 141 return self.val['null_str'].string (gdb.target_charset(), length = len) 142 143 def display_hint (self): 144 return 'string' 145 146pp_ls_encoding = None 147 148class pp_ls (object): 149 "Print a std::basic_string of some kind" 150 151 def __init__(self, val): 152 self.val = val 153 154 def to_string(self): 155 if pp_ls_encoding is not None: 156 return self.val['lazy_str'].lazy_string(encoding = pp_ls_encoding) 157 else: 158 return self.val['lazy_str'].lazy_string() 159 160 def display_hint (self): 161 return 'string' 162 163class pp_hint_error (object): 164 "Throw error from display_hint" 165 166 def __init__(self, val): 167 self.val = val 168 169 def to_string(self): 170 return 'hint_error_val' 171 172 def display_hint (self): 173 raise Exception("hint failed") 174 175class pp_children_as_list (object): 176 "Throw error from display_hint" 177 178 def __init__(self, val): 179 self.val = val 180 181 def to_string(self): 182 return 'children_as_list_val' 183 184 def children (self): 185 return [('one', 1)] 186 187class pp_outer (object): 188 "Print struct outer" 189 190 def __init__ (self, val): 191 self.val = val 192 193 def to_string (self): 194 return "x = %s" % self.val['x'] 195 196 def children (self): 197 yield 's', self.val['s'] 198 yield 'x', self.val['x'] 199 200class MemoryErrorString (object): 201 "Raise an error" 202 203 def __init__(self, val): 204 self.val = val 205 206 def to_string(self): 207 raise gdb.MemoryError ("Cannot access memory.") 208 209 def display_hint (self): 210 return 'string' 211 212class pp_eval_type (object): 213 def __init__(self, val): 214 self.val = val 215 216 def to_string(self): 217 gdb.execute("bt", to_string=True) 218 return "eval=<" + str(gdb.parse_and_eval("eval_func (123456789, 2, 3, 4, 5, 6, 7, 8)")) + ">" 219 220def lookup_function (val): 221 "Look-up and return a pretty-printer that can print val." 222 223 # Get the type. 224 type = val.type 225 226 # If it points to a reference, get the reference. 227 if type.code == gdb.TYPE_CODE_REF: 228 type = type.target () 229 230 # Get the unqualified type, stripped of typedefs. 231 type = type.unqualified ().strip_typedefs () 232 233 # Get the type name. 234 typename = type.tag 235 236 if typename == None: 237 return None 238 239 # Iterate over local dictionary of types to determine 240 # if a printer is registered for that type. Return an 241 # instantiation of the printer if found. 242 for function in pretty_printers_dict: 243 if function.match (typename): 244 return pretty_printers_dict[function] (val) 245 246 # Cannot find a pretty printer. Return None. 247 248 return None 249 250def disable_lookup_function (): 251 lookup_function.enabled = False 252 253def enable_lookup_function (): 254 lookup_function.enabled = True 255 256def register_pretty_printers (): 257 pretty_printers_dict[re.compile ('^struct s$')] = pp_s 258 pretty_printers_dict[re.compile ('^s$')] = pp_s 259 pretty_printers_dict[re.compile ('^S$')] = pp_s 260 261 pretty_printers_dict[re.compile ('^struct ss$')] = pp_ss 262 pretty_printers_dict[re.compile ('^ss$')] = pp_ss 263 pretty_printers_dict[re.compile ('^const S &$')] = pp_s 264 pretty_printers_dict[re.compile ('^SSS$')] = pp_sss 265 266 pretty_printers_dict[re.compile ('^VirtualTest$')] = pp_multiple_virtual 267 pretty_printers_dict[re.compile ('^Vbase1$')] = pp_vbase1 268 269 pretty_printers_dict[re.compile ('^struct nullstr$')] = pp_nullstr 270 pretty_printers_dict[re.compile ('^nullstr$')] = pp_nullstr 271 272 # Note that we purposely omit the typedef names here. 273 # Printer lookup is based on canonical name. 274 # However, we do need both tagged and untagged variants, to handle 275 # both the C and C++ cases. 276 pretty_printers_dict[re.compile ('^struct string_repr$')] = string_print 277 pretty_printers_dict[re.compile ('^struct container$')] = ContainerPrinter 278 pretty_printers_dict[re.compile ('^struct justchildren$')] = NoStringContainerPrinter 279 pretty_printers_dict[re.compile ('^string_repr$')] = string_print 280 pretty_printers_dict[re.compile ('^container$')] = ContainerPrinter 281 pretty_printers_dict[re.compile ('^justchildren$')] = NoStringContainerPrinter 282 283 pretty_printers_dict[re.compile ('^struct ns$')] = pp_ns 284 pretty_printers_dict[re.compile ('^ns$')] = pp_ns 285 286 pretty_printers_dict[re.compile ('^struct lazystring$')] = pp_ls 287 pretty_printers_dict[re.compile ('^lazystring$')] = pp_ls 288 289 pretty_printers_dict[re.compile ('^struct outerstruct$')] = pp_outer 290 pretty_printers_dict[re.compile ('^outerstruct$')] = pp_outer 291 292 pretty_printers_dict[re.compile ('^struct hint_error$')] = pp_hint_error 293 pretty_printers_dict[re.compile ('^hint_error$')] = pp_hint_error 294 295 pretty_printers_dict[re.compile ('^struct children_as_list$')] = pp_children_as_list 296 pretty_printers_dict[re.compile ('^children_as_list$')] = pp_children_as_list 297 298 pretty_printers_dict[re.compile ('^memory_error$')] = MemoryErrorString 299 300 pretty_printers_dict[re.compile ('^eval_type_s$')] = pp_eval_type 301 302pretty_printers_dict = {} 303 304register_pretty_printers () 305gdb.pretty_printers.append (lookup_function) 306