From patchwork Fri Oct 6 15:11:05 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Vrany X-Patchwork-Id: 77218 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 6B1D23856DDA for ; Fri, 6 Oct 2023 15:11:52 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 6B1D23856DDA DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1696605112; bh=jzQK59A7L8A5AmU4CsIf6RQ8EX7GflC6W6hykt32P4E=; h=To:CC:Subject:Date:In-Reply-To:References:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From:Reply-To:From; b=rGNpg1WU8m0znqfeCe6w5c+5QAAhcz2w9gMEEigmt+ZQf9r1XILnzJfok7Aid2CHE VhOAV60uQ4SHK4k7f7VrGnIgWietL59C8F2dKpVOIgd6Fjyp/k7k0jNKvF9oeGhA0J MPy0rLELJvFOGxmbPJG+rEDzvKgYcNwqejUgmE9M= X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from us-smtp-delivery-114.mimecast.com (us-smtp-delivery-114.mimecast.com [170.10.129.114]) by sourceware.org (Postfix) with ESMTPS id 5509B3856DC2 for ; Fri, 6 Oct 2023 15:11:24 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 5509B3856DC2 Received: from NAM12-DM6-obe.outbound.protection.outlook.com (mail-dm6nam12lp2172.outbound.protection.outlook.com [104.47.59.172]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-509-EgAJX56tM4GjH87-oICowg-1; Fri, 06 Oct 2023 11:11:22 -0400 X-MC-Unique: EgAJX56tM4GjH87-oICowg-1 Received: from SA0PR17MB4314.namprd17.prod.outlook.com (2603:10b6:806:e7::16) by CO3PR17MB5775.namprd17.prod.outlook.com (2603:10b6:303:17b::7) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6813.19; Fri, 6 Oct 2023 15:11:19 +0000 Received: from SA0PR17MB4314.namprd17.prod.outlook.com ([fe80::30eb:4c4a:cb5a:dd91]) by SA0PR17MB4314.namprd17.prod.outlook.com ([fe80::30eb:4c4a:cb5a:dd91%4]) with mapi id 15.20.6838.029; Fri, 6 Oct 2023 15:11:19 +0000 To: gdb-patches@sourceware.org CC: Jan Vrany , Andrew Burgess Subject: [PATCH v3 1/2] gdb/python: generalize serialize_mi_result() Date: Fri, 6 Oct 2023 16:11:05 +0100 Message-ID: <20231006151106.315633-2-jan.vrany@labware.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20231006151106.315633-1-jan.vrany@labware.com> References: <87bkddtamc.fsf@redhat.com> <20231006151106.315633-1-jan.vrany@labware.com> X-ClientProxiedBy: LO4P123CA0347.GBRP123.PROD.OUTLOOK.COM (2603:10a6:600:18d::10) To SA0PR17MB4314.namprd17.prod.outlook.com (2603:10b6:806:e7::16) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: SA0PR17MB4314:EE_|CO3PR17MB5775:EE_ X-MS-Office365-Filtering-Correlation-Id: e748f2b7-bd09-4e2c-8cda-08dbc67e7ea2 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0 X-Microsoft-Antispam-Message-Info: EqNQxKuuZoaHUULVMwOXHOVfjqJ6TzT42/HuMwrOkOHd1UCGhrOGGW/DjRvOiE62j9hN8UUWLfygl9To/7c9qVhLrkjtltGMLhDPlZJXuxtCzf3HeZImPfhE7QAKaAkYa2E/MIe9UBTPkfOyG+wfrWTjj8UHLjGmOkKV86CpokVssWnD7VJ0r8qFcZ7t742IdmP2XI+RrMZmrtwOEfP4zSAAi9FRayux996lL9tG2lDNUf+mY4H9FnWvffilSBfTnObWD4Y95K4W2pmbbizAkLIayMkdwtnQBopvJFeb6vOaSh67ivbDMxQMxmb3BHZgcklih3p7/3Df+kRZAjRFyQzgaAIxSZGrqFpuvvmBdqtdyAbEVZST7EJGbF7FnsW3ce4IbdmPJL70QZyjKBJty7GL22wBYNIbug/cBADqliSSSDqeXgRWjFzwt324/1G59Lff9znmPYX0iweB2xez+qTD3g2yk9ZaRNCbyGcEI0Eg+pUtDfkZi2Y/KTyObPpxzBouAtQ+Oz61GMnelpT+TgZ0yGokrTvdMoYteWxz69eaEhzIDeZzcsAKkXIWmCJQ X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:SA0PR17MB4314.namprd17.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230031)(366004)(136003)(346002)(39850400004)(396003)(376002)(230922051799003)(64100799003)(451199024)(1800799009)(186009)(478600001)(6506007)(6512007)(6666004)(6486002)(2616005)(26005)(316002)(54906003)(30864003)(1076003)(8676002)(36756003)(4326008)(2906002)(6916009)(5660300002)(8936002)(44832011)(66556008)(66946007)(41300700001)(86362001)(66476007)(38100700002)(83380400001); DIR:OUT; SFP:1101 X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: OyjzuZnnmG2p4nJAUcpQKFPkMGt7pjaB4DrAtMiN40Tz+YFWWzKZ/FURl/Qd0PFOObch7xCeBgLdGA18OXz5jak0EOwU7KBPa9fA+YmKEhx1UlkjJcgeGn37ZbCx1fMn7eNo1xRNuAXSS9WNWUSm02aXOmxqFEzIGx6t69TG5j/v3svuyQWJu5HrQyR3iDSzT0pFEwLxh5WHU0SzxQ1CMzDeWX/hAKti0o07ODCUmJMb6lKIg0WbO0ycFc8VHmNb4stexZVYgwjL2QzkkpWvST1vfwv22LeH29OspwNj/EFfABK1jszyT7PS3mQ9h4m339VbGnPjpkU3Y4QywjmXzLKlKVgxL9JEiRzTHHJsp3W421Qw3TwraYk7gmVCKahXjU14E2V212KY47qso6uVL8/e85DVl4aQz+RI/Du4AXtPv6lg0eMSVMEB/SAElM2p17U6Ta92Q878Bog/gy9ffi7fkl4yFFl1pfvFclBit+6vWgKJUFSOFvFQG7S7KX7AwShaXsTi3GRXTMdwlmqb6CP9D0+2izamlWD2VdWiKmroEz85WmU4QV+C+OpcTyuO1wqke7xigTRtcIrfxdUypkpKo5J061AujyCH2nehTGpxnVufQWqJjmyoCdHBVoJ+r94ottEoVuaej3Xf3J+pN0LcbXirEoOIpXVwnzzIKhuB32QnnTad6tLaFDw8dQ02ZLfarHztmuzn2a4o4thb8dTE7skiF87BfTsh5yhVuxx3IUqI8TSMw5AvdkI+ggP+/1OmFU/KeRf+upBtmgsCL5eqIhQxtDk/n/D7ikUHa23lprAg30kYRSCPp5y69yRFHr711TOUfu4Ijm/aLLaB+R/bMbSIbkGLlVW/eGYqaaMME2nSh1vivlBmvfHsDX0t/zzfTB8KgtsdIrqe8Mi3JdKnGMIruoQwcEip4csG0fDTOiW9a3jFN/++ht0O1kBPLch9S4+PXfmjJqLsix7SzKL6QzwtqMHezx7QMZuI4C+3CbRbRmBUhtNCTG0j2+leQpALJeQSJcRMIjklON0pdKKp6GcZ+WZoVJifoyChA0QJ18t5RNm5mIIYfz4zT9+QmA7wOwQZ75xbhpd/ZuxABcu44lINRfdlOA3TWrQDm3p2sR5ApbokDXo/mVBVc66/dLsQloyrww3wwtQr45M+8xakO+P0noWrT5IsKBAMlBqknzgZbqnxDw6a8f6bxp5jdRSgBybJWVUACsGlt7l+BshDxe6cpKOuMZuv19LIa1gYvgYGVLP65+5MUSMv6M7Y6wNmS0IwRPurX5LGqRFVgkLh0NS1Ef5Un1yisU4fDOjyE4DzF/U9eQHtkrFavvapjeTVlPtG+mFW6j3mpZDUq6LMXIIC3GVZYEG4YG+D0if5xnCAOoHTpMqKk2OTUeLpC6ZmJkLRad8sTyj9BogjmRWn3Nh6bX/hNSjr0kgNFELRFHiSMYCVGb9RHrraEmihe6d+toCwvTgXVUcwCrqF23fPvrjL3nvST63ZoTgABc5y9LQ/OW5LohJTLlTVKneHFowSUGcGGGA3aMx+5BiipJVR7QAYqqTlyWhB836Cd+aBvkPnxb3cY/OjZFlITWHb X-OriginatorOrg: labware.com X-MS-Exchange-CrossTenant-Network-Message-Id: e748f2b7-bd09-4e2c-8cda-08dbc67e7ea2 X-MS-Exchange-CrossTenant-AuthSource: SA0PR17MB4314.namprd17.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 06 Oct 2023 15:11:19.6750 (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: 0+BQ6h2GIyCRHadf0UmgDRb3dXiwZPmbZqLJd/oPK9vQZRz5WAqnJ2dqHE9ICpvyYjBzPkmy3vPHuBN9e4v/vA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: CO3PR17MB5775 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: labware.com X-Spam-Status: No, score=-12.1 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H5, RCVD_IN_MSPIKE_WL, 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: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Jan Vrany via Gdb-patches From: Jan Vrany Reply-To: Jan Vrany Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org Sender: "Gdb-patches" This commit generalizes serialize_mi_result() to make usable in different contexts than printing result of custom MI command. To do so, the check whether passed Python object is a dictionary has been moved to the caller - at the very least, different uses require different error messages. Also it has been renamed to serialize_mi_results() to better match GDB/MI output syntax (see corresponding section in documentation, in particular rules 'result-record' and 'async-output'. Since it is now more generic function, it has been moved to py-mi.c. This is a preparation for implementing Python support for sending custom MI async events. Approved-By: Andrew Burgess --- gdb/python/py-mi.c | 159 ++++++++++++++++++++++++++++++ gdb/python/py-micmd.c | 185 ++--------------------------------- gdb/python/python-internal.h | 13 +++ 3 files changed, 181 insertions(+), 176 deletions(-) diff --git a/gdb/python/py-mi.c b/gdb/python/py-mi.c index 66dc6fb8a32..36bcb6ceece 100644 --- a/gdb/python/py-mi.c +++ b/gdb/python/py-mi.c @@ -296,3 +296,162 @@ gdbpy_execute_mi_command (PyObject *self, PyObject *args, PyObject *kw) return uiout.result (); } + +/* Convert KEY_OBJ into a string that can be used as a field name in MI + output. KEY_OBJ must be a Python string object, and must only contain + characters suitable for use as an MI field name. + + If KEY_OBJ is not a string, or if KEY_OBJ contains invalid characters, + then an error is thrown. Otherwise, KEY_OBJ is converted to a string + and returned. */ + +static gdb::unique_xmalloc_ptr +py_object_to_mi_key (PyObject *key_obj) +{ + /* The key must be a string. */ + if (!PyUnicode_Check (key_obj)) + { + gdbpy_ref<> key_repr (PyObject_Repr (key_obj)); + gdb::unique_xmalloc_ptr key_repr_string; + if (key_repr != nullptr) + key_repr_string = python_string_to_target_string (key_repr.get ()); + if (key_repr_string == nullptr) + gdbpy_handle_exception (); + + gdbpy_error (_("non-string object used as key: %s"), + key_repr_string.get ()); + } + + gdb::unique_xmalloc_ptr key_string + = python_string_to_target_string (key_obj); + if (key_string == nullptr) + gdbpy_handle_exception (); + + /* Predicate function, returns true if NAME is a valid field name for use + in MI result output, otherwise, returns false. */ + auto is_valid_key_name = [] (const char *name) -> bool + { + gdb_assert (name != nullptr); + + if (*name == '\0' || !isalpha (*name)) + return false; + + for (; *name != '\0'; ++name) + if (!isalnum (*name) && *name != '_' && *name != '-') + return false; + + return true; + }; + + if (!is_valid_key_name (key_string.get ())) + { + if (*key_string.get () == '\0') + gdbpy_error (_("Invalid empty key in MI result")); + else + gdbpy_error (_("Invalid key in MI result: %s"), key_string.get ()); + } + + return key_string; +} + +/* Serialize RESULT and print it in MI format to the current_uiout. + FIELD_NAME is used as the name of this result field. + + RESULT can be a dictionary, a sequence, an iterator, or an object that + can be converted to a string, these are converted to the matching MI + output format (dictionaries as tuples, sequences and iterators as lists, + and strings as named fields). + + If anything goes wrong while formatting the output then an error is + thrown. + + This function is the recursive inner core of serialize_mi_result, and + should only be called from that function. */ + +static void +serialize_mi_result_1 (PyObject *result, const char *field_name) +{ + struct ui_out *uiout = current_uiout; + + if (PyDict_Check (result)) + { + PyObject *key, *value; + Py_ssize_t pos = 0; + ui_out_emit_tuple tuple_emitter (uiout, field_name); + while (PyDict_Next (result, &pos, &key, &value)) + { + gdb::unique_xmalloc_ptr key_string + (py_object_to_mi_key (key)); + serialize_mi_result_1 (value, key_string.get ()); + } + } + else if (PySequence_Check (result) && !PyUnicode_Check (result)) + { + ui_out_emit_list list_emitter (uiout, field_name); + Py_ssize_t len = PySequence_Size (result); + if (len == -1) + gdbpy_handle_exception (); + for (Py_ssize_t i = 0; i < len; ++i) + { + gdbpy_ref<> item (PySequence_ITEM (result, i)); + if (item == nullptr) + gdbpy_handle_exception (); + serialize_mi_result_1 (item.get (), nullptr); + } + } + else if (PyIter_Check (result)) + { + gdbpy_ref<> item; + ui_out_emit_list list_emitter (uiout, field_name); + while (true) + { + item.reset (PyIter_Next (result)); + if (item == nullptr) + { + if (PyErr_Occurred () != nullptr) + gdbpy_handle_exception (); + break; + } + serialize_mi_result_1 (item.get (), nullptr); + } + } + else + { + if (PyLong_Check (result)) + { + int overflow = 0; + gdb_py_longest val = gdb_py_long_as_long_and_overflow (result, + &overflow); + if (PyErr_Occurred () != nullptr) + gdbpy_handle_exception (); + if (overflow == 0) + { + uiout->field_signed (field_name, val); + return; + } + /* Fall through to the string case on overflow. */ + } + + gdb::unique_xmalloc_ptr string (gdbpy_obj_to_string (result)); + if (string == nullptr) + gdbpy_handle_exception (); + uiout->field_string (field_name, string.get ()); + } +} + +/* See python-internal.h. */ + +void +serialize_mi_results (PyObject *results) +{ + gdb_assert (PyDict_Check (results)); + + PyObject *key, *value; + Py_ssize_t pos = 0; + while (PyDict_Next (results, &pos, &key, &value)) + { + gdb::unique_xmalloc_ptr key_string + (py_object_to_mi_key (key)); + serialize_mi_result_1 (value, key_string.get ()); + } +} diff --git a/gdb/python/py-micmd.c b/gdb/python/py-micmd.c index 01fc6060ece..0153f84e7a0 100644 --- a/gdb/python/py-micmd.c +++ b/gdb/python/py-micmd.c @@ -173,178 +173,6 @@ extern PyTypeObject micmdpy_object_type static PyObject *invoke_cst; -/* Convert KEY_OBJ into a string that can be used as a field name in MI - output. KEY_OBJ must be a Python string object, and must only contain - characters suitable for use as an MI field name. - - If KEY_OBJ is not a string, or if KEY_OBJ contains invalid characters, - then an error is thrown. Otherwise, KEY_OBJ is converted to a string - and returned. */ - -static gdb::unique_xmalloc_ptr -py_object_to_mi_key (PyObject *key_obj) -{ - /* The key must be a string. */ - if (!PyUnicode_Check (key_obj)) - { - gdbpy_ref<> key_repr (PyObject_Repr (key_obj)); - gdb::unique_xmalloc_ptr key_repr_string; - if (key_repr != nullptr) - key_repr_string = python_string_to_target_string (key_repr.get ()); - if (key_repr_string == nullptr) - gdbpy_handle_exception (); - - gdbpy_error (_("non-string object used as key: %s"), - key_repr_string.get ()); - } - - gdb::unique_xmalloc_ptr key_string - = python_string_to_target_string (key_obj); - if (key_string == nullptr) - gdbpy_handle_exception (); - - /* Predicate function, returns true if NAME is a valid field name for use - in MI result output, otherwise, returns false. */ - auto is_valid_key_name = [] (const char *name) -> bool - { - gdb_assert (name != nullptr); - - if (*name == '\0' || !isalpha (*name)) - return false; - - for (; *name != '\0'; ++name) - if (!isalnum (*name) && *name != '_' && *name != '-') - return false; - - return true; - }; - - if (!is_valid_key_name (key_string.get ())) - { - if (*key_string.get () == '\0') - gdbpy_error (_("Invalid empty key in MI result")); - else - gdbpy_error (_("Invalid key in MI result: %s"), key_string.get ()); - } - - return key_string; -} - -/* Serialize RESULT and print it in MI format to the current_uiout. - FIELD_NAME is used as the name of this result field. - - RESULT can be a dictionary, a sequence, an iterator, or an object that - can be converted to a string, these are converted to the matching MI - output format (dictionaries as tuples, sequences and iterators as lists, - and strings as named fields). - - If anything goes wrong while formatting the output then an error is - thrown. - - This function is the recursive inner core of serialize_mi_result, and - should only be called from that function. */ - -static void -serialize_mi_result_1 (PyObject *result, const char *field_name) -{ - struct ui_out *uiout = current_uiout; - - if (PyDict_Check (result)) - { - PyObject *key, *value; - Py_ssize_t pos = 0; - ui_out_emit_tuple tuple_emitter (uiout, field_name); - while (PyDict_Next (result, &pos, &key, &value)) - { - gdb::unique_xmalloc_ptr key_string - (py_object_to_mi_key (key)); - serialize_mi_result_1 (value, key_string.get ()); - } - } - else if (PySequence_Check (result) && !PyUnicode_Check (result)) - { - ui_out_emit_list list_emitter (uiout, field_name); - Py_ssize_t len = PySequence_Size (result); - if (len == -1) - gdbpy_handle_exception (); - for (Py_ssize_t i = 0; i < len; ++i) - { - gdbpy_ref<> item (PySequence_ITEM (result, i)); - if (item == nullptr) - gdbpy_handle_exception (); - serialize_mi_result_1 (item.get (), nullptr); - } - } - else if (PyIter_Check (result)) - { - gdbpy_ref<> item; - ui_out_emit_list list_emitter (uiout, field_name); - while (true) - { - item.reset (PyIter_Next (result)); - if (item == nullptr) - { - if (PyErr_Occurred () != nullptr) - gdbpy_handle_exception (); - break; - } - serialize_mi_result_1 (item.get (), nullptr); - } - } - else - { - if (PyLong_Check (result)) - { - int overflow = 0; - gdb_py_longest val = gdb_py_long_as_long_and_overflow (result, - &overflow); - if (PyErr_Occurred () != nullptr) - gdbpy_handle_exception (); - if (overflow == 0) - { - uiout->field_signed (field_name, val); - return; - } - /* Fall through to the string case on overflow. */ - } - - gdb::unique_xmalloc_ptr string (gdbpy_obj_to_string (result)); - if (string == nullptr) - gdbpy_handle_exception (); - uiout->field_string (field_name, string.get ()); - } -} - -/* Serialize RESULT and print it in MI format to the current_uiout. - - This function handles the top-level result initially returned from the - invoke method of the Python command implementation. At the top-level - the result must be a dictionary. The values within this dictionary can - be a wider range of types. Handling the values of the top-level - dictionary is done by serialize_mi_result_1, see that function for more - details. - - If anything goes wrong while parsing and printing the MI output then an - error is thrown. */ - -static void -serialize_mi_result (PyObject *result) -{ - /* At the top-level, the result must be a dictionary. */ - - if (!PyDict_Check (result)) - gdbpy_error (_("Result from invoke must be a dictionary")); - - PyObject *key, *value; - Py_ssize_t pos = 0; - while (PyDict_Next (result, &pos, &key, &value)) - { - gdb::unique_xmalloc_ptr key_string - (py_object_to_mi_key (key)); - serialize_mi_result_1 (value, key_string.get ()); - } -} - /* Called when the MI command is invoked. PARSE contains the parsed command line arguments from the user. */ @@ -381,14 +209,19 @@ mi_command_py::invoke (struct mi_parse *parse) const gdb_assert (this->m_pyobj != nullptr); gdb_assert (PyErr_Occurred () == nullptr); - gdbpy_ref<> result + gdbpy_ref<> results (PyObject_CallMethodObjArgs ((PyObject *) this->m_pyobj.get (), invoke_cst, argobj.get (), nullptr)); - if (result == nullptr) + if (results == nullptr) gdbpy_handle_exception (); - if (result != Py_None) - serialize_mi_result (result.get ()); + if (results != Py_None) + { + /* At the top-level, the results must be a dictionary. */ + if (!PyDict_Check (results.get ())) + gdbpy_error (_("Result from invoke must be a dictionary")); + serialize_mi_results (results.get ()); + } } /* See declaration above. */ diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h index 93217375cc5..60b795ff98c 100644 --- a/gdb/python/python-internal.h +++ b/gdb/python/python-internal.h @@ -486,6 +486,19 @@ struct gdbarch *arch_object_to_gdbarch (PyObject *obj); extern PyObject *gdbpy_execute_mi_command (PyObject *self, PyObject *args, PyObject *kw); +/* Serialize RESULTS and print it in MI format to the current_uiout. + + This function handles the top-level results passed as a dictionary. + The caller is responsible for ensuring that. The values within this + dictionary can be a wider range of types. Handling the values of the top-level + dictionary is done by serialize_mi_result_1, see that function for more + details. + + If anything goes wrong while parsing and printing the MI output then an + error is thrown. */ + +extern void serialize_mi_results (PyObject *results); + /* Convert Python object OBJ to a program_space pointer. OBJ must be a gdb.Progspace reference. Return nullptr if the gdb.Progspace is not valid (see gdb.Progspace.is_valid), otherwise return the program_space