From patchwork Fri Feb 3 16:35:04 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pedro Alves X-Patchwork-Id: 19109 Received: (qmail 3428 invoked by alias); 3 Feb 2017 16:35:19 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 3411 invoked by uid 89); 3 Feb 2017 16:35:18 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.9 required=5.0 tests=BAYES_00, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy=3156, 1056, 2997, H*f:sk:1486077 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 03 Feb 2017 16:35:07 +0000 Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 4C1BB468; Fri, 3 Feb 2017 16:35:07 +0000 (UTC) Received: from [127.0.0.1] (ovpn04.gateway.prod.ext.ams2.redhat.com [10.39.146.4]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v13GZ5M2001033; Fri, 3 Feb 2017 11:35:06 -0500 Subject: Re: [PATCH] C++-fy struct interp/cli_interp/tui_interp/mi_interp To: Simon Marchi References: <1486077261-15720-1-git-send-email-palves@redhat.com> <39e660f4e4dac170eed26e625c38e6be@polymtl.ca> Cc: gdb-patches@sourceware.org From: Pedro Alves Message-ID: <6faf2409-f83b-d0ca-d011-b9d4f228b253@redhat.com> Date: Fri, 3 Feb 2017 16:35:04 +0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.4.0 MIME-Version: 1.0 In-Reply-To: <39e660f4e4dac170eed26e625c38e6be@polymtl.ca> On 02/03/2017 04:32 AM, Simon Marchi wrote: > Thanks, even though it's not a complete OO redesign, it's still a good > step. /me nods > There's a comment just above this block that you can update: > > /* Run the init proc. If it fails, try to restore the old interp. */ > Indeed. Fixed and pushed, as below. Thanks! From d6f9b0fbc7998909712cbc1b194f1cbd4ae8b6fa Mon Sep 17 00:00:00 2001 From: Pedro Alves Date: Fri, 3 Feb 2017 16:30:04 +0000 Subject: [PATCH] C++-fy struct interp/cli_interp/tui_interp/mi_interp - The interp->data field disappears, since we can put data in the interpreter directly now. The "init" method remains in place, but it now returns void. - A few places check if the interpreter method is NULL before calling it, and also check whether the method returns true/false. For some of those methods, all current implementations always return true. In those cases, this commit makes the C++-fied method return void instead and cleans up the callers. Tested on x86_64 Fedora 23. gdb/ChangeLog: 2017-02-03 Pedro Alves * cli/cli-interp.c (cli_interp_base::cli_interp_base) (cli_interp_base::~cli_interp_base): New. (cli_interp): New struct. (as_cli_interp): Cast the interp itself to cli_interp. (cli_interpreter_pre_command_loop): Rename to ... (cli_interp_base::pre_command_loop): ... this. Remove 'self' parameter. (cli_interpreter_init): Rename to ... (cli_interp::init): ... this. Remove 'self' parameter. Use boolean. Make extern. (cli_interpreter_resume): Rename to ... (cli_interp::resume): ... this. Remove 'data' parameter. Make extern. (cli_interpreter_suspend): Rename to ... (cli_interp::suspend): ... this. Remove 'data' parameter. Make extern. (cli_interpreter_exec): Rename to ... (cli_interp::exec): ... this. Remove 'data' parameter. Make extern. (cli_interpreter_supports_command_editing): Rename to ... (cli_interp_base::supports_command_editing): ... this. Remove 'interp' parameter. Make extern. (cli_ui_out): Rename to ... (cli_interp::interp_ui_out): ... this. Remove 'interp' parameter. Make extern. (cli_set_logging): Rename to ... (cli_interp_base::set_logging): ... this. Remove 'interp' parameter. Make extern. (cli_interp_procs): Delete. (cli_interp_factory): Adjust to use "new". * cli/cli-interp.h: Include "interps.h". (struct cli_interp_base): New struct. * interps.c (struct interp): Delete. Fields moved to interps.h. (interp_new): Delete. (interp::interp, interp::~interp): New. (interp_set): Use bool, and return void. Assume the interpreter has suspend, init and resume methods, and that the all return void. (set_top_level_interpreter): interp_set returns void. (interp_ui_out): Adapt. (current_interp_set_logging): Adapt. (interp_data): Delete. (interp_pre_command_loop, interp_supports_command_editing): Adapt. (interp_exec): Adapt. (top_level_interpreter_data): Delete. * interps.h (interp_init_ftype, interp_resume_ftype) (interp_suspend_ftype, interp_exec_ftype) (interp_pre_command_loop_ftype, interp_ui_out_ftype): Delete. (class interp): New. (interp_new): Delete. (interp_set): Now returns void. Use bool. (interp_data, top_level_interpreter_data): Delete. * mi/mi-common.h: Include interps.h. (class mi_interp): Inherit from interp. Define a ctor. Declare init, resume, suspect, exec, interp_ui_out, set_logging and pre_command_loop methods. * mi/mi-interp.c (as_mi_interp): Cast the interp itself. (mi_interpreter_init): Rename to ... (mi_interp::init): ... this. Remove the 'interp' parameter, use bool, return void and make extern. Adjust. (mi_interpreter_resume): ... Rename to ... (mi_interp::resume): ... this. Remove the 'data' parameter, return void and make extern. Adjust. (mi_interpreter_suspend): ... Rename to ... (mi_interp::suspend): ... this. Remove the 'data' parameter, return void and make extern. Adjust. (mi_interpreter_exec): ... Rename to ... (mi_interp::exec): ... this. Remove the 'data' parameter and make extern. Adjust. (mi_interpreter_pre_command_loop): ... Rename to ... (mi_interp::pre_command_loop): ... this. Remove the 'self' parameter and make extern. (mi_on_normal_stop_1): Adjust. (mi_ui_out): Rename to ... (mi_interp::interp_ui_out): ... this. Remove the 'interp' parameter and make extern. Adjust. (mi_set_logging): Rename to ... (mi_interp::set_logging): ... this. Remove the 'interp' parameter and make extern. Adjust. (mi_interp_procs): Delete. (mi_interp_factory): Adjust to use 'new'. * mi/mi-main.c (mi_cmd_gdb_exit, captured_mi_execute_command) (mi_print_exception, mi_execute_command, mi_load_progress): Adjust. * tui/tui-interp.c (tui_interp): New class. (as_tui_interp): Return a tui_interp pointer. (tui_on_normal_stop, tui_on_signal_received) (tui_on_end_stepping_range, tui_on_signal_exited, tui_on_exited) (tui_on_no_history, tui_on_user_selected_context_changed): Adjust to use interp::interp_ui_out. (tui_init): Rename to ... (tui_interp::init): ... this. Remove the 'self' parameter, use bool, return void and make extern. Adjust. (tui_resume): Rename to ... (tui_interp::resume): ... this. Remove the 'data' parameter, return void and make extern. Adjust. (tui_suspend): Rename to ... (tui_interp::suspend): ... this. Remove the 'data' parameter, return void and make extern. Adjust. (tui_ui_out): Rename to ... (tui_interp::interp_ui_out): ... this. Remove the 'self' parameter, and make extern. Adjust. (tui_exec): Rename to ... (tui_interp::exec): ... this. Remove the 'data' parameter and make extern. (tui_interp_procs): Delete. (tui_interp_factory): Use "new". --- gdb/ChangeLog | 110 ++++++++++++++++++++++++++++++++++++++++++++ gdb/cli/cli-interp.c | 89 ++++++++++++++++++------------------ gdb/cli/cli-interp.h | 15 +++++- gdb/interps.c | 127 ++++++++++----------------------------------------- gdb/interps.h | 58 +++++++++++------------ gdb/mi/mi-common.h | 19 +++++++- gdb/mi/mi-interp.c | 69 ++++++++++------------------ gdb/mi/mi-main.c | 14 ++---- gdb/tui/tui-interp.c | 74 ++++++++++++++---------------- 9 files changed, 304 insertions(+), 271 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 2f5ba2f..2016c81 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,113 @@ +2017-02-03 Pedro Alves + + * cli/cli-interp.c (cli_interp_base::cli_interp_base) + (cli_interp_base::~cli_interp_base): New. + (cli_interp): New struct. + (as_cli_interp): Cast the interp itself to cli_interp. + (cli_interpreter_pre_command_loop): Rename to ... + (cli_interp_base::pre_command_loop): ... this. Remove 'self' + parameter. + (cli_interpreter_init): Rename to ... + (cli_interp::init): ... this. Remove 'self' parameter. Use + boolean. Make extern. + (cli_interpreter_resume): Rename to ... + (cli_interp::resume): ... this. Remove 'data' parameter. Make + extern. + (cli_interpreter_suspend): Rename to ... + (cli_interp::suspend): ... this. Remove 'data' parameter. Make + extern. + (cli_interpreter_exec): Rename to ... + (cli_interp::exec): ... this. Remove 'data' parameter. Make + extern. + (cli_interpreter_supports_command_editing): Rename to ... + (cli_interp_base::supports_command_editing): ... this. Remove + 'interp' parameter. Make extern. + (cli_ui_out): Rename to ... + (cli_interp::interp_ui_out): ... this. Remove 'interp' parameter. + Make extern. + (cli_set_logging): Rename to ... + (cli_interp_base::set_logging): ... this. Remove 'interp' + parameter. Make extern. + (cli_interp_procs): Delete. + (cli_interp_factory): Adjust to use "new". + * cli/cli-interp.h: Include "interps.h". + (struct cli_interp_base): New struct. + * interps.c (struct interp): Delete. Fields moved to interps.h. + (interp_new): Delete. + (interp::interp, interp::~interp): New. + (interp_set): Use bool, and return void. Assume the interpreter + has suspend, init and resume methods, and that the all return + void. + (set_top_level_interpreter): interp_set returns void. + (interp_ui_out): Adapt. + (current_interp_set_logging): Adapt. + (interp_data): Delete. + (interp_pre_command_loop, interp_supports_command_editing): Adapt. + (interp_exec): Adapt. + (top_level_interpreter_data): Delete. + * interps.h (interp_init_ftype, interp_resume_ftype) + (interp_suspend_ftype, interp_exec_ftype) + (interp_pre_command_loop_ftype, interp_ui_out_ftype): Delete. + (class interp): New. + (interp_new): Delete. + (interp_set): Now returns void. Use bool. + (interp_data, top_level_interpreter_data): Delete. + * mi/mi-common.h: Include interps.h. + (class mi_interp): Inherit from interp. Define a ctor. Declare + init, resume, suspect, exec, interp_ui_out, set_logging and + pre_command_loop methods. + * mi/mi-interp.c (as_mi_interp): Cast the interp itself. + (mi_interpreter_init): Rename to ... + (mi_interp::init): ... this. Remove the 'interp' parameter, use + bool, return void and make extern. Adjust. + (mi_interpreter_resume): ... Rename to ... + (mi_interp::resume): ... this. Remove the 'data' parameter, + return void and make extern. Adjust. + (mi_interpreter_suspend): ... Rename to ... + (mi_interp::suspend): ... this. Remove the 'data' parameter, + return void and make extern. Adjust. + (mi_interpreter_exec): ... Rename to ... + (mi_interp::exec): ... this. Remove the 'data' parameter and make + extern. Adjust. + (mi_interpreter_pre_command_loop): ... Rename to ... + (mi_interp::pre_command_loop): ... this. Remove the 'self' + parameter and make extern. + (mi_on_normal_stop_1): Adjust. + (mi_ui_out): Rename to ... + (mi_interp::interp_ui_out): ... this. Remove the 'interp' + parameter and make extern. Adjust. + (mi_set_logging): Rename to ... + (mi_interp::set_logging): ... this. Remove the 'interp' + parameter and make extern. Adjust. + (mi_interp_procs): Delete. + (mi_interp_factory): Adjust to use 'new'. + * mi/mi-main.c (mi_cmd_gdb_exit, captured_mi_execute_command) + (mi_print_exception, mi_execute_command, mi_load_progress): + Adjust. + * tui/tui-interp.c (tui_interp): New class. + (as_tui_interp): Return a tui_interp pointer. + (tui_on_normal_stop, tui_on_signal_received) + (tui_on_end_stepping_range, tui_on_signal_exited, tui_on_exited) + (tui_on_no_history, tui_on_user_selected_context_changed): Adjust + to use interp::interp_ui_out. + (tui_init): Rename to ... + (tui_interp::init): ... this. Remove the 'self' parameter, use + bool, return void and make extern. Adjust. + (tui_resume): Rename to ... + (tui_interp::resume): ... this. Remove the 'data' parameter, + return void and make extern. Adjust. + (tui_suspend): Rename to ... + (tui_interp::suspend): ... this. Remove the 'data' parameter, + return void and make extern. Adjust. + (tui_ui_out): Rename to ... + (tui_interp::interp_ui_out): ... this. Remove the 'self' + parameter, and make extern. Adjust. + (tui_exec): Rename to ... + (tui_interp::exec): ... this. Remove the 'data' parameter and + make extern. + (tui_interp_procs): Delete. + (tui_interp_factory): Use "new". + 2017-02-02 Tom Tromey * rust-exp.y (ends_raw_string, space_then_number) diff --git a/gdb/cli/cli-interp.c b/gdb/cli/cli-interp.c index e0327f6..8712c75 100644 --- a/gdb/cli/cli-interp.c +++ b/gdb/cli/cli-interp.c @@ -30,13 +30,37 @@ #include "gdbthread.h" #include "thread-fsm.h" +cli_interp_base::cli_interp_base (const char *name) + : interp (name) +{} + +cli_interp_base::~cli_interp_base () +{} + /* The console interpreter. */ -struct cli_interp + +class cli_interp final : public cli_interp_base { + public: + explicit cli_interp (const char *name); + + void init (bool top_level) override; + void resume () override; + void suspend () override; + gdb_exception exec (const char *command_str) override; + ui_out *interp_ui_out () override; + /* The ui_out for the console interpreter. */ cli_ui_out *cli_uiout; }; +cli_interp::cli_interp (const char *name) + : cli_interp_base (name) +{ + /* Create a default uiout builder for the CLI. */ + this->cli_uiout = cli_out_new (gdb_stdout); +} + /* Suppress notification struct. */ struct cli_suppress_notification cli_suppress_notification = { @@ -50,7 +74,7 @@ static struct cli_interp * as_cli_interp (struct interp *interp) { if (strcmp (interp_name (interp), INTERP_CONSOLE) == 0) - return (struct cli_interp *) interp_data (interp); + return (struct cli_interp *) interp; return NULL; } @@ -255,24 +279,23 @@ cli_on_user_selected_context_changed (user_selected_what selection) /* pre_command_loop implementation. */ void -cli_interpreter_pre_command_loop (struct interp *self) +cli_interp_base::pre_command_loop () { display_gdb_prompt (0); } /* These implement the cli out interpreter: */ -static void * -cli_interpreter_init (struct interp *self, int top_level) +void +cli_interp::init (bool top_level) { - return interp_data (self); } -static int -cli_interpreter_resume (void *data) +void +cli_interp::resume () { struct ui *ui = current_ui; - struct cli_interp *cli = (struct cli_interp *) data; + struct cli_interp *cli = this; struct ui_file *stream; /*sync_execution = 1; */ @@ -294,21 +317,18 @@ cli_interpreter_resume (void *data) if (stream != NULL) cli->cli_uiout->set_stream (gdb_stdout); - - return 1; } -static int -cli_interpreter_suspend (void *data) +void +cli_interp::suspend () { gdb_disable_readline (); - return 1; } -static struct gdb_exception -cli_interpreter_exec (void *data, const char *command_str) +gdb_exception +cli_interp::exec (const char *command_str) { - struct cli_interp *cli = (struct cli_interp *) data; + struct cli_interp *cli = this; struct ui_file *old_stream; struct gdb_exception result; @@ -330,10 +350,10 @@ cli_interpreter_exec (void *data, const char *command_str) return result; } -int -cli_interpreter_supports_command_editing (struct interp *interp) +bool +cli_interp_base::supports_command_editing () { - return 1; + return true; } static struct gdb_exception @@ -365,10 +385,10 @@ safe_execute_command (struct ui_out *command_uiout, char *command, int from_tty) return e; } -static struct ui_out * -cli_ui_out (struct interp *self) +ui_out * +cli_interp::interp_ui_out () { - struct cli_interp *cli = (struct cli_interp *) interp_data (self); + struct cli_interp *cli = (struct cli_interp *) this; return cli->cli_uiout; } @@ -388,8 +408,7 @@ static saved_output_files saved_output; /* See cli-interp.h. */ void -cli_set_logging (struct interp *interp, - ui_file_up logfile, bool logging_redirect) +cli_interp_base::set_logging (ui_file_up logfile, bool logging_redirect) { if (logfile != NULL) { @@ -430,30 +449,12 @@ cli_set_logging (struct interp *interp, } } -/* The CLI interpreter's vtable. */ - -static const struct interp_procs cli_interp_procs = { - cli_interpreter_init, /* init_proc */ - cli_interpreter_resume, /* resume_proc */ - cli_interpreter_suspend, /* suspend_proc */ - cli_interpreter_exec, /* exec_proc */ - cli_ui_out, /* ui_out_proc */ - cli_set_logging, /* set_logging_proc */ - cli_interpreter_pre_command_loop, /* pre_command_loop_proc */ - cli_interpreter_supports_command_editing, /* supports_command_editing_proc */ -}; - /* Factory for CLI interpreters. */ static struct interp * cli_interp_factory (const char *name) { - struct cli_interp *cli = XNEW (struct cli_interp); - - /* Create a default uiout builder for the CLI. */ - cli->cli_uiout = cli_out_new (gdb_stdout); - - return interp_new (name, &cli_interp_procs, cli); + return new cli_interp (name); } /* Standard gdb initialization hook. */ diff --git a/gdb/cli/cli-interp.h b/gdb/cli/cli-interp.h index f93548c..de9da83 100644 --- a/gdb/cli/cli-interp.h +++ b/gdb/cli/cli-interp.h @@ -18,7 +18,20 @@ #ifndef CLI_INTERP_H #define CLI_INTERP_H 1 -struct interp; +#include "interps.h" + +/* A console-like interpreter. Implements functionality common to the + CLI and the TUI. */ +class cli_interp_base : public interp +{ +public: + explicit cli_interp_base (const char *name); + virtual ~cli_interp_base () = 0; + + void set_logging (ui_file_up logfile, bool logging_redirect) override; + void pre_command_loop () override; + bool supports_command_editing () override; +}; /* Make the output ui_file to use when logging is enabled. CURR_OUTPUT is the stream where output is currently being sent to diff --git a/gdb/interps.c b/gdb/interps.c index 06e7ccf..d31d53b 100644 --- a/gdb/interps.c +++ b/gdb/interps.c @@ -72,28 +72,6 @@ get_current_interp_info (void) return get_interp_info (current_ui); } -struct interp -{ - /* This is the name in "-i=" and set interpreter. */ - const char *name; - - /* Interpreters are stored in a linked list, this is the next - one... */ - struct interp *next; - - /* This is a cookie that an instance of the interpreter can use. - This is a bit confused right now as the exact initialization - sequence for it, and how it relates to the interpreter's uiout - object is a bit confused. */ - void *data; - - /* Has the init_proc been run? */ - int inited; - - const struct interp_procs *procs; - int quiet_p; -}; - /* The magic initialization routine for this module. */ void _initialize_interpreter (void); @@ -101,25 +79,16 @@ void _initialize_interpreter (void); static struct interp *interp_lookup_existing (struct ui *ui, const char *name); -/* interp_new - This allocates space for a new interpreter, - fills the fields from the inputs, and returns a pointer to the - interpreter. */ -struct interp * -interp_new (const char *name, const struct interp_procs *procs, void *data) +interp::interp (const char *name) { - struct interp *new_interp; - - new_interp = XNEW (struct interp); - - new_interp->name = xstrdup (name); - new_interp->data = data; - new_interp->quiet_p = 0; - new_interp->procs = procs; - new_interp->inited = 0; - - return new_interp; + this->name = xstrdup (name); + this->quiet_p = false; + this->inited = false; } +interp::~interp () +{} + /* An interpreter factory. Maps an interpreter name to the factory function that instantiates an interpreter by that name. */ @@ -177,11 +146,7 @@ interp_add (struct ui *ui, struct interp *interp) } /* This sets the current interpreter to be INTERP. If INTERP has not - been initialized, then this will also run the init proc. If the - init proc is successful, return 1, if it fails, set the old - interpreter back in place and return 0. If we can't restore the - old interpreter, then raise an internal error, since we are in - pretty bad shape at this point. + been initialized, then this will also run the init method. The TOP_LEVEL parameter tells if this new interpreter is the top-level one. The top-level is what is requested @@ -190,8 +155,9 @@ interp_add (struct ui *ui, struct interp *interp) MI is the top-level interpreter, then it will always report events such as target stops and new thread creation, even if they are caused by CLI commands. */ -int -interp_set (struct interp *interp, int top_level) + +void +interp_set (struct interp *interp, bool top_level) { struct ui_interp_info *ui_interp = get_current_interp_info (); struct interp *old_interp = ui_interp->current_interpreter; @@ -206,12 +172,7 @@ interp_set (struct interp *interp, int top_level) if (old_interp != NULL) { current_uiout->flush (); - if (old_interp->procs->suspend_proc - && !old_interp->procs->suspend_proc (old_interp->data)) - { - error (_("Could not suspend interpreter \"%s\"."), - old_interp->name); - } + old_interp->suspend (); } else { @@ -232,32 +193,20 @@ interp_set (struct interp *interp, int top_level) interpreter_p = xstrdup (interp->name); } - /* Run the init proc. If it fails, try to restore the old interp. */ - + /* Run the init proc. */ if (!interp->inited) { - if (interp->procs->init_proc != NULL) - { - interp->data = interp->procs->init_proc (interp, top_level); - } - interp->inited = 1; + interp->init (top_level); + interp->inited = true; } /* Do this only after the interpreter is initialized. */ - current_uiout = interp->procs->ui_out_proc (interp); + current_uiout = interp->interp_ui_out (); /* Clear out any installed interpreter hooks/event handlers. */ clear_interpreter_hooks (); - if (interp->procs->resume_proc != NULL - && (!interp->procs->resume_proc (interp->data))) - { - if (old_interp == NULL || !interp_set (old_interp, 0)) - internal_error (__FILE__, __LINE__, - _("Failed to initialize new interp \"%s\" %s"), - interp->name, "and could not restore old interp!\n"); - return 0; - } + interp->resume (); if (!first_time && !interp_quiet_p (interp)) { @@ -265,8 +214,6 @@ interp_set (struct interp *interp, int top_level) "Switching to interpreter \"%.24s\".\n", interp->name); current_uiout->text (buffer); } - - return 1; } /* Look up the interpreter for NAME. If no such interpreter exists, @@ -330,8 +277,7 @@ set_top_level_interpreter (const char *name) if (interp == NULL) error (_("Interpreter `%s' unrecognized"), name); /* Install it. */ - if (!interp_set (interp, 1)) - error (_("Interpreter `%s' failed to initialize."), name); + interp_set (interp, true); } /* Returns the current interpreter. */ @@ -343,7 +289,7 @@ interp_ui_out (struct interp *interp) if (interp == NULL) interp = ui_interp->current_interpreter; - return interp->procs->ui_out_proc (interp); + return interp->interp_ui_out (); } void @@ -353,8 +299,7 @@ current_interp_set_logging (ui_file_up logfile, struct ui_interp_info *ui_interp = get_current_interp_info (); struct interp *interp = ui_interp->current_interpreter; - return interp->procs->set_logging_proc (interp, std::move (logfile), - logging_redirect); + return interp->set_logging (std::move (logfile), logging_redirect); } /* Temporarily overrides the current interpreter. */ @@ -370,14 +315,6 @@ interp_set_temp (const char *name) return old_interp; } -/* Returns the interpreter's cookie. */ - -void * -interp_data (struct interp *interp) -{ - return interp->data; -} - /* Returns the interpreter's name. */ const char * @@ -427,8 +364,7 @@ interp_pre_command_loop (struct interp *interp) { gdb_assert (interp != NULL); - if (interp->procs->pre_command_loop_proc != NULL) - interp->procs->pre_command_loop_proc (interp); + interp->pre_command_loop (); } /* See interp.h */ @@ -436,9 +372,7 @@ interp_pre_command_loop (struct interp *interp) int interp_supports_command_editing (struct interp *interp) { - if (interp->procs->supports_command_editing_proc != NULL) - return interp->procs->supports_command_editing_proc (interp); - return 0; + return interp->supports_command_editing (); } int @@ -472,13 +406,11 @@ interp_exec (struct interp *interp, const char *command_str) struct gdb_exception ex; struct interp *save_command_interp; - gdb_assert (interp->procs->exec_proc != NULL); - /* See `command_interp' for why we do this. */ save_command_interp = ui_interp->command_interpreter; ui_interp->command_interpreter = interp; - ex = interp->procs->exec_proc (interp->data, command_str); + ex = interp->exec (command_str); ui_interp->command_interpreter = save_command_interp; @@ -539,8 +471,7 @@ interpreter_exec_cmd (char *args, int from_tty) old_quiet = interp_set_quiet (old_interp, 1); use_quiet = interp_set_quiet (interp_to_use, 1); - if (!interp_set (interp_to_use, 0)) - error (_("Could not switch to interpreter \"%s\"."), prules[0]); + interp_set (interp_to_use, false); for (i = 1; i < nrules; i++) { @@ -612,16 +543,6 @@ top_level_interpreter (void) return ui_interp->top_level_interpreter; } -void * -top_level_interpreter_data (void) -{ - struct interp *interp; - - interp = top_level_interpreter (); - gdb_assert (interp != NULL); - return interp->data; -} - /* See interps.h. */ struct interp * diff --git a/gdb/interps.h b/gdb/interps.h index ef2ceeb..e564980 100644 --- a/gdb/interps.h +++ b/gdb/interps.h @@ -41,53 +41,57 @@ extern struct gdb_exception interp_exec (struct interp *interp, const char *command); extern int interp_quiet_p (struct interp *interp); -typedef void *(interp_init_ftype) (struct interp *self, int top_level); -typedef int (interp_resume_ftype) (void *data); -typedef int (interp_suspend_ftype) (void *data); -typedef struct gdb_exception (interp_exec_ftype) (void *data, - const char *command); -typedef void (interp_pre_command_loop_ftype) (struct interp *self); -typedef struct ui_out *(interp_ui_out_ftype) (struct interp *self); +class interp +{ +public: + explicit interp (const char *name); + virtual ~interp () = 0; -typedef void (interp_set_logging_ftype) (struct interp *self, - ui_file_up logfile, - bool logging_redirect); + virtual void init (bool top_level) + {} -typedef int (interp_supports_command_editing_ftype) (struct interp *self); + virtual void resume () = 0; + virtual void suspend () = 0; -struct interp_procs -{ - interp_init_ftype *init_proc; - interp_resume_ftype *resume_proc; - interp_suspend_ftype *suspend_proc; - interp_exec_ftype *exec_proc; + virtual gdb_exception exec (const char *command) = 0; /* Returns the ui_out currently used to collect results for this interpreter. It can be a formatter for stdout, as is the case for the console & mi outputs, or it might be a result formatter. */ - interp_ui_out_ftype *ui_out_proc; + virtual ui_out *interp_ui_out () = 0; /* Provides a hook for interpreters to do any additional setup/cleanup that they might need when logging is enabled or disabled. */ - interp_set_logging_ftype *set_logging_proc; + virtual void set_logging (ui_file_up logfile, bool logging_redirect) = 0; /* Called before starting an event loop, to give the interpreter a chance to e.g., print a prompt. */ - interp_pre_command_loop_ftype *pre_command_loop_proc; + virtual void pre_command_loop () + {} /* Returns true if this interpreter supports using the readline library; false if it uses GDB's own simplified readline emulation. */ - interp_supports_command_editing_ftype *supports_command_editing_proc; + virtual bool supports_command_editing () + { return false; } + + /* This is the name in "-i=" and "set interpreter". */ + const char *name; + + /* Interpreters are stored in a linked list, this is the next + one... */ + struct interp *next; + + /* Has the init method been run? */ + bool inited; + + bool quiet_p; }; -extern struct interp *interp_new (const char *name, - const struct interp_procs *procs, - void *data); extern void interp_add (struct ui *ui, struct interp *interp); -extern int interp_set (struct interp *interp, int top_level); +extern void interp_set (struct interp *interp, bool top_level); /* Look up the interpreter for NAME, creating one if none exists yet. If NAME is not a interpreter type previously registered with @@ -101,7 +105,6 @@ extern struct interp *interp_lookup (struct ui *ui, const char *name); extern void set_top_level_interpreter (const char *name); extern struct ui_out *interp_ui_out (struct interp *interp); -extern void *interp_data (struct interp *interp); extern const char *interp_name (struct interp *interp); extern struct interp *interp_set_temp (const char *name); @@ -119,8 +122,7 @@ extern int current_interp_named_p (const char *name); extern void current_interp_set_logging (ui_file_up logfile, bool logging_redirect); -/* Returns opaque data associated with the top-level interpreter. */ -extern void *top_level_interpreter_data (void); +/* Returns the top-level interpreter. */ extern struct interp *top_level_interpreter (void); /* Return the current UI's current interpreter. */ diff --git a/gdb/mi/mi-common.h b/gdb/mi/mi-common.h index 9ee38b0..8fa9c9d 100644 --- a/gdb/mi/mi-common.h +++ b/gdb/mi/mi-common.h @@ -19,6 +19,8 @@ #ifndef MI_COMMON_H #define MI_COMMON_H +#include "interps.h" + struct mi_console_file; /* Represents the reason why GDB is sending an asynchronous command to @@ -50,8 +52,23 @@ enum async_reply_reason const char *async_reason_lookup (enum async_reply_reason reason); -struct mi_interp +/* An MI interpreter. */ + +class mi_interp final : public interp { +public: + mi_interp (const char *name) + : interp (name) + {} + + void init (bool top_level) override; + void resume () override; + void suspend () override; + gdb_exception exec (const char *command_str) override; + ui_out *interp_ui_out () override; + void set_logging (ui_file_up logfile, bool logging_redirect) override; + void pre_command_loop () override; + /* MI's output channels */ mi_console_file *out; mi_console_file *err; diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c index aa76989..86340e4 100644 --- a/gdb/mi/mi-interp.c +++ b/gdb/mi/mi-interp.c @@ -108,14 +108,14 @@ static struct mi_interp * as_mi_interp (struct interp *interp) { if (interp_ui_out (interp)->is_mi_like_p ()) - return (struct mi_interp *) interp_data (interp); + return (struct mi_interp *) interp; return NULL; } -static void * -mi_interpreter_init (struct interp *interp, int top_level) +void +mi_interp::init (bool top_level) { - struct mi_interp *mi = XNEW (struct mi_interp); + mi_interp *mi = this; const char *name; int mi_version; @@ -132,7 +132,7 @@ mi_interpreter_init (struct interp *interp, int top_level) mi->targ = new mi_console_file (mi->raw_stdout, "@", '"'); mi->event_channel = new mi_console_file (mi->raw_stdout, "=", 0); - name = interp_name (interp); + name = interp_name (this); /* INTERP_MI selects the most recent released version. "mi2" was released as part of GDB 6.0. */ if (strcmp (name, INTERP_MI) == 0) @@ -157,14 +157,12 @@ mi_interpreter_init (struct interp *interp, int top_level) up-front. */ iterate_over_inferiors (report_initial_inferior, mi); } - - return mi; } -static int -mi_interpreter_resume (void *data) +void +mi_interp::resume () { - struct mi_interp *mi = (struct mi_interp *) data; + struct mi_interp *mi = this; struct ui *ui = current_ui; /* As per hack note in mi_interpreter_init, swap in the output @@ -188,19 +186,16 @@ mi_interpreter_resume (void *data) clear_interpreter_hooks (); deprecated_show_load_progress = mi_load_progress; - - return 1; } -static int -mi_interpreter_suspend (void *data) +void +mi_interp::suspend () { gdb_disable_readline (); - return 1; } -static struct gdb_exception -mi_interpreter_exec (void *data, const char *command) +gdb_exception +mi_interp::exec (const char *command) { mi_execute_command_wrapper (command); return exception_none; @@ -327,10 +322,10 @@ mi_execute_command_input_handler (char *cmd) display_mi_prompt (mi); } -static void -mi_interpreter_pre_command_loop (struct interp *self) +void +mi_interp::pre_command_loop () { - struct mi_interp *mi = (struct mi_interp *) interp_data (self); + struct mi_interp *mi = this; /* Turn off 8 bit strings in quoted output. Any character with the high bit set is printed using C's octal format. */ @@ -658,7 +653,7 @@ mi_on_normal_stop_1 (struct bpstats *bs, int print_frame) using cli interpreter, be sure to use MI uiout for output, not the current one. */ struct ui_out *mi_uiout = interp_ui_out (top_level_interpreter ()); - struct mi_interp *mi = (struct mi_interp *) top_level_interpreter_data (); + struct mi_interp *mi = (struct mi_interp *) top_level_interpreter (); if (print_frame) { @@ -1362,24 +1357,19 @@ report_initial_inferior (struct inferior *inf, void *closure) return 0; } -static struct ui_out * -mi_ui_out (struct interp *interp) +ui_out * +mi_interp::interp_ui_out () { - struct mi_interp *mi = (struct mi_interp *) interp_data (interp); - - return mi->mi_uiout; + return this->mi_uiout; } /* Do MI-specific logging actions; save raw_stdout, and change all the consoles to use the supplied ui-file(s). */ -static void -mi_set_logging (struct interp *interp, - ui_file_up logfile, bool logging_redirect) +void +mi_interp::set_logging (ui_file_up logfile, bool logging_redirect) { - struct mi_interp *mi = (struct mi_interp *) interp_data (interp); - - gdb_assert (mi != NULL); + struct mi_interp *mi = this; if (logfile != NULL) { @@ -1403,25 +1393,12 @@ mi_set_logging (struct interp *interp, mi->event_channel->set_raw (mi->raw_stdout); } -/* The MI interpreter's vtable. */ - -static const struct interp_procs mi_interp_procs = -{ - mi_interpreter_init, /* init_proc */ - mi_interpreter_resume, /* resume_proc */ - mi_interpreter_suspend, /* suspend_proc */ - mi_interpreter_exec, /* exec_proc */ - mi_ui_out, /* ui_out_proc */ - mi_set_logging, /* set_logging_proc */ - mi_interpreter_pre_command_loop /* pre_command_loop_proc */ -}; - /* Factory for MI interpreters. */ static struct interp * mi_interp_factory (const char *name) { - return interp_new (name, &mi_interp_procs, NULL); + return new mi_interp (name); } extern initialize_file_ftype _initialize_mi_interp; /* -Wmissing-prototypes */ diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c index b249f2d..cf4e45a 100644 --- a/gdb/mi/mi-main.c +++ b/gdb/mi/mi-main.c @@ -147,8 +147,7 @@ static void print_diff (struct ui_file *file, struct mi_timestamp *start, void mi_cmd_gdb_exit (char *command, char **argv, int argc) { - struct mi_interp *mi - = (struct mi_interp *) interp_data (current_interpreter ()); + struct mi_interp *mi = (struct mi_interp *) current_interpreter (); /* We have to print everything right here because we never return. */ if (current_token) @@ -1974,7 +1973,7 @@ mi_cmd_remove_inferior (char *command, char **argv, int argc) static void captured_mi_execute_command (struct ui_out *uiout, struct mi_parse *context) { - struct mi_interp *mi = (struct mi_interp *) interp_data (command_interp ()); + struct mi_interp *mi = (struct mi_interp *) command_interp (); struct cleanup *cleanup; if (do_timings) @@ -2066,8 +2065,7 @@ captured_mi_execute_command (struct ui_out *uiout, struct mi_parse *context) static void mi_print_exception (const char *token, struct gdb_exception exception) { - struct mi_interp *mi - = (struct mi_interp *) interp_data (current_interpreter ()); + struct mi_interp *mi = (struct mi_interp *) current_interpreter (); fputs_unfiltered (token, mi->raw_stdout); fputs_unfiltered ("^error,msg=\"", mi->raw_stdout); @@ -2190,8 +2188,7 @@ mi_execute_command (const char *cmd, int from_tty) again. */ && !command_notifies_uscc_observer (command)) { - struct mi_interp *mi - = (struct mi_interp *) top_level_interpreter_data (); + struct mi_interp *mi = (struct mi_interp *) top_level_interpreter (); int report_change = 0; if (command->thread == -1) @@ -2378,8 +2375,7 @@ mi_load_progress (const char *section_name, int new_section; struct ui_out *saved_uiout; struct ui_out *uiout; - struct mi_interp *mi - = (struct mi_interp *) interp_data (current_interpreter ()); + struct mi_interp *mi = (struct mi_interp *) current_interpreter (); /* This function is called through deprecated_show_load_progress which means uiout may not be correct. Fix it for the duration diff --git a/gdb/tui/tui-interp.c b/gdb/tui/tui-interp.c index e2c0605..702c342 100644 --- a/gdb/tui/tui-interp.c +++ b/gdb/tui/tui-interp.c @@ -34,20 +34,32 @@ #include "observer.h" #include "gdbthread.h" -static struct ui_out *tui_ui_out (struct interp *self); - /* Set to 1 when the TUI mode must be activated when we first start gdb. */ static int tui_start_enabled = 0; +class tui_interp final : public cli_interp_base +{ +public: + explicit tui_interp (const char *name) + : cli_interp_base (name) + {} + + void init (bool top_level) override; + void resume () override; + void suspend () override; + gdb_exception exec (const char *command_str) override; + ui_out *interp_ui_out () override; +}; + /* Returns the INTERP if the INTERP is a TUI, and returns NULL otherwise. */ -static struct interp * +static tui_interp * as_tui_interp (struct interp *interp) { if (strcmp (interp_name (interp), INTERP_TUI) == 0) - return interp; + return (tui_interp *) interp; return NULL; } @@ -84,7 +96,7 @@ tui_on_normal_stop (struct bpstats *bs, int print_frame) thread = inferior_thread (); if (should_print_stop_to_console (interp, thread)) - print_stop_event (tui_ui_out (tui)); + print_stop_event (tui->interp_ui_out ()); } } @@ -100,7 +112,7 @@ tui_on_signal_received (enum gdb_signal siggnal) if (tui == NULL) continue; - print_signal_received_reason (tui_ui_out (tui), siggnal); + print_signal_received_reason (tui->interp_ui_out (), siggnal); } } @@ -116,7 +128,7 @@ tui_on_end_stepping_range (void) if (tui == NULL) continue; - print_end_stepping_range_reason (tui_ui_out (tui)); + print_end_stepping_range_reason (tui->interp_ui_out ()); } } @@ -132,7 +144,7 @@ tui_on_signal_exited (enum gdb_signal siggnal) if (tui == NULL) continue; - print_signal_exited_reason (tui_ui_out (tui), siggnal); + print_signal_exited_reason (tui->interp_ui_out (), siggnal); } } @@ -148,7 +160,7 @@ tui_on_exited (int exitstatus) if (tui == NULL) continue; - print_exited_reason (tui_ui_out (tui), exitstatus); + print_exited_reason (tui->interp_ui_out (), exitstatus); } } @@ -164,7 +176,7 @@ tui_on_no_history (void) if (tui == NULL) continue; - print_no_history_reason (tui_ui_out (tui)); + print_no_history_reason (tui->interp_ui_out ()); } } @@ -215,19 +227,19 @@ tui_on_user_selected_context_changed (user_selected_what selection) continue; if (selection & USER_SELECTED_INFERIOR) - print_selected_inferior (tui_ui_out (tui)); + print_selected_inferior (tui->interp_ui_out ()); if (tp != NULL && ((selection & (USER_SELECTED_THREAD | USER_SELECTED_FRAME)))) - print_selected_thread_frame (tui_ui_out (tui), selection); + print_selected_thread_frame (tui->interp_ui_out (), selection); } } /* These implement the TUI interpreter. */ -static void * -tui_init (struct interp *self, int top_level) +void +tui_interp::init (bool top_level) { /* Install exit handler to leave the screen in a good shape. */ atexit (tui_exit); @@ -238,12 +250,10 @@ tui_init (struct interp *self, int top_level) tui_initialize_win (); if (ui_file_isatty (gdb_stdout)) tui_initialize_readline (); - - return NULL; } -static int -tui_resume (void *data) +void +tui_interp::resume () { struct ui *ui = current_ui; struct ui_file *stream; @@ -268,19 +278,17 @@ tui_resume (void *data) if (tui_start_enabled) tui_enable (); - return 1; } -static int -tui_suspend (void *data) +void +tui_interp::suspend () { tui_start_enabled = tui_active; tui_disable (); - return 1; } -static struct ui_out * -tui_ui_out (struct interp *self) +ui_out * +tui_interp::interp_ui_out () { if (tui_active) return tui_out; @@ -288,31 +296,19 @@ tui_ui_out (struct interp *self) return tui_old_uiout; } -static struct gdb_exception -tui_exec (void *data, const char *command_str) +gdb_exception +tui_interp::exec (const char *command_str) { internal_error (__FILE__, __LINE__, _("tui_exec called")); } -/* The TUI interpreter's vtable. */ - -static const struct interp_procs tui_interp_procs = { - tui_init, - tui_resume, - tui_suspend, - tui_exec, - tui_ui_out, - cli_set_logging, - cli_interpreter_pre_command_loop, - cli_interpreter_supports_command_editing, -}; /* Factory for TUI interpreters. */ static struct interp * tui_interp_factory (const char *name) { - return interp_new (name, &tui_interp_procs, NULL); + return new tui_interp (name); } /* Provide a prototype to silence -Wmissing-prototypes. */