From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from NAM10-DM6-obe.outbound.protection.outlook.com (mail-dm6nam10on2073.outbound.protection.outlook.com [40.107.93.73]) by sourceware.org (Postfix) with ESMTPS id C8EC83858033 for ; Mon, 17 Jan 2022 12:44:54 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org C8EC83858033 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=Yu2u2r3tmTjhjvV/wGfRD27yYDdhoBN7oBURn2nYLDMNh3L2KP/AZicyjZZ1g3bmi6tuGVi4DQyQwa5/KsHSPUTeKz1A5AmOPoY//znXvUygFaOdjVBCtUnvrxg7CXzbsac7aMTbTjCDhsJinVWG3laKmqfkV1mHrrrqQRXOSyr5F7/3AFbkUzezOt76sUvbTL+vGkLR1J+BKo4AwNGN2SIMXv/wH+7YbvTg/UwLmJPMnGBoJy66swI54bIhJg2KmiaN7XCHVDBeKAj/V52FYSa/g7WnODRlaEK95SuF6mDtQbgG3THlv3dk6JAw0FEirCducQQsCK4Yd84dJIHInQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=RjFjy0xGVqhJhO/vewSkxV6F5HkgAfFhBrPN/zhW/EM=; b=nuFLqTIidpCUySC4IrBipVwMt5CeB5QhwDFNpkFvescquhMsOOQWW490FYZOiiCHBQ+jPFTG9k/R+WrID89Jo4S9QrIaO93mta0wbNeW5tnaF9YBkztsEJqG/hW6iujeGhZOyVR8Ax/IwT9SiUx5RvwFjp1I1sInzeoaqj1fT5CstTH1IJGqZnaYf3mrGQDdJ2D6H5bNFKM5WroO7DRimw4Z7XVIOT8Zm0cIpdMWcIg1XtViDdFJGQPXUWzNhTIzX0SPPdfUMPelyeRuQGbOSry/YH4qrSkMk266jxpNhOc60HWtWK4eq79v08eV3B2KXKVgAN0zPlrfaYwUeyyusw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=labware.com; dmarc=pass action=none header.from=labware.com; dkim=pass header.d=labware.com; arc=none Received: from DM6PR17MB3113.namprd17.prod.outlook.com (2603:10b6:5:6::10) by DM5PR17MB1484.namprd17.prod.outlook.com (2603:10b6:3:145::13) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4888.12; Mon, 17 Jan 2022 12:44:53 +0000 Received: from DM6PR17MB3113.namprd17.prod.outlook.com ([fe80::7839:31f:2416:6ba5]) by DM6PR17MB3113.namprd17.prod.outlook.com ([fe80::7839:31f:2416:6ba5%7]) with mapi id 15.20.4888.014; Mon, 17 Jan 2022 12:44:53 +0000 From: Jan Vrany To: gdb-patches@sourceware.org Cc: Jan Vrany Subject: [PATCH 3/5] gdb/python: allow redefinition of python GDB/MI commands Date: Mon, 17 Jan 2022 12:44:23 +0000 Message-Id: <20220117124425.2658516-4-jan.vrany@labware.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220117124425.2658516-1-jan.vrany@labware.com> References: <20220117124425.2658516-1-jan.vrany@labware.com> Content-Transfer-Encoding: 8bit Content-Type: text/plain X-ClientProxiedBy: LO4P123CA0334.GBRP123.PROD.OUTLOOK.COM (2603:10a6:600:18c::15) To DM6PR17MB3113.namprd17.prod.outlook.com (2603:10b6:5:6::10) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: c3d53890-c857-4b44-7e24-08d9d9b72895 X-MS-TrafficTypeDiagnostic: DM5PR17MB1484:EE_ X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:3276; X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: KXl+aFl4v4bhhmLT9FSJT4puEgfWpc4vSAQfvWdDo9dMxo+lEsUZJYAAf6EoeLDajOxCEWjng/aewQzMPQq/UbRlMzb5s7b1E9Iptfqev2U0w2eNplhYUkRZrFwWdgf3FPgtpErJPcaXLU/ILdk/gTJi66ebnueO2c74x6ENzSh1IQg7HiOIVnNbxsOkVoNC1WoVmaoVZyYq0SyVJGDwl0uiXeLU5wy1F8mU3aQwQR9AnI/kAu1SoIkD5pLLoFgiBneHTEeDZKXolfX0yA7nOmBzt+lxwcJtbRNASGrxmDjDx2/MDGup3/itdtv8xEhsNorjts/ZIUj6cm5N3hNLXiTZi2gF/w1bDCZqEgT6DAR/XiSKvwFNK0Aav77qqLai5pdYNiSLjz8s/KQzt3Im+oNpw9BUeb50w1ZEhokgevPmgbVWTVxP0wvXWAz2Akv0zigkiGjDdoaVPTFFOfSPwp7IgGgf14TB4VhQl7j4V422hv8mCJE0+sm3An0zmI8ciymdCG6neFtkWc7ENzZtOBx5h5V1c2XBQNGu82M75vVi60K70ah4u9j39tW8b/lnV2g3p4wK4qRD60wAI/D8wB71uknJIsk5+A37myKrV39539wwtqIqG9hgGLQwTJqWjuYA7NP1rQ9dHEHaJb66kelKDNiIUgtWg+wQVepJ/PNDK0e6etPpboPKYGPFKQHWeJEk1+PW5eVXO9yM1ebd4QAUypjl3R3iB7iLRhs2IO0= X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:DM6PR17MB3113.namprd17.prod.outlook.com; PTR:; CAT:NONE; SFS:(4636009)(366004)(4326008)(26005)(6916009)(1076003)(2906002)(316002)(6506007)(30864003)(36756003)(66946007)(6666004)(66476007)(66556008)(38100700002)(5660300002)(38350700002)(508600001)(186003)(107886003)(52116002)(86362001)(83380400001)(44832011)(6512007)(6486002)(8676002)(8936002)(2616005)(2004002); DIR:OUT; SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?/XSrepp22a7bwQjiyuVW1ubGNXh2KnvZjw1nUty5feU2OBvjsETOYrlozc59?= =?us-ascii?Q?icL90YN8lGCOfz0TyvBZfZKC4mOi9jJR3mvOfn5WPhWImRLAFKeXR9YN3hZq?= =?us-ascii?Q?uq3VtpXrY8uLgi96qvgVhfTPNn0aSdbCtKrKhJaHWkEMRA9AEVhjSLXHRXzT?= =?us-ascii?Q?t7OM5R4JrSkdFcNAjDb0mejEFjLOLLAgVoM18iKYKDCjgnuhf+KfL96t9PTN?= =?us-ascii?Q?aKeKKBu6v9sIT+l9byRzWZN+AcH/6eB2XQtQ7d6Zg9qqxUyOOtEgfta2O9fx?= =?us-ascii?Q?0x1wAkm0OJSLvDdgucMbwQBwgouwTbd+DHgOHsTro3R2iGKS/py6Cf4HVpdJ?= =?us-ascii?Q?6yfqpc4EBoUL/rVADZuDjofZOriNe4n9sCsahXbQSlQOij0Z+3Wmiwz9Y8si?= =?us-ascii?Q?NVWssOt6U4iRrhrL9VejoAqj/jJabu8hfMHxLes43HRmYRn47Q6CD+juJytr?= =?us-ascii?Q?263zsdOkHANkSDevJgUeTRJyWJ+pMlBDXMv8f0d/Zd1bNblXfqGhAoUQ4jn9?= =?us-ascii?Q?W9q/yMIWYQ0TNXNjUqgOeJ4gW56Tfu98xta3V4kNKpXB9RgzTHWf6x7POdgA?= =?us-ascii?Q?/32pV5Fu5E4nFxrB7kAu4ZDeQG2/9OXxqNpyCdXmbPp75q3Pl6J4Mq/ppoj3?= =?us-ascii?Q?1KyXfnlqoJjUSj3fzA4oo4GIui5fnNj52hseoGUMFHUnRGAFZ0RCW3T3LMgO?= =?us-ascii?Q?jOnvy2m4kt+DJKKslaDyxcXur0BwL4YLNswpYZAqAz692Ans3vGZP7uzMYgB?= =?us-ascii?Q?dOIOd5tq1KPXvo/pbNpjtyR+Wq+VwlEiiA+ryGQ93wWUI6Eb2cxY+Uzvqwri?= =?us-ascii?Q?PAy396WH3iwxzxLZkWgrZVjw2P1QKErb3s1HeT5NJadUyE6ZHtyryF5ce9uD?= =?us-ascii?Q?PyGF2BCf9Y6n52zseLOCjTGhcAGuUFYdDMtuds8lEiDEmO9Rl+ZYKkBWRYfo?= =?us-ascii?Q?j2NWWtxf6UXS3F6NmTg3NhjS1bPDrByeWV0aqEdazNlwH6BYSCGOhSwPzSWn?= =?us-ascii?Q?LnhD2O67gxaP16XzuAn6PNhf8SDOpG6SrX8eMYilB1OvKhxJUyDm7SR7VVXV?= =?us-ascii?Q?6MKEGKMvqnvRdmrCjsvpzAR5PICscc+jSm4C/o45NWhBeWhBFCh892h7WL8J?= =?us-ascii?Q?3BPuPCz7YZc9HZ26QoDwsEfBnmVbyf+shdRM1TJ/vG3o9vZeI/7QMQIlVJ+v?= =?us-ascii?Q?SqkEph2BU8H0oz3EQZjC3ffq5crqBf2rx3HfSl+KTc7zaEWOW67WKaxok2Ng?= =?us-ascii?Q?B/KwLa1umID0YaObcFyQSAamwPDnuoLj2izXAHYMmt7jCVYDH5ATSS4QuvDe?= =?us-ascii?Q?gNOcwi9q8b0j9u/1uxqk7E86LguJ4rJeaZcGfbtwha3FRwyKfzkl60cLZyxd?= =?us-ascii?Q?hXeDANqQnFFR/a0GLMS8UBVuI6JegW9ANg355dp5WBYySWDIyDpz882cjq6j?= =?us-ascii?Q?Vb1ahYXK0WkAUIZfb5zrT59QI/P8NUrXIClE55Vl1ZgYc+ljAy3RbPOr6a50?= =?us-ascii?Q?cwKmYhjGC3Q6bkNHyf4EzDaYZe6kgi99YSpEI7n0tLAn26hwOjki39hkKTW7?= =?us-ascii?Q?k2pplobShMqhIR9Bs0D59ttLCYqeGniIn/CpAWurjT5SXf+BCqsyjLfp/EGP?= =?us-ascii?Q?7Ba6mColg0bJ/8HgAPNVQkQ=3D?= X-OriginatorOrg: labware.com X-MS-Exchange-CrossTenant-Network-Message-Id: c3d53890-c857-4b44-7e24-08d9d9b72895 X-MS-Exchange-CrossTenant-AuthSource: DM6PR17MB3113.namprd17.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 17 Jan 2022 12:44:53.4326 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: b5db0322-1aa0-4c0a-859c-ad0f96966f4c X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: iuvk0T2s6AnHNJlxMlaI2z98gjT+O1l8FPAjlpeE9oSCliHkfOP+QrkiFTqpjpY4g7O3eJoJknymZWGT2r+1DQ== X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM5PR17MB1484 X-Spam-Status: No, score=-12.4 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_PASS, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 17 Jan 2022 12:44:57 -0000 Redefining python MI commands is especially useful when developing them. --- gdb/mi/mi-cmds.c | 10 +- gdb/mi/mi-cmds.h | 4 + gdb/python/py-micmd.c | 236 ++++++++++++++++++++++-------------------- gdb/python/py-micmd.h | 41 ++++---- gdb/python/python.c | 2 +- 5 files changed, 160 insertions(+), 133 deletions(-) diff --git a/gdb/mi/mi-cmds.c b/gdb/mi/mi-cmds.c index c82bc4810df..c2ec733ce06 100644 --- a/gdb/mi/mi-cmds.c +++ b/gdb/mi/mi-cmds.c @@ -141,7 +141,8 @@ insert_mi_cmd_entry (mi_command_up command) const std::string &name = command->name (); - if (mi_cmd_table.find (name) != mi_cmd_table.end ()) + auto existing = mi_cmd_table.find (name); + if (existing != mi_cmd_table.end () && !existing->second->can_be_redefined ()) return false; mi_cmd_table[name] = std::move (command); @@ -180,6 +181,13 @@ add_mi_cmd_cli (const char *name, const char *cli_name, int args_p, /* See mi-cmds.h. */ + +bool +mi_command::can_be_redefined () +{ + return false; +} + void mi_command::invoke (struct mi_parse *parse) const { diff --git a/gdb/mi/mi-cmds.h b/gdb/mi/mi-cmds.h index 75c5927e3cb..7d7aa52d4ae 100644 --- a/gdb/mi/mi-cmds.h +++ b/gdb/mi/mi-cmds.h @@ -23,6 +23,7 @@ #define MI_MI_CMDS_H #include +#include #include "gdbsupport/gdb_optional.h" enum print_values { @@ -163,6 +164,9 @@ struct mi_command wrong. */ void invoke (struct mi_parse *parse) const; + /* Return TRUE if the command can be redefined, FALSE otherwise. */ + virtual bool can_be_redefined (); + protected: /* The core of command invocation, this needs to be overridden in each diff --git a/gdb/python/py-micmd.c b/gdb/python/py-micmd.c index b94b748b25c..59bf534b5b9 100644 --- a/gdb/python/py-micmd.c +++ b/gdb/python/py-micmd.c @@ -1,6 +1,6 @@ /* MI Command Set for GDB, the GNU debugger. - Copyright (C) 2019 Free Software Foundation, Inc. + Copyright (C) 2019-2021 Free Software Foundation, Inc. This file is part of GDB. @@ -28,34 +28,40 @@ #include +/* Reference to Python string "invoke". Used by this module when obtaining + invoke() method of Python MI command. */ + static PyObject *invoke_cst; extern PyTypeObject micmdpy_object_type CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("micmdpy_object"); -/* If the command invoked returns a list, this function parses it and create an - appropriate MI out output. +/* Output Python OBJECT to MI channel as a "result" [+] named FIELD_NAME. Various + kinds of Python objects are supported: + + - Python 'dict' is emitted as a MI tuple. Only string keys are supported. + - Python sequence or iterator is emitted as MI list. + - Any other Python object converted to string using Python's str() and emitted + as MI string. - The returned values must be Python string, and can be contained within Python - lists and dictionaries. It is possible to have a multiple levels of lists - and/or dictionaries. */ + [+] "result" refers to GDB/MI output syntax rule "result". */ static void -parse_mi_result (PyObject *result, const char *field_name) +emit_py_result (PyObject *object, const char *field_name) { struct ui_out *uiout = current_uiout; - if (PyDict_Check (result)) + if (PyDict_Check (object)) { PyObject *key, *value; Py_ssize_t pos = 0; ui_out_emit_tuple tuple_emitter (uiout, field_name); - while (PyDict_Next (result, &pos, &key, &value)) - { - if (!PyString_Check (key)) - { - gdbpy_ref<> key_repr (PyObject_Repr (key)); - if (PyErr_Occurred () != NULL) + while (PyDict_Next (object, &pos, &key, &value)) + { + if (!PyString_Check (key)) + { + gdbpy_ref<> key_repr (PyObject_Repr (key)); + if (PyErr_Occurred () != NULL) { gdbpy_err_fetch ex; gdb::unique_xmalloc_ptr ex_msg (ex.to_string ()); @@ -67,42 +73,42 @@ parse_mi_result (PyObject *result, const char *field_name) ex_msg.get ()); } else - { - auto key_repr_string - = python_string_to_target_string (key_repr.get ()); - error (_("Non-string object used as key: %s."), + { + auto key_repr_string + = python_string_to_target_string (key_repr.get ()); + error (_("Non-string object used as key: %s."), key_repr_string.get ()); - } - } + } + } - auto key_string = python_string_to_target_string (key); - parse_mi_result (value, key_string.get ()); - } + auto key_string = python_string_to_target_string (key); + emit_py_result (value, key_string.get ()); + } } - else if (PySequence_Check (result) && !PyString_Check (result)) + else if (PySequence_Check (object) && !PyString_Check (object)) { ui_out_emit_list list_emitter (uiout, field_name); - for (Py_ssize_t i = 0; i < PySequence_Size (result); ++i) - { - gdbpy_ref<> item (PySequence_ITEM (result, i)); - parse_mi_result (item.get (), NULL); - } + for (Py_ssize_t i = 0; i < PySequence_Size (object); ++i) + { + gdbpy_ref<> item (PySequence_ITEM (object, i)); + emit_py_result (item.get (), NULL); + } } - else if (PyIter_Check (result)) + else if (PyIter_Check (object)) { gdbpy_ref<> item; ui_out_emit_list list_emitter (uiout, field_name); - while (item.reset (PyIter_Next (result)), item != nullptr) - parse_mi_result (item.get (), NULL); + while (item.reset (PyIter_Next (object)), item != nullptr) + emit_py_result (item.get (), NULL); } else { - gdb::unique_xmalloc_ptr string (gdbpy_obj_to_string (result)); + gdb::unique_xmalloc_ptr string (gdbpy_obj_to_string (object)); uiout->field_string (field_name, string.get ()); } } -/* Object initializer; sets up gdb-side structures for MI command. +/* Object initializer; sets up gdb-side structures for an MI command. Use: __init__(NAME). @@ -118,45 +124,34 @@ micmdpy_init (PyObject *self, PyObject *args, PyObject *kw) if (!PyArg_ParseTuple (args, "s", &name)) return -1; - /* Validate command name */ + /* Validate command name. */ const int name_len = strlen (name); if (name_len == 0) + error (_("MI command name is empty.")); + + if (name_len == 1 || name[0] != '-' || !isalnum (name[1])) + error (_("MI command name does not start with '-'" + " followed by at least one letter or digit.")); + + for (int i = 2; i < name_len; i++) { - error (_("MI command name is empty.")); - return -1; - } - else if ((name_len < 2) || (name[0] != '-') || !isalnum (name[1])) - { - error (_("MI command name does not start with '-'" - " followed by at least one letter or digit.")); - return -1; + if (!isalnum (name[i]) && name[i] != '-') + error (_("MI command name contains invalid character: %c."), name[i]); } - else - for (int i = 2; i < name_len; i++) - { - if (!isalnum (name[i]) && name[i] != '-') - { - error (_("MI command name contains invalid character: %c."), - name[i]); - return -1; - } - } if (!PyObject_HasAttr (self_ref.get (), invoke_cst)) - error (_("-%s: Python command object missing 'invoke' method."), name); + error (_("-%s: Python command object missing 'invoke' method."), name); try { - mi_command_up micommand = mi_command_up(new mi_command_py (name + 1, self_ref)); + mi_command_up micommand + = mi_command_up(new mi_command_py (name + 1, self_ref)); bool result = insert_mi_cmd_entry (std::move (micommand)); if (!result) - { - error (_("Unable to insert command." - "The name might already be in use.")); - return -1; - } + error (_("Unable to insert command. " + "The name might already be in use.")); } catch (const gdb_exception &except) { @@ -168,12 +163,18 @@ micmdpy_init (PyObject *self, PyObject *args, PyObject *kw) mi_command_py::mi_command_py (const char *name, gdbpy_ref<> object) : mi_command (NULL), - pyobj (object) + m_pyobj (object) { gdb_assert (name != nullptr && name[0] != '\0' && name[0] != '-'); m_name = name; } +bool +mi_command_py::can_be_redefined() +{ + return true; +} + void mi_command_py::do_invoke (struct mi_parse *parse) const { @@ -182,7 +183,12 @@ mi_command_py::do_invoke (struct mi_parse *parse) const if (parse->argv == NULL) error (_("Problem parsing arguments: %s %s"), parse->command, parse->args); - PyObject *obj = this->pyobj.get (); + /* Must save a copy of the name because the Python code may + replace the very same command that is currently executing. + See further below. */ + std::string name = this->name (); + + PyObject *obj = this->m_pyobj.get (); gdbpy_enter enter_py (get_current_arch (), current_language); @@ -190,29 +196,33 @@ mi_command_py::do_invoke (struct mi_parse *parse) const if (!PyObject_HasAttr (obj, invoke_cst)) error (_("-%s: Python command object missing 'invoke' method."), - name ()); - + name.c_str ()); gdbpy_ref<> argobj (PyList_New (parse->argc)); if (argobj == nullptr) { gdbpy_print_stack (); error (_("-%s: failed to create the Python arguments list."), - name ()); + name.c_str ()); } for (int i = 0; i < parse->argc; ++i) { gdbpy_ref<> str (PyUnicode_Decode (parse->argv[i], strlen (parse->argv[i]), - host_charset (), NULL)); + host_charset (), NULL)); if (PyList_SetItem (argobj.get (), i, str.release ()) != 0) - { - error (_("-%s: failed to create the Python arguments list."), - name ()); - } + { + error (_("-%s: failed to create the Python arguments list."), + name.c_str ()); + } } gdb_assert (PyErr_Occurred () == NULL); + + /* From this point on, THIS must not be used since Python code may replace + the very same command that is currently executing. This in turn leads + to destruction of THIS making it invalid. See insert_mi_cmd_entry. */ + gdbpy_ref<> result ( PyObject_CallMethodObjArgs (obj, invoke_cst, argobj.get (), NULL)); if (PyErr_Occurred () != NULL) @@ -221,20 +231,21 @@ mi_command_py::do_invoke (struct mi_parse *parse) const gdb::unique_xmalloc_ptr ex_msg (ex.to_string ()); if (ex_msg == NULL || *ex_msg == '\0') - error (_("-%s: failed to execute command"), name ()); + error (_("-%s: failed to execute command"), name.c_str ()); else - error (_("-%s: %s"), name (), ex_msg.get ()); + error (_("-%s: %s"), name.c_str (), ex_msg.get ()); } else { if (Py_None != result) - parse_mi_result (result.get (), "result"); + emit_py_result (result.get (), "result"); } } -void mi_command_py::finalize () +void +mi_command_py::finalize () { - this->pyobj.reset (nullptr); + this->m_pyobj.reset (nullptr); } /* Initialize the MI command object. */ @@ -247,7 +258,7 @@ gdbpy_initialize_micommands () return -1; if (gdb_pymodule_addobject (gdb_module, "MICommand", - (PyObject *) &micmdpy_object_type) + (PyObject *) &micmdpy_object_type) < 0) return -1; @@ -261,40 +272,41 @@ gdbpy_initialize_micommands () static PyMethodDef micmdpy_object_methods[] = {{0}}; PyTypeObject micmdpy_object_type = { - PyVarObject_HEAD_INIT (NULL, 0) "gdb.MICommand", /*tp_name */ - sizeof (micmdpy_object), /*tp_basicsize */ - 0, /*tp_itemsize */ - 0, /*tp_dealloc */ - 0, /*tp_print */ - 0, /*tp_getattr */ - 0, /*tp_setattr */ - 0, /*tp_compare */ - 0, /*tp_repr */ - 0, /*tp_as_number */ - 0, /*tp_as_sequence */ - 0, /*tp_as_mapping */ - 0, /*tp_hash */ - 0, /*tp_call */ - 0, /*tp_str */ - 0, /*tp_getattro */ - 0, /*tp_setattro */ - 0, /*tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags */ - "GDB mi-command object", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - micmdpy_object_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - micmdpy_init, /* tp_init */ - 0, /* tp_alloc */ + PyVarObject_HEAD_INIT (NULL, 0) + "gdb.MICommand", /*tp_name */ + sizeof (micmdpy_object), /*tp_basicsize */ + 0, /*tp_itemsize */ + 0, /*tp_dealloc */ + 0, /*tp_print */ + 0, /*tp_getattr */ + 0, /*tp_setattr */ + 0, /*tp_compare */ + 0, /*tp_repr */ + 0, /*tp_as_number */ + 0, /*tp_as_sequence */ + 0, /*tp_as_mapping */ + 0, /*tp_hash */ + 0, /*tp_call */ + 0, /*tp_str */ + 0, /*tp_getattro */ + 0, /*tp_setattro */ + 0, /*tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags */ + "GDB mi-command object", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + micmdpy_object_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + micmdpy_init, /* tp_init */ + 0, /* tp_alloc */ }; diff --git a/gdb/python/py-micmd.h b/gdb/python/py-micmd.h index b6b25351ac7..1c675a7c1fb 100644 --- a/gdb/python/py-micmd.h +++ b/gdb/python/py-micmd.h @@ -1,6 +1,6 @@ /* MI Command Set for GDB, the GNU debugger. - Copyright (C) 2019 Free Software Foundation, Inc. + Copyright (C) 2019-2021 Free Software Foundation, Inc. This file is part of GDB. @@ -30,34 +30,37 @@ struct micmdpy_object PyObject_HEAD }; -typedef struct micmdpy_object micmdpy_object; - /* MI command implemented in Python. */ class mi_command_py : public mi_command { - public: - /* Constructs a new mi_command_py object. NAME is command name without - leading dash. OBJECT is a reference to a Python object implementing - the command. This object should inherit from gdb.MICommand and should - implement method invoke (args). */ - mi_command_py (const char *name, gdbpy_ref<> object); +public: + /* Constructs a new mi_command_py object. NAME is command name without + leading dash. OBJECT is a reference to a Python object implementing + the command. This object should inherit from gdb.MICommand and should + implement method invoke (args). */ + mi_command_py (const char *name, gdbpy_ref<> object); + bool can_be_redefined () override; - /* This is called just before shutting down a Python interpreter - to release python object implementing the command. */ - void finalize (); + /* This is called just before shutting down the Python interpreter + to release python object implementing the command. */ + void finalize (); - virtual const char *name () const override - { return m_name.c_str(); } + virtual const char *name () const override + { + return m_name.c_str(); + } - protected: - virtual void do_invoke(struct mi_parse *parse) const override; +protected: + virtual void do_invoke(struct mi_parse *parse) const override; - private: - std::string m_name; +private: + /* The name of the command. */ + std::string m_name; - gdbpy_ref<> pyobj; + /* Reference to Python object implementing the command. */ + gdbpy_ref<> m_pyobj; }; #endif diff --git a/gdb/python/python.c b/gdb/python/python.c index 6e2ed32bf90..f8af27704cd 100644 --- a/gdb/python/python.c +++ b/gdb/python/python.c @@ -1701,7 +1701,7 @@ finalize_python (void *ignore) python_gdbarch = target_gdbarch (); python_language = current_language; - for (const auto& name_and_cmd : mi_cmd_table) + for (const auto &name_and_cmd : mi_cmd_table) { mi_command *cmd = name_and_cmd.second.get (); mi_command_py *cmd_py = dynamic_cast (cmd); -- 2.30.2