From patchwork Thu Sep 28 17:46:25 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom Tromey X-Patchwork-Id: 146243 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:cae8:0:b0:403:3b70:6f57 with SMTP id r8csp3494746vqu; Thu, 28 Sep 2023 10:56:45 -0700 (PDT) X-Google-Smtp-Source: AGHT+IGlLT/W0t/XYf10m1TgX4VoVSfWWlc+O5yYxt0PdRsXHtX3mPIl38Cm0DmlXMUmJT2cIHHa X-Received: by 2002:a17:906:24e:b0:9ae:53af:c57f with SMTP id 14-20020a170906024e00b009ae53afc57fmr2153540ejl.65.1695923805106; Thu, 28 Sep 2023 10:56:45 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1695923805; cv=none; d=google.com; s=arc-20160816; b=oyX9jQdvSvh1MxtZT6A7sEneQ97eLLWqYWNkG2fDsmBok17WfPX1EWU9BHtg0f+5de WsUG0rVjrn73ZHGvN7+MpS9KWAsHolCUuZM+eni9KwXSkV+fUsIhkv86nE0wk8DZnkK8 qvLVvVO0FaFgL3IVvXSs9uP+oOh+kQ7GnFuLUvMrbVCZUZ6d5qS/a056VuT83DaQ09Ef cHFnjAy/RpA6+zQ4f9abTylYFqUfeGSUfHabmSNSjbPsFllgbX/QsTYk9WQfCQLbq/gC /qAU0Yn9HcPfZQYvSeBVlNyvweo/DT6ANApr8JDJmQgmtsZUUo9VP/HOqSEKAlFzXQKp hmIg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature:dmarc-filter:delivered-to; bh=/vPRrldHqgDYL+UAoJalEQR5zTgKO5b8w+o0g3/utGI=; fh=Ogh3zaPUNpdNYHofIVNHsbX+D3lwaT1T8Jhe/MolwAA=; b=Buk4Pbnss31BfRE8GaEwn1t24kO5sbAwmkvvis+QUR34fqMbxXbNeEbQ2FUtU+jrWa DOw7qNlMJ032M0M/lLMDcUWa1IQjAO6bmXsH0hjrg5SyeR5hi42FNI+2QDwd0P9aJMyI JSjLu//z6iZ5i/4Ar/oeoEX5FxT8Gsafa6jyrMbMfLkXDTCUPYFJX4pOMzozGz4HrUNJ +2XtLXQc51kVBCw5CqadSA/PFZq3Qo1ZuRTi+jcdx+m4Gqoilu3R+vkY0iiE54IJaucF BD0fAD0m7Fju/Wv5K03nMg0ckHigTMo9AkLKfwPFmjhZQCVpgjlyWwqwkQhQ/f/fYmIv SfGw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@adacore.com header.s=google header.b=OM8GeJQR; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=adacore.com Received: from server2.sourceware.org (ip-8-43-85-97.sourceware.org. [8.43.85.97]) by mx.google.com with ESMTPS id qc10-20020a170906d8aa00b009ae43ae1dd2si16589068ejb.275.2023.09.28.10.56.44 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 28 Sep 2023 10:56:45 -0700 (PDT) Received-SPF: pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) client-ip=8.43.85.97; Authentication-Results: mx.google.com; dkim=pass header.i=@adacore.com header.s=google header.b=OM8GeJQR; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=adacore.com Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 675483888C66 for ; Thu, 28 Sep 2023 17:50:07 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-il1-x12c.google.com (mail-il1-x12c.google.com [IPv6:2607:f8b0:4864:20::12c]) by sourceware.org (Postfix) with ESMTPS id 9AACC385841B for ; Thu, 28 Sep 2023 17:46:43 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 9AACC385841B Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=adacore.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=adacore.com Received: by mail-il1-x12c.google.com with SMTP id e9e14a558f8ab-3513b5a9e8eso27766485ab.0 for ; Thu, 28 Sep 2023 10:46:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=adacore.com; s=google; t=1695923203; x=1696528003; darn=gcc.gnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=/vPRrldHqgDYL+UAoJalEQR5zTgKO5b8w+o0g3/utGI=; b=OM8GeJQRsWxUy9jlnvHgNFu5UOsUWcWRaSbWk2XKviJd2NMvtabrIRvksM5HbeM0NN vEExRxdyFqPe/kSa08vYjur2M6EECMMiaWq49yUBjQOl4Y/XZc/eg2wvW9ZAOKYqgGlO V8ERJ7CTbm6RlDWYidZ1rXbtNLywLvbTRlt0y6v+WKyobtQwowNxjW39oRhuBdr/qH4Z deun2gCf+WwKm8zuI3CUKE56CJvhzqthu1FOIkYR0nffwnbR3Du4xYMrZIL+KO/ApcJa tL0/Cv9ON+hLkveC0EhIPnzvwVphyxY4lPfHUDsvApX8jOxMISRiX7U5Xb4Hvk6wKOpC 9nFQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1695923203; x=1696528003; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=/vPRrldHqgDYL+UAoJalEQR5zTgKO5b8w+o0g3/utGI=; b=mgvy4NKqgmGQtBmSPvlJiIhOr1pxe8TyQfGThoyHKgOavqOxvLuJw7QGQzc3cX+00o SUNYMERTLuuHpNx5OcRwethw5Pu6UNT7ur26V1s2Y+G6EshjJWsPb7L0wJs4aE1pRyWA MmOFWOsPn3MACact0WpIjKuVqKfbt7cwtI+kDKsTOKy6+kdQ+dUksKdPB3PlEuZ87d9F 9wyEu571MqQnnEQ+Uds1bj1IWVTStOtkvEbepsPBVLntvMNwJClp0+6Q9vdu9ecSKdgY F4VSYA57MP340US83ukBhfG5YfUDPB1s1BkonadHWXhQsZscxad/ZOA+/l/0HklMhRk5 oO4A== X-Gm-Message-State: AOJu0YzKqO8A/4jKKUSprDhMjEs9yIktHO6vSPoGLaoomiNttu2dXema N4PMa4+0wCQAIa4/3LG5cA++kUlxtXy59bMYQ8l7HQ== X-Received: by 2002:a05:6e02:e11:b0:351:c52:5092 with SMTP id a17-20020a056e020e1100b003510c525092mr1627622ilk.3.1695923202447; Thu, 28 Sep 2023 10:46:42 -0700 (PDT) Received: from localhost.localdomain (71-211-130-31.hlrn.qwest.net. [71.211.130.31]) by smtp.gmail.com with ESMTPSA id p6-20020a92d486000000b0034fc8c1c24fsm3450963ilg.54.2023.09.28.10.46.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 28 Sep 2023 10:46:42 -0700 (PDT) From: Tom Tromey To: gcc-patches@gcc.gnu.org Cc: libstdc++@gcc.gnu.org, Tom Tromey Subject: [PATCH 2/7] libstdc++: Use gdb.ValuePrinter base class Date: Thu, 28 Sep 2023 11:46:25 -0600 Message-Id: <20230928174630.4004388-3-tromey@adacore.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20230928174630.4004388-1-tromey@adacore.com> References: <20230928174630.4004388-1-tromey@adacore.com> MIME-Version: 1.0 X-Spam-Status: No, score=-11.6 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1778304999564974956 X-GMAIL-MSGID: 1778304999564974956 GDB 14 will add a new ValuePrinter tag class that will be used to signal that pretty-printers will agree to the "extension protocol" -- essentially that they will follow some simple namespace rules, so that GDB can add new methods over time. A couple new methods have already been added to GDB, to support DAP. While I haven't implemented these for any libstdc++ printers yet, this patch makes the basic conversion: printers derive from gdb.ValuePrinter if it is available, and all "non-standard" (that is, not specified by GDB) members of the various value-printing classes are renamed to have a leading underscore. --- libstdc++-v3/python/libstdcxx/v6/printers.py | 1201 +++++++++--------- 1 file changed, 605 insertions(+), 596 deletions(-) diff --git a/libstdc++-v3/python/libstdcxx/v6/printers.py b/libstdc++-v3/python/libstdcxx/v6/printers.py index d60c8003a63..bbc4375541f 100644 --- a/libstdc++-v3/python/libstdcxx/v6/printers.py +++ b/libstdc++-v3/python/libstdcxx/v6/printers.py @@ -97,6 +97,12 @@ try: except ImportError: pass +# Use the base class if available. +if hasattr(gdb, 'ValuePrinter'): + printer_base = gdb.ValuePrinter +else: + printer_base = object + # Starting with the type ORIG, search for the member type NAME. This # handles searching upward through superclasses. This is needed to # work around http://sourceware.org/bugzilla/show_bug.cgi?id=13615. @@ -241,43 +247,43 @@ class SmartPtrIterator(Iterator): "An iterator for smart pointer types with a single 'child' value" def __init__(self, val): - self.val = val + self._val = val def __iter__(self): return self def __next__(self): - if self.val is None: + if self._val is None: raise StopIteration - self.val, val = None, self.val + self._val, val = None, self._val return ('get()', val) -class SharedPointerPrinter: +class SharedPointerPrinter(printer_base): "Print a shared_ptr, weak_ptr, atomic, or atomic" def __init__(self, typename, val): - self.typename = strip_versioned_namespace(typename) - self.val = val - self.pointer = val['_M_ptr'] + self._typename = strip_versioned_namespace(typename) + self._val = val + self._pointer = val['_M_ptr'] def children(self): - return SmartPtrIterator(self.pointer) + return SmartPtrIterator(self._pointer) # Return the _Sp_counted_base<>* that holds the refcounts. def _get_refcounts(self): - if self.typename == 'std::atomic': + if self._typename == 'std::atomic': # A tagged pointer is stored as uintptr_t. - ptr_val = self.val['_M_refcount']['_M_val']['_M_i'] + ptr_val = self._val['_M_refcount']['_M_val']['_M_i'] ptr_val = ptr_val - (ptr_val % 2) # clear lock bit - ptr_type = find_type(self.val['_M_refcount'].type, 'pointer') + ptr_type = find_type(self._val['_M_refcount'].type, 'pointer') return ptr_val.cast(ptr_type) - return self.val['_M_refcount']['_M_pi'] + return self._val['_M_refcount']['_M_pi'] def to_string(self): state = 'empty' refcounts = self._get_refcounts() - targ = self.val.type.template_argument(0) + targ = self._val.type.template_argument(0) targ = strip_versioned_namespace(str(targ)) if refcounts != 0: @@ -288,7 +294,7 @@ class SharedPointerPrinter: else: state = 'use count %d, weak count %d' % ( usecount, weakcount - 1) - return '%s<%s> (%s)' % (self.typename, targ, state) + return '%s<%s> (%s)' % (self._typename, targ, state) def _tuple_impl_get(val): @@ -347,17 +353,17 @@ def unique_ptr_get(val): return tuple_get(0, tuple_member) -class UniquePointerPrinter: +class UniquePointerPrinter(printer_base): "Print a unique_ptr" def __init__(self, typename, val): - self.val = val + self._val = val def children(self): - return SmartPtrIterator(unique_ptr_get(self.val)) + return SmartPtrIterator(unique_ptr_get(self._val)) def to_string(self): - return ('std::unique_ptr<%s>' % (str(self.val.type.template_argument(0)))) + return ('std::unique_ptr<%s>' % (str(self._val.type.template_argument(0)))) def get_value_from_aligned_membuf(buf, valtype): @@ -381,55 +387,56 @@ def get_value_from_list_node(node): raise ValueError("Unsupported implementation for %s" % str(node.type)) -class StdListPrinter: +class StdListPrinter(printer_base): "Print a std::list" class _iterator(Iterator): def __init__(self, nodetype, head): - self.nodetype = nodetype - self.base = head['_M_next'] - self.head = head.address - self.count = 0 + self._nodetype = nodetype + self._base = head['_M_next'] + self._head = head.address + self._count = 0 def __iter__(self): return self def __next__(self): - if self.base == self.head: + if self._base == self._head: raise StopIteration - elt = self.base.cast(self.nodetype).dereference() - self.base = elt['_M_next'] - count = self.count - self.count = self.count + 1 + elt = self._base.cast(self._nodetype).dereference() + self._base = elt['_M_next'] + count = self._count + self._count = self._count + 1 val = get_value_from_list_node(elt) return ('[%d]' % count, val) def __init__(self, typename, val): - self.typename = strip_versioned_namespace(typename) - self.val = val + self._typename = strip_versioned_namespace(typename) + self._val = val def children(self): - nodetype = lookup_node_type('_List_node', self.val.type).pointer() - return self._iterator(nodetype, self.val['_M_impl']['_M_node']) + nodetype = lookup_node_type('_List_node', self._val.type).pointer() + return self._iterator(nodetype, self._val['_M_impl']['_M_node']) def to_string(self): - headnode = self.val['_M_impl']['_M_node'] + headnode = self._val['_M_impl']['_M_node'] if headnode['_M_next'] == headnode.address: - return 'empty %s' % (self.typename) - return '%s' % (self.typename) + return 'empty %s' % (self._typename) + return '%s' % (self._typename) -class NodeIteratorPrinter: +class NodeIteratorPrinter(printer_base): def __init__(self, typename, val, contname, nodename): - self.val = val - self.typename = typename - self.contname = contname - self.nodetype = lookup_node_type(nodename, val.type) + self._val = val + self._typename = typename + self._contname = contname + self._nodetype = lookup_node_type(nodename, val.type) def to_string(self): - if not self.val['_M_node']: - return 'non-dereferenceable iterator for std::%s' % (self.contname) - node = self.val['_M_node'].cast(self.nodetype.pointer()).dereference() + if not self._val['_M_node']: + return 'non-dereferenceable iterator for std::%s' % (self._contname) + node = self._val['_M_node'].cast( + self._nodetype.pointer()).dereference() return str(get_value_from_list_node(node)) @@ -448,163 +455,164 @@ class StdFwdListIteratorPrinter(NodeIteratorPrinter): '_Fwd_list_node') -class StdSlistPrinter: +class StdSlistPrinter(printer_base): "Print a __gnu_cxx::slist" class _iterator(Iterator): def __init__(self, nodetype, head): - self.nodetype = nodetype - self.base = head['_M_head']['_M_next'] - self.count = 0 + self._nodetype = nodetype + self._base = head['_M_head']['_M_next'] + self._count = 0 def __iter__(self): return self def __next__(self): - if self.base == 0: + if self._base == 0: raise StopIteration - elt = self.base.cast(self.nodetype).dereference() - self.base = elt['_M_next'] - count = self.count - self.count = self.count + 1 + elt = self._base.cast(self._nodetype).dereference() + self._base = elt['_M_next'] + count = self._count + self._count = self._count + 1 return ('[%d]' % count, elt['_M_data']) def __init__(self, typename, val): - self.val = val + self._val = val def children(self): - nodetype = lookup_node_type('__gnu_cxx::_Slist_node', self.val.type) - return self._iterator(nodetype.pointer(), self.val) + nodetype = lookup_node_type('__gnu_cxx::_Slist_node', self._val.type) + return self._iterator(nodetype.pointer(), self._val) def to_string(self): - if self.val['_M_head']['_M_next'] == 0: + if self._val['_M_head']['_M_next'] == 0: return 'empty __gnu_cxx::slist' return '__gnu_cxx::slist' -class StdSlistIteratorPrinter: +class StdSlistIteratorPrinter(printer_base): "Print __gnu_cxx::slist::iterator" def __init__(self, typename, val): - self.val = val + self._val = val def to_string(self): - if not self.val['_M_node']: + if not self._val['_M_node']: return 'non-dereferenceable iterator for __gnu_cxx::slist' nodetype = lookup_node_type( - '__gnu_cxx::_Slist_node', self.val.type).pointer() - return str(self.val['_M_node'].cast(nodetype).dereference()['_M_data']) + '__gnu_cxx::_Slist_node', self._val.type).pointer() + return str(self._val['_M_node'].cast(nodetype).dereference()['_M_data']) -class StdVectorPrinter: +class StdVectorPrinter(printer_base): "Print a std::vector" class _iterator(Iterator): def __init__(self, start, finish, bitvec): - self.bitvec = bitvec + self._bitvec = bitvec if bitvec: - self.item = start['_M_p'] - self.so = 0 - self.finish = finish['_M_p'] - self.fo = finish['_M_offset'] - itype = self.item.dereference().type - self.isize = 8 * itype.sizeof + self._item = start['_M_p'] + self._so = 0 + self._finish = finish['_M_p'] + self._fo = finish['_M_offset'] + itype = self._item.dereference().type + self._isize = 8 * itype.sizeof else: - self.item = start - self.finish = finish - self.count = 0 + self._item = start + self._finish = finish + self._count = 0 def __iter__(self): return self def __next__(self): - count = self.count - self.count = self.count + 1 - if self.bitvec: - if self.item == self.finish and self.so >= self.fo: + count = self._count + self._count = self._count + 1 + if self._bitvec: + if self._item == self._finish and self._so >= self._fo: raise StopIteration - elt = bool(self.item.dereference() & (1 << self.so)) - self.so = self.so + 1 - if self.so >= self.isize: - self.item = self.item + 1 - self.so = 0 + elt = bool(self._item.dereference() & (1 << self._so)) + self._so = self._so + 1 + if self._so >= self._isize: + self._item = self._item + 1 + self._so = 0 return ('[%d]' % count, elt) else: - if self.item == self.finish: + if self._item == self._finish: raise StopIteration - elt = self.item.dereference() - self.item = self.item + 1 + elt = self._item.dereference() + self._item = self._item + 1 return ('[%d]' % count, elt) def __init__(self, typename, val): - self.typename = strip_versioned_namespace(typename) - self.val = val - self.is_bool = val.type.template_argument(0).code == gdb.TYPE_CODE_BOOL + self._typename = strip_versioned_namespace(typename) + self._val = val + self._is_bool = val.type.template_argument( + 0).code == gdb.TYPE_CODE_BOOL def children(self): - return self._iterator(self.val['_M_impl']['_M_start'], - self.val['_M_impl']['_M_finish'], - self.is_bool) + return self._iterator(self._val['_M_impl']['_M_start'], + self._val['_M_impl']['_M_finish'], + self._is_bool) def to_string(self): - start = self.val['_M_impl']['_M_start'] - finish = self.val['_M_impl']['_M_finish'] - end = self.val['_M_impl']['_M_end_of_storage'] - if self.is_bool: - start = self.val['_M_impl']['_M_start']['_M_p'] - finish = self.val['_M_impl']['_M_finish']['_M_p'] - fo = self.val['_M_impl']['_M_finish']['_M_offset'] + start = self._val['_M_impl']['_M_start'] + finish = self._val['_M_impl']['_M_finish'] + end = self._val['_M_impl']['_M_end_of_storage'] + if self._is_bool: + start = self._val['_M_impl']['_M_start']['_M_p'] + finish = self._val['_M_impl']['_M_finish']['_M_p'] + fo = self._val['_M_impl']['_M_finish']['_M_offset'] itype = start.dereference().type bl = 8 * itype.sizeof length = bl * (finish - start) + fo capacity = bl * (end - start) return ('%s of length %d, capacity %d' - % (self.typename, int(length), int(capacity))) + % (self._typename, int(length), int(capacity))) else: return ('%s of length %d, capacity %d' - % (self.typename, int(finish - start), int(end - start))) + % (self._typename, int(finish - start), int(end - start))) def display_hint(self): return 'array' -class StdVectorIteratorPrinter: +class StdVectorIteratorPrinter(printer_base): "Print std::vector::iterator" def __init__(self, typename, val): - self.val = val + self._val = val def to_string(self): - if not self.val['_M_current']: + if not self._val['_M_current']: return 'non-dereferenceable iterator for std::vector' - return str(self.val['_M_current'].dereference()) + return str(self._val['_M_current'].dereference()) -class StdBitIteratorPrinter: +class StdBitIteratorPrinter(printer_base): "Print std::vector's _Bit_iterator and _Bit_const_iterator" def __init__(self, typename, val): - self.val = val + self._val = val def to_string(self): - if not self.val['_M_p']: + if not self._val['_M_p']: return 'non-dereferenceable iterator for std::vector' - return bool(self.val['_M_p'].dereference() & (1 << self.val['_M_offset'])) + return bool(self._val['_M_p'].dereference() & (1 << self._val['_M_offset'])) -class StdBitReferencePrinter: +class StdBitReferencePrinter(printer_base): "Print std::vector::reference" def __init__(self, typename, val): - self.val = val + self._val = val def to_string(self): - if not self.val['_M_p']: + if not self._val['_M_p']: return 'invalid std::vector::reference' - return bool(self.val['_M_p'].dereference() & (self.val['_M_mask'])) + return bool(self._val['_M_p'].dereference() & (self._val['_M_mask'])) -class StdTuplePrinter: +class StdTuplePrinter(printer_base): "Print a std::tuple" class _iterator(Iterator): @@ -621,25 +629,25 @@ class StdTuplePrinter: "Top of tuple tree does not consist of a single node.") def __init__(self, head): - self.head = head + self._head = head # Set the base class as the initial head of the # tuple. - nodes = self.head.type.fields() + nodes = self._head.type.fields() if self._is_nonempty_tuple(nodes): # Set the actual head to the first pair. - self.head = self.head.cast(nodes[0].type) - self.count = 0 + self._head = self._head.cast(nodes[0].type) + self._count = 0 def __iter__(self): return self def __next__(self): # Check for further recursions in the inheritance tree. - # For a GCC 5+ tuple self.head is None after visiting all nodes: - if not self.head: + # For a GCC 5+ tuple self._head is None after visiting all nodes: + if not self._head: raise StopIteration - nodes = self.head.type.fields() + nodes = self._head.type.fields() # For a GCC 4.x tuple there is a final node with no fields: if len(nodes) == 0: raise StopIteration @@ -650,8 +658,8 @@ class StdTuplePrinter: if len(nodes) == 1: # This is the last node of a GCC 5+ std::tuple. - impl = self.head.cast(nodes[0].type) - self.head = None + impl = self._head.cast(nodes[0].type) + self._head = None else: # Either a node before the last node, or the last node of # a GCC 4.x tuple (which has an empty parent). @@ -660,52 +668,52 @@ class StdTuplePrinter: # - Right node is the actual class contained in the tuple. # Process right node. - impl = self.head.cast(nodes[1].type) + impl = self._head.cast(nodes[1].type) # Process left node and set it as head. - self.head = self.head.cast(nodes[0].type) + self._head = self._head.cast(nodes[0].type) - self.count = self.count + 1 + self._count = self._count + 1 # Finally, check the implementation. If it is # wrapped in _M_head_impl return that, otherwise return # the value "as is". fields = impl.type.fields() if len(fields) < 1 or fields[0].name != "_M_head_impl": - return ('[%d]' % (self.count - 1), impl) + return ('[%d]' % (self._count - 1), impl) else: - return ('[%d]' % (self.count - 1), impl['_M_head_impl']) + return ('[%d]' % (self._count - 1), impl['_M_head_impl']) def __init__(self, typename, val): - self.typename = strip_versioned_namespace(typename) - self.val = val + self._typename = strip_versioned_namespace(typename) + self._val = val def children(self): - return self._iterator(self.val) + return self._iterator(self._val) def to_string(self): - if len(self.val.type.fields()) == 0: - return 'empty %s' % (self.typename) - return '%s containing' % (self.typename) + if len(self._val.type.fields()) == 0: + return 'empty %s' % (self._typename) + return '%s containing' % (self._typename) -class StdStackOrQueuePrinter: +class StdStackOrQueuePrinter(printer_base): "Print a std::stack or std::queue" def __init__(self, typename, val): - self.typename = strip_versioned_namespace(typename) - self.visualizer = gdb.default_visualizer(val['c']) + self._typename = strip_versioned_namespace(typename) + self._visualizer = gdb.default_visualizer(val['c']) def children(self): - return self.visualizer.children() + return self._visualizer.children() def to_string(self): - return '%s wrapping: %s' % (self.typename, - self.visualizer.to_string()) + return '%s wrapping: %s' % (self._typename, + self._visualizer.to_string()) def display_hint(self): - if hasattr(self.visualizer, 'display_hint'): - return self.visualizer.display_hint() + if hasattr(self._visualizer, 'display_hint'): + return self._visualizer.display_hint() return None @@ -716,24 +724,24 @@ class RbtreeIterator(Iterator): """ def __init__(self, rbtree): - self.size = rbtree['_M_t']['_M_impl']['_M_node_count'] - self.node = rbtree['_M_t']['_M_impl']['_M_header']['_M_left'] - self.count = 0 + self._size = rbtree['_M_t']['_M_impl']['_M_node_count'] + self._node = rbtree['_M_t']['_M_impl']['_M_header']['_M_left'] + self._count = 0 def __iter__(self): return self def __len__(self): - return int(self.size) + return int(self._size) def __next__(self): - if self.count == self.size: + if self._count == self._size: raise StopIteration - result = self.node - self.count = self.count + 1 - if self.count < self.size: + result = self._node + self._count = self._count + 1 + if self._count < self._size: # Compute the next node. - node = self.node + node = self._node if node.dereference()['_M_right']: node = node.dereference()['_M_right'] while node.dereference()['_M_left']: @@ -745,7 +753,7 @@ class RbtreeIterator(Iterator): parent = parent.dereference()['_M_parent'] if node.dereference()['_M_right'] != parent: node = parent - self.node = node + self._node = node return result @@ -769,38 +777,38 @@ def get_value_from_Rb_tree_node(node): # class above. -class StdRbtreeIteratorPrinter: +class StdRbtreeIteratorPrinter(printer_base): "Print std::map::iterator, std::set::iterator, etc." def __init__(self, typename, val): - self.val = val - nodetype = lookup_node_type('_Rb_tree_node', self.val.type) - self.link_type = nodetype.pointer() + self._val = val + nodetype = lookup_node_type('_Rb_tree_node', self._val.type) + self._link_type = nodetype.pointer() def to_string(self): - if not self.val['_M_node']: + if not self._val['_M_node']: return 'non-dereferenceable iterator for associative container' - node = self.val['_M_node'].cast(self.link_type).dereference() + node = self._val['_M_node'].cast(self._link_type).dereference() return str(get_value_from_Rb_tree_node(node)) -class StdDebugIteratorPrinter: +class StdDebugIteratorPrinter(printer_base): "Print a debug enabled version of an iterator" def __init__(self, typename, val): - self.val = val + self._val = val # Just strip away the encapsulating __gnu_debug::_Safe_iterator # and return the wrapped iterator value. def to_string(self): base_type = gdb.lookup_type('__gnu_debug::_Safe_iterator_base') - itype = self.val.type.template_argument(0) - safe_seq = self.val.cast(base_type)['_M_sequence'] + itype = self._val.type.template_argument(0) + safe_seq = self._val.cast(base_type)['_M_sequence'] if not safe_seq: - return str(self.val.cast(itype)) - if self.val['_M_version'] != safe_seq['_M_version']: + return str(self._val.cast(itype)) + if self._val['_M_version'] != safe_seq['_M_version']: return "invalid iterator" - return str(self.val.cast(itype)) + return str(self._val.cast(itype)) def num_elements(num): @@ -808,101 +816,101 @@ def num_elements(num): return '1 element' if num == 1 else '%d elements' % num -class StdMapPrinter: +class StdMapPrinter(printer_base): "Print a std::map or std::multimap" # Turn an RbtreeIterator into a pretty-print iterator. class _iter(Iterator): def __init__(self, rbiter, type): - self.rbiter = rbiter - self.count = 0 - self.type = type + self._rbiter = rbiter + self._count = 0 + self._type = type def __iter__(self): return self def __next__(self): - if self.count % 2 == 0: - n = next(self.rbiter) - n = n.cast(self.type).dereference() + if self._count % 2 == 0: + n = next(self._rbiter) + n = n.cast(self._type).dereference() n = get_value_from_Rb_tree_node(n) - self.pair = n + self._pair = n item = n['first'] else: - item = self.pair['second'] - result = ('[%d]' % self.count, item) - self.count = self.count + 1 + item = self._pair['second'] + result = ('[%d]' % self._count, item) + self._count = self._count + 1 return result def __init__(self, typename, val): - self.typename = strip_versioned_namespace(typename) - self.val = val + self._typename = strip_versioned_namespace(typename) + self._val = val def to_string(self): - return '%s with %s' % (self.typename, - num_elements(len(RbtreeIterator(self.val)))) + return '%s with %s' % (self._typename, + num_elements(len(RbtreeIterator(self._val)))) def children(self): - node = lookup_node_type('_Rb_tree_node', self.val.type).pointer() - return self._iter(RbtreeIterator(self.val), node) + node = lookup_node_type('_Rb_tree_node', self._val.type).pointer() + return self._iter(RbtreeIterator(self._val), node) def display_hint(self): return 'map' -class StdSetPrinter: +class StdSetPrinter(printer_base): "Print a std::set or std::multiset" # Turn an RbtreeIterator into a pretty-print iterator. class _iter(Iterator): def __init__(self, rbiter, type): - self.rbiter = rbiter - self.count = 0 - self.type = type + self._rbiter = rbiter + self._count = 0 + self._type = type def __iter__(self): return self def __next__(self): - item = next(self.rbiter) - item = item.cast(self.type).dereference() + item = next(self._rbiter) + item = item.cast(self._type).dereference() item = get_value_from_Rb_tree_node(item) # FIXME: this is weird ... what to do? # Maybe a 'set' display hint? - result = ('[%d]' % self.count, item) - self.count = self.count + 1 + result = ('[%d]' % self._count, item) + self._count = self._count + 1 return result def __init__(self, typename, val): - self.typename = strip_versioned_namespace(typename) - self.val = val + self._typename = strip_versioned_namespace(typename) + self._val = val def to_string(self): - return '%s with %s' % (self.typename, - num_elements(len(RbtreeIterator(self.val)))) + return '%s with %s' % (self._typename, + num_elements(len(RbtreeIterator(self._val)))) def children(self): - node = lookup_node_type('_Rb_tree_node', self.val.type).pointer() - return self._iter(RbtreeIterator(self.val), node) + node = lookup_node_type('_Rb_tree_node', self._val.type).pointer() + return self._iter(RbtreeIterator(self._val), node) -class StdBitsetPrinter: +class StdBitsetPrinter(printer_base): "Print a std::bitset" def __init__(self, typename, val): - self.typename = strip_versioned_namespace(typename) - self.val = val + self._typename = strip_versioned_namespace(typename) + self._val = val def to_string(self): # If template_argument handled values, we could print the # size. Or we could use a regexp on the type. - return '%s' % (self.typename) + return '%s' % (self._typename) def children(self): try: # An empty bitset may not have any members which will # result in an exception being thrown. - words = self.val['_M_w'] + words = self._val['_M_w'] except: return [] @@ -933,102 +941,102 @@ class StdBitsetPrinter: return result -class StdDequePrinter: +class StdDequePrinter(printer_base): "Print a std::deque" class _iter(Iterator): def __init__(self, node, start, end, last, buffer_size): - self.node = node - self.p = start - self.end = end - self.last = last - self.buffer_size = buffer_size - self.count = 0 + self._node = node + self._p = start + self._end = end + self._last = last + self._buffer_size = buffer_size + self._count = 0 def __iter__(self): return self def __next__(self): - if self.p == self.last: + if self._p == self._last: raise StopIteration - result = ('[%d]' % self.count, self.p.dereference()) - self.count = self.count + 1 + result = ('[%d]' % self._count, self._p.dereference()) + self._count = self._count + 1 # Advance the 'cur' pointer. - self.p = self.p + 1 - if self.p == self.end: + self._p = self._p + 1 + if self._p == self._end: # If we got to the end of this bucket, move to the # next bucket. - self.node = self.node + 1 - self.p = self.node[0] - self.end = self.p + self.buffer_size + self._node = self._node + 1 + self._p = self._node[0] + self._end = self._p + self._buffer_size return result def __init__(self, typename, val): - self.typename = strip_versioned_namespace(typename) - self.val = val - self.elttype = val.type.template_argument(0) - size = self.elttype.sizeof + self._typename = strip_versioned_namespace(typename) + self._val = val + self._elttype = val.type.template_argument(0) + size = self._elttype.sizeof if size < 512: - self.buffer_size = int(512 / size) + self._buffer_size = int(512 / size) else: - self.buffer_size = 1 + self._buffer_size = 1 def to_string(self): - start = self.val['_M_impl']['_M_start'] - end = self.val['_M_impl']['_M_finish'] + start = self._val['_M_impl']['_M_start'] + end = self._val['_M_impl']['_M_finish'] delta_n = end['_M_node'] - start['_M_node'] - 1 delta_s = start['_M_last'] - start['_M_cur'] delta_e = end['_M_cur'] - end['_M_first'] - size = self.buffer_size * delta_n + delta_s + delta_e + size = self._buffer_size * delta_n + delta_s + delta_e - return '%s with %s' % (self.typename, num_elements(long(size))) + return '%s with %s' % (self._typename, num_elements(long(size))) def children(self): - start = self.val['_M_impl']['_M_start'] - end = self.val['_M_impl']['_M_finish'] + start = self._val['_M_impl']['_M_start'] + end = self._val['_M_impl']['_M_finish'] return self._iter(start['_M_node'], start['_M_cur'], start['_M_last'], - end['_M_cur'], self.buffer_size) + end['_M_cur'], self._buffer_size) def display_hint(self): return 'array' -class StdDequeIteratorPrinter: +class StdDequeIteratorPrinter(printer_base): "Print std::deque::iterator" def __init__(self, typename, val): - self.val = val + self._val = val def to_string(self): - if not self.val['_M_cur']: + if not self._val['_M_cur']: return 'non-dereferenceable iterator for std::deque' - return str(self.val['_M_cur'].dereference()) + return str(self._val['_M_cur'].dereference()) -class StdStringPrinter: +class StdStringPrinter(printer_base): "Print a std::basic_string of some kind" def __init__(self, typename, val): - self.val = val - self.new_string = typename.find("::__cxx11::basic_string") != -1 + self._val = val + self._new_string = typename.find("::__cxx11::basic_string") != -1 def to_string(self): # Make sure &string works, too. - type = self.val.type + type = self._val.type if type.code == gdb.TYPE_CODE_REF: type = type.target() # Calculate the length of the string so that to_string returns # the string according to length, not according to first null # encountered. - ptr = self.val['_M_dataplus']['_M_p'] - if self.new_string: - length = self.val['_M_string_length'] + ptr = self._val['_M_dataplus']['_M_p'] + if self._new_string: + length = self._val['_M_string_length'] # https://sourceware.org/bugzilla/show_bug.cgi?id=17728 ptr = ptr.cast(ptr.type.strip_typedefs()) else: @@ -1052,173 +1060,173 @@ def access_streambuf_ptrs(streambuf): return pbase, pptr, egptr -class StdStringBufPrinter: +class StdStringBufPrinter(printer_base): "Print a std::basic_stringbuf" def __init__(self, _, val): - self.val = val + self._val = val def to_string(self): - (pbase, pptr, egptr) = access_streambuf_ptrs(self.val) + (pbase, pptr, egptr) = access_streambuf_ptrs(self._val) # Logic from basic_stringbuf::_M_high_mark() if pptr: if not egptr or pptr > egptr: return pbase.string(length=pptr - pbase) else: return pbase.string(length=egptr - pbase) - return self.val['_M_string'] + return self._val['_M_string'] def display_hint(self): return 'string' -class StdStringStreamPrinter: +class StdStringStreamPrinter(printer_base): "Print a std::basic_stringstream" def __init__(self, typename, val): - self.val = val - self.typename = typename + self._val = val + self._typename = typename # Check if the stream was redirected: # This is essentially: val['_M_streambuf'] == val['_M_stringbuf'].address # However, GDB can't resolve the virtual inheritance, so we do that manually basetype = [f.type for f in val.type.fields() if f.is_base_class][0] gdb.set_convenience_variable('__stream', val.cast(basetype).address) - self.streambuf = gdb.parse_and_eval('$__stream->rdbuf()') - self.was_redirected = self.streambuf != val['_M_stringbuf'].address + self._streambuf = gdb.parse_and_eval('$__stream->rdbuf()') + self._was_redirected = self._streambuf != val['_M_stringbuf'].address def to_string(self): - if self.was_redirected: - return "%s redirected to %s" % (self.typename, self.streambuf.dereference()) - return self.val['_M_stringbuf'] + if self._was_redirected: + return "%s redirected to %s" % (self._typename, self._streambuf.dereference()) + return self._val['_M_stringbuf'] def display_hint(self): - if self.was_redirected: + if self._was_redirected: return None return 'string' class Tr1HashtableIterator(Iterator): def __init__(self, hashtable): - self.buckets = hashtable['_M_buckets'] - self.bucket = 0 - self.bucket_count = hashtable['_M_bucket_count'] - self.node_type = find_type(hashtable.type, '_Node').pointer() - self.node = 0 - while self.bucket != self.bucket_count: - self.node = self.buckets[self.bucket] - if self.node: + self._buckets = hashtable['_M_buckets'] + self._bucket = 0 + self._bucket_count = hashtable['_M_bucket_count'] + self._node_type = find_type(hashtable.type, '_Node').pointer() + self._node = 0 + while self._bucket != self._bucket_count: + self._node = self._buckets[self._bucket] + if self._node: break - self.bucket = self.bucket + 1 + self._bucket = self._bucket + 1 def __iter__(self): return self def __next__(self): - if self.node == 0: + if self._node == 0: raise StopIteration - node = self.node.cast(self.node_type) + node = self._node.cast(self._node_type) result = node.dereference()['_M_v'] - self.node = node.dereference()['_M_next'] - if self.node == 0: - self.bucket = self.bucket + 1 - while self.bucket != self.bucket_count: - self.node = self.buckets[self.bucket] - if self.node: + self._node = node.dereference()['_M_next'] + if self._node == 0: + self._bucket = self._bucket + 1 + while self._bucket != self._bucket_count: + self._node = self._buckets[self._bucket] + if self._node: break - self.bucket = self.bucket + 1 + self._bucket = self._bucket + 1 return result class StdHashtableIterator(Iterator): def __init__(self, hashtable): - self.node = hashtable['_M_before_begin']['_M_nxt'] + self._node = hashtable['_M_before_begin']['_M_nxt'] valtype = hashtable.type.template_argument(1) cached = hashtable.type.template_argument(9).template_argument(0) node_type = lookup_templ_spec('std::__detail::_Hash_node', str(valtype), 'true' if cached else 'false') - self.node_type = node_type.pointer() + self._node_type = node_type.pointer() def __iter__(self): return self def __next__(self): - if self.node == 0: + if self._node == 0: raise StopIteration - elt = self.node.cast(self.node_type).dereference() - self.node = elt['_M_nxt'] + elt = self._node.cast(self._node_type).dereference() + self._node = elt['_M_nxt'] valptr = elt['_M_storage'].address valptr = valptr.cast(elt.type.template_argument(0).pointer()) return valptr.dereference() -class Tr1UnorderedSetPrinter: +class Tr1UnorderedSetPrinter(printer_base): "Print a std::unordered_set or tr1::unordered_set" def __init__(self, typename, val): - self.typename = strip_versioned_namespace(typename) - self.val = val + self._typename = strip_versioned_namespace(typename) + self._val = val - def hashtable(self): - if self.typename.startswith('std::tr1'): - return self.val - return self.val['_M_h'] + def _hashtable(self): + if self._typename.startswith('std::tr1'): + return self._val + return self._val['_M_h'] def to_string(self): - count = self.hashtable()['_M_element_count'] - return '%s with %s' % (self.typename, num_elements(count)) + count = self._hashtable()['_M_element_count'] + return '%s with %s' % (self._typename, num_elements(count)) @staticmethod - def format_count(i): + def _format_count(i): return '[%d]' % i def children(self): - counter = imap(self.format_count, itertools.count()) - if self.typename.startswith('std::tr1'): - return izip(counter, Tr1HashtableIterator(self.hashtable())) - return izip(counter, StdHashtableIterator(self.hashtable())) + counter = imap(self._format_count, itertools.count()) + if self._typename.startswith('std::tr1'): + return izip(counter, Tr1HashtableIterator(self._hashtable())) + return izip(counter, StdHashtableIterator(self._hashtable())) -class Tr1UnorderedMapPrinter: +class Tr1UnorderedMapPrinter(printer_base): "Print a std::unordered_map or tr1::unordered_map" def __init__(self, typename, val): - self.typename = strip_versioned_namespace(typename) - self.val = val + self._typename = strip_versioned_namespace(typename) + self._val = val - def hashtable(self): - if self.typename.startswith('std::tr1'): - return self.val - return self.val['_M_h'] + def _hashtable(self): + if self._typename.startswith('std::tr1'): + return self._val + return self._val['_M_h'] def to_string(self): - count = self.hashtable()['_M_element_count'] - return '%s with %s' % (self.typename, num_elements(count)) + count = self._hashtable()['_M_element_count'] + return '%s with %s' % (self._typename, num_elements(count)) @staticmethod - def flatten(list): + def _flatten(list): for elt in list: for i in elt: yield i @staticmethod - def format_one(elt): + def _format_one(elt): return (elt['first'], elt['second']) @staticmethod - def format_count(i): + def _format_count(i): return '[%d]' % i def children(self): - counter = imap(self.format_count, itertools.count()) + counter = imap(self._format_count, itertools.count()) # Map over the hash table and flatten the result. - if self.typename.startswith('std::tr1'): - data = self.flatten( - imap(self.format_one, Tr1HashtableIterator(self.hashtable()))) + if self._typename.startswith('std::tr1'): + data = self._flatten( + imap(self._format_one, Tr1HashtableIterator(self._hashtable()))) # Zip the two iterators together. return izip(counter, data) - data = self.flatten( - imap(self.format_one, StdHashtableIterator(self.hashtable()))) + data = self._flatten( + imap(self._format_one, StdHashtableIterator(self._hashtable()))) # Zip the two iterators together. return izip(counter, data) @@ -1226,50 +1234,50 @@ class Tr1UnorderedMapPrinter: return 'map' -class StdForwardListPrinter: +class StdForwardListPrinter(printer_base): "Print a std::forward_list" class _iterator(Iterator): def __init__(self, nodetype, head): - self.nodetype = nodetype - self.base = head['_M_next'] - self.count = 0 + self._nodetype = nodetype + self._base = head['_M_next'] + self._count = 0 def __iter__(self): return self def __next__(self): - if self.base == 0: + if self._base == 0: raise StopIteration - elt = self.base.cast(self.nodetype).dereference() - self.base = elt['_M_next'] - count = self.count - self.count = self.count + 1 + elt = self._base.cast(self._nodetype).dereference() + self._base = elt['_M_next'] + count = self._count + self._count = self._count + 1 valptr = elt['_M_storage'].address valptr = valptr.cast(elt.type.template_argument(0).pointer()) return ('[%d]' % count, valptr.dereference()) def __init__(self, typename, val): - self.val = val - self.typename = strip_versioned_namespace(typename) + self._val = val + self._typename = strip_versioned_namespace(typename) def children(self): - nodetype = lookup_node_type('_Fwd_list_node', self.val.type).pointer() - return self._iterator(nodetype, self.val['_M_impl']['_M_head']) + nodetype = lookup_node_type('_Fwd_list_node', self._val.type).pointer() + return self._iterator(nodetype, self._val['_M_impl']['_M_head']) def to_string(self): - if self.val['_M_impl']['_M_head']['_M_next'] == 0: - return 'empty %s' % self.typename - return '%s' % self.typename + if self._val['_M_impl']['_M_head']['_M_next'] == 0: + return 'empty %s' % self._typename + return '%s' % self._typename -class SingleObjContainerPrinter(object): +class SingleObjContainerPrinter(printer_base): "Base class for printers of containers of single objects" def __init__(self, val, viz, hint=None): - self.contained_value = val - self.visualizer = viz - self.hint = hint + self._contained_value = val + self._visualizer = viz + self._hint = hint def _recognize(self, type): """Return TYPE as a string after applying type printers""" @@ -1281,30 +1289,30 @@ class SingleObjContainerPrinter(object): class _contained(Iterator): def __init__(self, val): - self.val = val + self._val = val def __iter__(self): return self def __next__(self): - if self.val is None: + if self._val is None: raise StopIteration - retval = self.val - self.val = None + retval = self._val + self._val = None return ('[contained value]', retval) def children(self): - if self.contained_value is None: + if self._contained_value is None: return self._contained(None) - if hasattr(self.visualizer, 'children'): - return self.visualizer.children() - return self._contained(self.contained_value) + if hasattr(self._visualizer, 'children'): + return self._visualizer.children() + return self._contained(self._contained_value) def display_hint(self): # if contained value is a map we want to display in the same way - if hasattr(self.visualizer, 'children') and hasattr(self.visualizer, 'display_hint'): - return self.visualizer.display_hint() - return self.hint + if hasattr(self._visualizer, 'children') and hasattr(self._visualizer, 'display_hint'): + return self._visualizer.display_hint() + return self._hint def function_pointer_to_name(f): @@ -1335,24 +1343,24 @@ class StdExpAnyPrinter(SingleObjContainerPrinter): "Print a std::any or std::experimental::any" def __init__(self, typename, val): - self.typename = strip_versioned_namespace(typename) - self.typename = re.sub( - '^std::experimental::fundamentals_v\d::', 'std::experimental::', self.typename, 1) - self.val = val - self.contained_type = None + self._typename = strip_versioned_namespace(typename) + self._typename = re.sub( + '^std::experimental::fundamentals_v\d::', 'std::experimental::', self._typename, 1) + self._val = val + self._contained_type = None contained_value = None visualizer = None - mgr = self.val['_M_manager'] + mgr = self._val['_M_manager'] if mgr != 0: func = function_pointer_to_name(mgr) if not func: - raise ValueError( - "Invalid function pointer in %s" % (self.typename)) + raise ValueError("Invalid function pointer in %s" % + (self._typename)) rx = r"""({0}::_Manager_\w+<.*>)::_S_manage\((enum )?{0}::_Op, (const {0}|{0} const) ?\*, (union )?{0}::_Arg ?\*\)""".format(typename) m = re.match(rx, func) if not m: raise ValueError( - "Unknown manager function in %s" % self.typename) + "Unknown manager function in %s" % self._typename) mgrname = m.group(1) # FIXME need to expand 'std::string' so that gdb.lookup_type works @@ -1388,27 +1396,27 @@ class StdExpAnyPrinter(SingleObjContainerPrinter): mgrtype = mgrtypes[0] else: mgrtype = gdb.lookup_type(mgrname) - self.contained_type = mgrtype.template_argument(0) + self._contained_type = mgrtype.template_argument(0) valptr = None if '::_Manager_internal' in mgrname: - valptr = self.val['_M_storage']['_M_buffer'].address + valptr = self._val['_M_storage']['_M_buffer'].address elif '::_Manager_external' in mgrname: - valptr = self.val['_M_storage']['_M_ptr'] + valptr = self._val['_M_storage']['_M_ptr'] else: raise ValueError( - "Unknown manager function in %s" % self.typename) + "Unknown manager function in %s" % self._typename) contained_value = valptr.cast( - self.contained_type.pointer()).dereference() + self._contained_type.pointer()).dereference() visualizer = gdb.default_visualizer(contained_value) super(StdExpAnyPrinter, self).__init__(contained_value, visualizer) def to_string(self): - if self.contained_type is None: - return '%s [no contained value]' % self.typename - desc = "%s containing " % self.typename - if hasattr(self.visualizer, 'children'): - return desc + self.visualizer.to_string() - valtype = self._recognize(self.contained_type) + if self._contained_type is None: + return '%s [no contained value]' % self._typename + desc = "%s containing " % self._typename + if hasattr(self._visualizer, 'children'): + return desc + self._visualizer.to_string() + valtype = self._recognize(self._contained_type) return desc + strip_versioned_namespace(str(valtype)) @@ -1418,10 +1426,10 @@ class StdExpOptionalPrinter(SingleObjContainerPrinter): def __init__(self, typename, val): valtype = self._recognize(val.type.template_argument(0)) typename = strip_versioned_namespace(typename) - self.typename = re.sub( + self._typename = re.sub( '^std::(experimental::|)(fundamentals_v\d::|)(.*)', r'std::\1\3', typename, 1) payload = val['_M_payload'] - if self.typename.startswith('std::experimental'): + if self._typename.startswith('std::experimental'): engaged = val['_M_engaged'] contained_value = payload else: @@ -1439,12 +1447,12 @@ class StdExpOptionalPrinter(SingleObjContainerPrinter): contained_value, visualizer) def to_string(self): - if self.contained_value is None: - return "%s [no contained value]" % self.typename - if hasattr(self.visualizer, 'children'): - return "%s containing %s" % (self.typename, - self.visualizer.to_string()) - return self.typename + if self._contained_value is None: + return "%s [no contained value]" % self._typename + if hasattr(self._visualizer, 'children'): + return "%s containing %s" % (self._typename, + self._visualizer.to_string()) + return self._typename class StdVariantPrinter(SingleObjContainerPrinter): @@ -1452,83 +1460,83 @@ class StdVariantPrinter(SingleObjContainerPrinter): def __init__(self, typename, val): alternatives = get_template_arg_list(val.type) - self.typename = strip_versioned_namespace(typename) - self.index = val['_M_index'] - if self.index >= len(alternatives): - self.contained_type = None + self._typename = strip_versioned_namespace(typename) + self._index = val['_M_index'] + if self._index >= len(alternatives): + self._contained_type = None contained_value = None visualizer = None else: - self.contained_type = alternatives[int(self.index)] + self._contained_type = alternatives[int(self._index)] addr = val['_M_u']['_M_first']['_M_storage'].address contained_value = addr.cast( - self.contained_type.pointer()).dereference() + self._contained_type.pointer()).dereference() visualizer = gdb.default_visualizer(contained_value) super(StdVariantPrinter, self).__init__( contained_value, visualizer, 'array') def to_string(self): - if self.contained_value is None: - return "%s [no contained value]" % self.typename - if hasattr(self.visualizer, 'children'): - return "%s [index %d] containing %s" % (self.typename, self.index, - self.visualizer.to_string()) - return "%s [index %d]" % (self.typename, self.index) + if self._contained_value is None: + return "%s [no contained value]" % self._typename + if hasattr(self._visualizer, 'children'): + return "%s [index %d] containing %s" % (self._typename, self._index, + self._visualizer.to_string()) + return "%s [index %d]" % (self._typename, self._index) class StdNodeHandlePrinter(SingleObjContainerPrinter): "Print a container node handle" def __init__(self, typename, val): - self.value_type = val.type.template_argument(1) + self._value_type = val.type.template_argument(1) nodetype = val.type.template_argument(2).template_argument(0) - self.is_rb_tree_node = is_specialization_of( + self._is_rb_tree_node = is_specialization_of( nodetype.name, '_Rb_tree_node') - self.is_map_node = val.type.template_argument(0) != self.value_type + self._is_map_node = val.type.template_argument(0) != self._value_type nodeptr = val['_M_ptr'] if nodeptr: - if self.is_rb_tree_node: + if self._is_rb_tree_node: contained_value = get_value_from_Rb_tree_node( nodeptr.dereference()) else: contained_value = get_value_from_aligned_membuf(nodeptr['_M_storage'], - self.value_type) + self._value_type) visualizer = gdb.default_visualizer(contained_value) else: contained_value = None visualizer = None optalloc = val['_M_alloc'] - self.alloc = optalloc['_M_payload'] if optalloc['_M_engaged'] else None + self._alloc = optalloc['_M_payload'] if optalloc['_M_engaged'] else None super(StdNodeHandlePrinter, self).__init__(contained_value, visualizer, 'array') def to_string(self): desc = 'node handle for ' - if not self.is_rb_tree_node: + if not self._is_rb_tree_node: desc += 'unordered ' - if self.is_map_node: + if self._is_map_node: desc += 'map' else: desc += 'set' - if self.contained_value: + if self._contained_value: desc += ' with element' - if hasattr(self.visualizer, 'children'): - return "%s = %s" % (desc, self.visualizer.to_string()) + if hasattr(self._visualizer, 'children'): + return "%s = %s" % (desc, self._visualizer.to_string()) return desc else: return 'empty %s' % desc -class StdExpStringViewPrinter: +class StdExpStringViewPrinter(printer_base): "Print a std::basic_string_view or std::experimental::basic_string_view" def __init__(self, typename, val): - self.val = val + self._val = val def to_string(self): - ptr = self.val['_M_str'] - len = self.val['_M_len'] + ptr = self._val['_M_str'] + len = self._val['_M_len'] if hasattr(ptr, "lazy_string"): return ptr.lazy_string(length=len) return ptr.string(length=len) @@ -1537,18 +1545,18 @@ class StdExpStringViewPrinter: return 'string' -class StdExpPathPrinter: +class StdExpPathPrinter(printer_base): "Print a std::experimental::filesystem::path" def __init__(self, typename, val): - self.val = val - self.typename = typename - start = self.val['_M_cmpts']['_M_impl']['_M_start'] - finish = self.val['_M_cmpts']['_M_impl']['_M_finish'] - self.num_cmpts = int(finish - start) + self._val = val + self._typename = typename + start = self._val['_M_cmpts']['_M_impl']['_M_start'] + finish = self._val['_M_cmpts']['_M_impl']['_M_finish'] + self._num_cmpts = int(finish - start) def _path_type(self): - t = str(self.val['_M_type']) + t = str(self._val['_M_type']) if t[-9:] == '_Root_dir': return "root-directory" if t[-10:] == '_Root_name': @@ -1556,8 +1564,8 @@ class StdExpPathPrinter: return None def to_string(self): - path = "%s" % self.val['_M_pathname'] - if self.num_cmpts == 0: + path = "%s" % self._val['_M_pathname'] + if self._num_cmpts == 0: t = self._path_type() if t: path = '%s [%s]' % (path, t) @@ -1565,46 +1573,46 @@ class StdExpPathPrinter: class _iterator(Iterator): def __init__(self, cmpts, pathtype): - self.pathtype = pathtype - self.item = cmpts['_M_impl']['_M_start'] - self.finish = cmpts['_M_impl']['_M_finish'] - self.count = 0 + self._pathtype = pathtype + self._item = cmpts['_M_impl']['_M_start'] + self._finish = cmpts['_M_impl']['_M_finish'] + self._count = 0 def __iter__(self): return self def __next__(self): - if self.item == self.finish: + if self._item == self._finish: raise StopIteration - item = self.item.dereference() - count = self.count - self.count = self.count + 1 - self.item = self.item + 1 + item = self._item.dereference() + count = self._count + self._count = self._count + 1 + self._item = self._item + 1 path = item['_M_pathname'] - t = StdExpPathPrinter(self.pathtype, item)._path_type() + t = StdExpPathPrinter(self._pathtype, item)._path_type() if not t: t = count return ('[%s]' % t, path) def children(self): - return self._iterator(self.val['_M_cmpts'], self.typename) + return self._iterator(self._val['_M_cmpts'], self._typename) -class StdPathPrinter: +class StdPathPrinter(printer_base): "Print a std::filesystem::path" def __init__(self, typename, val): - self.val = val - self.typename = typename - impl = unique_ptr_get(self.val['_M_cmpts']['_M_impl']) - self.type = impl.cast(gdb.lookup_type('uintptr_t')) & 3 - if self.type == 0: - self.impl = impl + self._val = val + self._typename = typename + impl = unique_ptr_get(self._val['_M_cmpts']['_M_impl']) + self._type = impl.cast(gdb.lookup_type('uintptr_t')) & 3 + if self._type == 0: + self._impl = impl else: - self.impl = None + self._impl = None def _path_type(self): - t = str(self.type.cast(gdb.lookup_type(self.typename + '::_Type'))) + t = str(self._type.cast(gdb.lookup_type(self._typename + '::_Type'))) if t[-9:] == '_Root_dir': return "root-directory" if t[-10:] == '_Root_name': @@ -1612,8 +1620,8 @@ class StdPathPrinter: return None def to_string(self): - path = "%s" % self.val['_M_pathname'] - if self.type != 0: + path = "%s" % self._val['_M_pathname'] + if self._type != 0: t = self._path_type() if t: path = '%s [%s]' % (path, t) @@ -1621,7 +1629,7 @@ class StdPathPrinter: class _iterator(Iterator): def __init__(self, impl, pathtype): - self.pathtype = pathtype + self._pathtype = pathtype if impl: # We can't access _Impl::_M_size because _Impl is incomplete # so cast to int* to access the _M_size member at offset zero, @@ -1630,96 +1638,96 @@ class StdPathPrinter: char_type = gdb.lookup_type('char') impl = impl.cast(int_type.pointer()) size = impl.dereference() - #self.capacity = (impl + 1).dereference() + #self._capacity = (impl + 1).dereference() if hasattr(gdb.Type, 'alignof'): sizeof_Impl = max(2 * int_type.sizeof, cmpt_type.alignof) else: sizeof_Impl = 2 * int_type.sizeof begin = impl.cast(char_type.pointer()) + sizeof_Impl - self.item = begin.cast(cmpt_type.pointer()) - self.finish = self.item + size - self.count = 0 + self._item = begin.cast(cmpt_type.pointer()) + self._finish = self._item + size + self._count = 0 else: - self.item = None - self.finish = None + self._item = None + self._finish = None def __iter__(self): return self def __next__(self): - if self.item == self.finish: + if self._item == self._finish: raise StopIteration - item = self.item.dereference() - count = self.count - self.count = self.count + 1 - self.item = self.item + 1 + item = self._item.dereference() + count = self._count + self._count = self._count + 1 + self._item = self._item + 1 path = item['_M_pathname'] - t = StdPathPrinter(self.pathtype, item)._path_type() + t = StdPathPrinter(self._pathtype, item)._path_type() if not t: t = count return ('[%s]' % t, path) def children(self): - return self._iterator(self.impl, self.typename) + return self._iterator(self._impl, self._typename) -class StdPairPrinter: +class StdPairPrinter(printer_base): "Print a std::pair object, with 'first' and 'second' as children" def __init__(self, typename, val): - self.val = val + self._val = val class _iter(Iterator): "An iterator for std::pair types. Returns 'first' then 'second'." def __init__(self, val): - self.val = val - self.which = 'first' + self._val = val + self._which = 'first' def __iter__(self): return self def __next__(self): - if self.which is None: + if self._which is None: raise StopIteration - which = self.which + which = self._which if which == 'first': - self.which = 'second' + self._which = 'second' else: - self.which = None - return (which, self.val[which]) + self._which = None + return (which, self._val[which]) def children(self): - return self._iter(self.val) + return self._iter(self._val) def to_string(self): return None -class StdCmpCatPrinter: +class StdCmpCatPrinter(printer_base): "Print a comparison category object" def __init__(self, typename, val): - self.typename = typename[typename.rfind(':')+1:] - self.val = val['_M_value'] + self._typename = typename[typename.rfind(':')+1:] + self._val = val['_M_value'] def to_string(self): - if self.typename == 'strong_ordering' and self.val == 0: + if self._typename == 'strong_ordering' and self._val == 0: name = 'equal' else: names = {2: 'unordered', -1: 'less', 0: 'equivalent', 1: 'greater'} - name = names[int(self.val)] - return 'std::{}::{}'.format(self.typename, name) + name = names[int(self._val)] + return 'std::{}::{}'.format(self._typename, name) -class StdErrorCodePrinter: +class StdErrorCodePrinter(printer_base): "Print a std::error_code or std::error_condition" _system_is_posix = None # Whether std::system_category() use errno values. def __init__(self, typename, val): - self.val = val - self.typename = strip_versioned_namespace(typename) + self._val = val + self._typename = strip_versioned_namespace(typename) # Do this only once ... if StdErrorCodePrinter._system_is_posix is None: try: @@ -1807,14 +1815,14 @@ class StdErrorCodePrinter: return name.split('::')[-1] def to_string(self): - value = self.val['_M_value'] - cat = self.val['_M_cat'] + value = self._val['_M_value'] + cat = self._val['_M_cat'] name, alt_name, enum, is_errno = self._category_info(cat) if value == 0: default_cats = {'error_code': 'system', 'error_condition': 'generic'} - if name == default_cats[self._unqualified_name(self.typename)]: - return self.typename + ' = { }' # default-constructed value + if name == default_cats[self._unqualified_name(self._typename)]: + return self._typename + ' = { }' # default-constructed value strval = str(value) if is_errno and value != 0: @@ -1829,21 +1837,21 @@ class StdErrorCodePrinter: name = '"%s"' % name else: name = alt_name - return '%s = {%s: %s}' % (self.typename, name, strval) + return '%s = {%s: %s}' % (self._typename, name, strval) -class StdRegexStatePrinter: +class StdRegexStatePrinter(printer_base): "Print a state node in the NFA for a std::regex" def __init__(self, typename, val): - self.val = val - self.typename = typename + self._val = val + self._typename = typename def to_string(self): - opcode = str(self.val['_M_opcode']) + opcode = str(self._val['_M_opcode']) if opcode: opcode = opcode[25:] - next_id = self.val['_M_next'] + next_id = self._val['_M_next'] variants = {'repeat': 'alt', 'alternative': 'alt', 'subexpr_begin': 'subexpr', 'subexpr_end': 'subexpr', @@ -1856,113 +1864,113 @@ class StdRegexStatePrinter: v = variants[opcode] s = "opcode={}, next={}".format(opcode, next_id) - if v is not None and self.val['_M_' + v] is not None: - s = "{}, {}={}".format(s, v, self.val['_M_' + v]) + if v is not None and self._val['_M_' + v] is not None: + s = "{}, {}={}".format(s, v, self._val['_M_' + v]) return "{%s}" % (s) -class StdSpanPrinter: +class StdSpanPrinter(printer_base): "Print a std::span" - class iterator(Iterator): + class _iterator(Iterator): def __init__(self, begin, size): - self.count = 0 - self.begin = begin - self.size = size + self._count = 0 + self._begin = begin + self._size = size def __iter__(self): return self def __next__(self): - if self.count == self.size: + if self._count == self._size: raise StopIteration - count = self.count - self.count = self.count + 1 - return '[%d]' % count, (self.begin + count).dereference() + count = self._count + self._count = self._count + 1 + return '[%d]' % count, (self._begin + count).dereference() def __init__(self, typename, val): - self.typename = strip_versioned_namespace(typename) - self.val = val + self._typename = strip_versioned_namespace(typename) + self._val = val if val.type.template_argument(1) == gdb.parse_and_eval('static_cast(-1)'): - self.size = val['_M_extent']['_M_extent_value'] + self._size = val['_M_extent']['_M_extent_value'] else: - self.size = val.type.template_argument(1) + self._size = val.type.template_argument(1) def to_string(self): - return '%s of length %d' % (self.typename, self.size) + return '%s of length %d' % (self._typename, self._size) def children(self): - return self.iterator(self.val['_M_ptr'], self.size) + return self._iterator(self._val['_M_ptr'], self._size) def display_hint(self): return 'array' -class StdInitializerListPrinter: +class StdInitializerListPrinter(printer_base): "Print a std::initializer_list" def __init__(self, typename, val): - self.typename = typename - self.val = val - self.size = val['_M_len'] + self._typename = typename + self._val = val + self._size = val['_M_len'] def to_string(self): - return '%s of length %d' % (self.typename, self.size) + return '%s of length %d' % (self._typename, self._size) def children(self): - return StdSpanPrinter.iterator(self.val['_M_array'], self.size) + return StdSpanPrinter._iterator(self._val['_M_array'], self._size) def display_hint(self): return 'array' -class StdAtomicPrinter: +class StdAtomicPrinter(printer_base): "Print a std:atomic" def __init__(self, typename, val): - self.typename = strip_versioned_namespace(typename) - self.val = val - self.shptr_printer = None - self.value_type = self.val.type.template_argument(0) - if self.value_type.tag is not None: - typ = strip_versioned_namespace(self.value_type.tag) + self._typename = strip_versioned_namespace(typename) + self._val = val + self._shptr_printer = None + self._value_type = self._val.type.template_argument(0) + if self._value_type.tag is not None: + typ = strip_versioned_namespace(self._value_type.tag) if typ.startswith('std::shared_ptr<') or typ.startswith('std::weak_ptr<'): impl = val['_M_impl'] - self.shptr_printer = SharedPointerPrinter(typename, impl) + self._shptr_printer = SharedPointerPrinter(typename, impl) self.children = self._shptr_children def _shptr_children(self): - return SmartPtrIterator(self.shptr_printer.pointer) + return SmartPtrIterator(self._shptr_printer._pointer) def to_string(self): - if self.shptr_printer is not None: - return self.shptr_printer.to_string() - - if self.value_type.code == gdb.TYPE_CODE_INT: - val = self.val['_M_i'] - elif self.value_type.code == gdb.TYPE_CODE_FLT: - val = self.val['_M_fp'] - elif self.value_type.code == gdb.TYPE_CODE_PTR: - val = self.val['_M_b']['_M_p'] - elif self.value_type.code == gdb.TYPE_CODE_BOOL: - val = self.val['_M_base']['_M_i'] + if self._shptr_printer is not None: + return self._shptr_printer.to_string() + + if self._value_type.code == gdb.TYPE_CODE_INT: + val = self._val['_M_i'] + elif self._value_type.code == gdb.TYPE_CODE_FLT: + val = self._val['_M_fp'] + elif self._value_type.code == gdb.TYPE_CODE_PTR: + val = self._val['_M_b']['_M_p'] + elif self._value_type.code == gdb.TYPE_CODE_BOOL: + val = self._val['_M_base']['_M_i'] else: - val = self.val['_M_i'] - return '%s<%s> = { %s }' % (self.typename, str(self.value_type), val) + val = self._val['_M_i'] + return '%s<%s> = { %s }' % (self._typename, str(self._value_type), val) -class StdFormatArgsPrinter: +class StdFormatArgsPrinter(printer_base): "Print a std::basic_format_args" # TODO: add printer for basic_format_arg and print out children. # TODO: add printer for __format::_ArgStore. def __init__(self, typename, val): - self.typename = strip_versioned_namespace(typename) - self.val = val + self._typename = strip_versioned_namespace(typename) + self._val = val def to_string(self): - targs = get_template_arg_list(self.val.type) + targs = get_template_arg_list(self._val.type) char_type = get_template_arg_list(targs[0])[1] if char_type == gdb.lookup_type('char'): typ = 'std::format_args' @@ -1971,32 +1979,32 @@ class StdFormatArgsPrinter: else: typ = 'std::basic_format_args' - size = self.val['_M_packed_size'] + size = self._val['_M_packed_size'] if size == 1: return "%s with 1 argument" % (typ) if size == 0: - size = self.val['_M_unpacked_size'] + size = self._val['_M_unpacked_size'] return "%s with %d arguments" % (typ, size) def std_ratio_t_tuple(ratio_type): # TODO use reduced period i.e. duration::period - period = self.val.type.template_argument(1) + period = self._val.type.template_argument(1) num = period.template_argument(0) den = period.template_argument(1) return (num, den) -class StdChronoDurationPrinter: +class StdChronoDurationPrinter(printer_base): "Print a std::chrono::duration" def __init__(self, typename, val): - self.typename = strip_versioned_namespace(typename) - self.val = val + self._typename = strip_versioned_namespace(typename) + self._val = val def _ratio(self): # TODO use reduced period i.e. duration::period - period = self.val.type.template_argument(1) + period = self._val.type.template_argument(1) num = period.template_argument(0) den = period.template_argument(1) return (num, den) @@ -2023,21 +2031,21 @@ class StdChronoDurationPrinter: return "[{}/{}]s".format(num, den) def to_string(self): - r = self.val['__r'] + r = self._val['__r'] if r.type.strip_typedefs().code == gdb.TYPE_CODE_FLT: r = "%g" % r return "std::chrono::duration = {{ {}{} }}".format(r, self._suffix()) -class StdChronoTimePointPrinter: +class StdChronoTimePointPrinter(printer_base): "Print a std::chrono::time_point" def __init__(self, typename, val): - self.typename = strip_versioned_namespace(typename) - self.val = val + self._typename = strip_versioned_namespace(typename) + self._val = val def _clock(self): - clock = self.val.type.template_argument(0) + clock = self._val.type.template_argument(0) name = strip_versioned_namespace(clock.name) if name == 'std::chrono::_V2::system_clock' \ or name == 'std::chrono::system_clock': @@ -2057,7 +2065,7 @@ class StdChronoTimePointPrinter: def to_string(self, abbrev=False): clock, offset = self._clock() - d = self.val['__d'] + d = self._val['__d'] r = d['__r'] printer = StdChronoDurationPrinter(d.type.name, d) suffix = printer._suffix() @@ -2076,16 +2084,16 @@ class StdChronoTimePointPrinter: return '%s = { %s }' % (clock, s) -class StdChronoZonedTimePrinter: +class StdChronoZonedTimePrinter(printer_base): "Print a std::chrono::zoned_time" def __init__(self, typename, val): - self.typename = strip_versioned_namespace(typename) - self.val = val + self._typename = strip_versioned_namespace(typename) + self._val = val def to_string(self): - zone = self.val['_M_zone'].dereference()['_M_name'] - time = self.val['_M_tp'] + zone = self._val['_M_zone'].dereference()['_M_name'] + time = self._val['_M_tp'] printer = StdChronoTimePointPrinter(time.type.name, time) time = printer.to_string(True) return 'std::chrono::zoned_time = {{ {} {} }}'.format(zone, time) @@ -2098,16 +2106,16 @@ weekdays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'] -class StdChronoCalendarPrinter: +class StdChronoCalendarPrinter(printer_base): "Print a std::chrono::day, std::chrono::month, std::chrono::year etc." def __init__(self, typename, val): - self.typename = strip_versioned_namespace(typename) - self.val = val + self._typename = strip_versioned_namespace(typename) + self._val = val def to_string(self): - val = self.val - typ = self.typename + val = self._val + typ = self._typename if 'month' in typ and typ != 'std::chrono::year_month_day_last': m = val['_M_m'] if typ.startswith('std::chrono::year'): @@ -2161,53 +2169,53 @@ class StdChronoCalendarPrinter: return '{:02}:{:02}:{:02}{}'.format(h, m, s, fract) -class StdChronoTimeZonePrinter: +class StdChronoTimeZonePrinter(printer_base): "Print a chrono::time_zone or chrono::time_zone_link" def __init__(self, typename, val): - self.typename = strip_versioned_namespace(typename) - self.val = val + self._typename = strip_versioned_namespace(typename) + self._val = val def to_string(self): - str = '%s = %s' % (self.typename, self.val['_M_name']) - if self.typename.endswith("_link"): - str += ' -> %s' % (self.val['_M_target']) + str = '%s = %s' % (self._typename, self._val['_M_name']) + if self._typename.endswith("_link"): + str += ' -> %s' % (self._val['_M_target']) return str -class StdChronoLeapSecondPrinter: +class StdChronoLeapSecondPrinter(printer_base): "Print a chrono::leap_second" def __init__(self, typename, val): - self.typename = strip_versioned_namespace(typename) - self.val = val + self._typename = strip_versioned_namespace(typename) + self._val = val def to_string(self): - date = self.val['_M_s']['__r'] + date = self._val['_M_s']['__r'] neg = '+-'[date < 0] - return '%s %d (%c)' % (self.typename, abs(date), neg) + return '%s %d (%c)' % (self._typename, abs(date), neg) -class StdChronoTzdbPrinter: +class StdChronoTzdbPrinter(printer_base): "Print a chrono::tzdb" def __init__(self, typename, val): - self.typename = strip_versioned_namespace(typename) - self.val = val + self._typename = strip_versioned_namespace(typename) + self._val = val def to_string(self): - return '%s %s' % (self.typename, self.val['version']) + return '%s %s' % (self._typename, self._val['version']) -class StdChronoTimeZoneRulePrinter: +class StdChronoTimeZoneRulePrinter(printer_base): "Print a chrono::time_zone rule" def __init__(self, typename, val): - self.typename = strip_versioned_namespace(typename) - self.val = val + self._typename = strip_versioned_namespace(typename) + self._val = val def to_string(self): - on = self.val['on'] + on = self._val['on'] kind = on['kind'] month = months[on['month']] suffixes = {1: 'st', 2: 'nd', 3: 'rd', @@ -2230,24 +2238,24 @@ class StdChronoTimeZoneRulePrinter: direction[1], month, ordinal_day) return 'time_zone rule {} from {} to {} starting on {}'.format( - self.val['name'], self.val['from'], self.val['to'], start) + self._val['name'], self._val['from'], self._val['to'], start) -class StdLocalePrinter: +class StdLocalePrinter(printer_base): "Print a std::locale" def __init__(self, typename, val): - self.val = val - self.typename = typename + self._val = val + self._typename = typename def to_string(self): - names = self.val['_M_impl']['_M_names'] + names = self._val['_M_impl']['_M_names'] mod = '' if names[0] == 0: name = '*' else: - cats = gdb.parse_and_eval(self.typename + '::_S_categories') - ncat = gdb.parse_and_eval(self.typename + '::_S_categories_size') + cats = gdb.parse_and_eval(self._typename + '::_S_categories') + ncat = gdb.parse_and_eval(self._typename + '::_S_categories_size') n = names[0].string() cat = cats[0].string() name = '{}={}'.format(cat, n) @@ -2284,7 +2292,7 @@ class RxPrinter(object): def __init__(self, name, function): super(RxPrinter, self).__init__() self.name = name - self.function = function + self._function = function self.enabled = True def invoke(self, value): @@ -2295,7 +2303,7 @@ class RxPrinter(object): if hasattr(gdb.Value, "referenced_value"): value = value.referenced_value() - return self.function(self.name, value) + return self._function(self.name, value) # A pretty-printer that conforms to the "PrettyPrinter" protocol from # gdb.printing. It can also be used directly as an old-style printer. @@ -2305,20 +2313,20 @@ class Printer(object): def __init__(self, name): super(Printer, self).__init__() self.name = name - self.subprinters = [] - self.lookup = {} + self._subprinters = [] + self._lookup = {} self.enabled = True - self.compiled_rx = re.compile('^([a-zA-Z0-9_:]+)(<.*>)?$') + self._compiled_rx = re.compile('^([a-zA-Z0-9_:]+)(<.*>)?$') def add(self, name, function): # A small sanity check. # FIXME - if not self.compiled_rx.match(name): + if not self._compiled_rx.match(name): raise ValueError( 'libstdc++ programming error: "%s" does not match' % name) printer = RxPrinter(name, function) - self.subprinters.append(printer) - self.lookup[name] = printer + self._subprinters.append(printer) + self._lookup[name] = printer # Add a name using _GLIBCXX_BEGIN_NAMESPACE_VERSION. def add_version(self, base, name, function): @@ -2351,7 +2359,7 @@ class Printer(object): # All the types we match are template types, so we can use a # dictionary. - match = self.compiled_rx.match(typename) + match = self._compiled_rx.match(typename) if not match: return None @@ -2361,8 +2369,8 @@ class Printer(object): if hasattr(gdb.Value, "referenced_value"): val = val.referenced_value() - if basename in self.lookup: - return self.lookup[basename].invoke(val) + if basename in self._lookup: + return self._lookup[basename].invoke(val) # Cannot find a pretty printer. Return None. return None @@ -2384,7 +2392,7 @@ class TemplateTypePrinter(object): def __init__(self, name, defargs): self.name = name - self.defargs = defargs + self._defargs = defargs self.enabled = True class _recognizer(object): @@ -2392,8 +2400,8 @@ class TemplateTypePrinter(object): def __init__(self, name, defargs): self.name = name - self.defargs = defargs - # self.type_obj = None + self._defargs = defargs + # self._type_obj = None def recognize(self, type_obj): """ @@ -2416,7 +2424,7 @@ class TemplateTypePrinter(object): # The actual template argument in the type: targ = template_args[n] # The default template argument for the class template: - defarg = self.defargs.get(n) + defarg = self._defargs.get(n) if defarg is not None: # Substitute other template arguments into the default: defarg = defarg.format(*template_args) @@ -2469,7 +2477,7 @@ class TemplateTypePrinter(object): def instantiate(self): "Return a recognizer object for this type printer." - return self._recognizer(self.name, self.defargs) + return self._recognizer(self.name, self._defargs) def add_one_template_type_printer(obj, name, defargs): @@ -2533,58 +2541,59 @@ class FilteringTypePrinter(object): """ def __init__(self, template, name, targ1=None): - self.template = template + self._template = template self.name = name - self.targ1 = targ1 + self._targ1 = targ1 self.enabled = True class _recognizer(object): "The recognizer class for FilteringTypePrinter." def __init__(self, template, name, targ1): - self.template = template + self._template = template self.name = name - self.targ1 = targ1 - self.type_obj = None + self._targ1 = targ1 + self._type_obj = None def recognize(self, type_obj): """ - If type_obj starts with self.template and is the same type as + If type_obj starts with self._template and is the same type as self.name then return self.name, otherwise None. """ if type_obj.tag is None: return None - if self.type_obj is None: - if self.targ1 is not None: - if not type_obj.tag.startswith('{}<{}'.format(self.template, self.targ1)): + if self._type_obj is None: + if self._targ1 is not None: + if not type_obj.tag.startswith('{}<{}'.format(self._template, self._targ1)): # Filter didn't match. return None - elif not type_obj.tag.startswith(self.template): + elif not type_obj.tag.startswith(self._template): # Filter didn't match. return None try: - self.type_obj = gdb.lookup_type(self.name).strip_typedefs() + self._type_obj = gdb.lookup_type( + self.name).strip_typedefs() except: pass - if self.type_obj is None: + if self._type_obj is None: return None - if gdb.types.get_basic_type(self.type_obj) == gdb.types.get_basic_type(type_obj): + if gdb.types.get_basic_type(self._type_obj) == gdb.types.get_basic_type(type_obj): return strip_inline_namespaces(self.name) # Workaround ambiguous typedefs matching both std:: and std::__cxx11:: symbols. - if self.template.split('::')[-1] == 'basic_string': - if self.type_obj.tag.replace('__cxx11::', '') == type_obj.tag.replace('__cxx11::', ''): + if self._template.split('::')[-1] == 'basic_string': + if self._type_obj.tag.replace('__cxx11::', '') == type_obj.tag.replace('__cxx11::', ''): return strip_inline_namespaces(self.name) return None def instantiate(self): "Return a recognizer object for this type printer." - return self._recognizer(self.template, self.name, self.targ1) + return self._recognizer(self._template, self.name, self._targ1) def add_one_type_printer(obj, template, name, targ1=None):