2009-02-06 21:33:59 +00:00
|
|
|
|
/* gdb commands implemented in Python
|
|
|
|
|
|
|
2026-01-05 08:13:29 -07:00
|
|
|
|
Copyright (C) 2008-2026 Free Software Foundation, Inc.
|
2009-02-06 21:33:59 +00:00
|
|
|
|
|
|
|
|
|
|
This file is part of GDB.
|
|
|
|
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
|
|
the Free Software Foundation; either version 3 of the License, or
|
|
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
|
|
|
|
|
|
|
|
|
|
|
* python/python-internal.h (struct language_defn): Declare.
(python_gdbarch, python_language): Likewise.
(ensure_python_env): Add prototype.
(make_cleanup_py_restore_gil): Remove prototype.
* python/python.c: Include "arch-utils.h", "value.h" and "language.h".
(python_gdbarch, python_language): New global variables.
(struct python_env): New data type.
(ensure_python_env, restore_python_env): New functions.
(eval_python_from_control_command): Call ensure_python_env to
install current architecture and language.
(python_command, gdbpy_new_objfile): Likewise.
* python/python-cmd.c: Include "arch-utils.h" and "language.h".
(cmdpy_destroyer, cmdpy_function, cmdpy_completer): Call
ensure_python_env.
* python/python-type.c (clean_up_objfile_types): Likewise.
* python/python-objfile.c: Include "language.h".
(clean_up_objfile): Call ensure_python_env.
* python/python-prettyprint.c (apply_val_pretty_printer): Likewise.
(apply_varobj_pretty_printer): Do not call PyGILState_Ensure.
* varobj.c (varobj_ensure_python_env): New helper function.
(varobj_get_display_hint, update_dynamic_varobj_children,
install_default_visualizer, varobj_set_visualizer, free_variable,
value_get_print_value): Call it.
(value_get_print_value): Add varobj argument instead of pretty
printer argument. Update all callers.
* python/python-utils.c (py_gil_restore, make_cleanup_py_restore_gil):
Remove.
* value.h (internal_function_fn): Add GDBARCH and LANGUAGE argument.
(call_internal_function): Likewise.
* value.c (call_internal_function): Likewise. Pass to handler.
* eval.c (evaluate_subexp_standard): Update call.
* python/python-function.c: Include "language.h".
(fnpy_call): Add GDBARCH and LANGAUAGE arguments and call
make_cleanup_python_env.
* python/python-value.c (builtin_type_pyint, builtin_type_pyfloat,
builtin_type_pylong, builtin_type_pybool, builtin_type_pychar,
valpy_str): Use python_gdbarch and python_language instead of
current_gdbarch and current_language.
* python/python-type.c (typy_lookup_typename): Likewise.
2009-07-02 17:04:23 +00:00
|
|
|
|
#include "arch-utils.h"
|
2009-02-06 21:33:59 +00:00
|
|
|
|
#include "value.h"
|
|
|
|
|
|
#include "python-internal.h"
|
|
|
|
|
|
#include "charset.h"
|
2024-04-23 15:22:44 -04:00
|
|
|
|
#include "cli/cli-cmds.h"
|
2009-02-06 21:33:59 +00:00
|
|
|
|
#include "cli/cli-decode.h"
|
|
|
|
|
|
#include "completer.h"
|
* python/python-internal.h (struct language_defn): Declare.
(python_gdbarch, python_language): Likewise.
(ensure_python_env): Add prototype.
(make_cleanup_py_restore_gil): Remove prototype.
* python/python.c: Include "arch-utils.h", "value.h" and "language.h".
(python_gdbarch, python_language): New global variables.
(struct python_env): New data type.
(ensure_python_env, restore_python_env): New functions.
(eval_python_from_control_command): Call ensure_python_env to
install current architecture and language.
(python_command, gdbpy_new_objfile): Likewise.
* python/python-cmd.c: Include "arch-utils.h" and "language.h".
(cmdpy_destroyer, cmdpy_function, cmdpy_completer): Call
ensure_python_env.
* python/python-type.c (clean_up_objfile_types): Likewise.
* python/python-objfile.c: Include "language.h".
(clean_up_objfile): Call ensure_python_env.
* python/python-prettyprint.c (apply_val_pretty_printer): Likewise.
(apply_varobj_pretty_printer): Do not call PyGILState_Ensure.
* varobj.c (varobj_ensure_python_env): New helper function.
(varobj_get_display_hint, update_dynamic_varobj_children,
install_default_visualizer, varobj_set_visualizer, free_variable,
value_get_print_value): Call it.
(value_get_print_value): Add varobj argument instead of pretty
printer argument. Update all callers.
* python/python-utils.c (py_gil_restore, make_cleanup_py_restore_gil):
Remove.
* value.h (internal_function_fn): Add GDBARCH and LANGUAGE argument.
(call_internal_function): Likewise.
* value.c (call_internal_function): Likewise. Pass to handler.
* eval.c (evaluate_subexp_standard): Update call.
* python/python-function.c: Include "language.h".
(fnpy_call): Add GDBARCH and LANGAUAGE arguments and call
make_cleanup_python_env.
* python/python-value.c (builtin_type_pyint, builtin_type_pyfloat,
builtin_type_pylong, builtin_type_pybool, builtin_type_pychar,
valpy_str): Use python_gdbarch and python_language instead of
current_gdbarch and current_language.
* python/python-type.c (typy_lookup_typename): Likewise.
2009-07-02 17:04:23 +00:00
|
|
|
|
#include "language.h"
|
2009-02-06 21:33:59 +00:00
|
|
|
|
|
|
|
|
|
|
/* Struct representing built-in completion types. */
|
|
|
|
|
|
struct cmdpy_completer
|
|
|
|
|
|
{
|
-Wwrite-strings: The Rest
This is the remainder boring constification that all looks more of less
borderline obvious IMO.
gdb/ChangeLog:
2017-04-05 Pedro Alves <palves@redhat.com>
* ada-exp.y (yyerror): Constify.
* ada-lang.c (bound_name, get_selections)
(ada_variant_discrim_type)
(ada_variant_discrim_name, ada_value_struct_elt)
(ada_lookup_struct_elt_type, is_unchecked_variant)
(ada_which_variant_applies, standard_exc, ada_get_next_arg)
(catch_ada_exception_command_split)
(catch_ada_assert_command_split, catch_assert_command)
(ada_op_name): Constify.
* ada-lang.h (ada_yyerror, get_selections)
(ada_variant_discrim_name, ada_value_struct_elt): Constify.
* arc-tdep.c (arc_print_frame_cache): Constify.
* arm-tdep.c (arm_skip_stub): Constify.
* ax-gdb.c (gen_binop, gen_struct_ref_recursive, gen_struct_ref)
(gen_aggregate_elt_ref): Constify.
* bcache.c (print_bcache_statistics): Constify.
* bcache.h (print_bcache_statistics): Constify.
* break-catch-throw.c (catch_exception_command_1):
* breakpoint.c (struct ep_type_description::description):
Constify.
(add_solib_catchpoint): Constify.
(catch_fork_command_1): Add cast.
(add_catch_command): Constify.
* breakpoint.h (add_catch_command, add_solib_catchpoint):
Constify.
* bsd-uthread.c (bsd_uthread_state): Constify.
* buildsym.c (patch_subfile_names): Constify.
* buildsym.h (next_symbol_text_func, patch_subfile_names):
Constify.
* c-exp.y (yyerror): Constify.
(token::oper): Constify.
* c-lang.h (c_yyerror, cp_print_class_member): Constify.
* c-varobj.c (cplus_describe_child): Constify.
* charset.c (find_charset_names): Add cast.
(find_charset_names): Constify array and add const_cast.
* cli/cli-cmds.c (complete_command, cd_command): Constify.
(edit_command): Constify.
* cli/cli-decode.c (lookup_cmd): Constify.
* cli/cli-dump.c (dump_memory_command, dump_value_command):
Constify.
(struct dump_context): Constify.
(add_dump_command, restore_command): Constify.
* cli/cli-script.c (get_command_line): Constify.
* cli/cli-script.h (get_command_line): Constify.
* cli/cli-utils.c (check_for_argument): Constify.
* cli/cli-utils.h (check_for_argument): Constify.
* coff-pe-read.c (struct read_pe_section_data): Constify.
* command.h (lookup_cmd): Constify.
* common/print-utils.c (decimal2str): Constify.
* completer.c (gdb_print_filename): Constify.
* corefile.c (set_gnutarget): Constify.
* cp-name-parser.y (yyerror): Constify.
* cp-valprint.c (cp_print_class_member): Constify.
* cris-tdep.c (cris_register_name, crisv32_register_name):
Constify.
* d-exp.y (yyerror): Constify.
(struct token::oper): Constify.
* d-lang.h (d_yyerror): Constify.
* dbxread.c (struct header_file_location::name): Constify.
(add_old_header_file, add_new_header_file, last_function_name)
(dbx_next_symbol_text, add_bincl_to_list)
(find_corresponding_bincl_psymtab, set_namestring)
(find_stab_function_addr, read_dbx_symtab, start_psymtab)
(dbx_end_psymtab, read_ofile_symtab, process_one_symbol):
* defs.h (command_line_input, print_address_symbolic)
(deprecated_readline_begin_hook): Constify.
* dwarf2read.c (anonymous_struct_prefix, dwarf_bool_name):
Constify.
* event-top.c (handle_line_of_input): Constify and add cast.
* exceptions.c (catch_errors): Constify.
* exceptions.h (catch_errors): Constify.
* expprint.c (print_subexp_standard, op_string, op_name)
(op_name_standard, dump_raw_expression, dump_raw_expression):
* expression.h (op_name, op_string, dump_raw_expression):
Constify.
* f-exp.y (yyerror): Constify.
(struct token::oper): Constify.
(struct f77_boolean_val::name): Constify.
* f-lang.c (f_word_break_characters): Constify.
* f-lang.h (f_yyerror): Constify.
* fork-child.c (fork_inferior): Add cast.
* frv-tdep.c (struct gdbarch_tdep::register_names): Constify.
(new_variant): Constify.
* gdbarch.sh (pstring_ptr, pstring_list): Constify.
* gdbarch.c: Regenerate.
* gdbcore.h (set_gnutarget): Constify.
* go-exp.y (yyerror): Constify.
(token::oper): Constify.
* go-lang.h (go_yyerror): Constify.
* go32-nat.c (go32_sysinfo): Constify.
* guile/scm-breakpoint.c (gdbscm_breakpoint_expression): Constify.
* guile/scm-cmd.c (cmdscm_function): Constify.
* guile/scm-param.c (pascm_param_value): Constify.
* h8300-tdep.c (h8300_register_name, h8300s_register_name)
(h8300sx_register_name): Constify.
* hppa-tdep.c (hppa32_register_name, hppa64_register_name):
Constify.
* ia64-tdep.c (ia64_register_names): Constify.
* infcmd.c (construct_inferior_arguments): Constify.
(path_command, attach_post_wait): Constify.
* language.c (show_range_command, show_case_command)
(unk_lang_error): Constify.
* language.h (language_defn::la_error)
(language_defn::la_name_of_this): Constify.
* linespec.c (decode_line_2): Constify.
* linux-thread-db.c (thread_db_err_str): Constify.
* lm32-tdep.c (lm32_register_name): Constify.
* m2-exp.y (yyerror): Constify.
* m2-lang.h (m2_yyerror): Constify.
* m32r-tdep.c (m32r_register_names): Constify and make static.
* m68hc11-tdep.c (m68hc11_register_names): Constify.
* m88k-tdep.c (m88k_register_name): Constify.
* macroexp.c (appendmem): Constify.
* mdebugread.c (fdr_name, add_data_symbol, parse_type)
(upgrade_type, parse_external, parse_partial_symbols)
(mdebug_next_symbol_text, cross_ref, mylookup_symbol, new_psymtab)
(new_symbol): Constify.
* memattr.c (mem_info_command): Constify.
* mep-tdep.c (register_name_from_keyword): Constify.
* mi/mi-cmd-env.c (mi_cmd_env_path, _initialize_mi_cmd_env):
Constify.
* mi/mi-cmd-stack.c (list_args_or_locals): Constify.
* mi/mi-cmd-var.c (mi_cmd_var_show_attributes): Constify.
* mi/mi-main.c (captured_mi_execute_command): Constify and add
cast.
(mi_execute_async_cli_command): Constify.
* mips-tdep.c (mips_register_name): Constify.
* mn10300-tdep.c (register_name, mn10300_generic_register_name)
(am33_register_name, am33_2_register_name)
* moxie-tdep.c (moxie_register_names): Constify.
* nat/linux-osdata.c (osdata_type): Constify fields.
* nto-tdep.c (nto_parse_redirection): Constify.
* objc-lang.c (lookup_struct_typedef, lookup_objc_class)
(lookup_child_selector): Constify.
(objc_methcall::name): Constify.
* objc-lang.h (lookup_objc_class, lookup_child_selector)
(lookup_struct_typedef): Constify.
* objfiles.c (pc_in_section): Constify.
* objfiles.h (pc_in_section): Constify.
* p-exp.y (struct token::oper): Constify.
(yyerror): Constify.
* p-lang.h (pascal_yyerror): Constify.
* parser-defs.h (op_name_standard): Constify.
(op_print::string): Constify.
(exp_descriptor::op_name): Constify.
* printcmd.c (print_address_symbolic): Constify.
* psymtab.c (print_partial_symbols): Constify.
* python/py-breakpoint.c (stop_func): Constify.
(bppy_get_expression): Constify.
* python/py-cmd.c (cmdpy_completer::name): Constify.
(cmdpy_function): Constify.
* python/py-event.c (evpy_add_attribute)
(gdbpy_initialize_event_generic): Constify.
* python/py-event.h (evpy_add_attribute)
(gdbpy_initialize_event_generic): Constify.
* python/py-evts.c (add_new_registry): Constify.
* python/py-finishbreakpoint.c (outofscope_func): Constify.
* python/py-framefilter.c (get_py_iter_from_func): Constify.
* python/py-inferior.c (get_buffer): Add cast.
* python/py-param.c (parm_constant::name): Constify.
* python/py-unwind.c (fprint_frame_id): Constify.
* python/python.c (gdbpy_parameter_value): Constify.
* remote-fileio.c (remote_fio_func_map): Make 'name' const.
* remote.c (memory_packet_config::name): Constify.
(show_packet_config_cmd, remote_write_bytes)
(remote_buffer_add_string):
* reverse.c (exec_reverse_once): Constify.
* rs6000-tdep.c (variant::name, variant::description): Constify.
* rust-exp.y (rustyyerror): Constify.
* rust-lang.c (rust_op_name): Constify.
* rust-lang.h (rustyyerror): Constify.
* serial.h (serial_ops::name): Constify.
* sh-tdep.c (sh_sh_register_name, sh_sh3_register_name)
(sh_sh3e_register_name, sh_sh2e_register_name)
(sh_sh2a_register_name, sh_sh2a_nofpu_register_name)
(sh_sh_dsp_register_name, sh_sh3_dsp_register_name)
(sh_sh4_register_name, sh_sh4_nofpu_register_name)
(sh_sh4al_dsp_register_name): Constify.
* sh64-tdep.c (sh64_register_name): Constify.
* solib-darwin.c (lookup_symbol_from_bfd): Constify.
* spu-tdep.c (spu_register_name, info_spu_dma_cmdlist): Constify.
* stabsread.c (patch_block_stabs, read_type_number)
(ref_map::stabs, ref_add, process_reference)
(symbol_reference_defined, define_symbol, define_symbol)
(error_type, read_type, read_member_functions, read_cpp_abbrev)
(read_one_struct_field, read_struct_fields, read_baseclasses)
(read_tilde_fields, read_struct_type, read_array_type)
(read_enum_type, read_sun_builtin_type, read_sun_floating_type)
(read_huge_number, read_range_type, read_args, common_block_start)
(find_name_end): Constify.
* stabsread.h (common_block_start, define_symbol)
(process_one_symbol, symbol_reference_defined, ref_add):
* symfile.c (get_section_index, add_symbol_file_command):
* symfile.h (get_section_index): Constify.
* target-descriptions.c (tdesc_type::name): Constify.
(tdesc_free_type): Add cast.
* target.c (find_default_run_target):
(add_deprecated_target_alias, find_default_run_target)
(target_announce_detach): Constify.
(do_option): Constify.
* target.h (add_deprecated_target_alias): Constify.
* thread.c (print_thread_info_1): Constify.
* top.c (deprecated_readline_begin_hook, command_line_input):
Constify.
(init_main): Add casts.
* top.h (handle_line_of_input): Constify.
* tracefile-tfile.c (tfile_write_uploaded_tsv): Constify.
* tracepoint.c (tvariables_info_1, trace_status_mi): Constify.
(tfind_command): Rename to ...
(tfind_command_1): ... this and constify.
(tfind_command): New function.
(tfind_end_command, tfind_start_command): Adjust.
(encode_source_string): Constify.
* tracepoint.h (encode_source_string): Constify.
* tui/tui-data.c (tui_partial_win_by_name): Constify.
* tui/tui-data.h (tui_partial_win_by_name): Constify.
* tui/tui-source.c (tui_set_source_content_nil): Constify.
* tui/tui-source.h (tui_set_source_content_nil): Constify.
* tui/tui-win.c (parse_scrolling_args): Constify.
* tui/tui-windata.c (tui_erase_data_content): Constify.
* tui/tui-windata.h (tui_erase_data_content): Constify.
* tui/tui-winsource.c (tui_erase_source_content): Constify.
* tui/tui.c (tui_enable): Add cast.
* utils.c (defaulted_query): Constify.
(init_page_info): Add cast.
(puts_debug, subset_compare): Constify.
* utils.h (subset_compare): Constify.
* varobj.c (varobj_format_string): Constify.
* varobj.h (varobj_format_string): Constify.
* vax-tdep.c (vax_register_name): Constify.
* windows-nat.c (windows_detach): Constify.
* xcoffread.c (process_linenos, xcoff_next_symbol_text): Constify.
* xml-support.c (gdb_xml_end_element): Constify.
* xml-tdesc.c (tdesc_start_reg): Constify.
* xstormy16-tdep.c (xstormy16_register_name): Constify.
* xtensa-tdep.c (xtensa_find_register_by_name): Constify.
* xtensa-tdep.h (xtensa_register_t::name): Constify.
gdb/gdbserver/ChangeLog:
2017-04-05 Pedro Alves <palves@redhat.com>
* gdbreplay.c (sync_error): Constify.
* linux-x86-low.c (push_opcode): Constify.
2017-04-05 19:21:37 +01:00
|
|
|
|
/* Python symbol name. */
|
|
|
|
|
|
const char *name;
|
2009-02-06 21:33:59 +00:00
|
|
|
|
/* Completion function. */
|
2012-06-13 15:41:24 +00:00
|
|
|
|
completer_ftype *completer;
|
2009-02-06 21:33:59 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
2014-05-13 19:44:51 -07:00
|
|
|
|
static const struct cmdpy_completer completers[] =
|
2009-02-06 21:33:59 +00:00
|
|
|
|
{
|
|
|
|
|
|
{ "COMPLETE_NONE", noop_completer },
|
gdb: split apart two different types of filename completion
Unfortunately we have two different types of filename completion in
GDB.
The majority of commands have what I call unquoted filename
completion, this is for commands like 'set logging file ...', 'target
core ...', and 'add-auto-load-safe-path ...'. For these commands
everything after the command name (that is not a command option) is
treated as a single filename. If the filename contains white space
then this does not need to be escaped, nor does the filename need to
be quoted. In fact, the filename argument is not de-quoted, and does
not have any escaping removed, so if a user does try to add such
things, they will be treated as part of the filename. As an example:
(gdb) target core "/path/that contains/some white space"
Will look for a directory calls '"' (double quotes) in the local
directory.
A small number of commands do de-quote and remove escapes from
filename arguments. These command accept what I call quoted and
escaped filenames. Right now these are the commands that specify the
file for GDB to debug, so:
file
exec-file
symbol-file
add-symbol-file
remove-symbol-file
As an example of this in action:
(gdb) file "/path/that contains/some white space"
In this case GDB would load the file:
/path/that contains/some white space
Current filename completion always assumes that filenames can be
quoted, though escaping doesn't work in completion right now. But the
assumption that quoting is allowed is clearly wrong.
This commit splits filename completion into two. The existing
filename_completer is retained, and is used for unquoted filenames. A
second filename_maybe_quoted_completer is added which can be used for
completing quoted filenames.
The filename completion test has been extended to cover more cases.
As part of the extended testing I need to know the character that
should be used to separate filenames within a path. For this TCL 8.6+
has $::tcl_platform(pathSeparator). To support older versions of TCL
I've added some code to testsuite/lib/gdb.exp.
You might notice that after this commit the completion for unquoted
files is all done in the brkchars phase, that is the function
filename_completer_handle_brkchars calculates the completions and
marks the completion_tracker as using a custom word point. The reason
for this is that we don't want to break on white space for this
completion, but if we rely on readline to find the completion word,
readline will consider the entire command line, and with no white
space in the word break character set, readline will end up using the
entire command line as the word to complete.
For now at least, the completer for quoted filenames does generate its
completions during the completion phase, though this is going to
change in a later commit.
2024-06-22 10:10:29 +01:00
|
|
|
|
{ "COMPLETE_FILENAME", filename_maybe_quoted_completer },
|
2009-02-06 21:33:59 +00:00
|
|
|
|
{ "COMPLETE_LOCATION", location_completer },
|
|
|
|
|
|
{ "COMPLETE_COMMAND", command_completer },
|
2017-07-17 11:55:42 +01:00
|
|
|
|
{ "COMPLETE_SYMBOL", symbol_completer },
|
2013-11-07 12:32:31 +00:00
|
|
|
|
{ "COMPLETE_EXPRESSION", expression_completer },
|
2009-02-06 21:33:59 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
#define N_COMPLETERS (sizeof (completers) / sizeof (completers[0]))
|
|
|
|
|
|
|
|
|
|
|
|
/* A gdb command. For the time being only ordinary commands (not
|
|
|
|
|
|
set/show commands) are allowed. */
|
2025-10-25 23:55:29 +01:00
|
|
|
|
struct cmdpy_object : public PyObject
|
2009-02-06 21:33:59 +00:00
|
|
|
|
{
|
|
|
|
|
|
/* The corresponding gdb command object, or NULL if the command is
|
|
|
|
|
|
no longer installed. */
|
|
|
|
|
|
struct cmd_list_element *command;
|
|
|
|
|
|
|
|
|
|
|
|
/* A prefix command requires storage for a list of its sub-commands.
|
|
|
|
|
|
A pointer to this is passed to add_prefix_command, and to add_cmd
|
|
|
|
|
|
for sub-commands of that prefix. If this Command is not a prefix
|
|
|
|
|
|
command, then this field is unused. */
|
|
|
|
|
|
struct cmd_list_element *sub_list;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
gdb/python: add type traits check for all PyObject sub-classes
All of our custom Python types are created as structs, like this:
struct some_new_type : public PyObject
{
... various fields ...
};
Then instances of this struct are created by calling PyObject_New,
either directly within GDB's C++ code, or within Python when a user's
Python script creates an instance of that class.
The problem is that Python is written in C, and PyObject_New doesn't
call any constructors for `some_new_type`, nor for any of the fields
within `some_new_type`.
If `some_new_type` is Plain Old Data (POD), then this is fine. Or, to
be more C++ specific, if `some_new_type` is trivially default
constructable, then we're fine.
But if a field within `some_new_type` has a non-trivial constructor,
then we're in trouble as that constructor will never be run.
An example of a problematic field type is frame_info_ptr. The
constructor for this type registers the new object with a central
management object, recording the `this` pointer, using this type within
`some_new_type` will not work as expected; frame invalidation will not
show up within the frame_info_ptr as you might expect.
And so, this type trait exists. Whenever a struct is created to define
a new Python type we should add a line like:
static_assert (gdb::is_python_allocatable_v<some_new_type>);
This will fail if any field of `some_new_type` are unsuitable for this
use.
We don't actually check is_trivially_default_constructible here. Some
types, e.g. ui_file_style::color, have non-trivial (or no default)
constructors, but are still safe to use within `some_new_type` because
their constructors just initialise data fields; there's nothing
"special" that the constructor does that cannot be achieved by
assigning the fields after creation with PyObject_New.
What actually matters is that the type is trivially destructible
(Python won't call C++ destructors, so destructors with side effects,
like deregistering from a list, would be skipped) and trivially
copyable (Python may copy objects with memcpy). Types like
frame_info_ptr, whose constructors and destructors have side effects
such as registering with a central management object, will be caught
because they are neither trivially destructible nor trivially copyable.
Simple POD types like ui_file_style are trivially destructible and
copyable, so pass this trait.
This commit adds the new type trait, and makes use of it in all cases
but one, pending_frame_object in python/py-unwind.c, has a field of
type frame_info_ptr, which is currently broken. This will be fixed,
and the static_assert added, in the next commit.
Approved-By: Tom Tromey <tom@tromey.com>
2026-05-14 09:39:57 +01:00
|
|
|
|
static_assert (gdb::is_python_allocatable_v<cmdpy_object>);
|
|
|
|
|
|
|
2025-10-21 10:00:20 -06:00
|
|
|
|
extern PyTypeObject cmdpy_object_type;
|
2009-02-06 21:33:59 +00:00
|
|
|
|
|
|
|
|
|
|
/* Constants used by this module. */
|
|
|
|
|
|
static PyObject *invoke_cst;
|
|
|
|
|
|
static PyObject *complete_cst;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Python function which wraps dont_repeat. */
|
|
|
|
|
|
static PyObject *
|
|
|
|
|
|
cmdpy_dont_repeat (PyObject *self, PyObject *args)
|
|
|
|
|
|
{
|
|
|
|
|
|
dont_repeat ();
|
2026-05-15 21:38:12 +02:00
|
|
|
|
return py_none ().release ();
|
2009-02-06 21:33:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Called if the gdb cmd_list_element is destroyed. */
|
2010-05-25 15:27:17 +00:00
|
|
|
|
|
2009-02-06 21:33:59 +00:00
|
|
|
|
static void
|
|
|
|
|
|
cmdpy_destroyer (struct cmd_list_element *self, void *context)
|
|
|
|
|
|
{
|
Change how Python architecture and language are handled
Currently, gdb's Python layer captures the current architecture and
language when "entering" Python code. This has some undesirable
effects, and so this series changes how this is handled.
First, there is code like this:
gdbpy_enter enter_py (python_gdbarch, python_language);
This is incorrect, because both of these are NULL when not otherwise
assigned. This can cause crashes in some cases -- I've added one to
the test suite. (Note that this crasher is just an example, other
ones along the same lines are possible.)
Second, when the language is captured in this way, it means that
Python code cannot affect the current language for its own purposes.
It's reasonable to want to write code like this:
gdb.execute('set language mumble')
... stuff using the current language
gdb.execute('set language previous-value')
However, this won't actually work, because the language is captured on
entry. I've added a test to show this as well.
This patch changes gdb to try to avoid capturing the current values.
The Python concept of the current gdbarch is only set in those few
cases where a non-default value is computed or needed; and the
language is not captured at all -- instead, in the cases where it's
required, the current language is temporarily changed.
2022-01-04 08:02:24 -07:00
|
|
|
|
gdbpy_enter enter_py;
|
2009-02-06 21:33:59 +00:00
|
|
|
|
|
|
|
|
|
|
/* Release our hold on the command object. */
|
2017-01-11 16:28:43 -07:00
|
|
|
|
gdbpy_ref<cmdpy_object> cmd ((cmdpy_object *) context);
|
2009-02-06 21:33:59 +00:00
|
|
|
|
cmd->command = NULL;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Called by gdb to invoke the command. */
|
2010-05-25 15:27:17 +00:00
|
|
|
|
|
2009-02-06 21:33:59 +00:00
|
|
|
|
static void
|
2021-06-29 23:10:32 -04:00
|
|
|
|
cmdpy_function (const char *args, int from_tty, cmd_list_element *command)
|
2009-02-06 21:33:59 +00:00
|
|
|
|
{
|
2021-06-25 21:35:40 -04:00
|
|
|
|
cmdpy_object *obj = (cmdpy_object *) command->context ();
|
2009-02-06 21:33:59 +00:00
|
|
|
|
|
Change how Python architecture and language are handled
Currently, gdb's Python layer captures the current architecture and
language when "entering" Python code. This has some undesirable
effects, and so this series changes how this is handled.
First, there is code like this:
gdbpy_enter enter_py (python_gdbarch, python_language);
This is incorrect, because both of these are NULL when not otherwise
assigned. This can cause crashes in some cases -- I've added one to
the test suite. (Note that this crasher is just an example, other
ones along the same lines are possible.)
Second, when the language is captured in this way, it means that
Python code cannot affect the current language for its own purposes.
It's reasonable to want to write code like this:
gdb.execute('set language mumble')
... stuff using the current language
gdb.execute('set language previous-value')
However, this won't actually work, because the language is captured on
entry. I've added a test to show this as well.
This patch changes gdb to try to avoid capturing the current values.
The Python concept of the current gdbarch is only set in those few
cases where a non-default value is computed or needed; and the
language is not captured at all -- instead, in the cases where it's
required, the current language is temporarily changed.
2022-01-04 08:02:24 -07:00
|
|
|
|
gdbpy_enter enter_py;
|
2009-02-06 21:33:59 +00:00
|
|
|
|
|
gdb/python/guile: user created prefix commands get help list
Consider GDB's builtin prefix set/show prefix sub-commands, if they
are invoked with no sub-command name then they work like this:
(gdb) show print
print address: Printing of addresses is on.
print array: Pretty formatting of arrays is off.
print array-indexes: Printing of array indexes is off.
print asm-demangle: Demangling of C++/ObjC names in disassembly listings is off.
... cut lots of lines ...
(gdb) set print
List of set print subcommands:
set print address -- Set printing of addresses.
set print array -- Set pretty formatting of arrays.
set print array-indexes -- Set printing of array indexes.
set print asm-demangle -- Set demangling of C++/ObjC names in disassembly listings.
... cut lots of lines ...
Type "help set print" followed by set print subcommand name for full documentation.
Type "apropos word" to search for commands related to "word".
Type "apropos -v word" for full documentation of commands related to "word".
Command name abbreviations are allowed if unambiguous.
(gdb)
That is 'show print' lists the values of all settings under the
'print' prefix, and 'set print' lists the help text for all settings
under the 'set print' prefix.
Now, if we try to create something similar using the Python API:
(gdb) python gdb.ParameterPrefix("my-prefix", gdb.COMMAND_NONE)
(gdb) python gdb.Parameter("my-prefix foo", gdb.COMMAND_OBSCURE, gdb.PARAM_BOOLEAN)
(gdb) show my-prefix
(gdb) set my-prefix
Neither 'show my-prefix' or 'set my-prefix' gives us the same details
relating to the sub-commands that we get with the builtin prefix
commands.
This commit aims to address this.
Currently, in cmdpy_init, when a new command is created, we always set
the commands callback function to cmdpy_function. It is within
cmdpy_function that we spot that the command is a prefix command, and
that there is no gdb.Command.invoke method, and so return early.
This commit changes things so that the rules are now:
1. For NON prefix commands, we continue to use cmdpy_function.
2. For prefix commands that do have a gdb.Command.invoke
method (i.e. can handle unknown sub-commands), continue to use
cmdpy_function.
3. For all other prefix commands, don't use cmdpy_function, instead
use GDB's normal callback function for set/show prefixes.
This requires splitting the current call to add_prefix_cmd into either
a call to add_prefix_cmd, add_show_prefix_cmd, or
add_basic_prefix_cmd, as appropriate.
After these changes, we now see this:
(gdb) python gdb.ParameterPrefix("my-prefix", gdb.COMMAND_NONE) │
(gdb) python gdb.Parameter("my-prefix foo", gdb.COMMAND_OBSCURE, gdb.PARAM_BOOLEAN)
(gdb) show my-prefix │
my-prefix foo: The current value of 'my-prefix foo' is "off".
(gdb) set my-prefix
List of "set my-prefix" subcommands:
set my-prefix foo -- Set the current value of 'my-prefix foo'.
Type "help set my-prefix" followed by subcommand name for full documentation.
Type "apropos word" to search for commands related to "word".
Type "apropos -v word" for full documentation of commands related to "word".
Command name abbreviations are allowed if unambiguous.
(gdb)
Which matches how a prefix defined within GDB would act.
I have made the same changes to the Guile API.
2025-04-12 09:15:53 +01:00
|
|
|
|
if (obj == nullptr)
|
2009-02-06 21:33:59 +00:00
|
|
|
|
error (_("Invalid invocation of Python command object."));
|
|
|
|
|
|
|
gdb/python/guile: user created prefix commands get help list
Consider GDB's builtin prefix set/show prefix sub-commands, if they
are invoked with no sub-command name then they work like this:
(gdb) show print
print address: Printing of addresses is on.
print array: Pretty formatting of arrays is off.
print array-indexes: Printing of array indexes is off.
print asm-demangle: Demangling of C++/ObjC names in disassembly listings is off.
... cut lots of lines ...
(gdb) set print
List of set print subcommands:
set print address -- Set printing of addresses.
set print array -- Set pretty formatting of arrays.
set print array-indexes -- Set printing of array indexes.
set print asm-demangle -- Set demangling of C++/ObjC names in disassembly listings.
... cut lots of lines ...
Type "help set print" followed by set print subcommand name for full documentation.
Type "apropos word" to search for commands related to "word".
Type "apropos -v word" for full documentation of commands related to "word".
Command name abbreviations are allowed if unambiguous.
(gdb)
That is 'show print' lists the values of all settings under the
'print' prefix, and 'set print' lists the help text for all settings
under the 'set print' prefix.
Now, if we try to create something similar using the Python API:
(gdb) python gdb.ParameterPrefix("my-prefix", gdb.COMMAND_NONE)
(gdb) python gdb.Parameter("my-prefix foo", gdb.COMMAND_OBSCURE, gdb.PARAM_BOOLEAN)
(gdb) show my-prefix
(gdb) set my-prefix
Neither 'show my-prefix' or 'set my-prefix' gives us the same details
relating to the sub-commands that we get with the builtin prefix
commands.
This commit aims to address this.
Currently, in cmdpy_init, when a new command is created, we always set
the commands callback function to cmdpy_function. It is within
cmdpy_function that we spot that the command is a prefix command, and
that there is no gdb.Command.invoke method, and so return early.
This commit changes things so that the rules are now:
1. For NON prefix commands, we continue to use cmdpy_function.
2. For prefix commands that do have a gdb.Command.invoke
method (i.e. can handle unknown sub-commands), continue to use
cmdpy_function.
3. For all other prefix commands, don't use cmdpy_function, instead
use GDB's normal callback function for set/show prefixes.
This requires splitting the current call to add_prefix_cmd into either
a call to add_prefix_cmd, add_show_prefix_cmd, or
add_basic_prefix_cmd, as appropriate.
After these changes, we now see this:
(gdb) python gdb.ParameterPrefix("my-prefix", gdb.COMMAND_NONE) │
(gdb) python gdb.Parameter("my-prefix foo", gdb.COMMAND_OBSCURE, gdb.PARAM_BOOLEAN)
(gdb) show my-prefix │
my-prefix foo: The current value of 'my-prefix foo' is "off".
(gdb) set my-prefix
List of "set my-prefix" subcommands:
set my-prefix foo -- Set the current value of 'my-prefix foo'.
Type "help set my-prefix" followed by subcommand name for full documentation.
Type "apropos word" to search for commands related to "word".
Type "apropos -v word" for full documentation of commands related to "word".
Command name abbreviations are allowed if unambiguous.
(gdb)
Which matches how a prefix defined within GDB would act.
I have made the same changes to the Guile API.
2025-04-12 09:15:53 +01:00
|
|
|
|
/* If we get here for a prefix command then the prefix command had an
|
|
|
|
|
|
'invoke' method when it was created. If the 'invoke' method is now
|
|
|
|
|
|
missing, then the user has done something weird (like deleting the
|
|
|
|
|
|
invoke method, yuck!). */
|
|
|
|
|
|
if (!PyObject_HasAttr ((PyObject *) obj, invoke_cst))
|
|
|
|
|
|
error (_("Python command object missing 'invoke' method."));
|
|
|
|
|
|
|
|
|
|
|
|
if (args == nullptr)
|
2009-02-06 21:33:59 +00:00
|
|
|
|
args = "";
|
Turn gdbpy_ref into a template
This turns gdbpy_ref into a template class, so that it can be used to
wrap subclasses of PyObject. The default argument remains PyObject;
and this necessitated renaming uses of "gdbpy_ref" to "gdbpy_ref<>".
gdb/ChangeLog
2017-02-10 Tom Tromey <tom@tromey.com>
* python/py-ref.h (gdbpy_ref_policy): Now a template.
(gdbpy_ref): Now a template; allow subclasses of PyObject to be
used.
* python/py-arch.c, python/py-bpevent.c, python/py-breakpoint.c,
python/py-cmd.c, python/py-continueevent.c, python/py-event.c,
python/py-exitedevent.c, python/py-finishbreakpoint.c,
python/py-framefilter.c, python/py-function.c,
python/py-inferior.c, python/py-infevents.c,
python/py-linetable.c, python/py-newobjfileevent.c,
python/py-param.c, python/py-prettyprint.c, python/py-ref.h,
python/py-signalevent.c, python/py-stopevent.c,
python/py-symbol.c, python/py-threadevent.c, python/py-type.c,
python/py-unwind.c, python/py-utils.c, python/py-value.c,
python/py-varobj.c, python/py-xmethods.c, python/python.c,
varobj.c: Change gdbpy_ref to gdbpy_ref<>.
2017-02-09 13:16:36 -07:00
|
|
|
|
gdbpy_ref<> argobj (PyUnicode_Decode (args, strlen (args), host_charset (),
|
|
|
|
|
|
NULL));
|
2016-11-12 11:12:41 -07:00
|
|
|
|
if (argobj == NULL)
|
2010-10-13 13:24:40 +00:00
|
|
|
|
{
|
|
|
|
|
|
gdbpy_print_stack ();
|
|
|
|
|
|
error (_("Could not convert arguments to Python string."));
|
|
|
|
|
|
}
|
2009-02-06 21:33:59 +00:00
|
|
|
|
|
2022-06-07 09:15:24 -06:00
|
|
|
|
gdbpy_ref<> ttyobj (PyBool_FromLong (from_tty));
|
Turn gdbpy_ref into a template
This turns gdbpy_ref into a template class, so that it can be used to
wrap subclasses of PyObject. The default argument remains PyObject;
and this necessitated renaming uses of "gdbpy_ref" to "gdbpy_ref<>".
gdb/ChangeLog
2017-02-10 Tom Tromey <tom@tromey.com>
* python/py-ref.h (gdbpy_ref_policy): Now a template.
(gdbpy_ref): Now a template; allow subclasses of PyObject to be
used.
* python/py-arch.c, python/py-bpevent.c, python/py-breakpoint.c,
python/py-cmd.c, python/py-continueevent.c, python/py-event.c,
python/py-exitedevent.c, python/py-finishbreakpoint.c,
python/py-framefilter.c, python/py-function.c,
python/py-inferior.c, python/py-infevents.c,
python/py-linetable.c, python/py-newobjfileevent.c,
python/py-param.c, python/py-prettyprint.c, python/py-ref.h,
python/py-signalevent.c, python/py-stopevent.c,
python/py-symbol.c, python/py-threadevent.c, python/py-type.c,
python/py-unwind.c, python/py-utils.c, python/py-value.c,
python/py-varobj.c, python/py-xmethods.c, python/python.c,
varobj.c: Change gdbpy_ref to gdbpy_ref<>.
2017-02-09 13:16:36 -07:00
|
|
|
|
gdbpy_ref<> result (PyObject_CallMethodObjArgs ((PyObject *) obj, invoke_cst,
|
|
|
|
|
|
argobj.get (), ttyobj.get (),
|
|
|
|
|
|
NULL));
|
2010-05-25 15:27:17 +00:00
|
|
|
|
|
2016-11-12 11:12:41 -07:00
|
|
|
|
if (result == NULL)
|
2018-09-15 00:57:12 -06:00
|
|
|
|
gdbpy_handle_exception ();
|
2009-02-06 21:33:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
PR python/16699: GDB Python command completion with overriden complete vs. completer class
This PR came from a Red Hat bug that was filed recently. I checked and
it still exists on HEAD, so here's a proposed fix. Although this is
marked as a Python backend bug, this is really about the completion
mechanism used by GDB. Since this code reminds me of my first attempt
to make a good noodle, it took me quite some time to fix it in a
non-intrusive way.
The problem is triggered when one registers a completion method inside a
class in a Python script, rather than registering the command using a
completer class directly. For example, consider the following script:
class MyFirstCommand(gdb.Command):
def __init__(self):
gdb.Command.__init__(self,'myfirstcommand',gdb.COMMAND_USER,gdb.COMPLETE_FILENAME)
def invoke(self,argument,from_tty):
raise gdb.GdbError('not implemented')
class MySecondCommand(gdb.Command):
def __init__(self):
gdb.Command.__init__(self,'mysecondcommand',gdb.COMMAND_USER)
def invoke(self,argument,from_tty):
raise gdb.GdbError('not implemented')
def complete(self,text,word):
return gdb.COMPLETE_FILENAME
MyFirstCommand ()
MySecondCommand ()
When one loads this into GDB and tries to complete filenames for both
myfirstcommand and mysecondcommand, she gets:
(gdb) myfirstcommand /hom<TAB>
(gdb) myfirstcommand /home/
^
...
(gdb) mysecondcommand /hom<TAB>
(gdb) mysecondcommand /home
^
(The "^" marks the final position of the cursor after the TAB).
So we see that myfirstcommand honors the COMPLETE_FILENAME class (as
specified in the command creation), but mysecondcommand does not. After
some investigation, I found that the problem lies with the set of word
break characters that is used for each case. The set should be the same
for both commands, but it is not.
During the process of deciding which type of completion should be used,
the code in gdb/completer.c:complete_line_internal analyses the command
that requested the completion and tries to determine the type of
completion wanted by checking which completion function will be called
(e.g., filename_completer for filenames, location_completer for
locations, etc.).
This all works fine for myfirstcommand, because immediately after the
command registration the Python backend already sets its completion
function to filename_completer (which then causes the
complete_line_internal function to choose the right set of word break
chars). However, for mysecondcommand, this decision is postponed to
when the completer function is evaluated, and the Python backend uses an
internal completer (called cmdpy_completer). complete_line_internal
doesn't know about this internal completer, and can't choose the right
set of word break chars in time, which then leads to a bad decision when
completing the "/hom" word.
So, after a few attempts, I decided to create another callback in
"struct cmd_list_element" that will be responsible for handling the case
when there is an unknown completer function for complete_line_internal
to work with. So far, only the Python backend uses this callback, and
only when the user provides a completer method instead of registering
the command directly with a completer class. I think this is the best
option because it not very intrusive (all the other commands will still
work normally), but especially because the whole completion code is so
messy that it would be hard to fix this without having to redesign
things.
I have regtested this on Fedora 18 x86_64, without regressions. I also
included a testcase.
gdb/ChangeLog:
2014-09-03 Sergio Durigan Junior <sergiodj@redhat.com>
PR python/16699
* cli/cli-decode.c (set_cmd_completer_handle_brkchars): New
function.
(add_cmd): Set "completer_handle_brkchars" to NULL.
* cli/cli-decode.h (struct cmd_list_element)
<completer_handle_brkchars>: New field.
* command.h (completer_ftype_void): New typedef.
(set_cmd_completer_handle_brkchars): New prototype.
* completer.c (set_gdb_completion_word_break_characters): New
function.
(complete_line_internal): Call "completer_handle_brkchars"
callback from command.
* completer.h: Include "command.h".
(set_gdb_completion_word_break_characters): New prototype.
* python/py-cmd.c (cmdpy_completer_helper): New function.
(cmdpy_completer_handle_brkchars): New function.
(cmdpy_completer): Adjust to use cmdpy_completer_helper.
(cmdpy_init): Set completer_handle_brkchars to
cmdpy_completer_handle_brkchars.
gdb/testsuite/ChangeLog:
2014-09-03 Sergio Durigan Junior <sergiodj@redhat.com>
PR python/16699
* gdb.python/py-completion.exp: New file.
* gdb.python/py-completion.py: Likewise.
2014-09-03 16:30:28 -04:00
|
|
|
|
/* Helper function for the Python command completers (both "pure"
|
|
|
|
|
|
completer and brkchar handler). This function takes COMMAND, TEXT
|
|
|
|
|
|
and WORD and tries to call the Python method for completion with
|
Fix Python completion when using the "complete" command
This patch is related to PR python/16699, and is an improvement over the
patch posted here:
<https://sourceware.org/ml/gdb-patches/2014-03/msg00301.html>
Keith noticed that, when using the "complete" command on GDB to complete
a Python command, some strange things could happen. In order to
understand what can go wrong, I need to explain how the Python
completion mechanism works.
When the user requests a completion of a Python command by using TAB,
GDB will first try to determine the right set of "brkchars" that will be
used when doing the completion. This is done by actually calling the
"complete" method of the Python class. Then, when we already know the
"brkchars" that will be used, we call the "complete" method again, for
the same values.
If you read the thread mentioned above, you will see that one of the
design decisions was to make the "cmdpy_completer_helper" (which is the
function the does the actual calling of the "complete" method) cache the
first result of the completion, since this result will be used in the
second call, to do the actual completion.
The problem is that the "complete" command does not process the
brkchars, and the current Python completion mechanism (improved by the
patch mentioned above) relies on GDB trying to determine the brkchars,
and then doing the completion itself. Therefore, when we use the
"complete" command instead of doing a TAB-completion on GDB, there is a
scenario where we can use the invalid cache of a previous Python command
that was completed before. For example:
(gdb) A <TAB>
(gdb) complete B
B value1
B value10
B value2
B value3
B value4
B value5
B value6
B value7
B value8
B value9
(gdb) B <TAB>
comp1 comp2 comp4 comp6 comp8
comp10 comp3 comp5 comp7 comp9
Here, we see that "complete B " gave a different result than "B <TAB>".
The reason for that is because "A <TAB>" was called before, and its
completion results were "value*", so when GDB tried to "complete B " it
wrongly answered with the results for A. The problem here is using a
wrong cache (A's cache) for completing B.
We tried to come up with a solution that would preserve the caching
mechanism, but it wasn't really possible. So I decided to completely
remove the cache, and doing the method calling twice for every
completion. This is not optimal, but I do not think it will impact
users noticeably.
It is worth mentioning another small issue that I found. The code was
doing:
wordobj = PyUnicode_Decode (word, sizeof (word), host_charset (), NULL);
which is totally wrong, because using "sizeof" here will lead to always
the same result. So I changed this to use "strlen". The testcase also
catches this problem.
Keith kindly expanded the existing testcase to cover the problem
described above, and everything is passing.
gdb/ChangeLog:
2015-04-08 Sergio Durigan Junior <sergiodj@redhat.com>
PR python/16699
* python/py-cmd.c (cmdpy_completer_helper): Adjust function to not
use a caching mechanism. Adjust comments and code to reflect
that. Replace 'sizeof' by 'strlen' when fetching 'wordobj'.
(cmdpy_completer_handle_brkchars): Adjust call to
cmdpy_completer_helper. Call Py_XDECREF for 'resultobj'.
(cmdpy_completer): Likewise.
gdb/testsuite/ChangeLog:
2015-04-08 Keith Seitz <keiths@redhat.com>
PR python/16699
* gdb.python/py-completion.exp: New tests for completion.
* gdb.python/py-completion.py (CompleteLimit1): New class.
(CompleteLimit2): Likewise.
(CompleteLimit3): Likewise.
(CompleteLimit4): Likewise.
(CompleteLimit5): Likewise.
(CompleteLimit6): Likewise.
(CompleteLimit7): Likewise.
2015-04-08 18:27:10 -04:00
|
|
|
|
these arguments.
|
|
|
|
|
|
|
|
|
|
|
|
This function is usually called twice: once when we are figuring out
|
|
|
|
|
|
the break characters to be used, and another to perform the real
|
|
|
|
|
|
completion itself. The reason for this two step dance is that we
|
|
|
|
|
|
need to know the set of "brkchars" to use early on, before we
|
|
|
|
|
|
actually try to perform the completion. But if a Python command
|
|
|
|
|
|
supplies a "complete" method then we have to call that method
|
|
|
|
|
|
first: it may return as its result the kind of completion to
|
|
|
|
|
|
perform and that will in turn specify which brkchars to use. IOW,
|
|
|
|
|
|
we need the result of the "complete" method before we actually
|
|
|
|
|
|
perform the completion. The only situation when this function is
|
|
|
|
|
|
not called twice is when the user uses the "complete" command: in
|
|
|
|
|
|
this scenario, there is no call to determine the "brkchars".
|
|
|
|
|
|
|
|
|
|
|
|
Ideally, it would be nice to cache the result of the first call (to
|
|
|
|
|
|
determine the "brkchars") and return this value directly in the
|
|
|
|
|
|
second call (to perform the actual completion). However, due to
|
|
|
|
|
|
the peculiarity of the "complete" command mentioned above, it is
|
|
|
|
|
|
possible to put GDB in a bad state if you perform a TAB-completion
|
|
|
|
|
|
and then a "complete"-completion sequentially. Therefore, we just
|
|
|
|
|
|
recalculate everything twice for TAB-completions.
|
PR python/16699: GDB Python command completion with overriden complete vs. completer class
This PR came from a Red Hat bug that was filed recently. I checked and
it still exists on HEAD, so here's a proposed fix. Although this is
marked as a Python backend bug, this is really about the completion
mechanism used by GDB. Since this code reminds me of my first attempt
to make a good noodle, it took me quite some time to fix it in a
non-intrusive way.
The problem is triggered when one registers a completion method inside a
class in a Python script, rather than registering the command using a
completer class directly. For example, consider the following script:
class MyFirstCommand(gdb.Command):
def __init__(self):
gdb.Command.__init__(self,'myfirstcommand',gdb.COMMAND_USER,gdb.COMPLETE_FILENAME)
def invoke(self,argument,from_tty):
raise gdb.GdbError('not implemented')
class MySecondCommand(gdb.Command):
def __init__(self):
gdb.Command.__init__(self,'mysecondcommand',gdb.COMMAND_USER)
def invoke(self,argument,from_tty):
raise gdb.GdbError('not implemented')
def complete(self,text,word):
return gdb.COMPLETE_FILENAME
MyFirstCommand ()
MySecondCommand ()
When one loads this into GDB and tries to complete filenames for both
myfirstcommand and mysecondcommand, she gets:
(gdb) myfirstcommand /hom<TAB>
(gdb) myfirstcommand /home/
^
...
(gdb) mysecondcommand /hom<TAB>
(gdb) mysecondcommand /home
^
(The "^" marks the final position of the cursor after the TAB).
So we see that myfirstcommand honors the COMPLETE_FILENAME class (as
specified in the command creation), but mysecondcommand does not. After
some investigation, I found that the problem lies with the set of word
break characters that is used for each case. The set should be the same
for both commands, but it is not.
During the process of deciding which type of completion should be used,
the code in gdb/completer.c:complete_line_internal analyses the command
that requested the completion and tries to determine the type of
completion wanted by checking which completion function will be called
(e.g., filename_completer for filenames, location_completer for
locations, etc.).
This all works fine for myfirstcommand, because immediately after the
command registration the Python backend already sets its completion
function to filename_completer (which then causes the
complete_line_internal function to choose the right set of word break
chars). However, for mysecondcommand, this decision is postponed to
when the completer function is evaluated, and the Python backend uses an
internal completer (called cmdpy_completer). complete_line_internal
doesn't know about this internal completer, and can't choose the right
set of word break chars in time, which then leads to a bad decision when
completing the "/hom" word.
So, after a few attempts, I decided to create another callback in
"struct cmd_list_element" that will be responsible for handling the case
when there is an unknown completer function for complete_line_internal
to work with. So far, only the Python backend uses this callback, and
only when the user provides a completer method instead of registering
the command directly with a completer class. I think this is the best
option because it not very intrusive (all the other commands will still
work normally), but especially because the whole completion code is so
messy that it would be hard to fix this without having to redesign
things.
I have regtested this on Fedora 18 x86_64, without regressions. I also
included a testcase.
gdb/ChangeLog:
2014-09-03 Sergio Durigan Junior <sergiodj@redhat.com>
PR python/16699
* cli/cli-decode.c (set_cmd_completer_handle_brkchars): New
function.
(add_cmd): Set "completer_handle_brkchars" to NULL.
* cli/cli-decode.h (struct cmd_list_element)
<completer_handle_brkchars>: New field.
* command.h (completer_ftype_void): New typedef.
(set_cmd_completer_handle_brkchars): New prototype.
* completer.c (set_gdb_completion_word_break_characters): New
function.
(complete_line_internal): Call "completer_handle_brkchars"
callback from command.
* completer.h: Include "command.h".
(set_gdb_completion_word_break_characters): New prototype.
* python/py-cmd.c (cmdpy_completer_helper): New function.
(cmdpy_completer_handle_brkchars): New function.
(cmdpy_completer): Adjust to use cmdpy_completer_helper.
(cmdpy_init): Set completer_handle_brkchars to
cmdpy_completer_handle_brkchars.
gdb/testsuite/ChangeLog:
2014-09-03 Sergio Durigan Junior <sergiodj@redhat.com>
PR python/16699
* gdb.python/py-completion.exp: New file.
* gdb.python/py-completion.py: Likewise.
2014-09-03 16:30:28 -04:00
|
|
|
|
|
2018-09-10 11:48:28 +01:00
|
|
|
|
This function returns a reference to the PyObject representing the
|
|
|
|
|
|
Python method call. */
|
PR python/16699: GDB Python command completion with overriden complete vs. completer class
This PR came from a Red Hat bug that was filed recently. I checked and
it still exists on HEAD, so here's a proposed fix. Although this is
marked as a Python backend bug, this is really about the completion
mechanism used by GDB. Since this code reminds me of my first attempt
to make a good noodle, it took me quite some time to fix it in a
non-intrusive way.
The problem is triggered when one registers a completion method inside a
class in a Python script, rather than registering the command using a
completer class directly. For example, consider the following script:
class MyFirstCommand(gdb.Command):
def __init__(self):
gdb.Command.__init__(self,'myfirstcommand',gdb.COMMAND_USER,gdb.COMPLETE_FILENAME)
def invoke(self,argument,from_tty):
raise gdb.GdbError('not implemented')
class MySecondCommand(gdb.Command):
def __init__(self):
gdb.Command.__init__(self,'mysecondcommand',gdb.COMMAND_USER)
def invoke(self,argument,from_tty):
raise gdb.GdbError('not implemented')
def complete(self,text,word):
return gdb.COMPLETE_FILENAME
MyFirstCommand ()
MySecondCommand ()
When one loads this into GDB and tries to complete filenames for both
myfirstcommand and mysecondcommand, she gets:
(gdb) myfirstcommand /hom<TAB>
(gdb) myfirstcommand /home/
^
...
(gdb) mysecondcommand /hom<TAB>
(gdb) mysecondcommand /home
^
(The "^" marks the final position of the cursor after the TAB).
So we see that myfirstcommand honors the COMPLETE_FILENAME class (as
specified in the command creation), but mysecondcommand does not. After
some investigation, I found that the problem lies with the set of word
break characters that is used for each case. The set should be the same
for both commands, but it is not.
During the process of deciding which type of completion should be used,
the code in gdb/completer.c:complete_line_internal analyses the command
that requested the completion and tries to determine the type of
completion wanted by checking which completion function will be called
(e.g., filename_completer for filenames, location_completer for
locations, etc.).
This all works fine for myfirstcommand, because immediately after the
command registration the Python backend already sets its completion
function to filename_completer (which then causes the
complete_line_internal function to choose the right set of word break
chars). However, for mysecondcommand, this decision is postponed to
when the completer function is evaluated, and the Python backend uses an
internal completer (called cmdpy_completer). complete_line_internal
doesn't know about this internal completer, and can't choose the right
set of word break chars in time, which then leads to a bad decision when
completing the "/hom" word.
So, after a few attempts, I decided to create another callback in
"struct cmd_list_element" that will be responsible for handling the case
when there is an unknown completer function for complete_line_internal
to work with. So far, only the Python backend uses this callback, and
only when the user provides a completer method instead of registering
the command directly with a completer class. I think this is the best
option because it not very intrusive (all the other commands will still
work normally), but especially because the whole completion code is so
messy that it would be hard to fix this without having to redesign
things.
I have regtested this on Fedora 18 x86_64, without regressions. I also
included a testcase.
gdb/ChangeLog:
2014-09-03 Sergio Durigan Junior <sergiodj@redhat.com>
PR python/16699
* cli/cli-decode.c (set_cmd_completer_handle_brkchars): New
function.
(add_cmd): Set "completer_handle_brkchars" to NULL.
* cli/cli-decode.h (struct cmd_list_element)
<completer_handle_brkchars>: New field.
* command.h (completer_ftype_void): New typedef.
(set_cmd_completer_handle_brkchars): New prototype.
* completer.c (set_gdb_completion_word_break_characters): New
function.
(complete_line_internal): Call "completer_handle_brkchars"
callback from command.
* completer.h: Include "command.h".
(set_gdb_completion_word_break_characters): New prototype.
* python/py-cmd.c (cmdpy_completer_helper): New function.
(cmdpy_completer_handle_brkchars): New function.
(cmdpy_completer): Adjust to use cmdpy_completer_helper.
(cmdpy_init): Set completer_handle_brkchars to
cmdpy_completer_handle_brkchars.
gdb/testsuite/ChangeLog:
2014-09-03 Sergio Durigan Junior <sergiodj@redhat.com>
PR python/16699
* gdb.python/py-completion.exp: New file.
* gdb.python/py-completion.py: Likewise.
2014-09-03 16:30:28 -04:00
|
|
|
|
|
2018-09-10 11:48:28 +01:00
|
|
|
|
static gdbpy_ref<>
|
PR python/16699: GDB Python command completion with overriden complete vs. completer class
This PR came from a Red Hat bug that was filed recently. I checked and
it still exists on HEAD, so here's a proposed fix. Although this is
marked as a Python backend bug, this is really about the completion
mechanism used by GDB. Since this code reminds me of my first attempt
to make a good noodle, it took me quite some time to fix it in a
non-intrusive way.
The problem is triggered when one registers a completion method inside a
class in a Python script, rather than registering the command using a
completer class directly. For example, consider the following script:
class MyFirstCommand(gdb.Command):
def __init__(self):
gdb.Command.__init__(self,'myfirstcommand',gdb.COMMAND_USER,gdb.COMPLETE_FILENAME)
def invoke(self,argument,from_tty):
raise gdb.GdbError('not implemented')
class MySecondCommand(gdb.Command):
def __init__(self):
gdb.Command.__init__(self,'mysecondcommand',gdb.COMMAND_USER)
def invoke(self,argument,from_tty):
raise gdb.GdbError('not implemented')
def complete(self,text,word):
return gdb.COMPLETE_FILENAME
MyFirstCommand ()
MySecondCommand ()
When one loads this into GDB and tries to complete filenames for both
myfirstcommand and mysecondcommand, she gets:
(gdb) myfirstcommand /hom<TAB>
(gdb) myfirstcommand /home/
^
...
(gdb) mysecondcommand /hom<TAB>
(gdb) mysecondcommand /home
^
(The "^" marks the final position of the cursor after the TAB).
So we see that myfirstcommand honors the COMPLETE_FILENAME class (as
specified in the command creation), but mysecondcommand does not. After
some investigation, I found that the problem lies with the set of word
break characters that is used for each case. The set should be the same
for both commands, but it is not.
During the process of deciding which type of completion should be used,
the code in gdb/completer.c:complete_line_internal analyses the command
that requested the completion and tries to determine the type of
completion wanted by checking which completion function will be called
(e.g., filename_completer for filenames, location_completer for
locations, etc.).
This all works fine for myfirstcommand, because immediately after the
command registration the Python backend already sets its completion
function to filename_completer (which then causes the
complete_line_internal function to choose the right set of word break
chars). However, for mysecondcommand, this decision is postponed to
when the completer function is evaluated, and the Python backend uses an
internal completer (called cmdpy_completer). complete_line_internal
doesn't know about this internal completer, and can't choose the right
set of word break chars in time, which then leads to a bad decision when
completing the "/hom" word.
So, after a few attempts, I decided to create another callback in
"struct cmd_list_element" that will be responsible for handling the case
when there is an unknown completer function for complete_line_internal
to work with. So far, only the Python backend uses this callback, and
only when the user provides a completer method instead of registering
the command directly with a completer class. I think this is the best
option because it not very intrusive (all the other commands will still
work normally), but especially because the whole completion code is so
messy that it would be hard to fix this without having to redesign
things.
I have regtested this on Fedora 18 x86_64, without regressions. I also
included a testcase.
gdb/ChangeLog:
2014-09-03 Sergio Durigan Junior <sergiodj@redhat.com>
PR python/16699
* cli/cli-decode.c (set_cmd_completer_handle_brkchars): New
function.
(add_cmd): Set "completer_handle_brkchars" to NULL.
* cli/cli-decode.h (struct cmd_list_element)
<completer_handle_brkchars>: New field.
* command.h (completer_ftype_void): New typedef.
(set_cmd_completer_handle_brkchars): New prototype.
* completer.c (set_gdb_completion_word_break_characters): New
function.
(complete_line_internal): Call "completer_handle_brkchars"
callback from command.
* completer.h: Include "command.h".
(set_gdb_completion_word_break_characters): New prototype.
* python/py-cmd.c (cmdpy_completer_helper): New function.
(cmdpy_completer_handle_brkchars): New function.
(cmdpy_completer): Adjust to use cmdpy_completer_helper.
(cmdpy_init): Set completer_handle_brkchars to
cmdpy_completer_handle_brkchars.
gdb/testsuite/ChangeLog:
2014-09-03 Sergio Durigan Junior <sergiodj@redhat.com>
PR python/16699
* gdb.python/py-completion.exp: New file.
* gdb.python/py-completion.py: Likewise.
2014-09-03 16:30:28 -04:00
|
|
|
|
cmdpy_completer_helper (struct cmd_list_element *command,
|
Fix Python completion when using the "complete" command
This patch is related to PR python/16699, and is an improvement over the
patch posted here:
<https://sourceware.org/ml/gdb-patches/2014-03/msg00301.html>
Keith noticed that, when using the "complete" command on GDB to complete
a Python command, some strange things could happen. In order to
understand what can go wrong, I need to explain how the Python
completion mechanism works.
When the user requests a completion of a Python command by using TAB,
GDB will first try to determine the right set of "brkchars" that will be
used when doing the completion. This is done by actually calling the
"complete" method of the Python class. Then, when we already know the
"brkchars" that will be used, we call the "complete" method again, for
the same values.
If you read the thread mentioned above, you will see that one of the
design decisions was to make the "cmdpy_completer_helper" (which is the
function the does the actual calling of the "complete" method) cache the
first result of the completion, since this result will be used in the
second call, to do the actual completion.
The problem is that the "complete" command does not process the
brkchars, and the current Python completion mechanism (improved by the
patch mentioned above) relies on GDB trying to determine the brkchars,
and then doing the completion itself. Therefore, when we use the
"complete" command instead of doing a TAB-completion on GDB, there is a
scenario where we can use the invalid cache of a previous Python command
that was completed before. For example:
(gdb) A <TAB>
(gdb) complete B
B value1
B value10
B value2
B value3
B value4
B value5
B value6
B value7
B value8
B value9
(gdb) B <TAB>
comp1 comp2 comp4 comp6 comp8
comp10 comp3 comp5 comp7 comp9
Here, we see that "complete B " gave a different result than "B <TAB>".
The reason for that is because "A <TAB>" was called before, and its
completion results were "value*", so when GDB tried to "complete B " it
wrongly answered with the results for A. The problem here is using a
wrong cache (A's cache) for completing B.
We tried to come up with a solution that would preserve the caching
mechanism, but it wasn't really possible. So I decided to completely
remove the cache, and doing the method calling twice for every
completion. This is not optimal, but I do not think it will impact
users noticeably.
It is worth mentioning another small issue that I found. The code was
doing:
wordobj = PyUnicode_Decode (word, sizeof (word), host_charset (), NULL);
which is totally wrong, because using "sizeof" here will lead to always
the same result. So I changed this to use "strlen". The testcase also
catches this problem.
Keith kindly expanded the existing testcase to cover the problem
described above, and everything is passing.
gdb/ChangeLog:
2015-04-08 Sergio Durigan Junior <sergiodj@redhat.com>
PR python/16699
* python/py-cmd.c (cmdpy_completer_helper): Adjust function to not
use a caching mechanism. Adjust comments and code to reflect
that. Replace 'sizeof' by 'strlen' when fetching 'wordobj'.
(cmdpy_completer_handle_brkchars): Adjust call to
cmdpy_completer_helper. Call Py_XDECREF for 'resultobj'.
(cmdpy_completer): Likewise.
gdb/testsuite/ChangeLog:
2015-04-08 Keith Seitz <keiths@redhat.com>
PR python/16699
* gdb.python/py-completion.exp: New tests for completion.
* gdb.python/py-completion.py (CompleteLimit1): New class.
(CompleteLimit2): Likewise.
(CompleteLimit3): Likewise.
(CompleteLimit4): Likewise.
(CompleteLimit5): Likewise.
(CompleteLimit6): Likewise.
(CompleteLimit7): Likewise.
2015-04-08 18:27:10 -04:00
|
|
|
|
const char *text, const char *word)
|
PR python/16699: GDB Python command completion with overriden complete vs. completer class
This PR came from a Red Hat bug that was filed recently. I checked and
it still exists on HEAD, so here's a proposed fix. Although this is
marked as a Python backend bug, this is really about the completion
mechanism used by GDB. Since this code reminds me of my first attempt
to make a good noodle, it took me quite some time to fix it in a
non-intrusive way.
The problem is triggered when one registers a completion method inside a
class in a Python script, rather than registering the command using a
completer class directly. For example, consider the following script:
class MyFirstCommand(gdb.Command):
def __init__(self):
gdb.Command.__init__(self,'myfirstcommand',gdb.COMMAND_USER,gdb.COMPLETE_FILENAME)
def invoke(self,argument,from_tty):
raise gdb.GdbError('not implemented')
class MySecondCommand(gdb.Command):
def __init__(self):
gdb.Command.__init__(self,'mysecondcommand',gdb.COMMAND_USER)
def invoke(self,argument,from_tty):
raise gdb.GdbError('not implemented')
def complete(self,text,word):
return gdb.COMPLETE_FILENAME
MyFirstCommand ()
MySecondCommand ()
When one loads this into GDB and tries to complete filenames for both
myfirstcommand and mysecondcommand, she gets:
(gdb) myfirstcommand /hom<TAB>
(gdb) myfirstcommand /home/
^
...
(gdb) mysecondcommand /hom<TAB>
(gdb) mysecondcommand /home
^
(The "^" marks the final position of the cursor after the TAB).
So we see that myfirstcommand honors the COMPLETE_FILENAME class (as
specified in the command creation), but mysecondcommand does not. After
some investigation, I found that the problem lies with the set of word
break characters that is used for each case. The set should be the same
for both commands, but it is not.
During the process of deciding which type of completion should be used,
the code in gdb/completer.c:complete_line_internal analyses the command
that requested the completion and tries to determine the type of
completion wanted by checking which completion function will be called
(e.g., filename_completer for filenames, location_completer for
locations, etc.).
This all works fine for myfirstcommand, because immediately after the
command registration the Python backend already sets its completion
function to filename_completer (which then causes the
complete_line_internal function to choose the right set of word break
chars). However, for mysecondcommand, this decision is postponed to
when the completer function is evaluated, and the Python backend uses an
internal completer (called cmdpy_completer). complete_line_internal
doesn't know about this internal completer, and can't choose the right
set of word break chars in time, which then leads to a bad decision when
completing the "/hom" word.
So, after a few attempts, I decided to create another callback in
"struct cmd_list_element" that will be responsible for handling the case
when there is an unknown completer function for complete_line_internal
to work with. So far, only the Python backend uses this callback, and
only when the user provides a completer method instead of registering
the command directly with a completer class. I think this is the best
option because it not very intrusive (all the other commands will still
work normally), but especially because the whole completion code is so
messy that it would be hard to fix this without having to redesign
things.
I have regtested this on Fedora 18 x86_64, without regressions. I also
included a testcase.
gdb/ChangeLog:
2014-09-03 Sergio Durigan Junior <sergiodj@redhat.com>
PR python/16699
* cli/cli-decode.c (set_cmd_completer_handle_brkchars): New
function.
(add_cmd): Set "completer_handle_brkchars" to NULL.
* cli/cli-decode.h (struct cmd_list_element)
<completer_handle_brkchars>: New field.
* command.h (completer_ftype_void): New typedef.
(set_cmd_completer_handle_brkchars): New prototype.
* completer.c (set_gdb_completion_word_break_characters): New
function.
(complete_line_internal): Call "completer_handle_brkchars"
callback from command.
* completer.h: Include "command.h".
(set_gdb_completion_word_break_characters): New prototype.
* python/py-cmd.c (cmdpy_completer_helper): New function.
(cmdpy_completer_handle_brkchars): New function.
(cmdpy_completer): Adjust to use cmdpy_completer_helper.
(cmdpy_init): Set completer_handle_brkchars to
cmdpy_completer_handle_brkchars.
gdb/testsuite/ChangeLog:
2014-09-03 Sergio Durigan Junior <sergiodj@redhat.com>
PR python/16699
* gdb.python/py-completion.exp: New file.
* gdb.python/py-completion.py: Likewise.
2014-09-03 16:30:28 -04:00
|
|
|
|
{
|
2021-06-25 21:35:40 -04:00
|
|
|
|
cmdpy_object *obj = (cmdpy_object *) command->context ();
|
PR python/16699: GDB Python command completion with overriden complete vs. completer class
This PR came from a Red Hat bug that was filed recently. I checked and
it still exists on HEAD, so here's a proposed fix. Although this is
marked as a Python backend bug, this is really about the completion
mechanism used by GDB. Since this code reminds me of my first attempt
to make a good noodle, it took me quite some time to fix it in a
non-intrusive way.
The problem is triggered when one registers a completion method inside a
class in a Python script, rather than registering the command using a
completer class directly. For example, consider the following script:
class MyFirstCommand(gdb.Command):
def __init__(self):
gdb.Command.__init__(self,'myfirstcommand',gdb.COMMAND_USER,gdb.COMPLETE_FILENAME)
def invoke(self,argument,from_tty):
raise gdb.GdbError('not implemented')
class MySecondCommand(gdb.Command):
def __init__(self):
gdb.Command.__init__(self,'mysecondcommand',gdb.COMMAND_USER)
def invoke(self,argument,from_tty):
raise gdb.GdbError('not implemented')
def complete(self,text,word):
return gdb.COMPLETE_FILENAME
MyFirstCommand ()
MySecondCommand ()
When one loads this into GDB and tries to complete filenames for both
myfirstcommand and mysecondcommand, she gets:
(gdb) myfirstcommand /hom<TAB>
(gdb) myfirstcommand /home/
^
...
(gdb) mysecondcommand /hom<TAB>
(gdb) mysecondcommand /home
^
(The "^" marks the final position of the cursor after the TAB).
So we see that myfirstcommand honors the COMPLETE_FILENAME class (as
specified in the command creation), but mysecondcommand does not. After
some investigation, I found that the problem lies with the set of word
break characters that is used for each case. The set should be the same
for both commands, but it is not.
During the process of deciding which type of completion should be used,
the code in gdb/completer.c:complete_line_internal analyses the command
that requested the completion and tries to determine the type of
completion wanted by checking which completion function will be called
(e.g., filename_completer for filenames, location_completer for
locations, etc.).
This all works fine for myfirstcommand, because immediately after the
command registration the Python backend already sets its completion
function to filename_completer (which then causes the
complete_line_internal function to choose the right set of word break
chars). However, for mysecondcommand, this decision is postponed to
when the completer function is evaluated, and the Python backend uses an
internal completer (called cmdpy_completer). complete_line_internal
doesn't know about this internal completer, and can't choose the right
set of word break chars in time, which then leads to a bad decision when
completing the "/hom" word.
So, after a few attempts, I decided to create another callback in
"struct cmd_list_element" that will be responsible for handling the case
when there is an unknown completer function for complete_line_internal
to work with. So far, only the Python backend uses this callback, and
only when the user provides a completer method instead of registering
the command directly with a completer class. I think this is the best
option because it not very intrusive (all the other commands will still
work normally), but especially because the whole completion code is so
messy that it would be hard to fix this without having to redesign
things.
I have regtested this on Fedora 18 x86_64, without regressions. I also
included a testcase.
gdb/ChangeLog:
2014-09-03 Sergio Durigan Junior <sergiodj@redhat.com>
PR python/16699
* cli/cli-decode.c (set_cmd_completer_handle_brkchars): New
function.
(add_cmd): Set "completer_handle_brkchars" to NULL.
* cli/cli-decode.h (struct cmd_list_element)
<completer_handle_brkchars>: New field.
* command.h (completer_ftype_void): New typedef.
(set_cmd_completer_handle_brkchars): New prototype.
* completer.c (set_gdb_completion_word_break_characters): New
function.
(complete_line_internal): Call "completer_handle_brkchars"
callback from command.
* completer.h: Include "command.h".
(set_gdb_completion_word_break_characters): New prototype.
* python/py-cmd.c (cmdpy_completer_helper): New function.
(cmdpy_completer_handle_brkchars): New function.
(cmdpy_completer): Adjust to use cmdpy_completer_helper.
(cmdpy_init): Set completer_handle_brkchars to
cmdpy_completer_handle_brkchars.
gdb/testsuite/ChangeLog:
2014-09-03 Sergio Durigan Junior <sergiodj@redhat.com>
PR python/16699
* gdb.python/py-completion.exp: New file.
* gdb.python/py-completion.py: Likewise.
2014-09-03 16:30:28 -04:00
|
|
|
|
|
Fix Python completion when using the "complete" command
This patch is related to PR python/16699, and is an improvement over the
patch posted here:
<https://sourceware.org/ml/gdb-patches/2014-03/msg00301.html>
Keith noticed that, when using the "complete" command on GDB to complete
a Python command, some strange things could happen. In order to
understand what can go wrong, I need to explain how the Python
completion mechanism works.
When the user requests a completion of a Python command by using TAB,
GDB will first try to determine the right set of "brkchars" that will be
used when doing the completion. This is done by actually calling the
"complete" method of the Python class. Then, when we already know the
"brkchars" that will be used, we call the "complete" method again, for
the same values.
If you read the thread mentioned above, you will see that one of the
design decisions was to make the "cmdpy_completer_helper" (which is the
function the does the actual calling of the "complete" method) cache the
first result of the completion, since this result will be used in the
second call, to do the actual completion.
The problem is that the "complete" command does not process the
brkchars, and the current Python completion mechanism (improved by the
patch mentioned above) relies on GDB trying to determine the brkchars,
and then doing the completion itself. Therefore, when we use the
"complete" command instead of doing a TAB-completion on GDB, there is a
scenario where we can use the invalid cache of a previous Python command
that was completed before. For example:
(gdb) A <TAB>
(gdb) complete B
B value1
B value10
B value2
B value3
B value4
B value5
B value6
B value7
B value8
B value9
(gdb) B <TAB>
comp1 comp2 comp4 comp6 comp8
comp10 comp3 comp5 comp7 comp9
Here, we see that "complete B " gave a different result than "B <TAB>".
The reason for that is because "A <TAB>" was called before, and its
completion results were "value*", so when GDB tried to "complete B " it
wrongly answered with the results for A. The problem here is using a
wrong cache (A's cache) for completing B.
We tried to come up with a solution that would preserve the caching
mechanism, but it wasn't really possible. So I decided to completely
remove the cache, and doing the method calling twice for every
completion. This is not optimal, but I do not think it will impact
users noticeably.
It is worth mentioning another small issue that I found. The code was
doing:
wordobj = PyUnicode_Decode (word, sizeof (word), host_charset (), NULL);
which is totally wrong, because using "sizeof" here will lead to always
the same result. So I changed this to use "strlen". The testcase also
catches this problem.
Keith kindly expanded the existing testcase to cover the problem
described above, and everything is passing.
gdb/ChangeLog:
2015-04-08 Sergio Durigan Junior <sergiodj@redhat.com>
PR python/16699
* python/py-cmd.c (cmdpy_completer_helper): Adjust function to not
use a caching mechanism. Adjust comments and code to reflect
that. Replace 'sizeof' by 'strlen' when fetching 'wordobj'.
(cmdpy_completer_handle_brkchars): Adjust call to
cmdpy_completer_helper. Call Py_XDECREF for 'resultobj'.
(cmdpy_completer): Likewise.
gdb/testsuite/ChangeLog:
2015-04-08 Keith Seitz <keiths@redhat.com>
PR python/16699
* gdb.python/py-completion.exp: New tests for completion.
* gdb.python/py-completion.py (CompleteLimit1): New class.
(CompleteLimit2): Likewise.
(CompleteLimit3): Likewise.
(CompleteLimit4): Likewise.
(CompleteLimit5): Likewise.
(CompleteLimit6): Likewise.
(CompleteLimit7): Likewise.
2015-04-08 18:27:10 -04:00
|
|
|
|
if (obj == NULL)
|
|
|
|
|
|
error (_("Invalid invocation of Python command object."));
|
|
|
|
|
|
if (!PyObject_HasAttr ((PyObject *) obj, complete_cst))
|
PR python/16699: GDB Python command completion with overriden complete vs. completer class
This PR came from a Red Hat bug that was filed recently. I checked and
it still exists on HEAD, so here's a proposed fix. Although this is
marked as a Python backend bug, this is really about the completion
mechanism used by GDB. Since this code reminds me of my first attempt
to make a good noodle, it took me quite some time to fix it in a
non-intrusive way.
The problem is triggered when one registers a completion method inside a
class in a Python script, rather than registering the command using a
completer class directly. For example, consider the following script:
class MyFirstCommand(gdb.Command):
def __init__(self):
gdb.Command.__init__(self,'myfirstcommand',gdb.COMMAND_USER,gdb.COMPLETE_FILENAME)
def invoke(self,argument,from_tty):
raise gdb.GdbError('not implemented')
class MySecondCommand(gdb.Command):
def __init__(self):
gdb.Command.__init__(self,'mysecondcommand',gdb.COMMAND_USER)
def invoke(self,argument,from_tty):
raise gdb.GdbError('not implemented')
def complete(self,text,word):
return gdb.COMPLETE_FILENAME
MyFirstCommand ()
MySecondCommand ()
When one loads this into GDB and tries to complete filenames for both
myfirstcommand and mysecondcommand, she gets:
(gdb) myfirstcommand /hom<TAB>
(gdb) myfirstcommand /home/
^
...
(gdb) mysecondcommand /hom<TAB>
(gdb) mysecondcommand /home
^
(The "^" marks the final position of the cursor after the TAB).
So we see that myfirstcommand honors the COMPLETE_FILENAME class (as
specified in the command creation), but mysecondcommand does not. After
some investigation, I found that the problem lies with the set of word
break characters that is used for each case. The set should be the same
for both commands, but it is not.
During the process of deciding which type of completion should be used,
the code in gdb/completer.c:complete_line_internal analyses the command
that requested the completion and tries to determine the type of
completion wanted by checking which completion function will be called
(e.g., filename_completer for filenames, location_completer for
locations, etc.).
This all works fine for myfirstcommand, because immediately after the
command registration the Python backend already sets its completion
function to filename_completer (which then causes the
complete_line_internal function to choose the right set of word break
chars). However, for mysecondcommand, this decision is postponed to
when the completer function is evaluated, and the Python backend uses an
internal completer (called cmdpy_completer). complete_line_internal
doesn't know about this internal completer, and can't choose the right
set of word break chars in time, which then leads to a bad decision when
completing the "/hom" word.
So, after a few attempts, I decided to create another callback in
"struct cmd_list_element" that will be responsible for handling the case
when there is an unknown completer function for complete_line_internal
to work with. So far, only the Python backend uses this callback, and
only when the user provides a completer method instead of registering
the command directly with a completer class. I think this is the best
option because it not very intrusive (all the other commands will still
work normally), but especially because the whole completion code is so
messy that it would be hard to fix this without having to redesign
things.
I have regtested this on Fedora 18 x86_64, without regressions. I also
included a testcase.
gdb/ChangeLog:
2014-09-03 Sergio Durigan Junior <sergiodj@redhat.com>
PR python/16699
* cli/cli-decode.c (set_cmd_completer_handle_brkchars): New
function.
(add_cmd): Set "completer_handle_brkchars" to NULL.
* cli/cli-decode.h (struct cmd_list_element)
<completer_handle_brkchars>: New field.
* command.h (completer_ftype_void): New typedef.
(set_cmd_completer_handle_brkchars): New prototype.
* completer.c (set_gdb_completion_word_break_characters): New
function.
(complete_line_internal): Call "completer_handle_brkchars"
callback from command.
* completer.h: Include "command.h".
(set_gdb_completion_word_break_characters): New prototype.
* python/py-cmd.c (cmdpy_completer_helper): New function.
(cmdpy_completer_handle_brkchars): New function.
(cmdpy_completer): Adjust to use cmdpy_completer_helper.
(cmdpy_init): Set completer_handle_brkchars to
cmdpy_completer_handle_brkchars.
gdb/testsuite/ChangeLog:
2014-09-03 Sergio Durigan Junior <sergiodj@redhat.com>
PR python/16699
* gdb.python/py-completion.exp: New file.
* gdb.python/py-completion.py: Likewise.
2014-09-03 16:30:28 -04:00
|
|
|
|
{
|
Fix Python completion when using the "complete" command
This patch is related to PR python/16699, and is an improvement over the
patch posted here:
<https://sourceware.org/ml/gdb-patches/2014-03/msg00301.html>
Keith noticed that, when using the "complete" command on GDB to complete
a Python command, some strange things could happen. In order to
understand what can go wrong, I need to explain how the Python
completion mechanism works.
When the user requests a completion of a Python command by using TAB,
GDB will first try to determine the right set of "brkchars" that will be
used when doing the completion. This is done by actually calling the
"complete" method of the Python class. Then, when we already know the
"brkchars" that will be used, we call the "complete" method again, for
the same values.
If you read the thread mentioned above, you will see that one of the
design decisions was to make the "cmdpy_completer_helper" (which is the
function the does the actual calling of the "complete" method) cache the
first result of the completion, since this result will be used in the
second call, to do the actual completion.
The problem is that the "complete" command does not process the
brkchars, and the current Python completion mechanism (improved by the
patch mentioned above) relies on GDB trying to determine the brkchars,
and then doing the completion itself. Therefore, when we use the
"complete" command instead of doing a TAB-completion on GDB, there is a
scenario where we can use the invalid cache of a previous Python command
that was completed before. For example:
(gdb) A <TAB>
(gdb) complete B
B value1
B value10
B value2
B value3
B value4
B value5
B value6
B value7
B value8
B value9
(gdb) B <TAB>
comp1 comp2 comp4 comp6 comp8
comp10 comp3 comp5 comp7 comp9
Here, we see that "complete B " gave a different result than "B <TAB>".
The reason for that is because "A <TAB>" was called before, and its
completion results were "value*", so when GDB tried to "complete B " it
wrongly answered with the results for A. The problem here is using a
wrong cache (A's cache) for completing B.
We tried to come up with a solution that would preserve the caching
mechanism, but it wasn't really possible. So I decided to completely
remove the cache, and doing the method calling twice for every
completion. This is not optimal, but I do not think it will impact
users noticeably.
It is worth mentioning another small issue that I found. The code was
doing:
wordobj = PyUnicode_Decode (word, sizeof (word), host_charset (), NULL);
which is totally wrong, because using "sizeof" here will lead to always
the same result. So I changed this to use "strlen". The testcase also
catches this problem.
Keith kindly expanded the existing testcase to cover the problem
described above, and everything is passing.
gdb/ChangeLog:
2015-04-08 Sergio Durigan Junior <sergiodj@redhat.com>
PR python/16699
* python/py-cmd.c (cmdpy_completer_helper): Adjust function to not
use a caching mechanism. Adjust comments and code to reflect
that. Replace 'sizeof' by 'strlen' when fetching 'wordobj'.
(cmdpy_completer_handle_brkchars): Adjust call to
cmdpy_completer_helper. Call Py_XDECREF for 'resultobj'.
(cmdpy_completer): Likewise.
gdb/testsuite/ChangeLog:
2015-04-08 Keith Seitz <keiths@redhat.com>
PR python/16699
* gdb.python/py-completion.exp: New tests for completion.
* gdb.python/py-completion.py (CompleteLimit1): New class.
(CompleteLimit2): Likewise.
(CompleteLimit3): Likewise.
(CompleteLimit4): Likewise.
(CompleteLimit5): Likewise.
(CompleteLimit6): Likewise.
(CompleteLimit7): Likewise.
2015-04-08 18:27:10 -04:00
|
|
|
|
/* If there is no complete method, don't error. */
|
|
|
|
|
|
return NULL;
|
|
|
|
|
|
}
|
PR python/16699: GDB Python command completion with overriden complete vs. completer class
This PR came from a Red Hat bug that was filed recently. I checked and
it still exists on HEAD, so here's a proposed fix. Although this is
marked as a Python backend bug, this is really about the completion
mechanism used by GDB. Since this code reminds me of my first attempt
to make a good noodle, it took me quite some time to fix it in a
non-intrusive way.
The problem is triggered when one registers a completion method inside a
class in a Python script, rather than registering the command using a
completer class directly. For example, consider the following script:
class MyFirstCommand(gdb.Command):
def __init__(self):
gdb.Command.__init__(self,'myfirstcommand',gdb.COMMAND_USER,gdb.COMPLETE_FILENAME)
def invoke(self,argument,from_tty):
raise gdb.GdbError('not implemented')
class MySecondCommand(gdb.Command):
def __init__(self):
gdb.Command.__init__(self,'mysecondcommand',gdb.COMMAND_USER)
def invoke(self,argument,from_tty):
raise gdb.GdbError('not implemented')
def complete(self,text,word):
return gdb.COMPLETE_FILENAME
MyFirstCommand ()
MySecondCommand ()
When one loads this into GDB and tries to complete filenames for both
myfirstcommand and mysecondcommand, she gets:
(gdb) myfirstcommand /hom<TAB>
(gdb) myfirstcommand /home/
^
...
(gdb) mysecondcommand /hom<TAB>
(gdb) mysecondcommand /home
^
(The "^" marks the final position of the cursor after the TAB).
So we see that myfirstcommand honors the COMPLETE_FILENAME class (as
specified in the command creation), but mysecondcommand does not. After
some investigation, I found that the problem lies with the set of word
break characters that is used for each case. The set should be the same
for both commands, but it is not.
During the process of deciding which type of completion should be used,
the code in gdb/completer.c:complete_line_internal analyses the command
that requested the completion and tries to determine the type of
completion wanted by checking which completion function will be called
(e.g., filename_completer for filenames, location_completer for
locations, etc.).
This all works fine for myfirstcommand, because immediately after the
command registration the Python backend already sets its completion
function to filename_completer (which then causes the
complete_line_internal function to choose the right set of word break
chars). However, for mysecondcommand, this decision is postponed to
when the completer function is evaluated, and the Python backend uses an
internal completer (called cmdpy_completer). complete_line_internal
doesn't know about this internal completer, and can't choose the right
set of word break chars in time, which then leads to a bad decision when
completing the "/hom" word.
So, after a few attempts, I decided to create another callback in
"struct cmd_list_element" that will be responsible for handling the case
when there is an unknown completer function for complete_line_internal
to work with. So far, only the Python backend uses this callback, and
only when the user provides a completer method instead of registering
the command directly with a completer class. I think this is the best
option because it not very intrusive (all the other commands will still
work normally), but especially because the whole completion code is so
messy that it would be hard to fix this without having to redesign
things.
I have regtested this on Fedora 18 x86_64, without regressions. I also
included a testcase.
gdb/ChangeLog:
2014-09-03 Sergio Durigan Junior <sergiodj@redhat.com>
PR python/16699
* cli/cli-decode.c (set_cmd_completer_handle_brkchars): New
function.
(add_cmd): Set "completer_handle_brkchars" to NULL.
* cli/cli-decode.h (struct cmd_list_element)
<completer_handle_brkchars>: New field.
* command.h (completer_ftype_void): New typedef.
(set_cmd_completer_handle_brkchars): New prototype.
* completer.c (set_gdb_completion_word_break_characters): New
function.
(complete_line_internal): Call "completer_handle_brkchars"
callback from command.
* completer.h: Include "command.h".
(set_gdb_completion_word_break_characters): New prototype.
* python/py-cmd.c (cmdpy_completer_helper): New function.
(cmdpy_completer_handle_brkchars): New function.
(cmdpy_completer): Adjust to use cmdpy_completer_helper.
(cmdpy_init): Set completer_handle_brkchars to
cmdpy_completer_handle_brkchars.
gdb/testsuite/ChangeLog:
2014-09-03 Sergio Durigan Junior <sergiodj@redhat.com>
PR python/16699
* gdb.python/py-completion.exp: New file.
* gdb.python/py-completion.py: Likewise.
2014-09-03 16:30:28 -04:00
|
|
|
|
|
Turn gdbpy_ref into a template
This turns gdbpy_ref into a template class, so that it can be used to
wrap subclasses of PyObject. The default argument remains PyObject;
and this necessitated renaming uses of "gdbpy_ref" to "gdbpy_ref<>".
gdb/ChangeLog
2017-02-10 Tom Tromey <tom@tromey.com>
* python/py-ref.h (gdbpy_ref_policy): Now a template.
(gdbpy_ref): Now a template; allow subclasses of PyObject to be
used.
* python/py-arch.c, python/py-bpevent.c, python/py-breakpoint.c,
python/py-cmd.c, python/py-continueevent.c, python/py-event.c,
python/py-exitedevent.c, python/py-finishbreakpoint.c,
python/py-framefilter.c, python/py-function.c,
python/py-inferior.c, python/py-infevents.c,
python/py-linetable.c, python/py-newobjfileevent.c,
python/py-param.c, python/py-prettyprint.c, python/py-ref.h,
python/py-signalevent.c, python/py-stopevent.c,
python/py-symbol.c, python/py-threadevent.c, python/py-type.c,
python/py-unwind.c, python/py-utils.c, python/py-value.c,
python/py-varobj.c, python/py-xmethods.c, python/python.c,
varobj.c: Change gdbpy_ref to gdbpy_ref<>.
2017-02-09 13:16:36 -07:00
|
|
|
|
gdbpy_ref<> textobj (PyUnicode_Decode (text, strlen (text), host_charset (),
|
|
|
|
|
|
NULL));
|
Fix Python completion when using the "complete" command
This patch is related to PR python/16699, and is an improvement over the
patch posted here:
<https://sourceware.org/ml/gdb-patches/2014-03/msg00301.html>
Keith noticed that, when using the "complete" command on GDB to complete
a Python command, some strange things could happen. In order to
understand what can go wrong, I need to explain how the Python
completion mechanism works.
When the user requests a completion of a Python command by using TAB,
GDB will first try to determine the right set of "brkchars" that will be
used when doing the completion. This is done by actually calling the
"complete" method of the Python class. Then, when we already know the
"brkchars" that will be used, we call the "complete" method again, for
the same values.
If you read the thread mentioned above, you will see that one of the
design decisions was to make the "cmdpy_completer_helper" (which is the
function the does the actual calling of the "complete" method) cache the
first result of the completion, since this result will be used in the
second call, to do the actual completion.
The problem is that the "complete" command does not process the
brkchars, and the current Python completion mechanism (improved by the
patch mentioned above) relies on GDB trying to determine the brkchars,
and then doing the completion itself. Therefore, when we use the
"complete" command instead of doing a TAB-completion on GDB, there is a
scenario where we can use the invalid cache of a previous Python command
that was completed before. For example:
(gdb) A <TAB>
(gdb) complete B
B value1
B value10
B value2
B value3
B value4
B value5
B value6
B value7
B value8
B value9
(gdb) B <TAB>
comp1 comp2 comp4 comp6 comp8
comp10 comp3 comp5 comp7 comp9
Here, we see that "complete B " gave a different result than "B <TAB>".
The reason for that is because "A <TAB>" was called before, and its
completion results were "value*", so when GDB tried to "complete B " it
wrongly answered with the results for A. The problem here is using a
wrong cache (A's cache) for completing B.
We tried to come up with a solution that would preserve the caching
mechanism, but it wasn't really possible. So I decided to completely
remove the cache, and doing the method calling twice for every
completion. This is not optimal, but I do not think it will impact
users noticeably.
It is worth mentioning another small issue that I found. The code was
doing:
wordobj = PyUnicode_Decode (word, sizeof (word), host_charset (), NULL);
which is totally wrong, because using "sizeof" here will lead to always
the same result. So I changed this to use "strlen". The testcase also
catches this problem.
Keith kindly expanded the existing testcase to cover the problem
described above, and everything is passing.
gdb/ChangeLog:
2015-04-08 Sergio Durigan Junior <sergiodj@redhat.com>
PR python/16699
* python/py-cmd.c (cmdpy_completer_helper): Adjust function to not
use a caching mechanism. Adjust comments and code to reflect
that. Replace 'sizeof' by 'strlen' when fetching 'wordobj'.
(cmdpy_completer_handle_brkchars): Adjust call to
cmdpy_completer_helper. Call Py_XDECREF for 'resultobj'.
(cmdpy_completer): Likewise.
gdb/testsuite/ChangeLog:
2015-04-08 Keith Seitz <keiths@redhat.com>
PR python/16699
* gdb.python/py-completion.exp: New tests for completion.
* gdb.python/py-completion.py (CompleteLimit1): New class.
(CompleteLimit2): Likewise.
(CompleteLimit3): Likewise.
(CompleteLimit4): Likewise.
(CompleteLimit5): Likewise.
(CompleteLimit6): Likewise.
(CompleteLimit7): Likewise.
2015-04-08 18:27:10 -04:00
|
|
|
|
if (textobj == NULL)
|
gdb/python: display errors from command completion
This commit makes the gdb.Command.complete methods more verbose when
it comes to error handling.
Previous to this commit if any commands implemented in Python
implemented the complete method, and if there were any errors
encountered when calling that complete method, then GDB would silently
hide the error and continue as if there were no completions.
This makes is difficult to debug any errors encountered when writing
completion methods, and encourages the idea that Python extensions can
be broken, and GDB will just silently work around them.
I don't think this is a good idea. GDB should encourage extensions to
be written correctly, and robustly, and one way in which GDB can (I
think) support this, is by pointing out when an extension goes wrong.
In this commit I've gone through the Python command completion code,
and added calls to gdbpy_print_stack() or gdbpy_print_stack_or_quit()
in places where we were either clearing the Python error, or, in some
cases, just not handling the error at all.
One thing I have not changed is in cmdpy_completer (py-cmd.c) where we
process the list of completions returned from the Command.complete
method; this routine includes a call to gdbpy_is_string to check a
possible completion is a string, if not the completion is ignored.
I was tempted to remove this check, attempt to complete each result to
a string, and display an error if the conversion fails. After all,
returning anything but a string is surely a mistake by the extension
author.
However, the docs clearly say that only strings within the returned
list will be considered as completions. Anything else is ignored. As
such, and to avoid (what I think is pretty unlikely) breakage of
existing code, I've retained the gdbpy_is_string check.
After the gdbpy_is_string check we call python_string_to_host_string,
if this call fails then I do now print the error, where before we
ignored the error. I think this is OK; if GDB thinks something is a
string, but still can't convert it to a string, then I think it's OK
to display the error in that case.
Another case which I was a little unsure about was in
cmdpy_completer_helper, and the call to PyObject_CallMethodObjArgs,
which is when we actually call Command.complete. Previously, if this
call resulted in an exception then we would ignore this and just
pretend there were no completions.
Of all the changes, this is possibly the one with the biggest
potential for breaking existing scripts, but also, is, I think, the
most useful change. If the user code is wrong in some way, such that
an exception is raised, then previously the user would have no obvious
feedback about this breakage. Now GDB will print the exception for
them, making it, I think, much easier to debug their extension. But,
if there is user code in the wild that relies on raising an exception
as a means to indicate there are no completions .... well, that code
is going to break after this commit. I think we can live with this
though, the exceptions means no completions thing was never documented
behaviour.
I also added a new error() call if the PyObject_CallMethodObjArgs call
raises an exception. This causes the completion mechanism within GDB
to stop. Within GDB the completion code is called twice, the first
time to compute the work break characters, and then a second time to
compute the actual completions.
If PyObject_CallMethodObjArgs raises an exception when computing the
word break character, and we print it by calling
gdbpy_print_stack_or_quit(), but then carry on as if
PyObject_CallMethodObjArgs had returns no completions, GDB will
call the Python completion code again, which results in another call
to PyObject_CallMethodObjArgs, which might raise the same exception
again. This results in the Python exception being printed twice.
By throwing a C++ exception after the failed
PyObject_CallMethodObjArgs call, the completion mechanism is aborted,
and no completions are offered. But importantly, the Python exception
is only printed once. I think this gives a much better user
experience.
I've added some tests to cover this case, as I think this is the most
likely case that a user will run into.
Approved-By: Tom Tromey <tom@tromey.com>
2023-11-27 21:29:53 +00:00
|
|
|
|
{
|
|
|
|
|
|
gdbpy_print_stack ();
|
|
|
|
|
|
error (_("Could not convert argument to Python string."));
|
|
|
|
|
|
}
|
Introduce class completion_tracker & rewrite completion<->readline interaction
This patch reworks the whole completion machinery, and prepares it
for later enhancements.
Adds a new "completion_tracker" class that is meant to hold everything
about the state of the current completion operation.
This class now has the responsibility of tracking the list of
completion matches, and checking whether the max completions limit has
been reached. You can look at this as this patch starting out by
C++fying the existing "completion_tracker" in symtab.c (it's just an
htab_t typedef currently), moving it to completer.h/c, and then making
it a class/generalizing/enhancing it.
Unlike with the current tracking, completion_tracker now checks
whether the limit has been reached on each completion match list
insertion. This both simplifies the max-completions handling code
(maybe_add_completion_enum is gone, for example), and is a
prerequisite for follow up patches.
The current completion_tracker is only used for symbol completions,
and the symbol code gets at the current instance via globals. This
patch cleans that up by adding a completion_tracker reference to the
signature of the completion functions, and passing the tracker around
everywhere necessary.
Then, the patch changes how the completion match list is handed over
to readline. Currently, we're using the rl_completion_entry_function
readline entry point, and the patch switches to
rl_attempted_completion_function. A following patch will want to let
GDB itself decide the common completion prefix between all matches
(what readline calls the "lowest common denominator"), instead of
having readline compute it, and that's not possible with the
rl_completion_entry_function entry point. Also,
rl_attempted_completion_function lets GDB hand over the match list to
readline as an array in one go instead of passing down matches one by
one, so from that angle it's a nicer entry point anyway.
Lastly, the patch catches exceptions around the readline entry points,
because we can't let C++ exceptions cross readline. We handle that in
the readline input entry point, but the completion entry point isn't
guarded, so GDB can abort if completion throws. E.g., in current
master:
(gdb) b -function "fun<tab>
terminate called after throwing an instance of 'gdb_exception_RETURN_MASK_ERROR'
Aborted (core dumped)
This patch fixes that. This will be exercised in the new tests added
later on in the series.
gdb/ChangeLog:
2017-07-17 Pedro Alves <palves@redhat.com>
* ada-lang.c (symbol_completion_match): Adjust comments.
(symbol_completion_add): Replace vector parameter with
completion_tracker parameter. Use it.
(ada_make_symbol_completion_list): Rename to...
(ada_collect_symbol_completion_matches): ... this. Add
completion_tracker parameter and use it.
(ada_language_defn): Adjust.
* break-catch-syscall.c (catch_syscall_completer): Adjust
prototype and work with completion_tracker instead of VEC.
* breakpoint.c (condition_completer): Adjust prototype and work
with completion_tracker instead of VEC.
* c-lang.c (c_language_defn, cplus_language_defn)
(asm_language_defn, minimal_language_defn): Adjust to renames.
* cli/cli-cmds.c (complete_command): Rework using
completion_tracker. Catch exceptions when completing.
* cli/cli-decode.c (integer_unlimited_completer)
(complete_on_cmdlist, complete_on_enum): Adjust prototype and work
with completion_tracker instead of VEC.
* command.h (struct completion_tracker): Forward declare.
(completer_ftype, completer_handle_brkchars_ftype): Change
types.
(complete_on_cmdlist, complete_on_enum): Adjust.
* completer.c: Include <algorithm>.
(struct gdb_completer_state): New.
(current_completion): New global.
(readline_line_completion_function): Delete.
(noop_completer, filename_completer)
(filename_completer_handle_brkchars, complete_files_symbols)
(linespec_location_completer): Adjust to work with a
completion_tracker instead of a VEC.
(string_or_empty): New.
(collect_explicit_location_matches): Adjust to work with a
completion_tracker instead of a VEC.
(explicit_location_completer): Rename to ...
(complete_explicit_location): ... this and adjust to work with a
completion_tracker instead of a VEC.
(location_completer): Adjust to work with a completion_tracker
instead of a VEC.
(add_struct_fields): Adjust to work with a completion_list instead
of VEC.
(expression_completer): Rename to ...
(complete_expression): ... this and adjust to work with a
completion_tracker instead of a VEC. Use complete_files_symbols.
(expression_completer): Reimplement on top of complete_expression.
(symbol_completer): Adjust to work with a completion_tracker
instead of a VEC.
(enum complete_line_internal_reason): Add describing comments.
(complete_line_internal_normal_command): Adjust to work with a
completion_tracker instead of a VEC.
(complete_line_internal): Rename to ...
(complete_line_internal_1): ... this and adjust to work with a
completion_tracker instead of a VEC. Assert TEXT is NULL in the
handle_brkchars phase.
(new_completion_tracker): Delete.
(complete_line_internal): Reimplement as TRY/CATCH wrapper around
complete_line_internal_1.
(free_completion_tracker): Delete.
(INITIAL_COMPLETION_HTAB_SIZE): New.
(completion_tracker::completion_tracker)
(completion_tracker::~completion_tracker): New.
(maybe_add_completion): Delete.
(completion_tracker::maybe_add_completion)
(completion_tracker::add_completion)
(completion_tracker::add_completions): New.
(throw_max_completions_reached_error): Delete.
(complete_line): Adjust to work with a completion_tracker instead
of a VEC. Don't create a completion_tracker_t or check for max
completions here.
(command_completer, command_completer_handle_brkchars)
(signal_completer, reg_or_group_completer_1)
(reg_or_group_completer, default_completer_handle_brkchars):
Adjust to work with a completion_tracker.
(gdb_completion_word_break_characters_throw): New.
(gdb_completion_word_break_characters): Reimplement.
(line_completion_function): Delete.
(completion_tracker::recompute_lowest_common_denominator)
(expand_preserving_ws)
(completion_tracker::build_completion_result)
(completion_result::completion_result)
(completion_result::completion_result)
(completion_result::~completion_result)
(completion_result::completion_result)
(completion_result::release_match_list, compare_cstrings)
(completion_result::sort_match_list)
(completion_result::reset_match_list)
(gdb_rl_attempted_completion_function_throw)
(gdb_rl_attempted_completion_function): New.
* completer.h (completion_list, struct completion_result)
(class completion_tracker): New.
(complete_line): Add completion_tracker parameter.
(readline_line_completion_function): Delete.
(gdb_rl_attempted_completion_function): New.
(noop_completer, filename_completer, expression_completer)
(location_completer, symbol_completer, command_completer)
(signal_completer, reg_or_group_completer): Update prototypes.
(completion_tracker_t, new_completion_tracker)
(make_cleanup_free_completion_tracker): Delete.
(enum maybe_add_completion_enum): Delete.
(maybe_add_completion): Delete.
(throw_max_completions_reached_error): Delete.
* corefile.c (complete_set_gnutarget): Adjust to work with a
completion_tracker instead of a VEC.
* cp-abi.c (cp_abi_completer): Adjust to work with a
completion_tracker instead of a VEC.
* d-lang.c (d_language_defn): Adjust.
* disasm.c (disassembler_options_completer): Adjust to work with a
completion_tracker instead of a VEC.
* f-lang.c (f_make_symbol_completion_list): Rename to ...
(f_collect_symbol_completion_matches): ... this. Adjust to work
with a completion_tracker instead of a VEC.
(f_language_defn): Adjust.
* go-lang.c (go_language_defn): Adjust.
* guile/scm-cmd.c (cmdscm_add_completion, cmdscm_completer):
Adjust to work with a completion_tracker instead of a VEC.
* infrun.c (handle_completer): Likewise.
* interps.c (interpreter_completer): Likewise.
* interps.h (interpreter_completer): Likewise.
* language.c (unknown_language_defn, auto_language_defn)
(local_language_defn): Adjust.
* language.h (language_defn::la_make_symbol_completion_list):
Rename to ...
(language_defn::la_collect_symbol_completion_matches): ... this
and adjust to work with a completion_tracker instead of a VEC.
* m2-lang.c (m2_language_defn): Adjust.
* objc-lang.c (objc_language_defn): Adjust.
* opencl-lang.c (opencl_language_defn): Adjust.
* p-lang.c (pascal_language_defn): Adjust.
* python/py-cmd.c (cmdpy_completer_helper): Handle NULL word.
(cmdpy_completer_handle_brkchars, cmdpy_completer): Adjust to work
with a completion_tracker.
* rust-lang.c (rust_language_defn): Adjust.
* symtab.c (free_completion_list, do_free_completion_list)
(return_val, completion_tracker): Delete.
(completion_list_add_name, completion_list_add_symbol)
(completion_list_add_msymbol, completion_list_objc_symbol)
(completion_list_add_fields, add_symtab_completions): Add
completion_tracker parameter and use it.
(default_make_symbol_completion_list_break_on_1): Rename to...
(default_collect_symbol_completion_matches_break_on): ... this.
Add completion_tracker parameter and use it instead of allocating
a completion tracker here.
(default_make_symbol_completion_list_break_on): Delete old
implementation.
(default_make_symbol_completion_list): Delete.
(default_collect_symbol_completion_matches): New.
(make_symbol_completion_list): Delete.
(collect_symbol_completion_matches): New.
(make_symbol_completion_type): Rename to ...
(collect_symbol_completion_matches_type): ... this. Add
completion_tracker parameter and use it instead of VEC.
(make_file_symbol_completion_list_1): Rename to...
(collect_file_symbol_completion_matches): ... this. Add
completion_tracker parameter and use it instead of VEC.
(make_file_symbol_completion_list): Delete.
(add_filename_to_list): Use completion_list instead of a VEC.
(add_partial_filename_data::list): Now a completion_list.
(make_source_files_completion_list): Work with a completion_list
instead of a VEC.
* symtab.h: Include "completer.h".
(default_make_symbol_completion_list_break_on)
(default_make_symbol_completion_list, make_symbol_completion_list)
(make_symbol_completion_type, make_file_symbol_completion_list)
(make_source_files_completion_list): Delete.
(default_collect_symbol_completion_matches_break_on)
(default_collect_symbol_completion_matches)
(collect_symbol_completion_matches)
(collect_symbol_completion_matches_type)
(collect_file_symbol_completion_matches)
(make_source_files_completion_list): New.
* top.c (init_main): Don't install a rl_completion_entry_function
hook. Install a rl_attempted_completion_function hook instead.
* tui/tui-layout.c (layout_completer): Adjust to work with a
completion_tracker.
* tui/tui-regs.c (tui_reggroup_completer):
* tui/tui-win.c (window_name_completer, focus_completer)
(winheight_completer): Adjust to work with a completion_tracker.
* value.c: Include "completer.h".
(complete_internalvar): Adjust to work with a completion_tracker.
* value.h (complete_internalvar): Likewise.
2017-07-17 14:45:59 +01:00
|
|
|
|
|
|
|
|
|
|
gdbpy_ref<> wordobj;
|
|
|
|
|
|
if (word == NULL)
|
|
|
|
|
|
{
|
|
|
|
|
|
/* "brkchars" phase. */
|
2026-05-15 21:38:12 +02:00
|
|
|
|
wordobj = py_none ();
|
Introduce class completion_tracker & rewrite completion<->readline interaction
This patch reworks the whole completion machinery, and prepares it
for later enhancements.
Adds a new "completion_tracker" class that is meant to hold everything
about the state of the current completion operation.
This class now has the responsibility of tracking the list of
completion matches, and checking whether the max completions limit has
been reached. You can look at this as this patch starting out by
C++fying the existing "completion_tracker" in symtab.c (it's just an
htab_t typedef currently), moving it to completer.h/c, and then making
it a class/generalizing/enhancing it.
Unlike with the current tracking, completion_tracker now checks
whether the limit has been reached on each completion match list
insertion. This both simplifies the max-completions handling code
(maybe_add_completion_enum is gone, for example), and is a
prerequisite for follow up patches.
The current completion_tracker is only used for symbol completions,
and the symbol code gets at the current instance via globals. This
patch cleans that up by adding a completion_tracker reference to the
signature of the completion functions, and passing the tracker around
everywhere necessary.
Then, the patch changes how the completion match list is handed over
to readline. Currently, we're using the rl_completion_entry_function
readline entry point, and the patch switches to
rl_attempted_completion_function. A following patch will want to let
GDB itself decide the common completion prefix between all matches
(what readline calls the "lowest common denominator"), instead of
having readline compute it, and that's not possible with the
rl_completion_entry_function entry point. Also,
rl_attempted_completion_function lets GDB hand over the match list to
readline as an array in one go instead of passing down matches one by
one, so from that angle it's a nicer entry point anyway.
Lastly, the patch catches exceptions around the readline entry points,
because we can't let C++ exceptions cross readline. We handle that in
the readline input entry point, but the completion entry point isn't
guarded, so GDB can abort if completion throws. E.g., in current
master:
(gdb) b -function "fun<tab>
terminate called after throwing an instance of 'gdb_exception_RETURN_MASK_ERROR'
Aborted (core dumped)
This patch fixes that. This will be exercised in the new tests added
later on in the series.
gdb/ChangeLog:
2017-07-17 Pedro Alves <palves@redhat.com>
* ada-lang.c (symbol_completion_match): Adjust comments.
(symbol_completion_add): Replace vector parameter with
completion_tracker parameter. Use it.
(ada_make_symbol_completion_list): Rename to...
(ada_collect_symbol_completion_matches): ... this. Add
completion_tracker parameter and use it.
(ada_language_defn): Adjust.
* break-catch-syscall.c (catch_syscall_completer): Adjust
prototype and work with completion_tracker instead of VEC.
* breakpoint.c (condition_completer): Adjust prototype and work
with completion_tracker instead of VEC.
* c-lang.c (c_language_defn, cplus_language_defn)
(asm_language_defn, minimal_language_defn): Adjust to renames.
* cli/cli-cmds.c (complete_command): Rework using
completion_tracker. Catch exceptions when completing.
* cli/cli-decode.c (integer_unlimited_completer)
(complete_on_cmdlist, complete_on_enum): Adjust prototype and work
with completion_tracker instead of VEC.
* command.h (struct completion_tracker): Forward declare.
(completer_ftype, completer_handle_brkchars_ftype): Change
types.
(complete_on_cmdlist, complete_on_enum): Adjust.
* completer.c: Include <algorithm>.
(struct gdb_completer_state): New.
(current_completion): New global.
(readline_line_completion_function): Delete.
(noop_completer, filename_completer)
(filename_completer_handle_brkchars, complete_files_symbols)
(linespec_location_completer): Adjust to work with a
completion_tracker instead of a VEC.
(string_or_empty): New.
(collect_explicit_location_matches): Adjust to work with a
completion_tracker instead of a VEC.
(explicit_location_completer): Rename to ...
(complete_explicit_location): ... this and adjust to work with a
completion_tracker instead of a VEC.
(location_completer): Adjust to work with a completion_tracker
instead of a VEC.
(add_struct_fields): Adjust to work with a completion_list instead
of VEC.
(expression_completer): Rename to ...
(complete_expression): ... this and adjust to work with a
completion_tracker instead of a VEC. Use complete_files_symbols.
(expression_completer): Reimplement on top of complete_expression.
(symbol_completer): Adjust to work with a completion_tracker
instead of a VEC.
(enum complete_line_internal_reason): Add describing comments.
(complete_line_internal_normal_command): Adjust to work with a
completion_tracker instead of a VEC.
(complete_line_internal): Rename to ...
(complete_line_internal_1): ... this and adjust to work with a
completion_tracker instead of a VEC. Assert TEXT is NULL in the
handle_brkchars phase.
(new_completion_tracker): Delete.
(complete_line_internal): Reimplement as TRY/CATCH wrapper around
complete_line_internal_1.
(free_completion_tracker): Delete.
(INITIAL_COMPLETION_HTAB_SIZE): New.
(completion_tracker::completion_tracker)
(completion_tracker::~completion_tracker): New.
(maybe_add_completion): Delete.
(completion_tracker::maybe_add_completion)
(completion_tracker::add_completion)
(completion_tracker::add_completions): New.
(throw_max_completions_reached_error): Delete.
(complete_line): Adjust to work with a completion_tracker instead
of a VEC. Don't create a completion_tracker_t or check for max
completions here.
(command_completer, command_completer_handle_brkchars)
(signal_completer, reg_or_group_completer_1)
(reg_or_group_completer, default_completer_handle_brkchars):
Adjust to work with a completion_tracker.
(gdb_completion_word_break_characters_throw): New.
(gdb_completion_word_break_characters): Reimplement.
(line_completion_function): Delete.
(completion_tracker::recompute_lowest_common_denominator)
(expand_preserving_ws)
(completion_tracker::build_completion_result)
(completion_result::completion_result)
(completion_result::completion_result)
(completion_result::~completion_result)
(completion_result::completion_result)
(completion_result::release_match_list, compare_cstrings)
(completion_result::sort_match_list)
(completion_result::reset_match_list)
(gdb_rl_attempted_completion_function_throw)
(gdb_rl_attempted_completion_function): New.
* completer.h (completion_list, struct completion_result)
(class completion_tracker): New.
(complete_line): Add completion_tracker parameter.
(readline_line_completion_function): Delete.
(gdb_rl_attempted_completion_function): New.
(noop_completer, filename_completer, expression_completer)
(location_completer, symbol_completer, command_completer)
(signal_completer, reg_or_group_completer): Update prototypes.
(completion_tracker_t, new_completion_tracker)
(make_cleanup_free_completion_tracker): Delete.
(enum maybe_add_completion_enum): Delete.
(maybe_add_completion): Delete.
(throw_max_completions_reached_error): Delete.
* corefile.c (complete_set_gnutarget): Adjust to work with a
completion_tracker instead of a VEC.
* cp-abi.c (cp_abi_completer): Adjust to work with a
completion_tracker instead of a VEC.
* d-lang.c (d_language_defn): Adjust.
* disasm.c (disassembler_options_completer): Adjust to work with a
completion_tracker instead of a VEC.
* f-lang.c (f_make_symbol_completion_list): Rename to ...
(f_collect_symbol_completion_matches): ... this. Adjust to work
with a completion_tracker instead of a VEC.
(f_language_defn): Adjust.
* go-lang.c (go_language_defn): Adjust.
* guile/scm-cmd.c (cmdscm_add_completion, cmdscm_completer):
Adjust to work with a completion_tracker instead of a VEC.
* infrun.c (handle_completer): Likewise.
* interps.c (interpreter_completer): Likewise.
* interps.h (interpreter_completer): Likewise.
* language.c (unknown_language_defn, auto_language_defn)
(local_language_defn): Adjust.
* language.h (language_defn::la_make_symbol_completion_list):
Rename to ...
(language_defn::la_collect_symbol_completion_matches): ... this
and adjust to work with a completion_tracker instead of a VEC.
* m2-lang.c (m2_language_defn): Adjust.
* objc-lang.c (objc_language_defn): Adjust.
* opencl-lang.c (opencl_language_defn): Adjust.
* p-lang.c (pascal_language_defn): Adjust.
* python/py-cmd.c (cmdpy_completer_helper): Handle NULL word.
(cmdpy_completer_handle_brkchars, cmdpy_completer): Adjust to work
with a completion_tracker.
* rust-lang.c (rust_language_defn): Adjust.
* symtab.c (free_completion_list, do_free_completion_list)
(return_val, completion_tracker): Delete.
(completion_list_add_name, completion_list_add_symbol)
(completion_list_add_msymbol, completion_list_objc_symbol)
(completion_list_add_fields, add_symtab_completions): Add
completion_tracker parameter and use it.
(default_make_symbol_completion_list_break_on_1): Rename to...
(default_collect_symbol_completion_matches_break_on): ... this.
Add completion_tracker parameter and use it instead of allocating
a completion tracker here.
(default_make_symbol_completion_list_break_on): Delete old
implementation.
(default_make_symbol_completion_list): Delete.
(default_collect_symbol_completion_matches): New.
(make_symbol_completion_list): Delete.
(collect_symbol_completion_matches): New.
(make_symbol_completion_type): Rename to ...
(collect_symbol_completion_matches_type): ... this. Add
completion_tracker parameter and use it instead of VEC.
(make_file_symbol_completion_list_1): Rename to...
(collect_file_symbol_completion_matches): ... this. Add
completion_tracker parameter and use it instead of VEC.
(make_file_symbol_completion_list): Delete.
(add_filename_to_list): Use completion_list instead of a VEC.
(add_partial_filename_data::list): Now a completion_list.
(make_source_files_completion_list): Work with a completion_list
instead of a VEC.
* symtab.h: Include "completer.h".
(default_make_symbol_completion_list_break_on)
(default_make_symbol_completion_list, make_symbol_completion_list)
(make_symbol_completion_type, make_file_symbol_completion_list)
(make_source_files_completion_list): Delete.
(default_collect_symbol_completion_matches_break_on)
(default_collect_symbol_completion_matches)
(collect_symbol_completion_matches)
(collect_symbol_completion_matches_type)
(collect_file_symbol_completion_matches)
(make_source_files_completion_list): New.
* top.c (init_main): Don't install a rl_completion_entry_function
hook. Install a rl_attempted_completion_function hook instead.
* tui/tui-layout.c (layout_completer): Adjust to work with a
completion_tracker.
* tui/tui-regs.c (tui_reggroup_completer):
* tui/tui-win.c (window_name_completer, focus_completer)
(winheight_completer): Adjust to work with a completion_tracker.
* value.c: Include "completer.h".
(complete_internalvar): Adjust to work with a completion_tracker.
* value.h (complete_internalvar): Likewise.
2017-07-17 14:45:59 +01:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
wordobj.reset (PyUnicode_Decode (word, strlen (word), host_charset (),
|
|
|
|
|
|
NULL));
|
|
|
|
|
|
if (wordobj == NULL)
|
gdb/python: display errors from command completion
This commit makes the gdb.Command.complete methods more verbose when
it comes to error handling.
Previous to this commit if any commands implemented in Python
implemented the complete method, and if there were any errors
encountered when calling that complete method, then GDB would silently
hide the error and continue as if there were no completions.
This makes is difficult to debug any errors encountered when writing
completion methods, and encourages the idea that Python extensions can
be broken, and GDB will just silently work around them.
I don't think this is a good idea. GDB should encourage extensions to
be written correctly, and robustly, and one way in which GDB can (I
think) support this, is by pointing out when an extension goes wrong.
In this commit I've gone through the Python command completion code,
and added calls to gdbpy_print_stack() or gdbpy_print_stack_or_quit()
in places where we were either clearing the Python error, or, in some
cases, just not handling the error at all.
One thing I have not changed is in cmdpy_completer (py-cmd.c) where we
process the list of completions returned from the Command.complete
method; this routine includes a call to gdbpy_is_string to check a
possible completion is a string, if not the completion is ignored.
I was tempted to remove this check, attempt to complete each result to
a string, and display an error if the conversion fails. After all,
returning anything but a string is surely a mistake by the extension
author.
However, the docs clearly say that only strings within the returned
list will be considered as completions. Anything else is ignored. As
such, and to avoid (what I think is pretty unlikely) breakage of
existing code, I've retained the gdbpy_is_string check.
After the gdbpy_is_string check we call python_string_to_host_string,
if this call fails then I do now print the error, where before we
ignored the error. I think this is OK; if GDB thinks something is a
string, but still can't convert it to a string, then I think it's OK
to display the error in that case.
Another case which I was a little unsure about was in
cmdpy_completer_helper, and the call to PyObject_CallMethodObjArgs,
which is when we actually call Command.complete. Previously, if this
call resulted in an exception then we would ignore this and just
pretend there were no completions.
Of all the changes, this is possibly the one with the biggest
potential for breaking existing scripts, but also, is, I think, the
most useful change. If the user code is wrong in some way, such that
an exception is raised, then previously the user would have no obvious
feedback about this breakage. Now GDB will print the exception for
them, making it, I think, much easier to debug their extension. But,
if there is user code in the wild that relies on raising an exception
as a means to indicate there are no completions .... well, that code
is going to break after this commit. I think we can live with this
though, the exceptions means no completions thing was never documented
behaviour.
I also added a new error() call if the PyObject_CallMethodObjArgs call
raises an exception. This causes the completion mechanism within GDB
to stop. Within GDB the completion code is called twice, the first
time to compute the work break characters, and then a second time to
compute the actual completions.
If PyObject_CallMethodObjArgs raises an exception when computing the
word break character, and we print it by calling
gdbpy_print_stack_or_quit(), but then carry on as if
PyObject_CallMethodObjArgs had returns no completions, GDB will
call the Python completion code again, which results in another call
to PyObject_CallMethodObjArgs, which might raise the same exception
again. This results in the Python exception being printed twice.
By throwing a C++ exception after the failed
PyObject_CallMethodObjArgs call, the completion mechanism is aborted,
and no completions are offered. But importantly, the Python exception
is only printed once. I think this gives a much better user
experience.
I've added some tests to cover this case, as I think this is the most
likely case that a user will run into.
Approved-By: Tom Tromey <tom@tromey.com>
2023-11-27 21:29:53 +00:00
|
|
|
|
{
|
|
|
|
|
|
gdbpy_print_stack ();
|
|
|
|
|
|
error (_("Could not convert argument to Python string."));
|
|
|
|
|
|
}
|
Introduce class completion_tracker & rewrite completion<->readline interaction
This patch reworks the whole completion machinery, and prepares it
for later enhancements.
Adds a new "completion_tracker" class that is meant to hold everything
about the state of the current completion operation.
This class now has the responsibility of tracking the list of
completion matches, and checking whether the max completions limit has
been reached. You can look at this as this patch starting out by
C++fying the existing "completion_tracker" in symtab.c (it's just an
htab_t typedef currently), moving it to completer.h/c, and then making
it a class/generalizing/enhancing it.
Unlike with the current tracking, completion_tracker now checks
whether the limit has been reached on each completion match list
insertion. This both simplifies the max-completions handling code
(maybe_add_completion_enum is gone, for example), and is a
prerequisite for follow up patches.
The current completion_tracker is only used for symbol completions,
and the symbol code gets at the current instance via globals. This
patch cleans that up by adding a completion_tracker reference to the
signature of the completion functions, and passing the tracker around
everywhere necessary.
Then, the patch changes how the completion match list is handed over
to readline. Currently, we're using the rl_completion_entry_function
readline entry point, and the patch switches to
rl_attempted_completion_function. A following patch will want to let
GDB itself decide the common completion prefix between all matches
(what readline calls the "lowest common denominator"), instead of
having readline compute it, and that's not possible with the
rl_completion_entry_function entry point. Also,
rl_attempted_completion_function lets GDB hand over the match list to
readline as an array in one go instead of passing down matches one by
one, so from that angle it's a nicer entry point anyway.
Lastly, the patch catches exceptions around the readline entry points,
because we can't let C++ exceptions cross readline. We handle that in
the readline input entry point, but the completion entry point isn't
guarded, so GDB can abort if completion throws. E.g., in current
master:
(gdb) b -function "fun<tab>
terminate called after throwing an instance of 'gdb_exception_RETURN_MASK_ERROR'
Aborted (core dumped)
This patch fixes that. This will be exercised in the new tests added
later on in the series.
gdb/ChangeLog:
2017-07-17 Pedro Alves <palves@redhat.com>
* ada-lang.c (symbol_completion_match): Adjust comments.
(symbol_completion_add): Replace vector parameter with
completion_tracker parameter. Use it.
(ada_make_symbol_completion_list): Rename to...
(ada_collect_symbol_completion_matches): ... this. Add
completion_tracker parameter and use it.
(ada_language_defn): Adjust.
* break-catch-syscall.c (catch_syscall_completer): Adjust
prototype and work with completion_tracker instead of VEC.
* breakpoint.c (condition_completer): Adjust prototype and work
with completion_tracker instead of VEC.
* c-lang.c (c_language_defn, cplus_language_defn)
(asm_language_defn, minimal_language_defn): Adjust to renames.
* cli/cli-cmds.c (complete_command): Rework using
completion_tracker. Catch exceptions when completing.
* cli/cli-decode.c (integer_unlimited_completer)
(complete_on_cmdlist, complete_on_enum): Adjust prototype and work
with completion_tracker instead of VEC.
* command.h (struct completion_tracker): Forward declare.
(completer_ftype, completer_handle_brkchars_ftype): Change
types.
(complete_on_cmdlist, complete_on_enum): Adjust.
* completer.c: Include <algorithm>.
(struct gdb_completer_state): New.
(current_completion): New global.
(readline_line_completion_function): Delete.
(noop_completer, filename_completer)
(filename_completer_handle_brkchars, complete_files_symbols)
(linespec_location_completer): Adjust to work with a
completion_tracker instead of a VEC.
(string_or_empty): New.
(collect_explicit_location_matches): Adjust to work with a
completion_tracker instead of a VEC.
(explicit_location_completer): Rename to ...
(complete_explicit_location): ... this and adjust to work with a
completion_tracker instead of a VEC.
(location_completer): Adjust to work with a completion_tracker
instead of a VEC.
(add_struct_fields): Adjust to work with a completion_list instead
of VEC.
(expression_completer): Rename to ...
(complete_expression): ... this and adjust to work with a
completion_tracker instead of a VEC. Use complete_files_symbols.
(expression_completer): Reimplement on top of complete_expression.
(symbol_completer): Adjust to work with a completion_tracker
instead of a VEC.
(enum complete_line_internal_reason): Add describing comments.
(complete_line_internal_normal_command): Adjust to work with a
completion_tracker instead of a VEC.
(complete_line_internal): Rename to ...
(complete_line_internal_1): ... this and adjust to work with a
completion_tracker instead of a VEC. Assert TEXT is NULL in the
handle_brkchars phase.
(new_completion_tracker): Delete.
(complete_line_internal): Reimplement as TRY/CATCH wrapper around
complete_line_internal_1.
(free_completion_tracker): Delete.
(INITIAL_COMPLETION_HTAB_SIZE): New.
(completion_tracker::completion_tracker)
(completion_tracker::~completion_tracker): New.
(maybe_add_completion): Delete.
(completion_tracker::maybe_add_completion)
(completion_tracker::add_completion)
(completion_tracker::add_completions): New.
(throw_max_completions_reached_error): Delete.
(complete_line): Adjust to work with a completion_tracker instead
of a VEC. Don't create a completion_tracker_t or check for max
completions here.
(command_completer, command_completer_handle_brkchars)
(signal_completer, reg_or_group_completer_1)
(reg_or_group_completer, default_completer_handle_brkchars):
Adjust to work with a completion_tracker.
(gdb_completion_word_break_characters_throw): New.
(gdb_completion_word_break_characters): Reimplement.
(line_completion_function): Delete.
(completion_tracker::recompute_lowest_common_denominator)
(expand_preserving_ws)
(completion_tracker::build_completion_result)
(completion_result::completion_result)
(completion_result::completion_result)
(completion_result::~completion_result)
(completion_result::completion_result)
(completion_result::release_match_list, compare_cstrings)
(completion_result::sort_match_list)
(completion_result::reset_match_list)
(gdb_rl_attempted_completion_function_throw)
(gdb_rl_attempted_completion_function): New.
* completer.h (completion_list, struct completion_result)
(class completion_tracker): New.
(complete_line): Add completion_tracker parameter.
(readline_line_completion_function): Delete.
(gdb_rl_attempted_completion_function): New.
(noop_completer, filename_completer, expression_completer)
(location_completer, symbol_completer, command_completer)
(signal_completer, reg_or_group_completer): Update prototypes.
(completion_tracker_t, new_completion_tracker)
(make_cleanup_free_completion_tracker): Delete.
(enum maybe_add_completion_enum): Delete.
(maybe_add_completion): Delete.
(throw_max_completions_reached_error): Delete.
* corefile.c (complete_set_gnutarget): Adjust to work with a
completion_tracker instead of a VEC.
* cp-abi.c (cp_abi_completer): Adjust to work with a
completion_tracker instead of a VEC.
* d-lang.c (d_language_defn): Adjust.
* disasm.c (disassembler_options_completer): Adjust to work with a
completion_tracker instead of a VEC.
* f-lang.c (f_make_symbol_completion_list): Rename to ...
(f_collect_symbol_completion_matches): ... this. Adjust to work
with a completion_tracker instead of a VEC.
(f_language_defn): Adjust.
* go-lang.c (go_language_defn): Adjust.
* guile/scm-cmd.c (cmdscm_add_completion, cmdscm_completer):
Adjust to work with a completion_tracker instead of a VEC.
* infrun.c (handle_completer): Likewise.
* interps.c (interpreter_completer): Likewise.
* interps.h (interpreter_completer): Likewise.
* language.c (unknown_language_defn, auto_language_defn)
(local_language_defn): Adjust.
* language.h (language_defn::la_make_symbol_completion_list):
Rename to ...
(language_defn::la_collect_symbol_completion_matches): ... this
and adjust to work with a completion_tracker instead of a VEC.
* m2-lang.c (m2_language_defn): Adjust.
* objc-lang.c (objc_language_defn): Adjust.
* opencl-lang.c (opencl_language_defn): Adjust.
* p-lang.c (pascal_language_defn): Adjust.
* python/py-cmd.c (cmdpy_completer_helper): Handle NULL word.
(cmdpy_completer_handle_brkchars, cmdpy_completer): Adjust to work
with a completion_tracker.
* rust-lang.c (rust_language_defn): Adjust.
* symtab.c (free_completion_list, do_free_completion_list)
(return_val, completion_tracker): Delete.
(completion_list_add_name, completion_list_add_symbol)
(completion_list_add_msymbol, completion_list_objc_symbol)
(completion_list_add_fields, add_symtab_completions): Add
completion_tracker parameter and use it.
(default_make_symbol_completion_list_break_on_1): Rename to...
(default_collect_symbol_completion_matches_break_on): ... this.
Add completion_tracker parameter and use it instead of allocating
a completion tracker here.
(default_make_symbol_completion_list_break_on): Delete old
implementation.
(default_make_symbol_completion_list): Delete.
(default_collect_symbol_completion_matches): New.
(make_symbol_completion_list): Delete.
(collect_symbol_completion_matches): New.
(make_symbol_completion_type): Rename to ...
(collect_symbol_completion_matches_type): ... this. Add
completion_tracker parameter and use it instead of VEC.
(make_file_symbol_completion_list_1): Rename to...
(collect_file_symbol_completion_matches): ... this. Add
completion_tracker parameter and use it instead of VEC.
(make_file_symbol_completion_list): Delete.
(add_filename_to_list): Use completion_list instead of a VEC.
(add_partial_filename_data::list): Now a completion_list.
(make_source_files_completion_list): Work with a completion_list
instead of a VEC.
* symtab.h: Include "completer.h".
(default_make_symbol_completion_list_break_on)
(default_make_symbol_completion_list, make_symbol_completion_list)
(make_symbol_completion_type, make_file_symbol_completion_list)
(make_source_files_completion_list): Delete.
(default_collect_symbol_completion_matches_break_on)
(default_collect_symbol_completion_matches)
(collect_symbol_completion_matches)
(collect_symbol_completion_matches_type)
(collect_file_symbol_completion_matches)
(make_source_files_completion_list): New.
* top.c (init_main): Don't install a rl_completion_entry_function
hook. Install a rl_attempted_completion_function hook instead.
* tui/tui-layout.c (layout_completer): Adjust to work with a
completion_tracker.
* tui/tui-regs.c (tui_reggroup_completer):
* tui/tui-win.c (window_name_completer, focus_completer)
(winheight_completer): Adjust to work with a completion_tracker.
* value.c: Include "completer.h".
(complete_internalvar): Adjust to work with a completion_tracker.
* value.h (complete_internalvar): Likewise.
2017-07-17 14:45:59 +01:00
|
|
|
|
}
|
PR python/16699: GDB Python command completion with overriden complete vs. completer class
This PR came from a Red Hat bug that was filed recently. I checked and
it still exists on HEAD, so here's a proposed fix. Although this is
marked as a Python backend bug, this is really about the completion
mechanism used by GDB. Since this code reminds me of my first attempt
to make a good noodle, it took me quite some time to fix it in a
non-intrusive way.
The problem is triggered when one registers a completion method inside a
class in a Python script, rather than registering the command using a
completer class directly. For example, consider the following script:
class MyFirstCommand(gdb.Command):
def __init__(self):
gdb.Command.__init__(self,'myfirstcommand',gdb.COMMAND_USER,gdb.COMPLETE_FILENAME)
def invoke(self,argument,from_tty):
raise gdb.GdbError('not implemented')
class MySecondCommand(gdb.Command):
def __init__(self):
gdb.Command.__init__(self,'mysecondcommand',gdb.COMMAND_USER)
def invoke(self,argument,from_tty):
raise gdb.GdbError('not implemented')
def complete(self,text,word):
return gdb.COMPLETE_FILENAME
MyFirstCommand ()
MySecondCommand ()
When one loads this into GDB and tries to complete filenames for both
myfirstcommand and mysecondcommand, she gets:
(gdb) myfirstcommand /hom<TAB>
(gdb) myfirstcommand /home/
^
...
(gdb) mysecondcommand /hom<TAB>
(gdb) mysecondcommand /home
^
(The "^" marks the final position of the cursor after the TAB).
So we see that myfirstcommand honors the COMPLETE_FILENAME class (as
specified in the command creation), but mysecondcommand does not. After
some investigation, I found that the problem lies with the set of word
break characters that is used for each case. The set should be the same
for both commands, but it is not.
During the process of deciding which type of completion should be used,
the code in gdb/completer.c:complete_line_internal analyses the command
that requested the completion and tries to determine the type of
completion wanted by checking which completion function will be called
(e.g., filename_completer for filenames, location_completer for
locations, etc.).
This all works fine for myfirstcommand, because immediately after the
command registration the Python backend already sets its completion
function to filename_completer (which then causes the
complete_line_internal function to choose the right set of word break
chars). However, for mysecondcommand, this decision is postponed to
when the completer function is evaluated, and the Python backend uses an
internal completer (called cmdpy_completer). complete_line_internal
doesn't know about this internal completer, and can't choose the right
set of word break chars in time, which then leads to a bad decision when
completing the "/hom" word.
So, after a few attempts, I decided to create another callback in
"struct cmd_list_element" that will be responsible for handling the case
when there is an unknown completer function for complete_line_internal
to work with. So far, only the Python backend uses this callback, and
only when the user provides a completer method instead of registering
the command directly with a completer class. I think this is the best
option because it not very intrusive (all the other commands will still
work normally), but especially because the whole completion code is so
messy that it would be hard to fix this without having to redesign
things.
I have regtested this on Fedora 18 x86_64, without regressions. I also
included a testcase.
gdb/ChangeLog:
2014-09-03 Sergio Durigan Junior <sergiodj@redhat.com>
PR python/16699
* cli/cli-decode.c (set_cmd_completer_handle_brkchars): New
function.
(add_cmd): Set "completer_handle_brkchars" to NULL.
* cli/cli-decode.h (struct cmd_list_element)
<completer_handle_brkchars>: New field.
* command.h (completer_ftype_void): New typedef.
(set_cmd_completer_handle_brkchars): New prototype.
* completer.c (set_gdb_completion_word_break_characters): New
function.
(complete_line_internal): Call "completer_handle_brkchars"
callback from command.
* completer.h: Include "command.h".
(set_gdb_completion_word_break_characters): New prototype.
* python/py-cmd.c (cmdpy_completer_helper): New function.
(cmdpy_completer_handle_brkchars): New function.
(cmdpy_completer): Adjust to use cmdpy_completer_helper.
(cmdpy_init): Set completer_handle_brkchars to
cmdpy_completer_handle_brkchars.
gdb/testsuite/ChangeLog:
2014-09-03 Sergio Durigan Junior <sergiodj@redhat.com>
PR python/16699
* gdb.python/py-completion.exp: New file.
* gdb.python/py-completion.py: Likewise.
2014-09-03 16:30:28 -04:00
|
|
|
|
|
Turn gdbpy_ref into a template
This turns gdbpy_ref into a template class, so that it can be used to
wrap subclasses of PyObject. The default argument remains PyObject;
and this necessitated renaming uses of "gdbpy_ref" to "gdbpy_ref<>".
gdb/ChangeLog
2017-02-10 Tom Tromey <tom@tromey.com>
* python/py-ref.h (gdbpy_ref_policy): Now a template.
(gdbpy_ref): Now a template; allow subclasses of PyObject to be
used.
* python/py-arch.c, python/py-bpevent.c, python/py-breakpoint.c,
python/py-cmd.c, python/py-continueevent.c, python/py-event.c,
python/py-exitedevent.c, python/py-finishbreakpoint.c,
python/py-framefilter.c, python/py-function.c,
python/py-inferior.c, python/py-infevents.c,
python/py-linetable.c, python/py-newobjfileevent.c,
python/py-param.c, python/py-prettyprint.c, python/py-ref.h,
python/py-signalevent.c, python/py-stopevent.c,
python/py-symbol.c, python/py-threadevent.c, python/py-type.c,
python/py-unwind.c, python/py-utils.c, python/py-value.c,
python/py-varobj.c, python/py-xmethods.c, python/python.c,
varobj.c: Change gdbpy_ref to gdbpy_ref<>.
2017-02-09 13:16:36 -07:00
|
|
|
|
gdbpy_ref<> resultobj (PyObject_CallMethodObjArgs ((PyObject *) obj,
|
|
|
|
|
|
complete_cst,
|
|
|
|
|
|
textobj.get (),
|
|
|
|
|
|
wordobj.get (), NULL));
|
gdb/python: display errors from command completion
This commit makes the gdb.Command.complete methods more verbose when
it comes to error handling.
Previous to this commit if any commands implemented in Python
implemented the complete method, and if there were any errors
encountered when calling that complete method, then GDB would silently
hide the error and continue as if there were no completions.
This makes is difficult to debug any errors encountered when writing
completion methods, and encourages the idea that Python extensions can
be broken, and GDB will just silently work around them.
I don't think this is a good idea. GDB should encourage extensions to
be written correctly, and robustly, and one way in which GDB can (I
think) support this, is by pointing out when an extension goes wrong.
In this commit I've gone through the Python command completion code,
and added calls to gdbpy_print_stack() or gdbpy_print_stack_or_quit()
in places where we were either clearing the Python error, or, in some
cases, just not handling the error at all.
One thing I have not changed is in cmdpy_completer (py-cmd.c) where we
process the list of completions returned from the Command.complete
method; this routine includes a call to gdbpy_is_string to check a
possible completion is a string, if not the completion is ignored.
I was tempted to remove this check, attempt to complete each result to
a string, and display an error if the conversion fails. After all,
returning anything but a string is surely a mistake by the extension
author.
However, the docs clearly say that only strings within the returned
list will be considered as completions. Anything else is ignored. As
such, and to avoid (what I think is pretty unlikely) breakage of
existing code, I've retained the gdbpy_is_string check.
After the gdbpy_is_string check we call python_string_to_host_string,
if this call fails then I do now print the error, where before we
ignored the error. I think this is OK; if GDB thinks something is a
string, but still can't convert it to a string, then I think it's OK
to display the error in that case.
Another case which I was a little unsure about was in
cmdpy_completer_helper, and the call to PyObject_CallMethodObjArgs,
which is when we actually call Command.complete. Previously, if this
call resulted in an exception then we would ignore this and just
pretend there were no completions.
Of all the changes, this is possibly the one with the biggest
potential for breaking existing scripts, but also, is, I think, the
most useful change. If the user code is wrong in some way, such that
an exception is raised, then previously the user would have no obvious
feedback about this breakage. Now GDB will print the exception for
them, making it, I think, much easier to debug their extension. But,
if there is user code in the wild that relies on raising an exception
as a means to indicate there are no completions .... well, that code
is going to break after this commit. I think we can live with this
though, the exceptions means no completions thing was never documented
behaviour.
I also added a new error() call if the PyObject_CallMethodObjArgs call
raises an exception. This causes the completion mechanism within GDB
to stop. Within GDB the completion code is called twice, the first
time to compute the work break characters, and then a second time to
compute the actual completions.
If PyObject_CallMethodObjArgs raises an exception when computing the
word break character, and we print it by calling
gdbpy_print_stack_or_quit(), but then carry on as if
PyObject_CallMethodObjArgs had returns no completions, GDB will
call the Python completion code again, which results in another call
to PyObject_CallMethodObjArgs, which might raise the same exception
again. This results in the Python exception being printed twice.
By throwing a C++ exception after the failed
PyObject_CallMethodObjArgs call, the completion mechanism is aborted,
and no completions are offered. But importantly, the Python exception
is only printed once. I think this gives a much better user
experience.
I've added some tests to cover this case, as I think this is the most
likely case that a user will run into.
Approved-By: Tom Tromey <tom@tromey.com>
2023-11-27 21:29:53 +00:00
|
|
|
|
|
|
|
|
|
|
/* Check if an exception was raised by the Command.complete method. */
|
|
|
|
|
|
if (resultobj == nullptr)
|
Fix Python completion when using the "complete" command
This patch is related to PR python/16699, and is an improvement over the
patch posted here:
<https://sourceware.org/ml/gdb-patches/2014-03/msg00301.html>
Keith noticed that, when using the "complete" command on GDB to complete
a Python command, some strange things could happen. In order to
understand what can go wrong, I need to explain how the Python
completion mechanism works.
When the user requests a completion of a Python command by using TAB,
GDB will first try to determine the right set of "brkchars" that will be
used when doing the completion. This is done by actually calling the
"complete" method of the Python class. Then, when we already know the
"brkchars" that will be used, we call the "complete" method again, for
the same values.
If you read the thread mentioned above, you will see that one of the
design decisions was to make the "cmdpy_completer_helper" (which is the
function the does the actual calling of the "complete" method) cache the
first result of the completion, since this result will be used in the
second call, to do the actual completion.
The problem is that the "complete" command does not process the
brkchars, and the current Python completion mechanism (improved by the
patch mentioned above) relies on GDB trying to determine the brkchars,
and then doing the completion itself. Therefore, when we use the
"complete" command instead of doing a TAB-completion on GDB, there is a
scenario where we can use the invalid cache of a previous Python command
that was completed before. For example:
(gdb) A <TAB>
(gdb) complete B
B value1
B value10
B value2
B value3
B value4
B value5
B value6
B value7
B value8
B value9
(gdb) B <TAB>
comp1 comp2 comp4 comp6 comp8
comp10 comp3 comp5 comp7 comp9
Here, we see that "complete B " gave a different result than "B <TAB>".
The reason for that is because "A <TAB>" was called before, and its
completion results were "value*", so when GDB tried to "complete B " it
wrongly answered with the results for A. The problem here is using a
wrong cache (A's cache) for completing B.
We tried to come up with a solution that would preserve the caching
mechanism, but it wasn't really possible. So I decided to completely
remove the cache, and doing the method calling twice for every
completion. This is not optimal, but I do not think it will impact
users noticeably.
It is worth mentioning another small issue that I found. The code was
doing:
wordobj = PyUnicode_Decode (word, sizeof (word), host_charset (), NULL);
which is totally wrong, because using "sizeof" here will lead to always
the same result. So I changed this to use "strlen". The testcase also
catches this problem.
Keith kindly expanded the existing testcase to cover the problem
described above, and everything is passing.
gdb/ChangeLog:
2015-04-08 Sergio Durigan Junior <sergiodj@redhat.com>
PR python/16699
* python/py-cmd.c (cmdpy_completer_helper): Adjust function to not
use a caching mechanism. Adjust comments and code to reflect
that. Replace 'sizeof' by 'strlen' when fetching 'wordobj'.
(cmdpy_completer_handle_brkchars): Adjust call to
cmdpy_completer_helper. Call Py_XDECREF for 'resultobj'.
(cmdpy_completer): Likewise.
gdb/testsuite/ChangeLog:
2015-04-08 Keith Seitz <keiths@redhat.com>
PR python/16699
* gdb.python/py-completion.exp: New tests for completion.
* gdb.python/py-completion.py (CompleteLimit1): New class.
(CompleteLimit2): Likewise.
(CompleteLimit3): Likewise.
(CompleteLimit4): Likewise.
(CompleteLimit5): Likewise.
(CompleteLimit6): Likewise.
(CompleteLimit7): Likewise.
2015-04-08 18:27:10 -04:00
|
|
|
|
{
|
gdb/python: display errors from command completion
This commit makes the gdb.Command.complete methods more verbose when
it comes to error handling.
Previous to this commit if any commands implemented in Python
implemented the complete method, and if there were any errors
encountered when calling that complete method, then GDB would silently
hide the error and continue as if there were no completions.
This makes is difficult to debug any errors encountered when writing
completion methods, and encourages the idea that Python extensions can
be broken, and GDB will just silently work around them.
I don't think this is a good idea. GDB should encourage extensions to
be written correctly, and robustly, and one way in which GDB can (I
think) support this, is by pointing out when an extension goes wrong.
In this commit I've gone through the Python command completion code,
and added calls to gdbpy_print_stack() or gdbpy_print_stack_or_quit()
in places where we were either clearing the Python error, or, in some
cases, just not handling the error at all.
One thing I have not changed is in cmdpy_completer (py-cmd.c) where we
process the list of completions returned from the Command.complete
method; this routine includes a call to gdbpy_is_string to check a
possible completion is a string, if not the completion is ignored.
I was tempted to remove this check, attempt to complete each result to
a string, and display an error if the conversion fails. After all,
returning anything but a string is surely a mistake by the extension
author.
However, the docs clearly say that only strings within the returned
list will be considered as completions. Anything else is ignored. As
such, and to avoid (what I think is pretty unlikely) breakage of
existing code, I've retained the gdbpy_is_string check.
After the gdbpy_is_string check we call python_string_to_host_string,
if this call fails then I do now print the error, where before we
ignored the error. I think this is OK; if GDB thinks something is a
string, but still can't convert it to a string, then I think it's OK
to display the error in that case.
Another case which I was a little unsure about was in
cmdpy_completer_helper, and the call to PyObject_CallMethodObjArgs,
which is when we actually call Command.complete. Previously, if this
call resulted in an exception then we would ignore this and just
pretend there were no completions.
Of all the changes, this is possibly the one with the biggest
potential for breaking existing scripts, but also, is, I think, the
most useful change. If the user code is wrong in some way, such that
an exception is raised, then previously the user would have no obvious
feedback about this breakage. Now GDB will print the exception for
them, making it, I think, much easier to debug their extension. But,
if there is user code in the wild that relies on raising an exception
as a means to indicate there are no completions .... well, that code
is going to break after this commit. I think we can live with this
though, the exceptions means no completions thing was never documented
behaviour.
I also added a new error() call if the PyObject_CallMethodObjArgs call
raises an exception. This causes the completion mechanism within GDB
to stop. Within GDB the completion code is called twice, the first
time to compute the work break characters, and then a second time to
compute the actual completions.
If PyObject_CallMethodObjArgs raises an exception when computing the
word break character, and we print it by calling
gdbpy_print_stack_or_quit(), but then carry on as if
PyObject_CallMethodObjArgs had returns no completions, GDB will
call the Python completion code again, which results in another call
to PyObject_CallMethodObjArgs, which might raise the same exception
again. This results in the Python exception being printed twice.
By throwing a C++ exception after the failed
PyObject_CallMethodObjArgs call, the completion mechanism is aborted,
and no completions are offered. But importantly, the Python exception
is only printed once. I think this gives a much better user
experience.
I've added some tests to cover this case, as I think this is the most
likely case that a user will run into.
Approved-By: Tom Tromey <tom@tromey.com>
2023-11-27 21:29:53 +00:00
|
|
|
|
gdbpy_print_stack_or_quit ();
|
|
|
|
|
|
error (_("exception raised during Command.complete method"));
|
PR python/16699: GDB Python command completion with overriden complete vs. completer class
This PR came from a Red Hat bug that was filed recently. I checked and
it still exists on HEAD, so here's a proposed fix. Although this is
marked as a Python backend bug, this is really about the completion
mechanism used by GDB. Since this code reminds me of my first attempt
to make a good noodle, it took me quite some time to fix it in a
non-intrusive way.
The problem is triggered when one registers a completion method inside a
class in a Python script, rather than registering the command using a
completer class directly. For example, consider the following script:
class MyFirstCommand(gdb.Command):
def __init__(self):
gdb.Command.__init__(self,'myfirstcommand',gdb.COMMAND_USER,gdb.COMPLETE_FILENAME)
def invoke(self,argument,from_tty):
raise gdb.GdbError('not implemented')
class MySecondCommand(gdb.Command):
def __init__(self):
gdb.Command.__init__(self,'mysecondcommand',gdb.COMMAND_USER)
def invoke(self,argument,from_tty):
raise gdb.GdbError('not implemented')
def complete(self,text,word):
return gdb.COMPLETE_FILENAME
MyFirstCommand ()
MySecondCommand ()
When one loads this into GDB and tries to complete filenames for both
myfirstcommand and mysecondcommand, she gets:
(gdb) myfirstcommand /hom<TAB>
(gdb) myfirstcommand /home/
^
...
(gdb) mysecondcommand /hom<TAB>
(gdb) mysecondcommand /home
^
(The "^" marks the final position of the cursor after the TAB).
So we see that myfirstcommand honors the COMPLETE_FILENAME class (as
specified in the command creation), but mysecondcommand does not. After
some investigation, I found that the problem lies with the set of word
break characters that is used for each case. The set should be the same
for both commands, but it is not.
During the process of deciding which type of completion should be used,
the code in gdb/completer.c:complete_line_internal analyses the command
that requested the completion and tries to determine the type of
completion wanted by checking which completion function will be called
(e.g., filename_completer for filenames, location_completer for
locations, etc.).
This all works fine for myfirstcommand, because immediately after the
command registration the Python backend already sets its completion
function to filename_completer (which then causes the
complete_line_internal function to choose the right set of word break
chars). However, for mysecondcommand, this decision is postponed to
when the completer function is evaluated, and the Python backend uses an
internal completer (called cmdpy_completer). complete_line_internal
doesn't know about this internal completer, and can't choose the right
set of word break chars in time, which then leads to a bad decision when
completing the "/hom" word.
So, after a few attempts, I decided to create another callback in
"struct cmd_list_element" that will be responsible for handling the case
when there is an unknown completer function for complete_line_internal
to work with. So far, only the Python backend uses this callback, and
only when the user provides a completer method instead of registering
the command directly with a completer class. I think this is the best
option because it not very intrusive (all the other commands will still
work normally), but especially because the whole completion code is so
messy that it would be hard to fix this without having to redesign
things.
I have regtested this on Fedora 18 x86_64, without regressions. I also
included a testcase.
gdb/ChangeLog:
2014-09-03 Sergio Durigan Junior <sergiodj@redhat.com>
PR python/16699
* cli/cli-decode.c (set_cmd_completer_handle_brkchars): New
function.
(add_cmd): Set "completer_handle_brkchars" to NULL.
* cli/cli-decode.h (struct cmd_list_element)
<completer_handle_brkchars>: New field.
* command.h (completer_ftype_void): New typedef.
(set_cmd_completer_handle_brkchars): New prototype.
* completer.c (set_gdb_completion_word_break_characters): New
function.
(complete_line_internal): Call "completer_handle_brkchars"
callback from command.
* completer.h: Include "command.h".
(set_gdb_completion_word_break_characters): New prototype.
* python/py-cmd.c (cmdpy_completer_helper): New function.
(cmdpy_completer_handle_brkchars): New function.
(cmdpy_completer): Adjust to use cmdpy_completer_helper.
(cmdpy_init): Set completer_handle_brkchars to
cmdpy_completer_handle_brkchars.
gdb/testsuite/ChangeLog:
2014-09-03 Sergio Durigan Junior <sergiodj@redhat.com>
PR python/16699
* gdb.python/py-completion.exp: New file.
* gdb.python/py-completion.py: Likewise.
2014-09-03 16:30:28 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
2018-09-10 11:48:28 +01:00
|
|
|
|
return resultobj;
|
PR python/16699: GDB Python command completion with overriden complete vs. completer class
This PR came from a Red Hat bug that was filed recently. I checked and
it still exists on HEAD, so here's a proposed fix. Although this is
marked as a Python backend bug, this is really about the completion
mechanism used by GDB. Since this code reminds me of my first attempt
to make a good noodle, it took me quite some time to fix it in a
non-intrusive way.
The problem is triggered when one registers a completion method inside a
class in a Python script, rather than registering the command using a
completer class directly. For example, consider the following script:
class MyFirstCommand(gdb.Command):
def __init__(self):
gdb.Command.__init__(self,'myfirstcommand',gdb.COMMAND_USER,gdb.COMPLETE_FILENAME)
def invoke(self,argument,from_tty):
raise gdb.GdbError('not implemented')
class MySecondCommand(gdb.Command):
def __init__(self):
gdb.Command.__init__(self,'mysecondcommand',gdb.COMMAND_USER)
def invoke(self,argument,from_tty):
raise gdb.GdbError('not implemented')
def complete(self,text,word):
return gdb.COMPLETE_FILENAME
MyFirstCommand ()
MySecondCommand ()
When one loads this into GDB and tries to complete filenames for both
myfirstcommand and mysecondcommand, she gets:
(gdb) myfirstcommand /hom<TAB>
(gdb) myfirstcommand /home/
^
...
(gdb) mysecondcommand /hom<TAB>
(gdb) mysecondcommand /home
^
(The "^" marks the final position of the cursor after the TAB).
So we see that myfirstcommand honors the COMPLETE_FILENAME class (as
specified in the command creation), but mysecondcommand does not. After
some investigation, I found that the problem lies with the set of word
break characters that is used for each case. The set should be the same
for both commands, but it is not.
During the process of deciding which type of completion should be used,
the code in gdb/completer.c:complete_line_internal analyses the command
that requested the completion and tries to determine the type of
completion wanted by checking which completion function will be called
(e.g., filename_completer for filenames, location_completer for
locations, etc.).
This all works fine for myfirstcommand, because immediately after the
command registration the Python backend already sets its completion
function to filename_completer (which then causes the
complete_line_internal function to choose the right set of word break
chars). However, for mysecondcommand, this decision is postponed to
when the completer function is evaluated, and the Python backend uses an
internal completer (called cmdpy_completer). complete_line_internal
doesn't know about this internal completer, and can't choose the right
set of word break chars in time, which then leads to a bad decision when
completing the "/hom" word.
So, after a few attempts, I decided to create another callback in
"struct cmd_list_element" that will be responsible for handling the case
when there is an unknown completer function for complete_line_internal
to work with. So far, only the Python backend uses this callback, and
only when the user provides a completer method instead of registering
the command directly with a completer class. I think this is the best
option because it not very intrusive (all the other commands will still
work normally), but especially because the whole completion code is so
messy that it would be hard to fix this without having to redesign
things.
I have regtested this on Fedora 18 x86_64, without regressions. I also
included a testcase.
gdb/ChangeLog:
2014-09-03 Sergio Durigan Junior <sergiodj@redhat.com>
PR python/16699
* cli/cli-decode.c (set_cmd_completer_handle_brkchars): New
function.
(add_cmd): Set "completer_handle_brkchars" to NULL.
* cli/cli-decode.h (struct cmd_list_element)
<completer_handle_brkchars>: New field.
* command.h (completer_ftype_void): New typedef.
(set_cmd_completer_handle_brkchars): New prototype.
* completer.c (set_gdb_completion_word_break_characters): New
function.
(complete_line_internal): Call "completer_handle_brkchars"
callback from command.
* completer.h: Include "command.h".
(set_gdb_completion_word_break_characters): New prototype.
* python/py-cmd.c (cmdpy_completer_helper): New function.
(cmdpy_completer_handle_brkchars): New function.
(cmdpy_completer): Adjust to use cmdpy_completer_helper.
(cmdpy_init): Set completer_handle_brkchars to
cmdpy_completer_handle_brkchars.
gdb/testsuite/ChangeLog:
2014-09-03 Sergio Durigan Junior <sergiodj@redhat.com>
PR python/16699
* gdb.python/py-completion.exp: New file.
* gdb.python/py-completion.py: Likewise.
2014-09-03 16:30:28 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Python function called to determine the break characters of a
|
|
|
|
|
|
certain completer. We are only interested in knowing if the
|
|
|
|
|
|
completer registered by the user will return one of the integer
|
|
|
|
|
|
codes (see COMPLETER_* symbols). */
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
|
cmdpy_completer_handle_brkchars (struct cmd_list_element *command,
|
Introduce class completion_tracker & rewrite completion<->readline interaction
This patch reworks the whole completion machinery, and prepares it
for later enhancements.
Adds a new "completion_tracker" class that is meant to hold everything
about the state of the current completion operation.
This class now has the responsibility of tracking the list of
completion matches, and checking whether the max completions limit has
been reached. You can look at this as this patch starting out by
C++fying the existing "completion_tracker" in symtab.c (it's just an
htab_t typedef currently), moving it to completer.h/c, and then making
it a class/generalizing/enhancing it.
Unlike with the current tracking, completion_tracker now checks
whether the limit has been reached on each completion match list
insertion. This both simplifies the max-completions handling code
(maybe_add_completion_enum is gone, for example), and is a
prerequisite for follow up patches.
The current completion_tracker is only used for symbol completions,
and the symbol code gets at the current instance via globals. This
patch cleans that up by adding a completion_tracker reference to the
signature of the completion functions, and passing the tracker around
everywhere necessary.
Then, the patch changes how the completion match list is handed over
to readline. Currently, we're using the rl_completion_entry_function
readline entry point, and the patch switches to
rl_attempted_completion_function. A following patch will want to let
GDB itself decide the common completion prefix between all matches
(what readline calls the "lowest common denominator"), instead of
having readline compute it, and that's not possible with the
rl_completion_entry_function entry point. Also,
rl_attempted_completion_function lets GDB hand over the match list to
readline as an array in one go instead of passing down matches one by
one, so from that angle it's a nicer entry point anyway.
Lastly, the patch catches exceptions around the readline entry points,
because we can't let C++ exceptions cross readline. We handle that in
the readline input entry point, but the completion entry point isn't
guarded, so GDB can abort if completion throws. E.g., in current
master:
(gdb) b -function "fun<tab>
terminate called after throwing an instance of 'gdb_exception_RETURN_MASK_ERROR'
Aborted (core dumped)
This patch fixes that. This will be exercised in the new tests added
later on in the series.
gdb/ChangeLog:
2017-07-17 Pedro Alves <palves@redhat.com>
* ada-lang.c (symbol_completion_match): Adjust comments.
(symbol_completion_add): Replace vector parameter with
completion_tracker parameter. Use it.
(ada_make_symbol_completion_list): Rename to...
(ada_collect_symbol_completion_matches): ... this. Add
completion_tracker parameter and use it.
(ada_language_defn): Adjust.
* break-catch-syscall.c (catch_syscall_completer): Adjust
prototype and work with completion_tracker instead of VEC.
* breakpoint.c (condition_completer): Adjust prototype and work
with completion_tracker instead of VEC.
* c-lang.c (c_language_defn, cplus_language_defn)
(asm_language_defn, minimal_language_defn): Adjust to renames.
* cli/cli-cmds.c (complete_command): Rework using
completion_tracker. Catch exceptions when completing.
* cli/cli-decode.c (integer_unlimited_completer)
(complete_on_cmdlist, complete_on_enum): Adjust prototype and work
with completion_tracker instead of VEC.
* command.h (struct completion_tracker): Forward declare.
(completer_ftype, completer_handle_brkchars_ftype): Change
types.
(complete_on_cmdlist, complete_on_enum): Adjust.
* completer.c: Include <algorithm>.
(struct gdb_completer_state): New.
(current_completion): New global.
(readline_line_completion_function): Delete.
(noop_completer, filename_completer)
(filename_completer_handle_brkchars, complete_files_symbols)
(linespec_location_completer): Adjust to work with a
completion_tracker instead of a VEC.
(string_or_empty): New.
(collect_explicit_location_matches): Adjust to work with a
completion_tracker instead of a VEC.
(explicit_location_completer): Rename to ...
(complete_explicit_location): ... this and adjust to work with a
completion_tracker instead of a VEC.
(location_completer): Adjust to work with a completion_tracker
instead of a VEC.
(add_struct_fields): Adjust to work with a completion_list instead
of VEC.
(expression_completer): Rename to ...
(complete_expression): ... this and adjust to work with a
completion_tracker instead of a VEC. Use complete_files_symbols.
(expression_completer): Reimplement on top of complete_expression.
(symbol_completer): Adjust to work with a completion_tracker
instead of a VEC.
(enum complete_line_internal_reason): Add describing comments.
(complete_line_internal_normal_command): Adjust to work with a
completion_tracker instead of a VEC.
(complete_line_internal): Rename to ...
(complete_line_internal_1): ... this and adjust to work with a
completion_tracker instead of a VEC. Assert TEXT is NULL in the
handle_brkchars phase.
(new_completion_tracker): Delete.
(complete_line_internal): Reimplement as TRY/CATCH wrapper around
complete_line_internal_1.
(free_completion_tracker): Delete.
(INITIAL_COMPLETION_HTAB_SIZE): New.
(completion_tracker::completion_tracker)
(completion_tracker::~completion_tracker): New.
(maybe_add_completion): Delete.
(completion_tracker::maybe_add_completion)
(completion_tracker::add_completion)
(completion_tracker::add_completions): New.
(throw_max_completions_reached_error): Delete.
(complete_line): Adjust to work with a completion_tracker instead
of a VEC. Don't create a completion_tracker_t or check for max
completions here.
(command_completer, command_completer_handle_brkchars)
(signal_completer, reg_or_group_completer_1)
(reg_or_group_completer, default_completer_handle_brkchars):
Adjust to work with a completion_tracker.
(gdb_completion_word_break_characters_throw): New.
(gdb_completion_word_break_characters): Reimplement.
(line_completion_function): Delete.
(completion_tracker::recompute_lowest_common_denominator)
(expand_preserving_ws)
(completion_tracker::build_completion_result)
(completion_result::completion_result)
(completion_result::completion_result)
(completion_result::~completion_result)
(completion_result::completion_result)
(completion_result::release_match_list, compare_cstrings)
(completion_result::sort_match_list)
(completion_result::reset_match_list)
(gdb_rl_attempted_completion_function_throw)
(gdb_rl_attempted_completion_function): New.
* completer.h (completion_list, struct completion_result)
(class completion_tracker): New.
(complete_line): Add completion_tracker parameter.
(readline_line_completion_function): Delete.
(gdb_rl_attempted_completion_function): New.
(noop_completer, filename_completer, expression_completer)
(location_completer, symbol_completer, command_completer)
(signal_completer, reg_or_group_completer): Update prototypes.
(completion_tracker_t, new_completion_tracker)
(make_cleanup_free_completion_tracker): Delete.
(enum maybe_add_completion_enum): Delete.
(maybe_add_completion): Delete.
(throw_max_completions_reached_error): Delete.
* corefile.c (complete_set_gnutarget): Adjust to work with a
completion_tracker instead of a VEC.
* cp-abi.c (cp_abi_completer): Adjust to work with a
completion_tracker instead of a VEC.
* d-lang.c (d_language_defn): Adjust.
* disasm.c (disassembler_options_completer): Adjust to work with a
completion_tracker instead of a VEC.
* f-lang.c (f_make_symbol_completion_list): Rename to ...
(f_collect_symbol_completion_matches): ... this. Adjust to work
with a completion_tracker instead of a VEC.
(f_language_defn): Adjust.
* go-lang.c (go_language_defn): Adjust.
* guile/scm-cmd.c (cmdscm_add_completion, cmdscm_completer):
Adjust to work with a completion_tracker instead of a VEC.
* infrun.c (handle_completer): Likewise.
* interps.c (interpreter_completer): Likewise.
* interps.h (interpreter_completer): Likewise.
* language.c (unknown_language_defn, auto_language_defn)
(local_language_defn): Adjust.
* language.h (language_defn::la_make_symbol_completion_list):
Rename to ...
(language_defn::la_collect_symbol_completion_matches): ... this
and adjust to work with a completion_tracker instead of a VEC.
* m2-lang.c (m2_language_defn): Adjust.
* objc-lang.c (objc_language_defn): Adjust.
* opencl-lang.c (opencl_language_defn): Adjust.
* p-lang.c (pascal_language_defn): Adjust.
* python/py-cmd.c (cmdpy_completer_helper): Handle NULL word.
(cmdpy_completer_handle_brkchars, cmdpy_completer): Adjust to work
with a completion_tracker.
* rust-lang.c (rust_language_defn): Adjust.
* symtab.c (free_completion_list, do_free_completion_list)
(return_val, completion_tracker): Delete.
(completion_list_add_name, completion_list_add_symbol)
(completion_list_add_msymbol, completion_list_objc_symbol)
(completion_list_add_fields, add_symtab_completions): Add
completion_tracker parameter and use it.
(default_make_symbol_completion_list_break_on_1): Rename to...
(default_collect_symbol_completion_matches_break_on): ... this.
Add completion_tracker parameter and use it instead of allocating
a completion tracker here.
(default_make_symbol_completion_list_break_on): Delete old
implementation.
(default_make_symbol_completion_list): Delete.
(default_collect_symbol_completion_matches): New.
(make_symbol_completion_list): Delete.
(collect_symbol_completion_matches): New.
(make_symbol_completion_type): Rename to ...
(collect_symbol_completion_matches_type): ... this. Add
completion_tracker parameter and use it instead of VEC.
(make_file_symbol_completion_list_1): Rename to...
(collect_file_symbol_completion_matches): ... this. Add
completion_tracker parameter and use it instead of VEC.
(make_file_symbol_completion_list): Delete.
(add_filename_to_list): Use completion_list instead of a VEC.
(add_partial_filename_data::list): Now a completion_list.
(make_source_files_completion_list): Work with a completion_list
instead of a VEC.
* symtab.h: Include "completer.h".
(default_make_symbol_completion_list_break_on)
(default_make_symbol_completion_list, make_symbol_completion_list)
(make_symbol_completion_type, make_file_symbol_completion_list)
(make_source_files_completion_list): Delete.
(default_collect_symbol_completion_matches_break_on)
(default_collect_symbol_completion_matches)
(collect_symbol_completion_matches)
(collect_symbol_completion_matches_type)
(collect_file_symbol_completion_matches)
(make_source_files_completion_list): New.
* top.c (init_main): Don't install a rl_completion_entry_function
hook. Install a rl_attempted_completion_function hook instead.
* tui/tui-layout.c (layout_completer): Adjust to work with a
completion_tracker.
* tui/tui-regs.c (tui_reggroup_completer):
* tui/tui-win.c (window_name_completer, focus_completer)
(winheight_completer): Adjust to work with a completion_tracker.
* value.c: Include "completer.h".
(complete_internalvar): Adjust to work with a completion_tracker.
* value.h (complete_internalvar): Likewise.
2017-07-17 14:45:59 +01:00
|
|
|
|
completion_tracker &tracker,
|
PR python/16699: GDB Python command completion with overriden complete vs. completer class
This PR came from a Red Hat bug that was filed recently. I checked and
it still exists on HEAD, so here's a proposed fix. Although this is
marked as a Python backend bug, this is really about the completion
mechanism used by GDB. Since this code reminds me of my first attempt
to make a good noodle, it took me quite some time to fix it in a
non-intrusive way.
The problem is triggered when one registers a completion method inside a
class in a Python script, rather than registering the command using a
completer class directly. For example, consider the following script:
class MyFirstCommand(gdb.Command):
def __init__(self):
gdb.Command.__init__(self,'myfirstcommand',gdb.COMMAND_USER,gdb.COMPLETE_FILENAME)
def invoke(self,argument,from_tty):
raise gdb.GdbError('not implemented')
class MySecondCommand(gdb.Command):
def __init__(self):
gdb.Command.__init__(self,'mysecondcommand',gdb.COMMAND_USER)
def invoke(self,argument,from_tty):
raise gdb.GdbError('not implemented')
def complete(self,text,word):
return gdb.COMPLETE_FILENAME
MyFirstCommand ()
MySecondCommand ()
When one loads this into GDB and tries to complete filenames for both
myfirstcommand and mysecondcommand, she gets:
(gdb) myfirstcommand /hom<TAB>
(gdb) myfirstcommand /home/
^
...
(gdb) mysecondcommand /hom<TAB>
(gdb) mysecondcommand /home
^
(The "^" marks the final position of the cursor after the TAB).
So we see that myfirstcommand honors the COMPLETE_FILENAME class (as
specified in the command creation), but mysecondcommand does not. After
some investigation, I found that the problem lies with the set of word
break characters that is used for each case. The set should be the same
for both commands, but it is not.
During the process of deciding which type of completion should be used,
the code in gdb/completer.c:complete_line_internal analyses the command
that requested the completion and tries to determine the type of
completion wanted by checking which completion function will be called
(e.g., filename_completer for filenames, location_completer for
locations, etc.).
This all works fine for myfirstcommand, because immediately after the
command registration the Python backend already sets its completion
function to filename_completer (which then causes the
complete_line_internal function to choose the right set of word break
chars). However, for mysecondcommand, this decision is postponed to
when the completer function is evaluated, and the Python backend uses an
internal completer (called cmdpy_completer). complete_line_internal
doesn't know about this internal completer, and can't choose the right
set of word break chars in time, which then leads to a bad decision when
completing the "/hom" word.
So, after a few attempts, I decided to create another callback in
"struct cmd_list_element" that will be responsible for handling the case
when there is an unknown completer function for complete_line_internal
to work with. So far, only the Python backend uses this callback, and
only when the user provides a completer method instead of registering
the command directly with a completer class. I think this is the best
option because it not very intrusive (all the other commands will still
work normally), but especially because the whole completion code is so
messy that it would be hard to fix this without having to redesign
things.
I have regtested this on Fedora 18 x86_64, without regressions. I also
included a testcase.
gdb/ChangeLog:
2014-09-03 Sergio Durigan Junior <sergiodj@redhat.com>
PR python/16699
* cli/cli-decode.c (set_cmd_completer_handle_brkchars): New
function.
(add_cmd): Set "completer_handle_brkchars" to NULL.
* cli/cli-decode.h (struct cmd_list_element)
<completer_handle_brkchars>: New field.
* command.h (completer_ftype_void): New typedef.
(set_cmd_completer_handle_brkchars): New prototype.
* completer.c (set_gdb_completion_word_break_characters): New
function.
(complete_line_internal): Call "completer_handle_brkchars"
callback from command.
* completer.h: Include "command.h".
(set_gdb_completion_word_break_characters): New prototype.
* python/py-cmd.c (cmdpy_completer_helper): New function.
(cmdpy_completer_handle_brkchars): New function.
(cmdpy_completer): Adjust to use cmdpy_completer_helper.
(cmdpy_init): Set completer_handle_brkchars to
cmdpy_completer_handle_brkchars.
gdb/testsuite/ChangeLog:
2014-09-03 Sergio Durigan Junior <sergiodj@redhat.com>
PR python/16699
* gdb.python/py-completion.exp: New file.
* gdb.python/py-completion.py: Likewise.
2014-09-03 16:30:28 -04:00
|
|
|
|
const char *text, const char *word)
|
|
|
|
|
|
{
|
Change how Python architecture and language are handled
Currently, gdb's Python layer captures the current architecture and
language when "entering" Python code. This has some undesirable
effects, and so this series changes how this is handled.
First, there is code like this:
gdbpy_enter enter_py (python_gdbarch, python_language);
This is incorrect, because both of these are NULL when not otherwise
assigned. This can cause crashes in some cases -- I've added one to
the test suite. (Note that this crasher is just an example, other
ones along the same lines are possible.)
Second, when the language is captured in this way, it means that
Python code cannot affect the current language for its own purposes.
It's reasonable to want to write code like this:
gdb.execute('set language mumble')
... stuff using the current language
gdb.execute('set language previous-value')
However, this won't actually work, because the language is captured on
entry. I've added a test to show this as well.
This patch changes gdb to try to avoid capturing the current values.
The Python concept of the current gdbarch is only set in those few
cases where a non-default value is computed or needed; and the
language is not captured at all -- instead, in the cases where it's
required, the current language is temporarily changed.
2022-01-04 08:02:24 -07:00
|
|
|
|
gdbpy_enter enter_py;
|
PR python/16699: GDB Python command completion with overriden complete vs. completer class
This PR came from a Red Hat bug that was filed recently. I checked and
it still exists on HEAD, so here's a proposed fix. Although this is
marked as a Python backend bug, this is really about the completion
mechanism used by GDB. Since this code reminds me of my first attempt
to make a good noodle, it took me quite some time to fix it in a
non-intrusive way.
The problem is triggered when one registers a completion method inside a
class in a Python script, rather than registering the command using a
completer class directly. For example, consider the following script:
class MyFirstCommand(gdb.Command):
def __init__(self):
gdb.Command.__init__(self,'myfirstcommand',gdb.COMMAND_USER,gdb.COMPLETE_FILENAME)
def invoke(self,argument,from_tty):
raise gdb.GdbError('not implemented')
class MySecondCommand(gdb.Command):
def __init__(self):
gdb.Command.__init__(self,'mysecondcommand',gdb.COMMAND_USER)
def invoke(self,argument,from_tty):
raise gdb.GdbError('not implemented')
def complete(self,text,word):
return gdb.COMPLETE_FILENAME
MyFirstCommand ()
MySecondCommand ()
When one loads this into GDB and tries to complete filenames for both
myfirstcommand and mysecondcommand, she gets:
(gdb) myfirstcommand /hom<TAB>
(gdb) myfirstcommand /home/
^
...
(gdb) mysecondcommand /hom<TAB>
(gdb) mysecondcommand /home
^
(The "^" marks the final position of the cursor after the TAB).
So we see that myfirstcommand honors the COMPLETE_FILENAME class (as
specified in the command creation), but mysecondcommand does not. After
some investigation, I found that the problem lies with the set of word
break characters that is used for each case. The set should be the same
for both commands, but it is not.
During the process of deciding which type of completion should be used,
the code in gdb/completer.c:complete_line_internal analyses the command
that requested the completion and tries to determine the type of
completion wanted by checking which completion function will be called
(e.g., filename_completer for filenames, location_completer for
locations, etc.).
This all works fine for myfirstcommand, because immediately after the
command registration the Python backend already sets its completion
function to filename_completer (which then causes the
complete_line_internal function to choose the right set of word break
chars). However, for mysecondcommand, this decision is postponed to
when the completer function is evaluated, and the Python backend uses an
internal completer (called cmdpy_completer). complete_line_internal
doesn't know about this internal completer, and can't choose the right
set of word break chars in time, which then leads to a bad decision when
completing the "/hom" word.
So, after a few attempts, I decided to create another callback in
"struct cmd_list_element" that will be responsible for handling the case
when there is an unknown completer function for complete_line_internal
to work with. So far, only the Python backend uses this callback, and
only when the user provides a completer method instead of registering
the command directly with a completer class. I think this is the best
option because it not very intrusive (all the other commands will still
work normally), but especially because the whole completion code is so
messy that it would be hard to fix this without having to redesign
things.
I have regtested this on Fedora 18 x86_64, without regressions. I also
included a testcase.
gdb/ChangeLog:
2014-09-03 Sergio Durigan Junior <sergiodj@redhat.com>
PR python/16699
* cli/cli-decode.c (set_cmd_completer_handle_brkchars): New
function.
(add_cmd): Set "completer_handle_brkchars" to NULL.
* cli/cli-decode.h (struct cmd_list_element)
<completer_handle_brkchars>: New field.
* command.h (completer_ftype_void): New typedef.
(set_cmd_completer_handle_brkchars): New prototype.
* completer.c (set_gdb_completion_word_break_characters): New
function.
(complete_line_internal): Call "completer_handle_brkchars"
callback from command.
* completer.h: Include "command.h".
(set_gdb_completion_word_break_characters): New prototype.
* python/py-cmd.c (cmdpy_completer_helper): New function.
(cmdpy_completer_handle_brkchars): New function.
(cmdpy_completer): Adjust to use cmdpy_completer_helper.
(cmdpy_init): Set completer_handle_brkchars to
cmdpy_completer_handle_brkchars.
gdb/testsuite/ChangeLog:
2014-09-03 Sergio Durigan Junior <sergiodj@redhat.com>
PR python/16699
* gdb.python/py-completion.exp: New file.
* gdb.python/py-completion.py: Likewise.
2014-09-03 16:30:28 -04:00
|
|
|
|
|
2018-09-10 11:48:28 +01:00
|
|
|
|
/* Calling our helper to obtain a reference to the PyObject of the Python
|
PR python/16699: GDB Python command completion with overriden complete vs. completer class
This PR came from a Red Hat bug that was filed recently. I checked and
it still exists on HEAD, so here's a proposed fix. Although this is
marked as a Python backend bug, this is really about the completion
mechanism used by GDB. Since this code reminds me of my first attempt
to make a good noodle, it took me quite some time to fix it in a
non-intrusive way.
The problem is triggered when one registers a completion method inside a
class in a Python script, rather than registering the command using a
completer class directly. For example, consider the following script:
class MyFirstCommand(gdb.Command):
def __init__(self):
gdb.Command.__init__(self,'myfirstcommand',gdb.COMMAND_USER,gdb.COMPLETE_FILENAME)
def invoke(self,argument,from_tty):
raise gdb.GdbError('not implemented')
class MySecondCommand(gdb.Command):
def __init__(self):
gdb.Command.__init__(self,'mysecondcommand',gdb.COMMAND_USER)
def invoke(self,argument,from_tty):
raise gdb.GdbError('not implemented')
def complete(self,text,word):
return gdb.COMPLETE_FILENAME
MyFirstCommand ()
MySecondCommand ()
When one loads this into GDB and tries to complete filenames for both
myfirstcommand and mysecondcommand, she gets:
(gdb) myfirstcommand /hom<TAB>
(gdb) myfirstcommand /home/
^
...
(gdb) mysecondcommand /hom<TAB>
(gdb) mysecondcommand /home
^
(The "^" marks the final position of the cursor after the TAB).
So we see that myfirstcommand honors the COMPLETE_FILENAME class (as
specified in the command creation), but mysecondcommand does not. After
some investigation, I found that the problem lies with the set of word
break characters that is used for each case. The set should be the same
for both commands, but it is not.
During the process of deciding which type of completion should be used,
the code in gdb/completer.c:complete_line_internal analyses the command
that requested the completion and tries to determine the type of
completion wanted by checking which completion function will be called
(e.g., filename_completer for filenames, location_completer for
locations, etc.).
This all works fine for myfirstcommand, because immediately after the
command registration the Python backend already sets its completion
function to filename_completer (which then causes the
complete_line_internal function to choose the right set of word break
chars). However, for mysecondcommand, this decision is postponed to
when the completer function is evaluated, and the Python backend uses an
internal completer (called cmdpy_completer). complete_line_internal
doesn't know about this internal completer, and can't choose the right
set of word break chars in time, which then leads to a bad decision when
completing the "/hom" word.
So, after a few attempts, I decided to create another callback in
"struct cmd_list_element" that will be responsible for handling the case
when there is an unknown completer function for complete_line_internal
to work with. So far, only the Python backend uses this callback, and
only when the user provides a completer method instead of registering
the command directly with a completer class. I think this is the best
option because it not very intrusive (all the other commands will still
work normally), but especially because the whole completion code is so
messy that it would be hard to fix this without having to redesign
things.
I have regtested this on Fedora 18 x86_64, without regressions. I also
included a testcase.
gdb/ChangeLog:
2014-09-03 Sergio Durigan Junior <sergiodj@redhat.com>
PR python/16699
* cli/cli-decode.c (set_cmd_completer_handle_brkchars): New
function.
(add_cmd): Set "completer_handle_brkchars" to NULL.
* cli/cli-decode.h (struct cmd_list_element)
<completer_handle_brkchars>: New field.
* command.h (completer_ftype_void): New typedef.
(set_cmd_completer_handle_brkchars): New prototype.
* completer.c (set_gdb_completion_word_break_characters): New
function.
(complete_line_internal): Call "completer_handle_brkchars"
callback from command.
* completer.h: Include "command.h".
(set_gdb_completion_word_break_characters): New prototype.
* python/py-cmd.c (cmdpy_completer_helper): New function.
(cmdpy_completer_handle_brkchars): New function.
(cmdpy_completer): Adjust to use cmdpy_completer_helper.
(cmdpy_init): Set completer_handle_brkchars to
cmdpy_completer_handle_brkchars.
gdb/testsuite/ChangeLog:
2014-09-03 Sergio Durigan Junior <sergiodj@redhat.com>
PR python/16699
* gdb.python/py-completion.exp: New file.
* gdb.python/py-completion.py: Likewise.
2014-09-03 16:30:28 -04:00
|
|
|
|
function. */
|
2018-09-10 11:48:28 +01:00
|
|
|
|
gdbpy_ref<> resultobj = cmdpy_completer_helper (command, text, word);
|
PR python/16699: GDB Python command completion with overriden complete vs. completer class
This PR came from a Red Hat bug that was filed recently. I checked and
it still exists on HEAD, so here's a proposed fix. Although this is
marked as a Python backend bug, this is really about the completion
mechanism used by GDB. Since this code reminds me of my first attempt
to make a good noodle, it took me quite some time to fix it in a
non-intrusive way.
The problem is triggered when one registers a completion method inside a
class in a Python script, rather than registering the command using a
completer class directly. For example, consider the following script:
class MyFirstCommand(gdb.Command):
def __init__(self):
gdb.Command.__init__(self,'myfirstcommand',gdb.COMMAND_USER,gdb.COMPLETE_FILENAME)
def invoke(self,argument,from_tty):
raise gdb.GdbError('not implemented')
class MySecondCommand(gdb.Command):
def __init__(self):
gdb.Command.__init__(self,'mysecondcommand',gdb.COMMAND_USER)
def invoke(self,argument,from_tty):
raise gdb.GdbError('not implemented')
def complete(self,text,word):
return gdb.COMPLETE_FILENAME
MyFirstCommand ()
MySecondCommand ()
When one loads this into GDB and tries to complete filenames for both
myfirstcommand and mysecondcommand, she gets:
(gdb) myfirstcommand /hom<TAB>
(gdb) myfirstcommand /home/
^
...
(gdb) mysecondcommand /hom<TAB>
(gdb) mysecondcommand /home
^
(The "^" marks the final position of the cursor after the TAB).
So we see that myfirstcommand honors the COMPLETE_FILENAME class (as
specified in the command creation), but mysecondcommand does not. After
some investigation, I found that the problem lies with the set of word
break characters that is used for each case. The set should be the same
for both commands, but it is not.
During the process of deciding which type of completion should be used,
the code in gdb/completer.c:complete_line_internal analyses the command
that requested the completion and tries to determine the type of
completion wanted by checking which completion function will be called
(e.g., filename_completer for filenames, location_completer for
locations, etc.).
This all works fine for myfirstcommand, because immediately after the
command registration the Python backend already sets its completion
function to filename_completer (which then causes the
complete_line_internal function to choose the right set of word break
chars). However, for mysecondcommand, this decision is postponed to
when the completer function is evaluated, and the Python backend uses an
internal completer (called cmdpy_completer). complete_line_internal
doesn't know about this internal completer, and can't choose the right
set of word break chars in time, which then leads to a bad decision when
completing the "/hom" word.
So, after a few attempts, I decided to create another callback in
"struct cmd_list_element" that will be responsible for handling the case
when there is an unknown completer function for complete_line_internal
to work with. So far, only the Python backend uses this callback, and
only when the user provides a completer method instead of registering
the command directly with a completer class. I think this is the best
option because it not very intrusive (all the other commands will still
work normally), but especially because the whole completion code is so
messy that it would be hard to fix this without having to redesign
things.
I have regtested this on Fedora 18 x86_64, without regressions. I also
included a testcase.
gdb/ChangeLog:
2014-09-03 Sergio Durigan Junior <sergiodj@redhat.com>
PR python/16699
* cli/cli-decode.c (set_cmd_completer_handle_brkchars): New
function.
(add_cmd): Set "completer_handle_brkchars" to NULL.
* cli/cli-decode.h (struct cmd_list_element)
<completer_handle_brkchars>: New field.
* command.h (completer_ftype_void): New typedef.
(set_cmd_completer_handle_brkchars): New prototype.
* completer.c (set_gdb_completion_word_break_characters): New
function.
(complete_line_internal): Call "completer_handle_brkchars"
callback from command.
* completer.h: Include "command.h".
(set_gdb_completion_word_break_characters): New prototype.
* python/py-cmd.c (cmdpy_completer_helper): New function.
(cmdpy_completer_handle_brkchars): New function.
(cmdpy_completer): Adjust to use cmdpy_completer_helper.
(cmdpy_init): Set completer_handle_brkchars to
cmdpy_completer_handle_brkchars.
gdb/testsuite/ChangeLog:
2014-09-03 Sergio Durigan Junior <sergiodj@redhat.com>
PR python/16699
* gdb.python/py-completion.exp: New file.
* gdb.python/py-completion.py: Likewise.
2014-09-03 16:30:28 -04:00
|
|
|
|
|
|
|
|
|
|
/* Check if there was an error. */
|
|
|
|
|
|
if (resultobj == NULL)
|
2016-11-20 10:23:08 -07:00
|
|
|
|
return;
|
PR python/16699: GDB Python command completion with overriden complete vs. completer class
This PR came from a Red Hat bug that was filed recently. I checked and
it still exists on HEAD, so here's a proposed fix. Although this is
marked as a Python backend bug, this is really about the completion
mechanism used by GDB. Since this code reminds me of my first attempt
to make a good noodle, it took me quite some time to fix it in a
non-intrusive way.
The problem is triggered when one registers a completion method inside a
class in a Python script, rather than registering the command using a
completer class directly. For example, consider the following script:
class MyFirstCommand(gdb.Command):
def __init__(self):
gdb.Command.__init__(self,'myfirstcommand',gdb.COMMAND_USER,gdb.COMPLETE_FILENAME)
def invoke(self,argument,from_tty):
raise gdb.GdbError('not implemented')
class MySecondCommand(gdb.Command):
def __init__(self):
gdb.Command.__init__(self,'mysecondcommand',gdb.COMMAND_USER)
def invoke(self,argument,from_tty):
raise gdb.GdbError('not implemented')
def complete(self,text,word):
return gdb.COMPLETE_FILENAME
MyFirstCommand ()
MySecondCommand ()
When one loads this into GDB and tries to complete filenames for both
myfirstcommand and mysecondcommand, she gets:
(gdb) myfirstcommand /hom<TAB>
(gdb) myfirstcommand /home/
^
...
(gdb) mysecondcommand /hom<TAB>
(gdb) mysecondcommand /home
^
(The "^" marks the final position of the cursor after the TAB).
So we see that myfirstcommand honors the COMPLETE_FILENAME class (as
specified in the command creation), but mysecondcommand does not. After
some investigation, I found that the problem lies with the set of word
break characters that is used for each case. The set should be the same
for both commands, but it is not.
During the process of deciding which type of completion should be used,
the code in gdb/completer.c:complete_line_internal analyses the command
that requested the completion and tries to determine the type of
completion wanted by checking which completion function will be called
(e.g., filename_completer for filenames, location_completer for
locations, etc.).
This all works fine for myfirstcommand, because immediately after the
command registration the Python backend already sets its completion
function to filename_completer (which then causes the
complete_line_internal function to choose the right set of word break
chars). However, for mysecondcommand, this decision is postponed to
when the completer function is evaluated, and the Python backend uses an
internal completer (called cmdpy_completer). complete_line_internal
doesn't know about this internal completer, and can't choose the right
set of word break chars in time, which then leads to a bad decision when
completing the "/hom" word.
So, after a few attempts, I decided to create another callback in
"struct cmd_list_element" that will be responsible for handling the case
when there is an unknown completer function for complete_line_internal
to work with. So far, only the Python backend uses this callback, and
only when the user provides a completer method instead of registering
the command directly with a completer class. I think this is the best
option because it not very intrusive (all the other commands will still
work normally), but especially because the whole completion code is so
messy that it would be hard to fix this without having to redesign
things.
I have regtested this on Fedora 18 x86_64, without regressions. I also
included a testcase.
gdb/ChangeLog:
2014-09-03 Sergio Durigan Junior <sergiodj@redhat.com>
PR python/16699
* cli/cli-decode.c (set_cmd_completer_handle_brkchars): New
function.
(add_cmd): Set "completer_handle_brkchars" to NULL.
* cli/cli-decode.h (struct cmd_list_element)
<completer_handle_brkchars>: New field.
* command.h (completer_ftype_void): New typedef.
(set_cmd_completer_handle_brkchars): New prototype.
* completer.c (set_gdb_completion_word_break_characters): New
function.
(complete_line_internal): Call "completer_handle_brkchars"
callback from command.
* completer.h: Include "command.h".
(set_gdb_completion_word_break_characters): New prototype.
* python/py-cmd.c (cmdpy_completer_helper): New function.
(cmdpy_completer_handle_brkchars): New function.
(cmdpy_completer): Adjust to use cmdpy_completer_helper.
(cmdpy_init): Set completer_handle_brkchars to
cmdpy_completer_handle_brkchars.
gdb/testsuite/ChangeLog:
2014-09-03 Sergio Durigan Junior <sergiodj@redhat.com>
PR python/16699
* gdb.python/py-completion.exp: New file.
* gdb.python/py-completion.py: Likewise.
2014-09-03 16:30:28 -04:00
|
|
|
|
|
2022-03-21 10:07:41 -04:00
|
|
|
|
if (PyLong_Check (resultobj.get ()))
|
PR python/16699: GDB Python command completion with overriden complete vs. completer class
This PR came from a Red Hat bug that was filed recently. I checked and
it still exists on HEAD, so here's a proposed fix. Although this is
marked as a Python backend bug, this is really about the completion
mechanism used by GDB. Since this code reminds me of my first attempt
to make a good noodle, it took me quite some time to fix it in a
non-intrusive way.
The problem is triggered when one registers a completion method inside a
class in a Python script, rather than registering the command using a
completer class directly. For example, consider the following script:
class MyFirstCommand(gdb.Command):
def __init__(self):
gdb.Command.__init__(self,'myfirstcommand',gdb.COMMAND_USER,gdb.COMPLETE_FILENAME)
def invoke(self,argument,from_tty):
raise gdb.GdbError('not implemented')
class MySecondCommand(gdb.Command):
def __init__(self):
gdb.Command.__init__(self,'mysecondcommand',gdb.COMMAND_USER)
def invoke(self,argument,from_tty):
raise gdb.GdbError('not implemented')
def complete(self,text,word):
return gdb.COMPLETE_FILENAME
MyFirstCommand ()
MySecondCommand ()
When one loads this into GDB and tries to complete filenames for both
myfirstcommand and mysecondcommand, she gets:
(gdb) myfirstcommand /hom<TAB>
(gdb) myfirstcommand /home/
^
...
(gdb) mysecondcommand /hom<TAB>
(gdb) mysecondcommand /home
^
(The "^" marks the final position of the cursor after the TAB).
So we see that myfirstcommand honors the COMPLETE_FILENAME class (as
specified in the command creation), but mysecondcommand does not. After
some investigation, I found that the problem lies with the set of word
break characters that is used for each case. The set should be the same
for both commands, but it is not.
During the process of deciding which type of completion should be used,
the code in gdb/completer.c:complete_line_internal analyses the command
that requested the completion and tries to determine the type of
completion wanted by checking which completion function will be called
(e.g., filename_completer for filenames, location_completer for
locations, etc.).
This all works fine for myfirstcommand, because immediately after the
command registration the Python backend already sets its completion
function to filename_completer (which then causes the
complete_line_internal function to choose the right set of word break
chars). However, for mysecondcommand, this decision is postponed to
when the completer function is evaluated, and the Python backend uses an
internal completer (called cmdpy_completer). complete_line_internal
doesn't know about this internal completer, and can't choose the right
set of word break chars in time, which then leads to a bad decision when
completing the "/hom" word.
So, after a few attempts, I decided to create another callback in
"struct cmd_list_element" that will be responsible for handling the case
when there is an unknown completer function for complete_line_internal
to work with. So far, only the Python backend uses this callback, and
only when the user provides a completer method instead of registering
the command directly with a completer class. I think this is the best
option because it not very intrusive (all the other commands will still
work normally), but especially because the whole completion code is so
messy that it would be hard to fix this without having to redesign
things.
I have regtested this on Fedora 18 x86_64, without regressions. I also
included a testcase.
gdb/ChangeLog:
2014-09-03 Sergio Durigan Junior <sergiodj@redhat.com>
PR python/16699
* cli/cli-decode.c (set_cmd_completer_handle_brkchars): New
function.
(add_cmd): Set "completer_handle_brkchars" to NULL.
* cli/cli-decode.h (struct cmd_list_element)
<completer_handle_brkchars>: New field.
* command.h (completer_ftype_void): New typedef.
(set_cmd_completer_handle_brkchars): New prototype.
* completer.c (set_gdb_completion_word_break_characters): New
function.
(complete_line_internal): Call "completer_handle_brkchars"
callback from command.
* completer.h: Include "command.h".
(set_gdb_completion_word_break_characters): New prototype.
* python/py-cmd.c (cmdpy_completer_helper): New function.
(cmdpy_completer_handle_brkchars): New function.
(cmdpy_completer): Adjust to use cmdpy_completer_helper.
(cmdpy_init): Set completer_handle_brkchars to
cmdpy_completer_handle_brkchars.
gdb/testsuite/ChangeLog:
2014-09-03 Sergio Durigan Junior <sergiodj@redhat.com>
PR python/16699
* gdb.python/py-completion.exp: New file.
* gdb.python/py-completion.py: Likewise.
2014-09-03 16:30:28 -04:00
|
|
|
|
{
|
|
|
|
|
|
/* User code may also return one of the completion constants,
|
|
|
|
|
|
thus requesting that sort of completion. We are only
|
|
|
|
|
|
interested in this kind of return. */
|
|
|
|
|
|
long value;
|
|
|
|
|
|
|
2016-11-20 10:23:08 -07:00
|
|
|
|
if (!gdb_py_int_as_long (resultobj.get (), &value))
|
gdb/python: display errors from command completion
This commit makes the gdb.Command.complete methods more verbose when
it comes to error handling.
Previous to this commit if any commands implemented in Python
implemented the complete method, and if there were any errors
encountered when calling that complete method, then GDB would silently
hide the error and continue as if there were no completions.
This makes is difficult to debug any errors encountered when writing
completion methods, and encourages the idea that Python extensions can
be broken, and GDB will just silently work around them.
I don't think this is a good idea. GDB should encourage extensions to
be written correctly, and robustly, and one way in which GDB can (I
think) support this, is by pointing out when an extension goes wrong.
In this commit I've gone through the Python command completion code,
and added calls to gdbpy_print_stack() or gdbpy_print_stack_or_quit()
in places where we were either clearing the Python error, or, in some
cases, just not handling the error at all.
One thing I have not changed is in cmdpy_completer (py-cmd.c) where we
process the list of completions returned from the Command.complete
method; this routine includes a call to gdbpy_is_string to check a
possible completion is a string, if not the completion is ignored.
I was tempted to remove this check, attempt to complete each result to
a string, and display an error if the conversion fails. After all,
returning anything but a string is surely a mistake by the extension
author.
However, the docs clearly say that only strings within the returned
list will be considered as completions. Anything else is ignored. As
such, and to avoid (what I think is pretty unlikely) breakage of
existing code, I've retained the gdbpy_is_string check.
After the gdbpy_is_string check we call python_string_to_host_string,
if this call fails then I do now print the error, where before we
ignored the error. I think this is OK; if GDB thinks something is a
string, but still can't convert it to a string, then I think it's OK
to display the error in that case.
Another case which I was a little unsure about was in
cmdpy_completer_helper, and the call to PyObject_CallMethodObjArgs,
which is when we actually call Command.complete. Previously, if this
call resulted in an exception then we would ignore this and just
pretend there were no completions.
Of all the changes, this is possibly the one with the biggest
potential for breaking existing scripts, but also, is, I think, the
most useful change. If the user code is wrong in some way, such that
an exception is raised, then previously the user would have no obvious
feedback about this breakage. Now GDB will print the exception for
them, making it, I think, much easier to debug their extension. But,
if there is user code in the wild that relies on raising an exception
as a means to indicate there are no completions .... well, that code
is going to break after this commit. I think we can live with this
though, the exceptions means no completions thing was never documented
behaviour.
I also added a new error() call if the PyObject_CallMethodObjArgs call
raises an exception. This causes the completion mechanism within GDB
to stop. Within GDB the completion code is called twice, the first
time to compute the work break characters, and then a second time to
compute the actual completions.
If PyObject_CallMethodObjArgs raises an exception when computing the
word break character, and we print it by calling
gdbpy_print_stack_or_quit(), but then carry on as if
PyObject_CallMethodObjArgs had returns no completions, GDB will
call the Python completion code again, which results in another call
to PyObject_CallMethodObjArgs, which might raise the same exception
again. This results in the Python exception being printed twice.
By throwing a C++ exception after the failed
PyObject_CallMethodObjArgs call, the completion mechanism is aborted,
and no completions are offered. But importantly, the Python exception
is only printed once. I think this gives a much better user
experience.
I've added some tests to cover this case, as I think this is the most
likely case that a user will run into.
Approved-By: Tom Tromey <tom@tromey.com>
2023-11-27 21:29:53 +00:00
|
|
|
|
gdbpy_print_stack ();
|
PR python/16699: GDB Python command completion with overriden complete vs. completer class
This PR came from a Red Hat bug that was filed recently. I checked and
it still exists on HEAD, so here's a proposed fix. Although this is
marked as a Python backend bug, this is really about the completion
mechanism used by GDB. Since this code reminds me of my first attempt
to make a good noodle, it took me quite some time to fix it in a
non-intrusive way.
The problem is triggered when one registers a completion method inside a
class in a Python script, rather than registering the command using a
completer class directly. For example, consider the following script:
class MyFirstCommand(gdb.Command):
def __init__(self):
gdb.Command.__init__(self,'myfirstcommand',gdb.COMMAND_USER,gdb.COMPLETE_FILENAME)
def invoke(self,argument,from_tty):
raise gdb.GdbError('not implemented')
class MySecondCommand(gdb.Command):
def __init__(self):
gdb.Command.__init__(self,'mysecondcommand',gdb.COMMAND_USER)
def invoke(self,argument,from_tty):
raise gdb.GdbError('not implemented')
def complete(self,text,word):
return gdb.COMPLETE_FILENAME
MyFirstCommand ()
MySecondCommand ()
When one loads this into GDB and tries to complete filenames for both
myfirstcommand and mysecondcommand, she gets:
(gdb) myfirstcommand /hom<TAB>
(gdb) myfirstcommand /home/
^
...
(gdb) mysecondcommand /hom<TAB>
(gdb) mysecondcommand /home
^
(The "^" marks the final position of the cursor after the TAB).
So we see that myfirstcommand honors the COMPLETE_FILENAME class (as
specified in the command creation), but mysecondcommand does not. After
some investigation, I found that the problem lies with the set of word
break characters that is used for each case. The set should be the same
for both commands, but it is not.
During the process of deciding which type of completion should be used,
the code in gdb/completer.c:complete_line_internal analyses the command
that requested the completion and tries to determine the type of
completion wanted by checking which completion function will be called
(e.g., filename_completer for filenames, location_completer for
locations, etc.).
This all works fine for myfirstcommand, because immediately after the
command registration the Python backend already sets its completion
function to filename_completer (which then causes the
complete_line_internal function to choose the right set of word break
chars). However, for mysecondcommand, this decision is postponed to
when the completer function is evaluated, and the Python backend uses an
internal completer (called cmdpy_completer). complete_line_internal
doesn't know about this internal completer, and can't choose the right
set of word break chars in time, which then leads to a bad decision when
completing the "/hom" word.
So, after a few attempts, I decided to create another callback in
"struct cmd_list_element" that will be responsible for handling the case
when there is an unknown completer function for complete_line_internal
to work with. So far, only the Python backend uses this callback, and
only when the user provides a completer method instead of registering
the command directly with a completer class. I think this is the best
option because it not very intrusive (all the other commands will still
work normally), but especially because the whole completion code is so
messy that it would be hard to fix this without having to redesign
things.
I have regtested this on Fedora 18 x86_64, without regressions. I also
included a testcase.
gdb/ChangeLog:
2014-09-03 Sergio Durigan Junior <sergiodj@redhat.com>
PR python/16699
* cli/cli-decode.c (set_cmd_completer_handle_brkchars): New
function.
(add_cmd): Set "completer_handle_brkchars" to NULL.
* cli/cli-decode.h (struct cmd_list_element)
<completer_handle_brkchars>: New field.
* command.h (completer_ftype_void): New typedef.
(set_cmd_completer_handle_brkchars): New prototype.
* completer.c (set_gdb_completion_word_break_characters): New
function.
(complete_line_internal): Call "completer_handle_brkchars"
callback from command.
* completer.h: Include "command.h".
(set_gdb_completion_word_break_characters): New prototype.
* python/py-cmd.c (cmdpy_completer_helper): New function.
(cmdpy_completer_handle_brkchars): New function.
(cmdpy_completer): Adjust to use cmdpy_completer_helper.
(cmdpy_init): Set completer_handle_brkchars to
cmdpy_completer_handle_brkchars.
gdb/testsuite/ChangeLog:
2014-09-03 Sergio Durigan Junior <sergiodj@redhat.com>
PR python/16699
* gdb.python/py-completion.exp: New file.
* gdb.python/py-completion.py: Likewise.
2014-09-03 16:30:28 -04:00
|
|
|
|
else if (value >= 0 && value < (long) N_COMPLETERS)
|
|
|
|
|
|
{
|
2017-07-17 12:05:03 +01:00
|
|
|
|
completer_handle_brkchars_ftype *brkchars_fn;
|
|
|
|
|
|
|
PR python/16699: GDB Python command completion with overriden complete vs. completer class
This PR came from a Red Hat bug that was filed recently. I checked and
it still exists on HEAD, so here's a proposed fix. Although this is
marked as a Python backend bug, this is really about the completion
mechanism used by GDB. Since this code reminds me of my first attempt
to make a good noodle, it took me quite some time to fix it in a
non-intrusive way.
The problem is triggered when one registers a completion method inside a
class in a Python script, rather than registering the command using a
completer class directly. For example, consider the following script:
class MyFirstCommand(gdb.Command):
def __init__(self):
gdb.Command.__init__(self,'myfirstcommand',gdb.COMMAND_USER,gdb.COMPLETE_FILENAME)
def invoke(self,argument,from_tty):
raise gdb.GdbError('not implemented')
class MySecondCommand(gdb.Command):
def __init__(self):
gdb.Command.__init__(self,'mysecondcommand',gdb.COMMAND_USER)
def invoke(self,argument,from_tty):
raise gdb.GdbError('not implemented')
def complete(self,text,word):
return gdb.COMPLETE_FILENAME
MyFirstCommand ()
MySecondCommand ()
When one loads this into GDB and tries to complete filenames for both
myfirstcommand and mysecondcommand, she gets:
(gdb) myfirstcommand /hom<TAB>
(gdb) myfirstcommand /home/
^
...
(gdb) mysecondcommand /hom<TAB>
(gdb) mysecondcommand /home
^
(The "^" marks the final position of the cursor after the TAB).
So we see that myfirstcommand honors the COMPLETE_FILENAME class (as
specified in the command creation), but mysecondcommand does not. After
some investigation, I found that the problem lies with the set of word
break characters that is used for each case. The set should be the same
for both commands, but it is not.
During the process of deciding which type of completion should be used,
the code in gdb/completer.c:complete_line_internal analyses the command
that requested the completion and tries to determine the type of
completion wanted by checking which completion function will be called
(e.g., filename_completer for filenames, location_completer for
locations, etc.).
This all works fine for myfirstcommand, because immediately after the
command registration the Python backend already sets its completion
function to filename_completer (which then causes the
complete_line_internal function to choose the right set of word break
chars). However, for mysecondcommand, this decision is postponed to
when the completer function is evaluated, and the Python backend uses an
internal completer (called cmdpy_completer). complete_line_internal
doesn't know about this internal completer, and can't choose the right
set of word break chars in time, which then leads to a bad decision when
completing the "/hom" word.
So, after a few attempts, I decided to create another callback in
"struct cmd_list_element" that will be responsible for handling the case
when there is an unknown completer function for complete_line_internal
to work with. So far, only the Python backend uses this callback, and
only when the user provides a completer method instead of registering
the command directly with a completer class. I think this is the best
option because it not very intrusive (all the other commands will still
work normally), but especially because the whole completion code is so
messy that it would be hard to fix this without having to redesign
things.
I have regtested this on Fedora 18 x86_64, without regressions. I also
included a testcase.
gdb/ChangeLog:
2014-09-03 Sergio Durigan Junior <sergiodj@redhat.com>
PR python/16699
* cli/cli-decode.c (set_cmd_completer_handle_brkchars): New
function.
(add_cmd): Set "completer_handle_brkchars" to NULL.
* cli/cli-decode.h (struct cmd_list_element)
<completer_handle_brkchars>: New field.
* command.h (completer_ftype_void): New typedef.
(set_cmd_completer_handle_brkchars): New prototype.
* completer.c (set_gdb_completion_word_break_characters): New
function.
(complete_line_internal): Call "completer_handle_brkchars"
callback from command.
* completer.h: Include "command.h".
(set_gdb_completion_word_break_characters): New prototype.
* python/py-cmd.c (cmdpy_completer_helper): New function.
(cmdpy_completer_handle_brkchars): New function.
(cmdpy_completer): Adjust to use cmdpy_completer_helper.
(cmdpy_init): Set completer_handle_brkchars to
cmdpy_completer_handle_brkchars.
gdb/testsuite/ChangeLog:
2014-09-03 Sergio Durigan Junior <sergiodj@redhat.com>
PR python/16699
* gdb.python/py-completion.exp: New file.
* gdb.python/py-completion.py: Likewise.
2014-09-03 16:30:28 -04:00
|
|
|
|
/* This is the core of this function. Depending on which
|
|
|
|
|
|
completer type the Python function returns, we have to
|
|
|
|
|
|
adjust the break characters accordingly. */
|
2017-07-17 12:05:03 +01:00
|
|
|
|
brkchars_fn = (completer_handle_brkchars_func_for_completer
|
|
|
|
|
|
(completers[value].completer));
|
Introduce class completion_tracker & rewrite completion<->readline interaction
This patch reworks the whole completion machinery, and prepares it
for later enhancements.
Adds a new "completion_tracker" class that is meant to hold everything
about the state of the current completion operation.
This class now has the responsibility of tracking the list of
completion matches, and checking whether the max completions limit has
been reached. You can look at this as this patch starting out by
C++fying the existing "completion_tracker" in symtab.c (it's just an
htab_t typedef currently), moving it to completer.h/c, and then making
it a class/generalizing/enhancing it.
Unlike with the current tracking, completion_tracker now checks
whether the limit has been reached on each completion match list
insertion. This both simplifies the max-completions handling code
(maybe_add_completion_enum is gone, for example), and is a
prerequisite for follow up patches.
The current completion_tracker is only used for symbol completions,
and the symbol code gets at the current instance via globals. This
patch cleans that up by adding a completion_tracker reference to the
signature of the completion functions, and passing the tracker around
everywhere necessary.
Then, the patch changes how the completion match list is handed over
to readline. Currently, we're using the rl_completion_entry_function
readline entry point, and the patch switches to
rl_attempted_completion_function. A following patch will want to let
GDB itself decide the common completion prefix between all matches
(what readline calls the "lowest common denominator"), instead of
having readline compute it, and that's not possible with the
rl_completion_entry_function entry point. Also,
rl_attempted_completion_function lets GDB hand over the match list to
readline as an array in one go instead of passing down matches one by
one, so from that angle it's a nicer entry point anyway.
Lastly, the patch catches exceptions around the readline entry points,
because we can't let C++ exceptions cross readline. We handle that in
the readline input entry point, but the completion entry point isn't
guarded, so GDB can abort if completion throws. E.g., in current
master:
(gdb) b -function "fun<tab>
terminate called after throwing an instance of 'gdb_exception_RETURN_MASK_ERROR'
Aborted (core dumped)
This patch fixes that. This will be exercised in the new tests added
later on in the series.
gdb/ChangeLog:
2017-07-17 Pedro Alves <palves@redhat.com>
* ada-lang.c (symbol_completion_match): Adjust comments.
(symbol_completion_add): Replace vector parameter with
completion_tracker parameter. Use it.
(ada_make_symbol_completion_list): Rename to...
(ada_collect_symbol_completion_matches): ... this. Add
completion_tracker parameter and use it.
(ada_language_defn): Adjust.
* break-catch-syscall.c (catch_syscall_completer): Adjust
prototype and work with completion_tracker instead of VEC.
* breakpoint.c (condition_completer): Adjust prototype and work
with completion_tracker instead of VEC.
* c-lang.c (c_language_defn, cplus_language_defn)
(asm_language_defn, minimal_language_defn): Adjust to renames.
* cli/cli-cmds.c (complete_command): Rework using
completion_tracker. Catch exceptions when completing.
* cli/cli-decode.c (integer_unlimited_completer)
(complete_on_cmdlist, complete_on_enum): Adjust prototype and work
with completion_tracker instead of VEC.
* command.h (struct completion_tracker): Forward declare.
(completer_ftype, completer_handle_brkchars_ftype): Change
types.
(complete_on_cmdlist, complete_on_enum): Adjust.
* completer.c: Include <algorithm>.
(struct gdb_completer_state): New.
(current_completion): New global.
(readline_line_completion_function): Delete.
(noop_completer, filename_completer)
(filename_completer_handle_brkchars, complete_files_symbols)
(linespec_location_completer): Adjust to work with a
completion_tracker instead of a VEC.
(string_or_empty): New.
(collect_explicit_location_matches): Adjust to work with a
completion_tracker instead of a VEC.
(explicit_location_completer): Rename to ...
(complete_explicit_location): ... this and adjust to work with a
completion_tracker instead of a VEC.
(location_completer): Adjust to work with a completion_tracker
instead of a VEC.
(add_struct_fields): Adjust to work with a completion_list instead
of VEC.
(expression_completer): Rename to ...
(complete_expression): ... this and adjust to work with a
completion_tracker instead of a VEC. Use complete_files_symbols.
(expression_completer): Reimplement on top of complete_expression.
(symbol_completer): Adjust to work with a completion_tracker
instead of a VEC.
(enum complete_line_internal_reason): Add describing comments.
(complete_line_internal_normal_command): Adjust to work with a
completion_tracker instead of a VEC.
(complete_line_internal): Rename to ...
(complete_line_internal_1): ... this and adjust to work with a
completion_tracker instead of a VEC. Assert TEXT is NULL in the
handle_brkchars phase.
(new_completion_tracker): Delete.
(complete_line_internal): Reimplement as TRY/CATCH wrapper around
complete_line_internal_1.
(free_completion_tracker): Delete.
(INITIAL_COMPLETION_HTAB_SIZE): New.
(completion_tracker::completion_tracker)
(completion_tracker::~completion_tracker): New.
(maybe_add_completion): Delete.
(completion_tracker::maybe_add_completion)
(completion_tracker::add_completion)
(completion_tracker::add_completions): New.
(throw_max_completions_reached_error): Delete.
(complete_line): Adjust to work with a completion_tracker instead
of a VEC. Don't create a completion_tracker_t or check for max
completions here.
(command_completer, command_completer_handle_brkchars)
(signal_completer, reg_or_group_completer_1)
(reg_or_group_completer, default_completer_handle_brkchars):
Adjust to work with a completion_tracker.
(gdb_completion_word_break_characters_throw): New.
(gdb_completion_word_break_characters): Reimplement.
(line_completion_function): Delete.
(completion_tracker::recompute_lowest_common_denominator)
(expand_preserving_ws)
(completion_tracker::build_completion_result)
(completion_result::completion_result)
(completion_result::completion_result)
(completion_result::~completion_result)
(completion_result::completion_result)
(completion_result::release_match_list, compare_cstrings)
(completion_result::sort_match_list)
(completion_result::reset_match_list)
(gdb_rl_attempted_completion_function_throw)
(gdb_rl_attempted_completion_function): New.
* completer.h (completion_list, struct completion_result)
(class completion_tracker): New.
(complete_line): Add completion_tracker parameter.
(readline_line_completion_function): Delete.
(gdb_rl_attempted_completion_function): New.
(noop_completer, filename_completer, expression_completer)
(location_completer, symbol_completer, command_completer)
(signal_completer, reg_or_group_completer): Update prototypes.
(completion_tracker_t, new_completion_tracker)
(make_cleanup_free_completion_tracker): Delete.
(enum maybe_add_completion_enum): Delete.
(maybe_add_completion): Delete.
(throw_max_completions_reached_error): Delete.
* corefile.c (complete_set_gnutarget): Adjust to work with a
completion_tracker instead of a VEC.
* cp-abi.c (cp_abi_completer): Adjust to work with a
completion_tracker instead of a VEC.
* d-lang.c (d_language_defn): Adjust.
* disasm.c (disassembler_options_completer): Adjust to work with a
completion_tracker instead of a VEC.
* f-lang.c (f_make_symbol_completion_list): Rename to ...
(f_collect_symbol_completion_matches): ... this. Adjust to work
with a completion_tracker instead of a VEC.
(f_language_defn): Adjust.
* go-lang.c (go_language_defn): Adjust.
* guile/scm-cmd.c (cmdscm_add_completion, cmdscm_completer):
Adjust to work with a completion_tracker instead of a VEC.
* infrun.c (handle_completer): Likewise.
* interps.c (interpreter_completer): Likewise.
* interps.h (interpreter_completer): Likewise.
* language.c (unknown_language_defn, auto_language_defn)
(local_language_defn): Adjust.
* language.h (language_defn::la_make_symbol_completion_list):
Rename to ...
(language_defn::la_collect_symbol_completion_matches): ... this
and adjust to work with a completion_tracker instead of a VEC.
* m2-lang.c (m2_language_defn): Adjust.
* objc-lang.c (objc_language_defn): Adjust.
* opencl-lang.c (opencl_language_defn): Adjust.
* p-lang.c (pascal_language_defn): Adjust.
* python/py-cmd.c (cmdpy_completer_helper): Handle NULL word.
(cmdpy_completer_handle_brkchars, cmdpy_completer): Adjust to work
with a completion_tracker.
* rust-lang.c (rust_language_defn): Adjust.
* symtab.c (free_completion_list, do_free_completion_list)
(return_val, completion_tracker): Delete.
(completion_list_add_name, completion_list_add_symbol)
(completion_list_add_msymbol, completion_list_objc_symbol)
(completion_list_add_fields, add_symtab_completions): Add
completion_tracker parameter and use it.
(default_make_symbol_completion_list_break_on_1): Rename to...
(default_collect_symbol_completion_matches_break_on): ... this.
Add completion_tracker parameter and use it instead of allocating
a completion tracker here.
(default_make_symbol_completion_list_break_on): Delete old
implementation.
(default_make_symbol_completion_list): Delete.
(default_collect_symbol_completion_matches): New.
(make_symbol_completion_list): Delete.
(collect_symbol_completion_matches): New.
(make_symbol_completion_type): Rename to ...
(collect_symbol_completion_matches_type): ... this. Add
completion_tracker parameter and use it instead of VEC.
(make_file_symbol_completion_list_1): Rename to...
(collect_file_symbol_completion_matches): ... this. Add
completion_tracker parameter and use it instead of VEC.
(make_file_symbol_completion_list): Delete.
(add_filename_to_list): Use completion_list instead of a VEC.
(add_partial_filename_data::list): Now a completion_list.
(make_source_files_completion_list): Work with a completion_list
instead of a VEC.
* symtab.h: Include "completer.h".
(default_make_symbol_completion_list_break_on)
(default_make_symbol_completion_list, make_symbol_completion_list)
(make_symbol_completion_type, make_file_symbol_completion_list)
(make_source_files_completion_list): Delete.
(default_collect_symbol_completion_matches_break_on)
(default_collect_symbol_completion_matches)
(collect_symbol_completion_matches)
(collect_symbol_completion_matches_type)
(collect_file_symbol_completion_matches)
(make_source_files_completion_list): New.
* top.c (init_main): Don't install a rl_completion_entry_function
hook. Install a rl_attempted_completion_function hook instead.
* tui/tui-layout.c (layout_completer): Adjust to work with a
completion_tracker.
* tui/tui-regs.c (tui_reggroup_completer):
* tui/tui-win.c (window_name_completer, focus_completer)
(winheight_completer): Adjust to work with a completion_tracker.
* value.c: Include "completer.h".
(complete_internalvar): Adjust to work with a completion_tracker.
* value.h (complete_internalvar): Likewise.
2017-07-17 14:45:59 +01:00
|
|
|
|
brkchars_fn (command, tracker, text, word);
|
PR python/16699: GDB Python command completion with overriden complete vs. completer class
This PR came from a Red Hat bug that was filed recently. I checked and
it still exists on HEAD, so here's a proposed fix. Although this is
marked as a Python backend bug, this is really about the completion
mechanism used by GDB. Since this code reminds me of my first attempt
to make a good noodle, it took me quite some time to fix it in a
non-intrusive way.
The problem is triggered when one registers a completion method inside a
class in a Python script, rather than registering the command using a
completer class directly. For example, consider the following script:
class MyFirstCommand(gdb.Command):
def __init__(self):
gdb.Command.__init__(self,'myfirstcommand',gdb.COMMAND_USER,gdb.COMPLETE_FILENAME)
def invoke(self,argument,from_tty):
raise gdb.GdbError('not implemented')
class MySecondCommand(gdb.Command):
def __init__(self):
gdb.Command.__init__(self,'mysecondcommand',gdb.COMMAND_USER)
def invoke(self,argument,from_tty):
raise gdb.GdbError('not implemented')
def complete(self,text,word):
return gdb.COMPLETE_FILENAME
MyFirstCommand ()
MySecondCommand ()
When one loads this into GDB and tries to complete filenames for both
myfirstcommand and mysecondcommand, she gets:
(gdb) myfirstcommand /hom<TAB>
(gdb) myfirstcommand /home/
^
...
(gdb) mysecondcommand /hom<TAB>
(gdb) mysecondcommand /home
^
(The "^" marks the final position of the cursor after the TAB).
So we see that myfirstcommand honors the COMPLETE_FILENAME class (as
specified in the command creation), but mysecondcommand does not. After
some investigation, I found that the problem lies with the set of word
break characters that is used for each case. The set should be the same
for both commands, but it is not.
During the process of deciding which type of completion should be used,
the code in gdb/completer.c:complete_line_internal analyses the command
that requested the completion and tries to determine the type of
completion wanted by checking which completion function will be called
(e.g., filename_completer for filenames, location_completer for
locations, etc.).
This all works fine for myfirstcommand, because immediately after the
command registration the Python backend already sets its completion
function to filename_completer (which then causes the
complete_line_internal function to choose the right set of word break
chars). However, for mysecondcommand, this decision is postponed to
when the completer function is evaluated, and the Python backend uses an
internal completer (called cmdpy_completer). complete_line_internal
doesn't know about this internal completer, and can't choose the right
set of word break chars in time, which then leads to a bad decision when
completing the "/hom" word.
So, after a few attempts, I decided to create another callback in
"struct cmd_list_element" that will be responsible for handling the case
when there is an unknown completer function for complete_line_internal
to work with. So far, only the Python backend uses this callback, and
only when the user provides a completer method instead of registering
the command directly with a completer class. I think this is the best
option because it not very intrusive (all the other commands will still
work normally), but especially because the whole completion code is so
messy that it would be hard to fix this without having to redesign
things.
I have regtested this on Fedora 18 x86_64, without regressions. I also
included a testcase.
gdb/ChangeLog:
2014-09-03 Sergio Durigan Junior <sergiodj@redhat.com>
PR python/16699
* cli/cli-decode.c (set_cmd_completer_handle_brkchars): New
function.
(add_cmd): Set "completer_handle_brkchars" to NULL.
* cli/cli-decode.h (struct cmd_list_element)
<completer_handle_brkchars>: New field.
* command.h (completer_ftype_void): New typedef.
(set_cmd_completer_handle_brkchars): New prototype.
* completer.c (set_gdb_completion_word_break_characters): New
function.
(complete_line_internal): Call "completer_handle_brkchars"
callback from command.
* completer.h: Include "command.h".
(set_gdb_completion_word_break_characters): New prototype.
* python/py-cmd.c (cmdpy_completer_helper): New function.
(cmdpy_completer_handle_brkchars): New function.
(cmdpy_completer): Adjust to use cmdpy_completer_helper.
(cmdpy_init): Set completer_handle_brkchars to
cmdpy_completer_handle_brkchars.
gdb/testsuite/ChangeLog:
2014-09-03 Sergio Durigan Junior <sergiodj@redhat.com>
PR python/16699
* gdb.python/py-completion.exp: New file.
* gdb.python/py-completion.py: Likewise.
2014-09-03 16:30:28 -04:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2009-02-06 21:33:59 +00:00
|
|
|
|
/* Called by gdb for command completion. */
|
2011-09-08 19:51:27 +00:00
|
|
|
|
|
Introduce class completion_tracker & rewrite completion<->readline interaction
This patch reworks the whole completion machinery, and prepares it
for later enhancements.
Adds a new "completion_tracker" class that is meant to hold everything
about the state of the current completion operation.
This class now has the responsibility of tracking the list of
completion matches, and checking whether the max completions limit has
been reached. You can look at this as this patch starting out by
C++fying the existing "completion_tracker" in symtab.c (it's just an
htab_t typedef currently), moving it to completer.h/c, and then making
it a class/generalizing/enhancing it.
Unlike with the current tracking, completion_tracker now checks
whether the limit has been reached on each completion match list
insertion. This both simplifies the max-completions handling code
(maybe_add_completion_enum is gone, for example), and is a
prerequisite for follow up patches.
The current completion_tracker is only used for symbol completions,
and the symbol code gets at the current instance via globals. This
patch cleans that up by adding a completion_tracker reference to the
signature of the completion functions, and passing the tracker around
everywhere necessary.
Then, the patch changes how the completion match list is handed over
to readline. Currently, we're using the rl_completion_entry_function
readline entry point, and the patch switches to
rl_attempted_completion_function. A following patch will want to let
GDB itself decide the common completion prefix between all matches
(what readline calls the "lowest common denominator"), instead of
having readline compute it, and that's not possible with the
rl_completion_entry_function entry point. Also,
rl_attempted_completion_function lets GDB hand over the match list to
readline as an array in one go instead of passing down matches one by
one, so from that angle it's a nicer entry point anyway.
Lastly, the patch catches exceptions around the readline entry points,
because we can't let C++ exceptions cross readline. We handle that in
the readline input entry point, but the completion entry point isn't
guarded, so GDB can abort if completion throws. E.g., in current
master:
(gdb) b -function "fun<tab>
terminate called after throwing an instance of 'gdb_exception_RETURN_MASK_ERROR'
Aborted (core dumped)
This patch fixes that. This will be exercised in the new tests added
later on in the series.
gdb/ChangeLog:
2017-07-17 Pedro Alves <palves@redhat.com>
* ada-lang.c (symbol_completion_match): Adjust comments.
(symbol_completion_add): Replace vector parameter with
completion_tracker parameter. Use it.
(ada_make_symbol_completion_list): Rename to...
(ada_collect_symbol_completion_matches): ... this. Add
completion_tracker parameter and use it.
(ada_language_defn): Adjust.
* break-catch-syscall.c (catch_syscall_completer): Adjust
prototype and work with completion_tracker instead of VEC.
* breakpoint.c (condition_completer): Adjust prototype and work
with completion_tracker instead of VEC.
* c-lang.c (c_language_defn, cplus_language_defn)
(asm_language_defn, minimal_language_defn): Adjust to renames.
* cli/cli-cmds.c (complete_command): Rework using
completion_tracker. Catch exceptions when completing.
* cli/cli-decode.c (integer_unlimited_completer)
(complete_on_cmdlist, complete_on_enum): Adjust prototype and work
with completion_tracker instead of VEC.
* command.h (struct completion_tracker): Forward declare.
(completer_ftype, completer_handle_brkchars_ftype): Change
types.
(complete_on_cmdlist, complete_on_enum): Adjust.
* completer.c: Include <algorithm>.
(struct gdb_completer_state): New.
(current_completion): New global.
(readline_line_completion_function): Delete.
(noop_completer, filename_completer)
(filename_completer_handle_brkchars, complete_files_symbols)
(linespec_location_completer): Adjust to work with a
completion_tracker instead of a VEC.
(string_or_empty): New.
(collect_explicit_location_matches): Adjust to work with a
completion_tracker instead of a VEC.
(explicit_location_completer): Rename to ...
(complete_explicit_location): ... this and adjust to work with a
completion_tracker instead of a VEC.
(location_completer): Adjust to work with a completion_tracker
instead of a VEC.
(add_struct_fields): Adjust to work with a completion_list instead
of VEC.
(expression_completer): Rename to ...
(complete_expression): ... this and adjust to work with a
completion_tracker instead of a VEC. Use complete_files_symbols.
(expression_completer): Reimplement on top of complete_expression.
(symbol_completer): Adjust to work with a completion_tracker
instead of a VEC.
(enum complete_line_internal_reason): Add describing comments.
(complete_line_internal_normal_command): Adjust to work with a
completion_tracker instead of a VEC.
(complete_line_internal): Rename to ...
(complete_line_internal_1): ... this and adjust to work with a
completion_tracker instead of a VEC. Assert TEXT is NULL in the
handle_brkchars phase.
(new_completion_tracker): Delete.
(complete_line_internal): Reimplement as TRY/CATCH wrapper around
complete_line_internal_1.
(free_completion_tracker): Delete.
(INITIAL_COMPLETION_HTAB_SIZE): New.
(completion_tracker::completion_tracker)
(completion_tracker::~completion_tracker): New.
(maybe_add_completion): Delete.
(completion_tracker::maybe_add_completion)
(completion_tracker::add_completion)
(completion_tracker::add_completions): New.
(throw_max_completions_reached_error): Delete.
(complete_line): Adjust to work with a completion_tracker instead
of a VEC. Don't create a completion_tracker_t or check for max
completions here.
(command_completer, command_completer_handle_brkchars)
(signal_completer, reg_or_group_completer_1)
(reg_or_group_completer, default_completer_handle_brkchars):
Adjust to work with a completion_tracker.
(gdb_completion_word_break_characters_throw): New.
(gdb_completion_word_break_characters): Reimplement.
(line_completion_function): Delete.
(completion_tracker::recompute_lowest_common_denominator)
(expand_preserving_ws)
(completion_tracker::build_completion_result)
(completion_result::completion_result)
(completion_result::completion_result)
(completion_result::~completion_result)
(completion_result::completion_result)
(completion_result::release_match_list, compare_cstrings)
(completion_result::sort_match_list)
(completion_result::reset_match_list)
(gdb_rl_attempted_completion_function_throw)
(gdb_rl_attempted_completion_function): New.
* completer.h (completion_list, struct completion_result)
(class completion_tracker): New.
(complete_line): Add completion_tracker parameter.
(readline_line_completion_function): Delete.
(gdb_rl_attempted_completion_function): New.
(noop_completer, filename_completer, expression_completer)
(location_completer, symbol_completer, command_completer)
(signal_completer, reg_or_group_completer): Update prototypes.
(completion_tracker_t, new_completion_tracker)
(make_cleanup_free_completion_tracker): Delete.
(enum maybe_add_completion_enum): Delete.
(maybe_add_completion): Delete.
(throw_max_completions_reached_error): Delete.
* corefile.c (complete_set_gnutarget): Adjust to work with a
completion_tracker instead of a VEC.
* cp-abi.c (cp_abi_completer): Adjust to work with a
completion_tracker instead of a VEC.
* d-lang.c (d_language_defn): Adjust.
* disasm.c (disassembler_options_completer): Adjust to work with a
completion_tracker instead of a VEC.
* f-lang.c (f_make_symbol_completion_list): Rename to ...
(f_collect_symbol_completion_matches): ... this. Adjust to work
with a completion_tracker instead of a VEC.
(f_language_defn): Adjust.
* go-lang.c (go_language_defn): Adjust.
* guile/scm-cmd.c (cmdscm_add_completion, cmdscm_completer):
Adjust to work with a completion_tracker instead of a VEC.
* infrun.c (handle_completer): Likewise.
* interps.c (interpreter_completer): Likewise.
* interps.h (interpreter_completer): Likewise.
* language.c (unknown_language_defn, auto_language_defn)
(local_language_defn): Adjust.
* language.h (language_defn::la_make_symbol_completion_list):
Rename to ...
(language_defn::la_collect_symbol_completion_matches): ... this
and adjust to work with a completion_tracker instead of a VEC.
* m2-lang.c (m2_language_defn): Adjust.
* objc-lang.c (objc_language_defn): Adjust.
* opencl-lang.c (opencl_language_defn): Adjust.
* p-lang.c (pascal_language_defn): Adjust.
* python/py-cmd.c (cmdpy_completer_helper): Handle NULL word.
(cmdpy_completer_handle_brkchars, cmdpy_completer): Adjust to work
with a completion_tracker.
* rust-lang.c (rust_language_defn): Adjust.
* symtab.c (free_completion_list, do_free_completion_list)
(return_val, completion_tracker): Delete.
(completion_list_add_name, completion_list_add_symbol)
(completion_list_add_msymbol, completion_list_objc_symbol)
(completion_list_add_fields, add_symtab_completions): Add
completion_tracker parameter and use it.
(default_make_symbol_completion_list_break_on_1): Rename to...
(default_collect_symbol_completion_matches_break_on): ... this.
Add completion_tracker parameter and use it instead of allocating
a completion tracker here.
(default_make_symbol_completion_list_break_on): Delete old
implementation.
(default_make_symbol_completion_list): Delete.
(default_collect_symbol_completion_matches): New.
(make_symbol_completion_list): Delete.
(collect_symbol_completion_matches): New.
(make_symbol_completion_type): Rename to ...
(collect_symbol_completion_matches_type): ... this. Add
completion_tracker parameter and use it instead of VEC.
(make_file_symbol_completion_list_1): Rename to...
(collect_file_symbol_completion_matches): ... this. Add
completion_tracker parameter and use it instead of VEC.
(make_file_symbol_completion_list): Delete.
(add_filename_to_list): Use completion_list instead of a VEC.
(add_partial_filename_data::list): Now a completion_list.
(make_source_files_completion_list): Work with a completion_list
instead of a VEC.
* symtab.h: Include "completer.h".
(default_make_symbol_completion_list_break_on)
(default_make_symbol_completion_list, make_symbol_completion_list)
(make_symbol_completion_type, make_file_symbol_completion_list)
(make_source_files_completion_list): Delete.
(default_collect_symbol_completion_matches_break_on)
(default_collect_symbol_completion_matches)
(collect_symbol_completion_matches)
(collect_symbol_completion_matches_type)
(collect_file_symbol_completion_matches)
(make_source_files_completion_list): New.
* top.c (init_main): Don't install a rl_completion_entry_function
hook. Install a rl_attempted_completion_function hook instead.
* tui/tui-layout.c (layout_completer): Adjust to work with a
completion_tracker.
* tui/tui-regs.c (tui_reggroup_completer):
* tui/tui-win.c (window_name_completer, focus_completer)
(winheight_completer): Adjust to work with a completion_tracker.
* value.c: Include "completer.h".
(complete_internalvar): Adjust to work with a completion_tracker.
* value.h (complete_internalvar): Likewise.
2017-07-17 14:45:59 +01:00
|
|
|
|
static void
|
Constify strings in tracepoint.c, lookup_cmd and the completers.
This is sort of a continuation of Keith's parse_exp_1 constification
patch. It started out by undoing these bits:
@@ -754,9 +754,12 @@ validate_actionline (char **line, struct
tmp_p = p;
for (loc = t->base.loc; loc; loc = loc->next)
{
- p = tmp_p;
- exp = parse_exp_1 (&p, loc->address,
+ const char *q;
+
+ q = tmp_p;
+ exp = parse_exp_1 (&q, loc->address,
block_for_pc (loc->address), 1);
+ p = (char *) q;
and progressively making more things const upwards, fixing fallout,
rinse repeat, until GDB built again (--enable-targets=all).
That ended up constifying lookup_cmd/add_cmd and (lots of) friends,
and the completers.
I didn't try to constify the command hooks themselves, because I know
upfront there are commands that write to the command string argument,
and I think I managed to stop at a nice non-hacky split point already.
I think the only non-really-super-obvious changes are
tracepoint.c:validate_actionline, and tracepoint.c:trace_dump_actions.
The rest is just mostly about 'char *' => 'const char *', 'char **'=>
'const char **', and the occasional (e.g., deprecated_cmd_warning)
case of 'char **'=> 'const char *', where/when I noticed that nothing
actually cares about the pointer to pointer output.
Tested on x86_64 Fedora 17, native and gdbserver.
gdb/
2013-03-13 Pedro Alves <palves@redhat.com>
* ada-lang.c (struct add_partial_datum) <text, text0, word>: Make
fields const.
(ada_make_symbol_completion_list): Make "text0" parameter const.
* ax-gdb.c (agent_eval_command_one): Make "exp" parameter const.
* breakpoint.c (condition_completer): Make "text" and "word"
parameters const. Adjust.
(check_tracepoint_command): Adjust to validate_actionline
prototype change.
(catch_syscall_completer): Make "text" and "word" parameters
const.
* cli/cli-cmds.c (show_user): Make "comname" local const.
(valid_command_p): Make "command" parameter const.
(alias_command): Make "alias_prefix" and "command_prefix" locals
const.
* cli/cli-decode.c (add_cmd): Make "name" parameter const.
(add_alias_cmd): Make "name" and "oldname" parameters const.
Adjust. No longer make copy of OLDNAME.
(add_prefix_cmd, add_abbrev_prefix_cmd, add_set_or_show_cmd)
(add_setshow_cmd_full, add_setshow_enum_cmd)
(add_setshow_auto_boolean_cmd, add_setshow_boolean_cmd)
(add_setshow_filename_cmd, add_setshow_string_cmd)
(add_setshow_string_noescape_cmd)
(add_setshow_optional_filename_cmd, add_setshow_integer_cmd)
(add_setshow_uinteger_cmd, add_setshow_zinteger_cmd)
(add_setshow_zuinteger_unlimited_cmd, add_setshow_zuinteger_cmd)
(delete_cmd, add_info, add_info_alias, add_com, add_com_alias):
Make "name" parameter const.
(help_cmd): Rename "command" parameter to "arg". New const local
"command".
(find_cmd): Make "command" parameter const.
(lookup_cmd_1): Make "text" parameter pointer to const. Adjust to
deprecated_cmd_warning prototype change.
(undef_cmd_error): Make "cmdtype" parameter const.
(lookup_cmd): Make "line" parameter const.
(deprecated_cmd_warning): Change type of "text" parameter to
pointer to const char, from pointer to pointer to char. Adjust.
(lookup_cmd_composition): Make "text" parameter const.
(complete_on_cmdlist, complete_on_enum): Make "text" and "word"
parameters const.
* cli/cli-decode.h (struct cmd_list_element) <name>: Make field
const.
* cli/cli-script.c (validate_comname): Make "tem" local const.
(define_command): New const local "tem_c". Use it in calls to
lookup_cmd.
(document_command): Make "tem" and "comfull" locals const.
(show_user_1): Make "prefix" and "name" parameters const.
* cli-script.h (show_user_1): Make "prefix" and "name" parameters
const.
* command.h (add_cmd, add_alias_cmd, add_prefix_cmd)
(add_abbrev_prefix_cmd, completer_ftype, lookup_cmd, lookup_cmd_1)
(deprecated_cmd_warning, lookup_cmd_composition, add_com)
(add_com_alias, add_info, add_info_alias, complete_on_cmdlist)
(complete_on_enum, add_setshow_enum_cmd)
(add_setshow_auto_boolean_cmd, add_setshow_boolean_cmd)
(add_setshow_filename_cmd, add_setshow_string_cmd)
(add_setshow_string_noescape_cmd)
(add_setshow_optional_filename_cmd, add_setshow_integer_cmd)
(add_setshow_uinteger_cmd, add_setshow_zinteger_cmd)
(add_setshow_zuinteger_cmd, add_setshow_zuinteger_unlimited_cmd):
Change prototypes, constifying strings.
* completer.c (noop_completer, filename_completer): Make "text"
and "prefix" parameters const.
(location_completer, expression_completer)
(complete_line_internal): Make "text" and "prefix" parameters
const and adjust.
(command_completer, signal_completer): Make "text" and "prefix"
parameters const.
* completer.h (noop_completer, filename_completer)
(expression_completer, location_completer, command_completer)
(signal_completer): Change prototypes.
* corefile.c (complete_set_gnutarget): Make "text" and "word"
parameters const.
* cp-abi.c (cp_abi_completer): Likewise.
* expression.h (parse_expression_for_completion): Change
prototype.
* f-lang.c (f_make_symbol_completion_list): Make "text" and "word"
parameters const.
* infcmd.c (_initialize_infcmd): Make "cmd_name" local const.
* infrun.c (handle_completer): Make "text" and "word" parameters
const.
* interps.c (interpreter_completer): Make "text" and "word"
parameters const.
* language.h (struct language_defn)
<la_make_symbol_completion_list>: Make "text" and "word"
parameters const.
* parse.c (parse_exp_1): Move const hack to parse_exp_in_context.
(parse_exp_in_context): Rename to ...
(parse_exp_in_context_1): ... this.
(parse_exp_in_context): Reimplement, with const hack from
parse_exp_1.
(parse_expression_for_completion): Make "string" parameter const.
* printcmd.c (decode_format): Make "string_ptr" parameter pointer
to pointer to const char. Adjust.
(print_command_1): Make "exp" parameter const.
(output_command): Rename to ...
(output_command_const): ... this. Make "exp" parameter const.
(output_command): Reimplement.
(x_command): Adjust.
(display_command): Rename "exp" parameter to "arg". New "exp"
local, const version of "arg".
* python/py-auto-load.c (gdbpy_initialize_auto_load): Make
"cmd_name" local const.
* python/py-cmd.c (cmdpy_destroyer): Cast const away in xfree
call.
(cmdpy_completer): Make "text" and "word" parameters const.
(gdbpy_parse_command_name): Make "prefix_text2" local const.
* python/py-param.c (add_setshow_generic): Make "tmp_name" local
const.
* remote.c (_initialize_remote): Make "cmd_name" local const.
* symtab.c (language_search_unquoted_string): Make "text" and "p"
parameters const. Adjust.
(completion_list_add_fields): Make "sym_text", "text" and "word"
parameters const.
(struct add_name_data) <sym_text, text, word>: Make fields const.
(default_make_symbol_completion_list_break_on): Make "text" and
"word" parameters const. Adjust locals.
(default_make_symbol_completion_list)
(make_symbol_completion_list, make_symbol_completion_type)
(make_symbol_completion_list_fn): Make "text" and "word"
parameters const.
(make_file_symbol_completion_list): Make "text", "word" and
"srcfile" parameters const. Adjust locals.
(add_filename_to_list): Make "text" and "word" parameters const.
(struct add_partial_filename_data) <text, word>: Make fields
const.
(make_source_files_completion_list): Make "text" and "word"
parameters const.
* symtab.h (default_make_symbol_completion_list_break_on)
(default_make_symbol_completion_list, make_symbol_completion_list)
(make_symbol_completion_type enum type_code)
(make_symbol_completion_list_fn make_file_symbol_completion_list)
(make_source_files_completion_list): Change prototype.
* top.c (execute_command): Adjust to pass pointer to pointer to
const char to lookup_cmd, and to deprecated_cmd_warning prototype
change.
(set_verbose): Make "cmdname" local const.
* tracepoint.c (decode_agent_options): Make "exp" parameter const,
and adjust.
(validate_actionline): Make "line" parameter a pointer to const
char, and adjust.
(encode_actions_1): Make "action_exp" local const, and adjust.
(encode_actions): Adjust.
(replace_comma): Delete.
(trace_dump_actions): Make "action_exp" and "next_comma" locals
const, and adjust. Don't frob the action string while splitting
it at commas. Instead, make a copy of each split substring in
turn.
(trace_dump_command): Adjust to validate_actionline prototype
change.
* tracepoint.h (decode_agent_options, decode_agent_options)
(encode_actions, validate_actionline): Change prototypes.
* valprint.h (output_command): Delete declaration.
(output_command_const): Declare.
* value.c (function_destroyer): Cast const away in xfree call.
2013-03-13 18:34:55 +00:00
|
|
|
|
cmdpy_completer (struct cmd_list_element *command,
|
Introduce class completion_tracker & rewrite completion<->readline interaction
This patch reworks the whole completion machinery, and prepares it
for later enhancements.
Adds a new "completion_tracker" class that is meant to hold everything
about the state of the current completion operation.
This class now has the responsibility of tracking the list of
completion matches, and checking whether the max completions limit has
been reached. You can look at this as this patch starting out by
C++fying the existing "completion_tracker" in symtab.c (it's just an
htab_t typedef currently), moving it to completer.h/c, and then making
it a class/generalizing/enhancing it.
Unlike with the current tracking, completion_tracker now checks
whether the limit has been reached on each completion match list
insertion. This both simplifies the max-completions handling code
(maybe_add_completion_enum is gone, for example), and is a
prerequisite for follow up patches.
The current completion_tracker is only used for symbol completions,
and the symbol code gets at the current instance via globals. This
patch cleans that up by adding a completion_tracker reference to the
signature of the completion functions, and passing the tracker around
everywhere necessary.
Then, the patch changes how the completion match list is handed over
to readline. Currently, we're using the rl_completion_entry_function
readline entry point, and the patch switches to
rl_attempted_completion_function. A following patch will want to let
GDB itself decide the common completion prefix between all matches
(what readline calls the "lowest common denominator"), instead of
having readline compute it, and that's not possible with the
rl_completion_entry_function entry point. Also,
rl_attempted_completion_function lets GDB hand over the match list to
readline as an array in one go instead of passing down matches one by
one, so from that angle it's a nicer entry point anyway.
Lastly, the patch catches exceptions around the readline entry points,
because we can't let C++ exceptions cross readline. We handle that in
the readline input entry point, but the completion entry point isn't
guarded, so GDB can abort if completion throws. E.g., in current
master:
(gdb) b -function "fun<tab>
terminate called after throwing an instance of 'gdb_exception_RETURN_MASK_ERROR'
Aborted (core dumped)
This patch fixes that. This will be exercised in the new tests added
later on in the series.
gdb/ChangeLog:
2017-07-17 Pedro Alves <palves@redhat.com>
* ada-lang.c (symbol_completion_match): Adjust comments.
(symbol_completion_add): Replace vector parameter with
completion_tracker parameter. Use it.
(ada_make_symbol_completion_list): Rename to...
(ada_collect_symbol_completion_matches): ... this. Add
completion_tracker parameter and use it.
(ada_language_defn): Adjust.
* break-catch-syscall.c (catch_syscall_completer): Adjust
prototype and work with completion_tracker instead of VEC.
* breakpoint.c (condition_completer): Adjust prototype and work
with completion_tracker instead of VEC.
* c-lang.c (c_language_defn, cplus_language_defn)
(asm_language_defn, minimal_language_defn): Adjust to renames.
* cli/cli-cmds.c (complete_command): Rework using
completion_tracker. Catch exceptions when completing.
* cli/cli-decode.c (integer_unlimited_completer)
(complete_on_cmdlist, complete_on_enum): Adjust prototype and work
with completion_tracker instead of VEC.
* command.h (struct completion_tracker): Forward declare.
(completer_ftype, completer_handle_brkchars_ftype): Change
types.
(complete_on_cmdlist, complete_on_enum): Adjust.
* completer.c: Include <algorithm>.
(struct gdb_completer_state): New.
(current_completion): New global.
(readline_line_completion_function): Delete.
(noop_completer, filename_completer)
(filename_completer_handle_brkchars, complete_files_symbols)
(linespec_location_completer): Adjust to work with a
completion_tracker instead of a VEC.
(string_or_empty): New.
(collect_explicit_location_matches): Adjust to work with a
completion_tracker instead of a VEC.
(explicit_location_completer): Rename to ...
(complete_explicit_location): ... this and adjust to work with a
completion_tracker instead of a VEC.
(location_completer): Adjust to work with a completion_tracker
instead of a VEC.
(add_struct_fields): Adjust to work with a completion_list instead
of VEC.
(expression_completer): Rename to ...
(complete_expression): ... this and adjust to work with a
completion_tracker instead of a VEC. Use complete_files_symbols.
(expression_completer): Reimplement on top of complete_expression.
(symbol_completer): Adjust to work with a completion_tracker
instead of a VEC.
(enum complete_line_internal_reason): Add describing comments.
(complete_line_internal_normal_command): Adjust to work with a
completion_tracker instead of a VEC.
(complete_line_internal): Rename to ...
(complete_line_internal_1): ... this and adjust to work with a
completion_tracker instead of a VEC. Assert TEXT is NULL in the
handle_brkchars phase.
(new_completion_tracker): Delete.
(complete_line_internal): Reimplement as TRY/CATCH wrapper around
complete_line_internal_1.
(free_completion_tracker): Delete.
(INITIAL_COMPLETION_HTAB_SIZE): New.
(completion_tracker::completion_tracker)
(completion_tracker::~completion_tracker): New.
(maybe_add_completion): Delete.
(completion_tracker::maybe_add_completion)
(completion_tracker::add_completion)
(completion_tracker::add_completions): New.
(throw_max_completions_reached_error): Delete.
(complete_line): Adjust to work with a completion_tracker instead
of a VEC. Don't create a completion_tracker_t or check for max
completions here.
(command_completer, command_completer_handle_brkchars)
(signal_completer, reg_or_group_completer_1)
(reg_or_group_completer, default_completer_handle_brkchars):
Adjust to work with a completion_tracker.
(gdb_completion_word_break_characters_throw): New.
(gdb_completion_word_break_characters): Reimplement.
(line_completion_function): Delete.
(completion_tracker::recompute_lowest_common_denominator)
(expand_preserving_ws)
(completion_tracker::build_completion_result)
(completion_result::completion_result)
(completion_result::completion_result)
(completion_result::~completion_result)
(completion_result::completion_result)
(completion_result::release_match_list, compare_cstrings)
(completion_result::sort_match_list)
(completion_result::reset_match_list)
(gdb_rl_attempted_completion_function_throw)
(gdb_rl_attempted_completion_function): New.
* completer.h (completion_list, struct completion_result)
(class completion_tracker): New.
(complete_line): Add completion_tracker parameter.
(readline_line_completion_function): Delete.
(gdb_rl_attempted_completion_function): New.
(noop_completer, filename_completer, expression_completer)
(location_completer, symbol_completer, command_completer)
(signal_completer, reg_or_group_completer): Update prototypes.
(completion_tracker_t, new_completion_tracker)
(make_cleanup_free_completion_tracker): Delete.
(enum maybe_add_completion_enum): Delete.
(maybe_add_completion): Delete.
(throw_max_completions_reached_error): Delete.
* corefile.c (complete_set_gnutarget): Adjust to work with a
completion_tracker instead of a VEC.
* cp-abi.c (cp_abi_completer): Adjust to work with a
completion_tracker instead of a VEC.
* d-lang.c (d_language_defn): Adjust.
* disasm.c (disassembler_options_completer): Adjust to work with a
completion_tracker instead of a VEC.
* f-lang.c (f_make_symbol_completion_list): Rename to ...
(f_collect_symbol_completion_matches): ... this. Adjust to work
with a completion_tracker instead of a VEC.
(f_language_defn): Adjust.
* go-lang.c (go_language_defn): Adjust.
* guile/scm-cmd.c (cmdscm_add_completion, cmdscm_completer):
Adjust to work with a completion_tracker instead of a VEC.
* infrun.c (handle_completer): Likewise.
* interps.c (interpreter_completer): Likewise.
* interps.h (interpreter_completer): Likewise.
* language.c (unknown_language_defn, auto_language_defn)
(local_language_defn): Adjust.
* language.h (language_defn::la_make_symbol_completion_list):
Rename to ...
(language_defn::la_collect_symbol_completion_matches): ... this
and adjust to work with a completion_tracker instead of a VEC.
* m2-lang.c (m2_language_defn): Adjust.
* objc-lang.c (objc_language_defn): Adjust.
* opencl-lang.c (opencl_language_defn): Adjust.
* p-lang.c (pascal_language_defn): Adjust.
* python/py-cmd.c (cmdpy_completer_helper): Handle NULL word.
(cmdpy_completer_handle_brkchars, cmdpy_completer): Adjust to work
with a completion_tracker.
* rust-lang.c (rust_language_defn): Adjust.
* symtab.c (free_completion_list, do_free_completion_list)
(return_val, completion_tracker): Delete.
(completion_list_add_name, completion_list_add_symbol)
(completion_list_add_msymbol, completion_list_objc_symbol)
(completion_list_add_fields, add_symtab_completions): Add
completion_tracker parameter and use it.
(default_make_symbol_completion_list_break_on_1): Rename to...
(default_collect_symbol_completion_matches_break_on): ... this.
Add completion_tracker parameter and use it instead of allocating
a completion tracker here.
(default_make_symbol_completion_list_break_on): Delete old
implementation.
(default_make_symbol_completion_list): Delete.
(default_collect_symbol_completion_matches): New.
(make_symbol_completion_list): Delete.
(collect_symbol_completion_matches): New.
(make_symbol_completion_type): Rename to ...
(collect_symbol_completion_matches_type): ... this. Add
completion_tracker parameter and use it instead of VEC.
(make_file_symbol_completion_list_1): Rename to...
(collect_file_symbol_completion_matches): ... this. Add
completion_tracker parameter and use it instead of VEC.
(make_file_symbol_completion_list): Delete.
(add_filename_to_list): Use completion_list instead of a VEC.
(add_partial_filename_data::list): Now a completion_list.
(make_source_files_completion_list): Work with a completion_list
instead of a VEC.
* symtab.h: Include "completer.h".
(default_make_symbol_completion_list_break_on)
(default_make_symbol_completion_list, make_symbol_completion_list)
(make_symbol_completion_type, make_file_symbol_completion_list)
(make_source_files_completion_list): Delete.
(default_collect_symbol_completion_matches_break_on)
(default_collect_symbol_completion_matches)
(collect_symbol_completion_matches)
(collect_symbol_completion_matches_type)
(collect_file_symbol_completion_matches)
(make_source_files_completion_list): New.
* top.c (init_main): Don't install a rl_completion_entry_function
hook. Install a rl_attempted_completion_function hook instead.
* tui/tui-layout.c (layout_completer): Adjust to work with a
completion_tracker.
* tui/tui-regs.c (tui_reggroup_completer):
* tui/tui-win.c (window_name_completer, focus_completer)
(winheight_completer): Adjust to work with a completion_tracker.
* value.c: Include "completer.h".
(complete_internalvar): Adjust to work with a completion_tracker.
* value.h (complete_internalvar): Likewise.
2017-07-17 14:45:59 +01:00
|
|
|
|
completion_tracker &tracker,
|
Constify strings in tracepoint.c, lookup_cmd and the completers.
This is sort of a continuation of Keith's parse_exp_1 constification
patch. It started out by undoing these bits:
@@ -754,9 +754,12 @@ validate_actionline (char **line, struct
tmp_p = p;
for (loc = t->base.loc; loc; loc = loc->next)
{
- p = tmp_p;
- exp = parse_exp_1 (&p, loc->address,
+ const char *q;
+
+ q = tmp_p;
+ exp = parse_exp_1 (&q, loc->address,
block_for_pc (loc->address), 1);
+ p = (char *) q;
and progressively making more things const upwards, fixing fallout,
rinse repeat, until GDB built again (--enable-targets=all).
That ended up constifying lookup_cmd/add_cmd and (lots of) friends,
and the completers.
I didn't try to constify the command hooks themselves, because I know
upfront there are commands that write to the command string argument,
and I think I managed to stop at a nice non-hacky split point already.
I think the only non-really-super-obvious changes are
tracepoint.c:validate_actionline, and tracepoint.c:trace_dump_actions.
The rest is just mostly about 'char *' => 'const char *', 'char **'=>
'const char **', and the occasional (e.g., deprecated_cmd_warning)
case of 'char **'=> 'const char *', where/when I noticed that nothing
actually cares about the pointer to pointer output.
Tested on x86_64 Fedora 17, native and gdbserver.
gdb/
2013-03-13 Pedro Alves <palves@redhat.com>
* ada-lang.c (struct add_partial_datum) <text, text0, word>: Make
fields const.
(ada_make_symbol_completion_list): Make "text0" parameter const.
* ax-gdb.c (agent_eval_command_one): Make "exp" parameter const.
* breakpoint.c (condition_completer): Make "text" and "word"
parameters const. Adjust.
(check_tracepoint_command): Adjust to validate_actionline
prototype change.
(catch_syscall_completer): Make "text" and "word" parameters
const.
* cli/cli-cmds.c (show_user): Make "comname" local const.
(valid_command_p): Make "command" parameter const.
(alias_command): Make "alias_prefix" and "command_prefix" locals
const.
* cli/cli-decode.c (add_cmd): Make "name" parameter const.
(add_alias_cmd): Make "name" and "oldname" parameters const.
Adjust. No longer make copy of OLDNAME.
(add_prefix_cmd, add_abbrev_prefix_cmd, add_set_or_show_cmd)
(add_setshow_cmd_full, add_setshow_enum_cmd)
(add_setshow_auto_boolean_cmd, add_setshow_boolean_cmd)
(add_setshow_filename_cmd, add_setshow_string_cmd)
(add_setshow_string_noescape_cmd)
(add_setshow_optional_filename_cmd, add_setshow_integer_cmd)
(add_setshow_uinteger_cmd, add_setshow_zinteger_cmd)
(add_setshow_zuinteger_unlimited_cmd, add_setshow_zuinteger_cmd)
(delete_cmd, add_info, add_info_alias, add_com, add_com_alias):
Make "name" parameter const.
(help_cmd): Rename "command" parameter to "arg". New const local
"command".
(find_cmd): Make "command" parameter const.
(lookup_cmd_1): Make "text" parameter pointer to const. Adjust to
deprecated_cmd_warning prototype change.
(undef_cmd_error): Make "cmdtype" parameter const.
(lookup_cmd): Make "line" parameter const.
(deprecated_cmd_warning): Change type of "text" parameter to
pointer to const char, from pointer to pointer to char. Adjust.
(lookup_cmd_composition): Make "text" parameter const.
(complete_on_cmdlist, complete_on_enum): Make "text" and "word"
parameters const.
* cli/cli-decode.h (struct cmd_list_element) <name>: Make field
const.
* cli/cli-script.c (validate_comname): Make "tem" local const.
(define_command): New const local "tem_c". Use it in calls to
lookup_cmd.
(document_command): Make "tem" and "comfull" locals const.
(show_user_1): Make "prefix" and "name" parameters const.
* cli-script.h (show_user_1): Make "prefix" and "name" parameters
const.
* command.h (add_cmd, add_alias_cmd, add_prefix_cmd)
(add_abbrev_prefix_cmd, completer_ftype, lookup_cmd, lookup_cmd_1)
(deprecated_cmd_warning, lookup_cmd_composition, add_com)
(add_com_alias, add_info, add_info_alias, complete_on_cmdlist)
(complete_on_enum, add_setshow_enum_cmd)
(add_setshow_auto_boolean_cmd, add_setshow_boolean_cmd)
(add_setshow_filename_cmd, add_setshow_string_cmd)
(add_setshow_string_noescape_cmd)
(add_setshow_optional_filename_cmd, add_setshow_integer_cmd)
(add_setshow_uinteger_cmd, add_setshow_zinteger_cmd)
(add_setshow_zuinteger_cmd, add_setshow_zuinteger_unlimited_cmd):
Change prototypes, constifying strings.
* completer.c (noop_completer, filename_completer): Make "text"
and "prefix" parameters const.
(location_completer, expression_completer)
(complete_line_internal): Make "text" and "prefix" parameters
const and adjust.
(command_completer, signal_completer): Make "text" and "prefix"
parameters const.
* completer.h (noop_completer, filename_completer)
(expression_completer, location_completer, command_completer)
(signal_completer): Change prototypes.
* corefile.c (complete_set_gnutarget): Make "text" and "word"
parameters const.
* cp-abi.c (cp_abi_completer): Likewise.
* expression.h (parse_expression_for_completion): Change
prototype.
* f-lang.c (f_make_symbol_completion_list): Make "text" and "word"
parameters const.
* infcmd.c (_initialize_infcmd): Make "cmd_name" local const.
* infrun.c (handle_completer): Make "text" and "word" parameters
const.
* interps.c (interpreter_completer): Make "text" and "word"
parameters const.
* language.h (struct language_defn)
<la_make_symbol_completion_list>: Make "text" and "word"
parameters const.
* parse.c (parse_exp_1): Move const hack to parse_exp_in_context.
(parse_exp_in_context): Rename to ...
(parse_exp_in_context_1): ... this.
(parse_exp_in_context): Reimplement, with const hack from
parse_exp_1.
(parse_expression_for_completion): Make "string" parameter const.
* printcmd.c (decode_format): Make "string_ptr" parameter pointer
to pointer to const char. Adjust.
(print_command_1): Make "exp" parameter const.
(output_command): Rename to ...
(output_command_const): ... this. Make "exp" parameter const.
(output_command): Reimplement.
(x_command): Adjust.
(display_command): Rename "exp" parameter to "arg". New "exp"
local, const version of "arg".
* python/py-auto-load.c (gdbpy_initialize_auto_load): Make
"cmd_name" local const.
* python/py-cmd.c (cmdpy_destroyer): Cast const away in xfree
call.
(cmdpy_completer): Make "text" and "word" parameters const.
(gdbpy_parse_command_name): Make "prefix_text2" local const.
* python/py-param.c (add_setshow_generic): Make "tmp_name" local
const.
* remote.c (_initialize_remote): Make "cmd_name" local const.
* symtab.c (language_search_unquoted_string): Make "text" and "p"
parameters const. Adjust.
(completion_list_add_fields): Make "sym_text", "text" and "word"
parameters const.
(struct add_name_data) <sym_text, text, word>: Make fields const.
(default_make_symbol_completion_list_break_on): Make "text" and
"word" parameters const. Adjust locals.
(default_make_symbol_completion_list)
(make_symbol_completion_list, make_symbol_completion_type)
(make_symbol_completion_list_fn): Make "text" and "word"
parameters const.
(make_file_symbol_completion_list): Make "text", "word" and
"srcfile" parameters const. Adjust locals.
(add_filename_to_list): Make "text" and "word" parameters const.
(struct add_partial_filename_data) <text, word>: Make fields
const.
(make_source_files_completion_list): Make "text" and "word"
parameters const.
* symtab.h (default_make_symbol_completion_list_break_on)
(default_make_symbol_completion_list, make_symbol_completion_list)
(make_symbol_completion_type enum type_code)
(make_symbol_completion_list_fn make_file_symbol_completion_list)
(make_source_files_completion_list): Change prototype.
* top.c (execute_command): Adjust to pass pointer to pointer to
const char to lookup_cmd, and to deprecated_cmd_warning prototype
change.
(set_verbose): Make "cmdname" local const.
* tracepoint.c (decode_agent_options): Make "exp" parameter const,
and adjust.
(validate_actionline): Make "line" parameter a pointer to const
char, and adjust.
(encode_actions_1): Make "action_exp" local const, and adjust.
(encode_actions): Adjust.
(replace_comma): Delete.
(trace_dump_actions): Make "action_exp" and "next_comma" locals
const, and adjust. Don't frob the action string while splitting
it at commas. Instead, make a copy of each split substring in
turn.
(trace_dump_command): Adjust to validate_actionline prototype
change.
* tracepoint.h (decode_agent_options, decode_agent_options)
(encode_actions, validate_actionline): Change prototypes.
* valprint.h (output_command): Delete declaration.
(output_command_const): Declare.
* value.c (function_destroyer): Cast const away in xfree call.
2013-03-13 18:34:55 +00:00
|
|
|
|
const char *text, const char *word)
|
2009-02-06 21:33:59 +00:00
|
|
|
|
{
|
Change how Python architecture and language are handled
Currently, gdb's Python layer captures the current architecture and
language when "entering" Python code. This has some undesirable
effects, and so this series changes how this is handled.
First, there is code like this:
gdbpy_enter enter_py (python_gdbarch, python_language);
This is incorrect, because both of these are NULL when not otherwise
assigned. This can cause crashes in some cases -- I've added one to
the test suite. (Note that this crasher is just an example, other
ones along the same lines are possible.)
Second, when the language is captured in this way, it means that
Python code cannot affect the current language for its own purposes.
It's reasonable to want to write code like this:
gdb.execute('set language mumble')
... stuff using the current language
gdb.execute('set language previous-value')
However, this won't actually work, because the language is captured on
entry. I've added a test to show this as well.
This patch changes gdb to try to avoid capturing the current values.
The Python concept of the current gdbarch is only set in those few
cases where a non-default value is computed or needed; and the
language is not captured at all -- instead, in the cases where it's
required, the current language is temporarily changed.
2022-01-04 08:02:24 -07:00
|
|
|
|
gdbpy_enter enter_py;
|
2009-02-06 21:33:59 +00:00
|
|
|
|
|
2018-09-10 11:48:28 +01:00
|
|
|
|
/* Calling our helper to obtain a reference to the PyObject of the Python
|
PR python/16699: GDB Python command completion with overriden complete vs. completer class
This PR came from a Red Hat bug that was filed recently. I checked and
it still exists on HEAD, so here's a proposed fix. Although this is
marked as a Python backend bug, this is really about the completion
mechanism used by GDB. Since this code reminds me of my first attempt
to make a good noodle, it took me quite some time to fix it in a
non-intrusive way.
The problem is triggered when one registers a completion method inside a
class in a Python script, rather than registering the command using a
completer class directly. For example, consider the following script:
class MyFirstCommand(gdb.Command):
def __init__(self):
gdb.Command.__init__(self,'myfirstcommand',gdb.COMMAND_USER,gdb.COMPLETE_FILENAME)
def invoke(self,argument,from_tty):
raise gdb.GdbError('not implemented')
class MySecondCommand(gdb.Command):
def __init__(self):
gdb.Command.__init__(self,'mysecondcommand',gdb.COMMAND_USER)
def invoke(self,argument,from_tty):
raise gdb.GdbError('not implemented')
def complete(self,text,word):
return gdb.COMPLETE_FILENAME
MyFirstCommand ()
MySecondCommand ()
When one loads this into GDB and tries to complete filenames for both
myfirstcommand and mysecondcommand, she gets:
(gdb) myfirstcommand /hom<TAB>
(gdb) myfirstcommand /home/
^
...
(gdb) mysecondcommand /hom<TAB>
(gdb) mysecondcommand /home
^
(The "^" marks the final position of the cursor after the TAB).
So we see that myfirstcommand honors the COMPLETE_FILENAME class (as
specified in the command creation), but mysecondcommand does not. After
some investigation, I found that the problem lies with the set of word
break characters that is used for each case. The set should be the same
for both commands, but it is not.
During the process of deciding which type of completion should be used,
the code in gdb/completer.c:complete_line_internal analyses the command
that requested the completion and tries to determine the type of
completion wanted by checking which completion function will be called
(e.g., filename_completer for filenames, location_completer for
locations, etc.).
This all works fine for myfirstcommand, because immediately after the
command registration the Python backend already sets its completion
function to filename_completer (which then causes the
complete_line_internal function to choose the right set of word break
chars). However, for mysecondcommand, this decision is postponed to
when the completer function is evaluated, and the Python backend uses an
internal completer (called cmdpy_completer). complete_line_internal
doesn't know about this internal completer, and can't choose the right
set of word break chars in time, which then leads to a bad decision when
completing the "/hom" word.
So, after a few attempts, I decided to create another callback in
"struct cmd_list_element" that will be responsible for handling the case
when there is an unknown completer function for complete_line_internal
to work with. So far, only the Python backend uses this callback, and
only when the user provides a completer method instead of registering
the command directly with a completer class. I think this is the best
option because it not very intrusive (all the other commands will still
work normally), but especially because the whole completion code is so
messy that it would be hard to fix this without having to redesign
things.
I have regtested this on Fedora 18 x86_64, without regressions. I also
included a testcase.
gdb/ChangeLog:
2014-09-03 Sergio Durigan Junior <sergiodj@redhat.com>
PR python/16699
* cli/cli-decode.c (set_cmd_completer_handle_brkchars): New
function.
(add_cmd): Set "completer_handle_brkchars" to NULL.
* cli/cli-decode.h (struct cmd_list_element)
<completer_handle_brkchars>: New field.
* command.h (completer_ftype_void): New typedef.
(set_cmd_completer_handle_brkchars): New prototype.
* completer.c (set_gdb_completion_word_break_characters): New
function.
(complete_line_internal): Call "completer_handle_brkchars"
callback from command.
* completer.h: Include "command.h".
(set_gdb_completion_word_break_characters): New prototype.
* python/py-cmd.c (cmdpy_completer_helper): New function.
(cmdpy_completer_handle_brkchars): New function.
(cmdpy_completer): Adjust to use cmdpy_completer_helper.
(cmdpy_init): Set completer_handle_brkchars to
cmdpy_completer_handle_brkchars.
gdb/testsuite/ChangeLog:
2014-09-03 Sergio Durigan Junior <sergiodj@redhat.com>
PR python/16699
* gdb.python/py-completion.exp: New file.
* gdb.python/py-completion.py: Likewise.
2014-09-03 16:30:28 -04:00
|
|
|
|
function. */
|
2018-09-10 11:48:28 +01:00
|
|
|
|
gdbpy_ref<> resultobj = cmdpy_completer_helper (command, text, word);
|
2009-02-06 21:33:59 +00:00
|
|
|
|
|
PR python/16699: GDB Python command completion with overriden complete vs. completer class
This PR came from a Red Hat bug that was filed recently. I checked and
it still exists on HEAD, so here's a proposed fix. Although this is
marked as a Python backend bug, this is really about the completion
mechanism used by GDB. Since this code reminds me of my first attempt
to make a good noodle, it took me quite some time to fix it in a
non-intrusive way.
The problem is triggered when one registers a completion method inside a
class in a Python script, rather than registering the command using a
completer class directly. For example, consider the following script:
class MyFirstCommand(gdb.Command):
def __init__(self):
gdb.Command.__init__(self,'myfirstcommand',gdb.COMMAND_USER,gdb.COMPLETE_FILENAME)
def invoke(self,argument,from_tty):
raise gdb.GdbError('not implemented')
class MySecondCommand(gdb.Command):
def __init__(self):
gdb.Command.__init__(self,'mysecondcommand',gdb.COMMAND_USER)
def invoke(self,argument,from_tty):
raise gdb.GdbError('not implemented')
def complete(self,text,word):
return gdb.COMPLETE_FILENAME
MyFirstCommand ()
MySecondCommand ()
When one loads this into GDB and tries to complete filenames for both
myfirstcommand and mysecondcommand, she gets:
(gdb) myfirstcommand /hom<TAB>
(gdb) myfirstcommand /home/
^
...
(gdb) mysecondcommand /hom<TAB>
(gdb) mysecondcommand /home
^
(The "^" marks the final position of the cursor after the TAB).
So we see that myfirstcommand honors the COMPLETE_FILENAME class (as
specified in the command creation), but mysecondcommand does not. After
some investigation, I found that the problem lies with the set of word
break characters that is used for each case. The set should be the same
for both commands, but it is not.
During the process of deciding which type of completion should be used,
the code in gdb/completer.c:complete_line_internal analyses the command
that requested the completion and tries to determine the type of
completion wanted by checking which completion function will be called
(e.g., filename_completer for filenames, location_completer for
locations, etc.).
This all works fine for myfirstcommand, because immediately after the
command registration the Python backend already sets its completion
function to filename_completer (which then causes the
complete_line_internal function to choose the right set of word break
chars). However, for mysecondcommand, this decision is postponed to
when the completer function is evaluated, and the Python backend uses an
internal completer (called cmdpy_completer). complete_line_internal
doesn't know about this internal completer, and can't choose the right
set of word break chars in time, which then leads to a bad decision when
completing the "/hom" word.
So, after a few attempts, I decided to create another callback in
"struct cmd_list_element" that will be responsible for handling the case
when there is an unknown completer function for complete_line_internal
to work with. So far, only the Python backend uses this callback, and
only when the user provides a completer method instead of registering
the command directly with a completer class. I think this is the best
option because it not very intrusive (all the other commands will still
work normally), but especially because the whole completion code is so
messy that it would be hard to fix this without having to redesign
things.
I have regtested this on Fedora 18 x86_64, without regressions. I also
included a testcase.
gdb/ChangeLog:
2014-09-03 Sergio Durigan Junior <sergiodj@redhat.com>
PR python/16699
* cli/cli-decode.c (set_cmd_completer_handle_brkchars): New
function.
(add_cmd): Set "completer_handle_brkchars" to NULL.
* cli/cli-decode.h (struct cmd_list_element)
<completer_handle_brkchars>: New field.
* command.h (completer_ftype_void): New typedef.
(set_cmd_completer_handle_brkchars): New prototype.
* completer.c (set_gdb_completion_word_break_characters): New
function.
(complete_line_internal): Call "completer_handle_brkchars"
callback from command.
* completer.h: Include "command.h".
(set_gdb_completion_word_break_characters): New prototype.
* python/py-cmd.c (cmdpy_completer_helper): New function.
(cmdpy_completer_handle_brkchars): New function.
(cmdpy_completer): Adjust to use cmdpy_completer_helper.
(cmdpy_init): Set completer_handle_brkchars to
cmdpy_completer_handle_brkchars.
gdb/testsuite/ChangeLog:
2014-09-03 Sergio Durigan Junior <sergiodj@redhat.com>
PR python/16699
* gdb.python/py-completion.exp: New file.
* gdb.python/py-completion.py: Likewise.
2014-09-03 16:30:28 -04:00
|
|
|
|
/* If the result object of calling the Python function is NULL, it
|
Introduce class completion_tracker & rewrite completion<->readline interaction
This patch reworks the whole completion machinery, and prepares it
for later enhancements.
Adds a new "completion_tracker" class that is meant to hold everything
about the state of the current completion operation.
This class now has the responsibility of tracking the list of
completion matches, and checking whether the max completions limit has
been reached. You can look at this as this patch starting out by
C++fying the existing "completion_tracker" in symtab.c (it's just an
htab_t typedef currently), moving it to completer.h/c, and then making
it a class/generalizing/enhancing it.
Unlike with the current tracking, completion_tracker now checks
whether the limit has been reached on each completion match list
insertion. This both simplifies the max-completions handling code
(maybe_add_completion_enum is gone, for example), and is a
prerequisite for follow up patches.
The current completion_tracker is only used for symbol completions,
and the symbol code gets at the current instance via globals. This
patch cleans that up by adding a completion_tracker reference to the
signature of the completion functions, and passing the tracker around
everywhere necessary.
Then, the patch changes how the completion match list is handed over
to readline. Currently, we're using the rl_completion_entry_function
readline entry point, and the patch switches to
rl_attempted_completion_function. A following patch will want to let
GDB itself decide the common completion prefix between all matches
(what readline calls the "lowest common denominator"), instead of
having readline compute it, and that's not possible with the
rl_completion_entry_function entry point. Also,
rl_attempted_completion_function lets GDB hand over the match list to
readline as an array in one go instead of passing down matches one by
one, so from that angle it's a nicer entry point anyway.
Lastly, the patch catches exceptions around the readline entry points,
because we can't let C++ exceptions cross readline. We handle that in
the readline input entry point, but the completion entry point isn't
guarded, so GDB can abort if completion throws. E.g., in current
master:
(gdb) b -function "fun<tab>
terminate called after throwing an instance of 'gdb_exception_RETURN_MASK_ERROR'
Aborted (core dumped)
This patch fixes that. This will be exercised in the new tests added
later on in the series.
gdb/ChangeLog:
2017-07-17 Pedro Alves <palves@redhat.com>
* ada-lang.c (symbol_completion_match): Adjust comments.
(symbol_completion_add): Replace vector parameter with
completion_tracker parameter. Use it.
(ada_make_symbol_completion_list): Rename to...
(ada_collect_symbol_completion_matches): ... this. Add
completion_tracker parameter and use it.
(ada_language_defn): Adjust.
* break-catch-syscall.c (catch_syscall_completer): Adjust
prototype and work with completion_tracker instead of VEC.
* breakpoint.c (condition_completer): Adjust prototype and work
with completion_tracker instead of VEC.
* c-lang.c (c_language_defn, cplus_language_defn)
(asm_language_defn, minimal_language_defn): Adjust to renames.
* cli/cli-cmds.c (complete_command): Rework using
completion_tracker. Catch exceptions when completing.
* cli/cli-decode.c (integer_unlimited_completer)
(complete_on_cmdlist, complete_on_enum): Adjust prototype and work
with completion_tracker instead of VEC.
* command.h (struct completion_tracker): Forward declare.
(completer_ftype, completer_handle_brkchars_ftype): Change
types.
(complete_on_cmdlist, complete_on_enum): Adjust.
* completer.c: Include <algorithm>.
(struct gdb_completer_state): New.
(current_completion): New global.
(readline_line_completion_function): Delete.
(noop_completer, filename_completer)
(filename_completer_handle_brkchars, complete_files_symbols)
(linespec_location_completer): Adjust to work with a
completion_tracker instead of a VEC.
(string_or_empty): New.
(collect_explicit_location_matches): Adjust to work with a
completion_tracker instead of a VEC.
(explicit_location_completer): Rename to ...
(complete_explicit_location): ... this and adjust to work with a
completion_tracker instead of a VEC.
(location_completer): Adjust to work with a completion_tracker
instead of a VEC.
(add_struct_fields): Adjust to work with a completion_list instead
of VEC.
(expression_completer): Rename to ...
(complete_expression): ... this and adjust to work with a
completion_tracker instead of a VEC. Use complete_files_symbols.
(expression_completer): Reimplement on top of complete_expression.
(symbol_completer): Adjust to work with a completion_tracker
instead of a VEC.
(enum complete_line_internal_reason): Add describing comments.
(complete_line_internal_normal_command): Adjust to work with a
completion_tracker instead of a VEC.
(complete_line_internal): Rename to ...
(complete_line_internal_1): ... this and adjust to work with a
completion_tracker instead of a VEC. Assert TEXT is NULL in the
handle_brkchars phase.
(new_completion_tracker): Delete.
(complete_line_internal): Reimplement as TRY/CATCH wrapper around
complete_line_internal_1.
(free_completion_tracker): Delete.
(INITIAL_COMPLETION_HTAB_SIZE): New.
(completion_tracker::completion_tracker)
(completion_tracker::~completion_tracker): New.
(maybe_add_completion): Delete.
(completion_tracker::maybe_add_completion)
(completion_tracker::add_completion)
(completion_tracker::add_completions): New.
(throw_max_completions_reached_error): Delete.
(complete_line): Adjust to work with a completion_tracker instead
of a VEC. Don't create a completion_tracker_t or check for max
completions here.
(command_completer, command_completer_handle_brkchars)
(signal_completer, reg_or_group_completer_1)
(reg_or_group_completer, default_completer_handle_brkchars):
Adjust to work with a completion_tracker.
(gdb_completion_word_break_characters_throw): New.
(gdb_completion_word_break_characters): Reimplement.
(line_completion_function): Delete.
(completion_tracker::recompute_lowest_common_denominator)
(expand_preserving_ws)
(completion_tracker::build_completion_result)
(completion_result::completion_result)
(completion_result::completion_result)
(completion_result::~completion_result)
(completion_result::completion_result)
(completion_result::release_match_list, compare_cstrings)
(completion_result::sort_match_list)
(completion_result::reset_match_list)
(gdb_rl_attempted_completion_function_throw)
(gdb_rl_attempted_completion_function): New.
* completer.h (completion_list, struct completion_result)
(class completion_tracker): New.
(complete_line): Add completion_tracker parameter.
(readline_line_completion_function): Delete.
(gdb_rl_attempted_completion_function): New.
(noop_completer, filename_completer, expression_completer)
(location_completer, symbol_completer, command_completer)
(signal_completer, reg_or_group_completer): Update prototypes.
(completion_tracker_t, new_completion_tracker)
(make_cleanup_free_completion_tracker): Delete.
(enum maybe_add_completion_enum): Delete.
(maybe_add_completion): Delete.
(throw_max_completions_reached_error): Delete.
* corefile.c (complete_set_gnutarget): Adjust to work with a
completion_tracker instead of a VEC.
* cp-abi.c (cp_abi_completer): Adjust to work with a
completion_tracker instead of a VEC.
* d-lang.c (d_language_defn): Adjust.
* disasm.c (disassembler_options_completer): Adjust to work with a
completion_tracker instead of a VEC.
* f-lang.c (f_make_symbol_completion_list): Rename to ...
(f_collect_symbol_completion_matches): ... this. Adjust to work
with a completion_tracker instead of a VEC.
(f_language_defn): Adjust.
* go-lang.c (go_language_defn): Adjust.
* guile/scm-cmd.c (cmdscm_add_completion, cmdscm_completer):
Adjust to work with a completion_tracker instead of a VEC.
* infrun.c (handle_completer): Likewise.
* interps.c (interpreter_completer): Likewise.
* interps.h (interpreter_completer): Likewise.
* language.c (unknown_language_defn, auto_language_defn)
(local_language_defn): Adjust.
* language.h (language_defn::la_make_symbol_completion_list):
Rename to ...
(language_defn::la_collect_symbol_completion_matches): ... this
and adjust to work with a completion_tracker instead of a VEC.
* m2-lang.c (m2_language_defn): Adjust.
* objc-lang.c (objc_language_defn): Adjust.
* opencl-lang.c (opencl_language_defn): Adjust.
* p-lang.c (pascal_language_defn): Adjust.
* python/py-cmd.c (cmdpy_completer_helper): Handle NULL word.
(cmdpy_completer_handle_brkchars, cmdpy_completer): Adjust to work
with a completion_tracker.
* rust-lang.c (rust_language_defn): Adjust.
* symtab.c (free_completion_list, do_free_completion_list)
(return_val, completion_tracker): Delete.
(completion_list_add_name, completion_list_add_symbol)
(completion_list_add_msymbol, completion_list_objc_symbol)
(completion_list_add_fields, add_symtab_completions): Add
completion_tracker parameter and use it.
(default_make_symbol_completion_list_break_on_1): Rename to...
(default_collect_symbol_completion_matches_break_on): ... this.
Add completion_tracker parameter and use it instead of allocating
a completion tracker here.
(default_make_symbol_completion_list_break_on): Delete old
implementation.
(default_make_symbol_completion_list): Delete.
(default_collect_symbol_completion_matches): New.
(make_symbol_completion_list): Delete.
(collect_symbol_completion_matches): New.
(make_symbol_completion_type): Rename to ...
(collect_symbol_completion_matches_type): ... this. Add
completion_tracker parameter and use it instead of VEC.
(make_file_symbol_completion_list_1): Rename to...
(collect_file_symbol_completion_matches): ... this. Add
completion_tracker parameter and use it instead of VEC.
(make_file_symbol_completion_list): Delete.
(add_filename_to_list): Use completion_list instead of a VEC.
(add_partial_filename_data::list): Now a completion_list.
(make_source_files_completion_list): Work with a completion_list
instead of a VEC.
* symtab.h: Include "completer.h".
(default_make_symbol_completion_list_break_on)
(default_make_symbol_completion_list, make_symbol_completion_list)
(make_symbol_completion_type, make_file_symbol_completion_list)
(make_source_files_completion_list): Delete.
(default_collect_symbol_completion_matches_break_on)
(default_collect_symbol_completion_matches)
(collect_symbol_completion_matches)
(collect_symbol_completion_matches_type)
(collect_file_symbol_completion_matches)
(make_source_files_completion_list): New.
* top.c (init_main): Don't install a rl_completion_entry_function
hook. Install a rl_attempted_completion_function hook instead.
* tui/tui-layout.c (layout_completer): Adjust to work with a
completion_tracker.
* tui/tui-regs.c (tui_reggroup_completer):
* tui/tui-win.c (window_name_completer, focus_completer)
(winheight_completer): Adjust to work with a completion_tracker.
* value.c: Include "completer.h".
(complete_internalvar): Adjust to work with a completion_tracker.
* value.h (complete_internalvar): Likewise.
2017-07-17 14:45:59 +01:00
|
|
|
|
means that there was an error. In this case, just give up. */
|
PR python/16699: GDB Python command completion with overriden complete vs. completer class
This PR came from a Red Hat bug that was filed recently. I checked and
it still exists on HEAD, so here's a proposed fix. Although this is
marked as a Python backend bug, this is really about the completion
mechanism used by GDB. Since this code reminds me of my first attempt
to make a good noodle, it took me quite some time to fix it in a
non-intrusive way.
The problem is triggered when one registers a completion method inside a
class in a Python script, rather than registering the command using a
completer class directly. For example, consider the following script:
class MyFirstCommand(gdb.Command):
def __init__(self):
gdb.Command.__init__(self,'myfirstcommand',gdb.COMMAND_USER,gdb.COMPLETE_FILENAME)
def invoke(self,argument,from_tty):
raise gdb.GdbError('not implemented')
class MySecondCommand(gdb.Command):
def __init__(self):
gdb.Command.__init__(self,'mysecondcommand',gdb.COMMAND_USER)
def invoke(self,argument,from_tty):
raise gdb.GdbError('not implemented')
def complete(self,text,word):
return gdb.COMPLETE_FILENAME
MyFirstCommand ()
MySecondCommand ()
When one loads this into GDB and tries to complete filenames for both
myfirstcommand and mysecondcommand, she gets:
(gdb) myfirstcommand /hom<TAB>
(gdb) myfirstcommand /home/
^
...
(gdb) mysecondcommand /hom<TAB>
(gdb) mysecondcommand /home
^
(The "^" marks the final position of the cursor after the TAB).
So we see that myfirstcommand honors the COMPLETE_FILENAME class (as
specified in the command creation), but mysecondcommand does not. After
some investigation, I found that the problem lies with the set of word
break characters that is used for each case. The set should be the same
for both commands, but it is not.
During the process of deciding which type of completion should be used,
the code in gdb/completer.c:complete_line_internal analyses the command
that requested the completion and tries to determine the type of
completion wanted by checking which completion function will be called
(e.g., filename_completer for filenames, location_completer for
locations, etc.).
This all works fine for myfirstcommand, because immediately after the
command registration the Python backend already sets its completion
function to filename_completer (which then causes the
complete_line_internal function to choose the right set of word break
chars). However, for mysecondcommand, this decision is postponed to
when the completer function is evaluated, and the Python backend uses an
internal completer (called cmdpy_completer). complete_line_internal
doesn't know about this internal completer, and can't choose the right
set of word break chars in time, which then leads to a bad decision when
completing the "/hom" word.
So, after a few attempts, I decided to create another callback in
"struct cmd_list_element" that will be responsible for handling the case
when there is an unknown completer function for complete_line_internal
to work with. So far, only the Python backend uses this callback, and
only when the user provides a completer method instead of registering
the command directly with a completer class. I think this is the best
option because it not very intrusive (all the other commands will still
work normally), but especially because the whole completion code is so
messy that it would be hard to fix this without having to redesign
things.
I have regtested this on Fedora 18 x86_64, without regressions. I also
included a testcase.
gdb/ChangeLog:
2014-09-03 Sergio Durigan Junior <sergiodj@redhat.com>
PR python/16699
* cli/cli-decode.c (set_cmd_completer_handle_brkchars): New
function.
(add_cmd): Set "completer_handle_brkchars" to NULL.
* cli/cli-decode.h (struct cmd_list_element)
<completer_handle_brkchars>: New field.
* command.h (completer_ftype_void): New typedef.
(set_cmd_completer_handle_brkchars): New prototype.
* completer.c (set_gdb_completion_word_break_characters): New
function.
(complete_line_internal): Call "completer_handle_brkchars"
callback from command.
* completer.h: Include "command.h".
(set_gdb_completion_word_break_characters): New prototype.
* python/py-cmd.c (cmdpy_completer_helper): New function.
(cmdpy_completer_handle_brkchars): New function.
(cmdpy_completer): Adjust to use cmdpy_completer_helper.
(cmdpy_init): Set completer_handle_brkchars to
cmdpy_completer_handle_brkchars.
gdb/testsuite/ChangeLog:
2014-09-03 Sergio Durigan Junior <sergiodj@redhat.com>
PR python/16699
* gdb.python/py-completion.exp: New file.
* gdb.python/py-completion.py: Likewise.
2014-09-03 16:30:28 -04:00
|
|
|
|
if (resultobj == NULL)
|
Introduce class completion_tracker & rewrite completion<->readline interaction
This patch reworks the whole completion machinery, and prepares it
for later enhancements.
Adds a new "completion_tracker" class that is meant to hold everything
about the state of the current completion operation.
This class now has the responsibility of tracking the list of
completion matches, and checking whether the max completions limit has
been reached. You can look at this as this patch starting out by
C++fying the existing "completion_tracker" in symtab.c (it's just an
htab_t typedef currently), moving it to completer.h/c, and then making
it a class/generalizing/enhancing it.
Unlike with the current tracking, completion_tracker now checks
whether the limit has been reached on each completion match list
insertion. This both simplifies the max-completions handling code
(maybe_add_completion_enum is gone, for example), and is a
prerequisite for follow up patches.
The current completion_tracker is only used for symbol completions,
and the symbol code gets at the current instance via globals. This
patch cleans that up by adding a completion_tracker reference to the
signature of the completion functions, and passing the tracker around
everywhere necessary.
Then, the patch changes how the completion match list is handed over
to readline. Currently, we're using the rl_completion_entry_function
readline entry point, and the patch switches to
rl_attempted_completion_function. A following patch will want to let
GDB itself decide the common completion prefix between all matches
(what readline calls the "lowest common denominator"), instead of
having readline compute it, and that's not possible with the
rl_completion_entry_function entry point. Also,
rl_attempted_completion_function lets GDB hand over the match list to
readline as an array in one go instead of passing down matches one by
one, so from that angle it's a nicer entry point anyway.
Lastly, the patch catches exceptions around the readline entry points,
because we can't let C++ exceptions cross readline. We handle that in
the readline input entry point, but the completion entry point isn't
guarded, so GDB can abort if completion throws. E.g., in current
master:
(gdb) b -function "fun<tab>
terminate called after throwing an instance of 'gdb_exception_RETURN_MASK_ERROR'
Aborted (core dumped)
This patch fixes that. This will be exercised in the new tests added
later on in the series.
gdb/ChangeLog:
2017-07-17 Pedro Alves <palves@redhat.com>
* ada-lang.c (symbol_completion_match): Adjust comments.
(symbol_completion_add): Replace vector parameter with
completion_tracker parameter. Use it.
(ada_make_symbol_completion_list): Rename to...
(ada_collect_symbol_completion_matches): ... this. Add
completion_tracker parameter and use it.
(ada_language_defn): Adjust.
* break-catch-syscall.c (catch_syscall_completer): Adjust
prototype and work with completion_tracker instead of VEC.
* breakpoint.c (condition_completer): Adjust prototype and work
with completion_tracker instead of VEC.
* c-lang.c (c_language_defn, cplus_language_defn)
(asm_language_defn, minimal_language_defn): Adjust to renames.
* cli/cli-cmds.c (complete_command): Rework using
completion_tracker. Catch exceptions when completing.
* cli/cli-decode.c (integer_unlimited_completer)
(complete_on_cmdlist, complete_on_enum): Adjust prototype and work
with completion_tracker instead of VEC.
* command.h (struct completion_tracker): Forward declare.
(completer_ftype, completer_handle_brkchars_ftype): Change
types.
(complete_on_cmdlist, complete_on_enum): Adjust.
* completer.c: Include <algorithm>.
(struct gdb_completer_state): New.
(current_completion): New global.
(readline_line_completion_function): Delete.
(noop_completer, filename_completer)
(filename_completer_handle_brkchars, complete_files_symbols)
(linespec_location_completer): Adjust to work with a
completion_tracker instead of a VEC.
(string_or_empty): New.
(collect_explicit_location_matches): Adjust to work with a
completion_tracker instead of a VEC.
(explicit_location_completer): Rename to ...
(complete_explicit_location): ... this and adjust to work with a
completion_tracker instead of a VEC.
(location_completer): Adjust to work with a completion_tracker
instead of a VEC.
(add_struct_fields): Adjust to work with a completion_list instead
of VEC.
(expression_completer): Rename to ...
(complete_expression): ... this and adjust to work with a
completion_tracker instead of a VEC. Use complete_files_symbols.
(expression_completer): Reimplement on top of complete_expression.
(symbol_completer): Adjust to work with a completion_tracker
instead of a VEC.
(enum complete_line_internal_reason): Add describing comments.
(complete_line_internal_normal_command): Adjust to work with a
completion_tracker instead of a VEC.
(complete_line_internal): Rename to ...
(complete_line_internal_1): ... this and adjust to work with a
completion_tracker instead of a VEC. Assert TEXT is NULL in the
handle_brkchars phase.
(new_completion_tracker): Delete.
(complete_line_internal): Reimplement as TRY/CATCH wrapper around
complete_line_internal_1.
(free_completion_tracker): Delete.
(INITIAL_COMPLETION_HTAB_SIZE): New.
(completion_tracker::completion_tracker)
(completion_tracker::~completion_tracker): New.
(maybe_add_completion): Delete.
(completion_tracker::maybe_add_completion)
(completion_tracker::add_completion)
(completion_tracker::add_completions): New.
(throw_max_completions_reached_error): Delete.
(complete_line): Adjust to work with a completion_tracker instead
of a VEC. Don't create a completion_tracker_t or check for max
completions here.
(command_completer, command_completer_handle_brkchars)
(signal_completer, reg_or_group_completer_1)
(reg_or_group_completer, default_completer_handle_brkchars):
Adjust to work with a completion_tracker.
(gdb_completion_word_break_characters_throw): New.
(gdb_completion_word_break_characters): Reimplement.
(line_completion_function): Delete.
(completion_tracker::recompute_lowest_common_denominator)
(expand_preserving_ws)
(completion_tracker::build_completion_result)
(completion_result::completion_result)
(completion_result::completion_result)
(completion_result::~completion_result)
(completion_result::completion_result)
(completion_result::release_match_list, compare_cstrings)
(completion_result::sort_match_list)
(completion_result::reset_match_list)
(gdb_rl_attempted_completion_function_throw)
(gdb_rl_attempted_completion_function): New.
* completer.h (completion_list, struct completion_result)
(class completion_tracker): New.
(complete_line): Add completion_tracker parameter.
(readline_line_completion_function): Delete.
(gdb_rl_attempted_completion_function): New.
(noop_completer, filename_completer, expression_completer)
(location_completer, symbol_completer, command_completer)
(signal_completer, reg_or_group_completer): Update prototypes.
(completion_tracker_t, new_completion_tracker)
(make_cleanup_free_completion_tracker): Delete.
(enum maybe_add_completion_enum): Delete.
(maybe_add_completion): Delete.
(throw_max_completions_reached_error): Delete.
* corefile.c (complete_set_gnutarget): Adjust to work with a
completion_tracker instead of a VEC.
* cp-abi.c (cp_abi_completer): Adjust to work with a
completion_tracker instead of a VEC.
* d-lang.c (d_language_defn): Adjust.
* disasm.c (disassembler_options_completer): Adjust to work with a
completion_tracker instead of a VEC.
* f-lang.c (f_make_symbol_completion_list): Rename to ...
(f_collect_symbol_completion_matches): ... this. Adjust to work
with a completion_tracker instead of a VEC.
(f_language_defn): Adjust.
* go-lang.c (go_language_defn): Adjust.
* guile/scm-cmd.c (cmdscm_add_completion, cmdscm_completer):
Adjust to work with a completion_tracker instead of a VEC.
* infrun.c (handle_completer): Likewise.
* interps.c (interpreter_completer): Likewise.
* interps.h (interpreter_completer): Likewise.
* language.c (unknown_language_defn, auto_language_defn)
(local_language_defn): Adjust.
* language.h (language_defn::la_make_symbol_completion_list):
Rename to ...
(language_defn::la_collect_symbol_completion_matches): ... this
and adjust to work with a completion_tracker instead of a VEC.
* m2-lang.c (m2_language_defn): Adjust.
* objc-lang.c (objc_language_defn): Adjust.
* opencl-lang.c (opencl_language_defn): Adjust.
* p-lang.c (pascal_language_defn): Adjust.
* python/py-cmd.c (cmdpy_completer_helper): Handle NULL word.
(cmdpy_completer_handle_brkchars, cmdpy_completer): Adjust to work
with a completion_tracker.
* rust-lang.c (rust_language_defn): Adjust.
* symtab.c (free_completion_list, do_free_completion_list)
(return_val, completion_tracker): Delete.
(completion_list_add_name, completion_list_add_symbol)
(completion_list_add_msymbol, completion_list_objc_symbol)
(completion_list_add_fields, add_symtab_completions): Add
completion_tracker parameter and use it.
(default_make_symbol_completion_list_break_on_1): Rename to...
(default_collect_symbol_completion_matches_break_on): ... this.
Add completion_tracker parameter and use it instead of allocating
a completion tracker here.
(default_make_symbol_completion_list_break_on): Delete old
implementation.
(default_make_symbol_completion_list): Delete.
(default_collect_symbol_completion_matches): New.
(make_symbol_completion_list): Delete.
(collect_symbol_completion_matches): New.
(make_symbol_completion_type): Rename to ...
(collect_symbol_completion_matches_type): ... this. Add
completion_tracker parameter and use it instead of VEC.
(make_file_symbol_completion_list_1): Rename to...
(collect_file_symbol_completion_matches): ... this. Add
completion_tracker parameter and use it instead of VEC.
(make_file_symbol_completion_list): Delete.
(add_filename_to_list): Use completion_list instead of a VEC.
(add_partial_filename_data::list): Now a completion_list.
(make_source_files_completion_list): Work with a completion_list
instead of a VEC.
* symtab.h: Include "completer.h".
(default_make_symbol_completion_list_break_on)
(default_make_symbol_completion_list, make_symbol_completion_list)
(make_symbol_completion_type, make_file_symbol_completion_list)
(make_source_files_completion_list): Delete.
(default_collect_symbol_completion_matches_break_on)
(default_collect_symbol_completion_matches)
(collect_symbol_completion_matches)
(collect_symbol_completion_matches_type)
(collect_file_symbol_completion_matches)
(make_source_files_completion_list): New.
* top.c (init_main): Don't install a rl_completion_entry_function
hook. Install a rl_attempted_completion_function hook instead.
* tui/tui-layout.c (layout_completer): Adjust to work with a
completion_tracker.
* tui/tui-regs.c (tui_reggroup_completer):
* tui/tui-win.c (window_name_completer, focus_completer)
(winheight_completer): Adjust to work with a completion_tracker.
* value.c: Include "completer.h".
(complete_internalvar): Adjust to work with a completion_tracker.
* value.h (complete_internalvar): Likewise.
2017-07-17 14:45:59 +01:00
|
|
|
|
return;
|
2009-02-06 21:33:59 +00:00
|
|
|
|
|
2022-03-21 10:07:41 -04:00
|
|
|
|
if (PyLong_Check (resultobj.get ()))
|
2009-02-06 21:33:59 +00:00
|
|
|
|
{
|
2013-05-20 20:21:55 +00:00
|
|
|
|
/* User code may also return one of the completion constants,
|
|
|
|
|
|
thus requesting that sort of completion. */
|
|
|
|
|
|
long value;
|
|
|
|
|
|
|
2016-11-20 10:23:08 -07:00
|
|
|
|
if (! gdb_py_int_as_long (resultobj.get (), &value))
|
gdb/python: display errors from command completion
This commit makes the gdb.Command.complete methods more verbose when
it comes to error handling.
Previous to this commit if any commands implemented in Python
implemented the complete method, and if there were any errors
encountered when calling that complete method, then GDB would silently
hide the error and continue as if there were no completions.
This makes is difficult to debug any errors encountered when writing
completion methods, and encourages the idea that Python extensions can
be broken, and GDB will just silently work around them.
I don't think this is a good idea. GDB should encourage extensions to
be written correctly, and robustly, and one way in which GDB can (I
think) support this, is by pointing out when an extension goes wrong.
In this commit I've gone through the Python command completion code,
and added calls to gdbpy_print_stack() or gdbpy_print_stack_or_quit()
in places where we were either clearing the Python error, or, in some
cases, just not handling the error at all.
One thing I have not changed is in cmdpy_completer (py-cmd.c) where we
process the list of completions returned from the Command.complete
method; this routine includes a call to gdbpy_is_string to check a
possible completion is a string, if not the completion is ignored.
I was tempted to remove this check, attempt to complete each result to
a string, and display an error if the conversion fails. After all,
returning anything but a string is surely a mistake by the extension
author.
However, the docs clearly say that only strings within the returned
list will be considered as completions. Anything else is ignored. As
such, and to avoid (what I think is pretty unlikely) breakage of
existing code, I've retained the gdbpy_is_string check.
After the gdbpy_is_string check we call python_string_to_host_string,
if this call fails then I do now print the error, where before we
ignored the error. I think this is OK; if GDB thinks something is a
string, but still can't convert it to a string, then I think it's OK
to display the error in that case.
Another case which I was a little unsure about was in
cmdpy_completer_helper, and the call to PyObject_CallMethodObjArgs,
which is when we actually call Command.complete. Previously, if this
call resulted in an exception then we would ignore this and just
pretend there were no completions.
Of all the changes, this is possibly the one with the biggest
potential for breaking existing scripts, but also, is, I think, the
most useful change. If the user code is wrong in some way, such that
an exception is raised, then previously the user would have no obvious
feedback about this breakage. Now GDB will print the exception for
them, making it, I think, much easier to debug their extension. But,
if there is user code in the wild that relies on raising an exception
as a means to indicate there are no completions .... well, that code
is going to break after this commit. I think we can live with this
though, the exceptions means no completions thing was never documented
behaviour.
I also added a new error() call if the PyObject_CallMethodObjArgs call
raises an exception. This causes the completion mechanism within GDB
to stop. Within GDB the completion code is called twice, the first
time to compute the work break characters, and then a second time to
compute the actual completions.
If PyObject_CallMethodObjArgs raises an exception when computing the
word break character, and we print it by calling
gdbpy_print_stack_or_quit(), but then carry on as if
PyObject_CallMethodObjArgs had returns no completions, GDB will
call the Python completion code again, which results in another call
to PyObject_CallMethodObjArgs, which might raise the same exception
again. This results in the Python exception being printed twice.
By throwing a C++ exception after the failed
PyObject_CallMethodObjArgs call, the completion mechanism is aborted,
and no completions are offered. But importantly, the Python exception
is only printed once. I think this gives a much better user
experience.
I've added some tests to cover this case, as I think this is the most
likely case that a user will run into.
Approved-By: Tom Tromey <tom@tromey.com>
2023-11-27 21:29:53 +00:00
|
|
|
|
gdbpy_print_stack ();
|
2013-05-20 20:21:55 +00:00
|
|
|
|
else if (value >= 0 && value < (long) N_COMPLETERS)
|
Introduce class completion_tracker & rewrite completion<->readline interaction
This patch reworks the whole completion machinery, and prepares it
for later enhancements.
Adds a new "completion_tracker" class that is meant to hold everything
about the state of the current completion operation.
This class now has the responsibility of tracking the list of
completion matches, and checking whether the max completions limit has
been reached. You can look at this as this patch starting out by
C++fying the existing "completion_tracker" in symtab.c (it's just an
htab_t typedef currently), moving it to completer.h/c, and then making
it a class/generalizing/enhancing it.
Unlike with the current tracking, completion_tracker now checks
whether the limit has been reached on each completion match list
insertion. This both simplifies the max-completions handling code
(maybe_add_completion_enum is gone, for example), and is a
prerequisite for follow up patches.
The current completion_tracker is only used for symbol completions,
and the symbol code gets at the current instance via globals. This
patch cleans that up by adding a completion_tracker reference to the
signature of the completion functions, and passing the tracker around
everywhere necessary.
Then, the patch changes how the completion match list is handed over
to readline. Currently, we're using the rl_completion_entry_function
readline entry point, and the patch switches to
rl_attempted_completion_function. A following patch will want to let
GDB itself decide the common completion prefix between all matches
(what readline calls the "lowest common denominator"), instead of
having readline compute it, and that's not possible with the
rl_completion_entry_function entry point. Also,
rl_attempted_completion_function lets GDB hand over the match list to
readline as an array in one go instead of passing down matches one by
one, so from that angle it's a nicer entry point anyway.
Lastly, the patch catches exceptions around the readline entry points,
because we can't let C++ exceptions cross readline. We handle that in
the readline input entry point, but the completion entry point isn't
guarded, so GDB can abort if completion throws. E.g., in current
master:
(gdb) b -function "fun<tab>
terminate called after throwing an instance of 'gdb_exception_RETURN_MASK_ERROR'
Aborted (core dumped)
This patch fixes that. This will be exercised in the new tests added
later on in the series.
gdb/ChangeLog:
2017-07-17 Pedro Alves <palves@redhat.com>
* ada-lang.c (symbol_completion_match): Adjust comments.
(symbol_completion_add): Replace vector parameter with
completion_tracker parameter. Use it.
(ada_make_symbol_completion_list): Rename to...
(ada_collect_symbol_completion_matches): ... this. Add
completion_tracker parameter and use it.
(ada_language_defn): Adjust.
* break-catch-syscall.c (catch_syscall_completer): Adjust
prototype and work with completion_tracker instead of VEC.
* breakpoint.c (condition_completer): Adjust prototype and work
with completion_tracker instead of VEC.
* c-lang.c (c_language_defn, cplus_language_defn)
(asm_language_defn, minimal_language_defn): Adjust to renames.
* cli/cli-cmds.c (complete_command): Rework using
completion_tracker. Catch exceptions when completing.
* cli/cli-decode.c (integer_unlimited_completer)
(complete_on_cmdlist, complete_on_enum): Adjust prototype and work
with completion_tracker instead of VEC.
* command.h (struct completion_tracker): Forward declare.
(completer_ftype, completer_handle_brkchars_ftype): Change
types.
(complete_on_cmdlist, complete_on_enum): Adjust.
* completer.c: Include <algorithm>.
(struct gdb_completer_state): New.
(current_completion): New global.
(readline_line_completion_function): Delete.
(noop_completer, filename_completer)
(filename_completer_handle_brkchars, complete_files_symbols)
(linespec_location_completer): Adjust to work with a
completion_tracker instead of a VEC.
(string_or_empty): New.
(collect_explicit_location_matches): Adjust to work with a
completion_tracker instead of a VEC.
(explicit_location_completer): Rename to ...
(complete_explicit_location): ... this and adjust to work with a
completion_tracker instead of a VEC.
(location_completer): Adjust to work with a completion_tracker
instead of a VEC.
(add_struct_fields): Adjust to work with a completion_list instead
of VEC.
(expression_completer): Rename to ...
(complete_expression): ... this and adjust to work with a
completion_tracker instead of a VEC. Use complete_files_symbols.
(expression_completer): Reimplement on top of complete_expression.
(symbol_completer): Adjust to work with a completion_tracker
instead of a VEC.
(enum complete_line_internal_reason): Add describing comments.
(complete_line_internal_normal_command): Adjust to work with a
completion_tracker instead of a VEC.
(complete_line_internal): Rename to ...
(complete_line_internal_1): ... this and adjust to work with a
completion_tracker instead of a VEC. Assert TEXT is NULL in the
handle_brkchars phase.
(new_completion_tracker): Delete.
(complete_line_internal): Reimplement as TRY/CATCH wrapper around
complete_line_internal_1.
(free_completion_tracker): Delete.
(INITIAL_COMPLETION_HTAB_SIZE): New.
(completion_tracker::completion_tracker)
(completion_tracker::~completion_tracker): New.
(maybe_add_completion): Delete.
(completion_tracker::maybe_add_completion)
(completion_tracker::add_completion)
(completion_tracker::add_completions): New.
(throw_max_completions_reached_error): Delete.
(complete_line): Adjust to work with a completion_tracker instead
of a VEC. Don't create a completion_tracker_t or check for max
completions here.
(command_completer, command_completer_handle_brkchars)
(signal_completer, reg_or_group_completer_1)
(reg_or_group_completer, default_completer_handle_brkchars):
Adjust to work with a completion_tracker.
(gdb_completion_word_break_characters_throw): New.
(gdb_completion_word_break_characters): Reimplement.
(line_completion_function): Delete.
(completion_tracker::recompute_lowest_common_denominator)
(expand_preserving_ws)
(completion_tracker::build_completion_result)
(completion_result::completion_result)
(completion_result::completion_result)
(completion_result::~completion_result)
(completion_result::completion_result)
(completion_result::release_match_list, compare_cstrings)
(completion_result::sort_match_list)
(completion_result::reset_match_list)
(gdb_rl_attempted_completion_function_throw)
(gdb_rl_attempted_completion_function): New.
* completer.h (completion_list, struct completion_result)
(class completion_tracker): New.
(complete_line): Add completion_tracker parameter.
(readline_line_completion_function): Delete.
(gdb_rl_attempted_completion_function): New.
(noop_completer, filename_completer, expression_completer)
(location_completer, symbol_completer, command_completer)
(signal_completer, reg_or_group_completer): Update prototypes.
(completion_tracker_t, new_completion_tracker)
(make_cleanup_free_completion_tracker): Delete.
(enum maybe_add_completion_enum): Delete.
(maybe_add_completion): Delete.
(throw_max_completions_reached_error): Delete.
* corefile.c (complete_set_gnutarget): Adjust to work with a
completion_tracker instead of a VEC.
* cp-abi.c (cp_abi_completer): Adjust to work with a
completion_tracker instead of a VEC.
* d-lang.c (d_language_defn): Adjust.
* disasm.c (disassembler_options_completer): Adjust to work with a
completion_tracker instead of a VEC.
* f-lang.c (f_make_symbol_completion_list): Rename to ...
(f_collect_symbol_completion_matches): ... this. Adjust to work
with a completion_tracker instead of a VEC.
(f_language_defn): Adjust.
* go-lang.c (go_language_defn): Adjust.
* guile/scm-cmd.c (cmdscm_add_completion, cmdscm_completer):
Adjust to work with a completion_tracker instead of a VEC.
* infrun.c (handle_completer): Likewise.
* interps.c (interpreter_completer): Likewise.
* interps.h (interpreter_completer): Likewise.
* language.c (unknown_language_defn, auto_language_defn)
(local_language_defn): Adjust.
* language.h (language_defn::la_make_symbol_completion_list):
Rename to ...
(language_defn::la_collect_symbol_completion_matches): ... this
and adjust to work with a completion_tracker instead of a VEC.
* m2-lang.c (m2_language_defn): Adjust.
* objc-lang.c (objc_language_defn): Adjust.
* opencl-lang.c (opencl_language_defn): Adjust.
* p-lang.c (pascal_language_defn): Adjust.
* python/py-cmd.c (cmdpy_completer_helper): Handle NULL word.
(cmdpy_completer_handle_brkchars, cmdpy_completer): Adjust to work
with a completion_tracker.
* rust-lang.c (rust_language_defn): Adjust.
* symtab.c (free_completion_list, do_free_completion_list)
(return_val, completion_tracker): Delete.
(completion_list_add_name, completion_list_add_symbol)
(completion_list_add_msymbol, completion_list_objc_symbol)
(completion_list_add_fields, add_symtab_completions): Add
completion_tracker parameter and use it.
(default_make_symbol_completion_list_break_on_1): Rename to...
(default_collect_symbol_completion_matches_break_on): ... this.
Add completion_tracker parameter and use it instead of allocating
a completion tracker here.
(default_make_symbol_completion_list_break_on): Delete old
implementation.
(default_make_symbol_completion_list): Delete.
(default_collect_symbol_completion_matches): New.
(make_symbol_completion_list): Delete.
(collect_symbol_completion_matches): New.
(make_symbol_completion_type): Rename to ...
(collect_symbol_completion_matches_type): ... this. Add
completion_tracker parameter and use it instead of VEC.
(make_file_symbol_completion_list_1): Rename to...
(collect_file_symbol_completion_matches): ... this. Add
completion_tracker parameter and use it instead of VEC.
(make_file_symbol_completion_list): Delete.
(add_filename_to_list): Use completion_list instead of a VEC.
(add_partial_filename_data::list): Now a completion_list.
(make_source_files_completion_list): Work with a completion_list
instead of a VEC.
* symtab.h: Include "completer.h".
(default_make_symbol_completion_list_break_on)
(default_make_symbol_completion_list, make_symbol_completion_list)
(make_symbol_completion_type, make_file_symbol_completion_list)
(make_source_files_completion_list): Delete.
(default_collect_symbol_completion_matches_break_on)
(default_collect_symbol_completion_matches)
(collect_symbol_completion_matches)
(collect_symbol_completion_matches_type)
(collect_file_symbol_completion_matches)
(make_source_files_completion_list): New.
* top.c (init_main): Don't install a rl_completion_entry_function
hook. Install a rl_attempted_completion_function hook instead.
* tui/tui-layout.c (layout_completer): Adjust to work with a
completion_tracker.
* tui/tui-regs.c (tui_reggroup_completer):
* tui/tui-win.c (window_name_completer, focus_completer)
(winheight_completer): Adjust to work with a completion_tracker.
* value.c: Include "completer.h".
(complete_internalvar): Adjust to work with a completion_tracker.
* value.h (complete_internalvar): Likewise.
2017-07-17 14:45:59 +01:00
|
|
|
|
completers[value].completer (command, tracker, text, word);
|
2013-05-20 20:21:55 +00:00
|
|
|
|
}
|
gdb/python: handle completion returning a non-sequence
GDB's Python API documentation for gdb.Command.complete() says:
The 'complete' method can return several values:
* If the return value is a sequence, the contents of the
sequence are used as the completions. It is up to 'complete'
to ensure that the contents actually do complete the word. A
zero-length sequence is allowed, it means that there were no
completions available. Only string elements of the sequence
are used; other elements in the sequence are ignored.
* If the return value is one of the 'COMPLETE_' constants
defined below, then the corresponding GDB-internal completion
function is invoked, and its result is used.
* All other results are treated as though there were no
available completions.
So, returning a non-sequence, and non-integer from a complete method
should be fine; it should just be treated as though there are no
completions.
However, if I write a complete method that returns None, I see this
behaviour:
(gdb) complete completefilenone x
Python Exception <class 'TypeError'>: 'NoneType' object is not iterable
warning: internal error: Unhandled Python exception
(gdb)
Which is caused because we currently assume that anything that is not
an integer must be iterable, and we call PyObject_GetIter on it. When
this call fails a Python exception is set, but instead of
clearing (and therefore ignoring) this exception as we do everywhere
else in the Python completion code, we instead just return with the
exception set.
In this commit I add a PySequence_Check call. If this call returns
false (and we've already checked the integer case) then we can assume
there are no completion results.
I've added a test which checks returning a non-sequence.
Approved-By: Tom Tromey <tom@tromey.com>
2023-11-16 14:42:56 +00:00
|
|
|
|
else if (PySequence_Check (resultobj.get ()))
|
2013-05-20 20:21:55 +00:00
|
|
|
|
{
|
Turn gdbpy_ref into a template
This turns gdbpy_ref into a template class, so that it can be used to
wrap subclasses of PyObject. The default argument remains PyObject;
and this necessitated renaming uses of "gdbpy_ref" to "gdbpy_ref<>".
gdb/ChangeLog
2017-02-10 Tom Tromey <tom@tromey.com>
* python/py-ref.h (gdbpy_ref_policy): Now a template.
(gdbpy_ref): Now a template; allow subclasses of PyObject to be
used.
* python/py-arch.c, python/py-bpevent.c, python/py-breakpoint.c,
python/py-cmd.c, python/py-continueevent.c, python/py-event.c,
python/py-exitedevent.c, python/py-finishbreakpoint.c,
python/py-framefilter.c, python/py-function.c,
python/py-inferior.c, python/py-infevents.c,
python/py-linetable.c, python/py-newobjfileevent.c,
python/py-param.c, python/py-prettyprint.c, python/py-ref.h,
python/py-signalevent.c, python/py-stopevent.c,
python/py-symbol.c, python/py-threadevent.c, python/py-type.c,
python/py-unwind.c, python/py-utils.c, python/py-value.c,
python/py-varobj.c, python/py-xmethods.c, python/python.c,
varobj.c: Change gdbpy_ref to gdbpy_ref<>.
2017-02-09 13:16:36 -07:00
|
|
|
|
gdbpy_ref<> iter (PyObject_GetIter (resultobj.get ()));
|
2010-05-17 21:23:25 +00:00
|
|
|
|
|
2013-05-20 20:21:55 +00:00
|
|
|
|
if (iter == NULL)
|
gdb/python: display errors from command completion
This commit makes the gdb.Command.complete methods more verbose when
it comes to error handling.
Previous to this commit if any commands implemented in Python
implemented the complete method, and if there were any errors
encountered when calling that complete method, then GDB would silently
hide the error and continue as if there were no completions.
This makes is difficult to debug any errors encountered when writing
completion methods, and encourages the idea that Python extensions can
be broken, and GDB will just silently work around them.
I don't think this is a good idea. GDB should encourage extensions to
be written correctly, and robustly, and one way in which GDB can (I
think) support this, is by pointing out when an extension goes wrong.
In this commit I've gone through the Python command completion code,
and added calls to gdbpy_print_stack() or gdbpy_print_stack_or_quit()
in places where we were either clearing the Python error, or, in some
cases, just not handling the error at all.
One thing I have not changed is in cmdpy_completer (py-cmd.c) where we
process the list of completions returned from the Command.complete
method; this routine includes a call to gdbpy_is_string to check a
possible completion is a string, if not the completion is ignored.
I was tempted to remove this check, attempt to complete each result to
a string, and display an error if the conversion fails. After all,
returning anything but a string is surely a mistake by the extension
author.
However, the docs clearly say that only strings within the returned
list will be considered as completions. Anything else is ignored. As
such, and to avoid (what I think is pretty unlikely) breakage of
existing code, I've retained the gdbpy_is_string check.
After the gdbpy_is_string check we call python_string_to_host_string,
if this call fails then I do now print the error, where before we
ignored the error. I think this is OK; if GDB thinks something is a
string, but still can't convert it to a string, then I think it's OK
to display the error in that case.
Another case which I was a little unsure about was in
cmdpy_completer_helper, and the call to PyObject_CallMethodObjArgs,
which is when we actually call Command.complete. Previously, if this
call resulted in an exception then we would ignore this and just
pretend there were no completions.
Of all the changes, this is possibly the one with the biggest
potential for breaking existing scripts, but also, is, I think, the
most useful change. If the user code is wrong in some way, such that
an exception is raised, then previously the user would have no obvious
feedback about this breakage. Now GDB will print the exception for
them, making it, I think, much easier to debug their extension. But,
if there is user code in the wild that relies on raising an exception
as a means to indicate there are no completions .... well, that code
is going to break after this commit. I think we can live with this
though, the exceptions means no completions thing was never documented
behaviour.
I also added a new error() call if the PyObject_CallMethodObjArgs call
raises an exception. This causes the completion mechanism within GDB
to stop. Within GDB the completion code is called twice, the first
time to compute the work break characters, and then a second time to
compute the actual completions.
If PyObject_CallMethodObjArgs raises an exception when computing the
word break character, and we print it by calling
gdbpy_print_stack_or_quit(), but then carry on as if
PyObject_CallMethodObjArgs had returns no completions, GDB will
call the Python completion code again, which results in another call
to PyObject_CallMethodObjArgs, which might raise the same exception
again. This results in the Python exception being printed twice.
By throwing a C++ exception after the failed
PyObject_CallMethodObjArgs call, the completion mechanism is aborted,
and no completions are offered. But importantly, the Python exception
is only printed once. I think this gives a much better user
experience.
I've added some tests to cover this case, as I think this is the most
likely case that a user will run into.
Approved-By: Tom Tromey <tom@tromey.com>
2023-11-27 21:29:53 +00:00
|
|
|
|
{
|
|
|
|
|
|
gdbpy_print_stack ();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2009-02-06 21:33:59 +00:00
|
|
|
|
|
2016-11-20 10:23:08 -07:00
|
|
|
|
while (true)
|
2009-02-06 21:33:59 +00:00
|
|
|
|
{
|
Turn gdbpy_ref into a template
This turns gdbpy_ref into a template class, so that it can be used to
wrap subclasses of PyObject. The default argument remains PyObject;
and this necessitated renaming uses of "gdbpy_ref" to "gdbpy_ref<>".
gdb/ChangeLog
2017-02-10 Tom Tromey <tom@tromey.com>
* python/py-ref.h (gdbpy_ref_policy): Now a template.
(gdbpy_ref): Now a template; allow subclasses of PyObject to be
used.
* python/py-arch.c, python/py-bpevent.c, python/py-breakpoint.c,
python/py-cmd.c, python/py-continueevent.c, python/py-event.c,
python/py-exitedevent.c, python/py-finishbreakpoint.c,
python/py-framefilter.c, python/py-function.c,
python/py-inferior.c, python/py-infevents.c,
python/py-linetable.c, python/py-newobjfileevent.c,
python/py-param.c, python/py-prettyprint.c, python/py-ref.h,
python/py-signalevent.c, python/py-stopevent.c,
python/py-symbol.c, python/py-threadevent.c, python/py-type.c,
python/py-unwind.c, python/py-utils.c, python/py-value.c,
python/py-varobj.c, python/py-xmethods.c, python/python.c,
varobj.c: Change gdbpy_ref to gdbpy_ref<>.
2017-02-09 13:16:36 -07:00
|
|
|
|
gdbpy_ref<> elt (PyIter_Next (iter.get ()));
|
2016-11-20 10:23:08 -07:00
|
|
|
|
if (elt == NULL)
|
gdb/python: display errors from command completion
This commit makes the gdb.Command.complete methods more verbose when
it comes to error handling.
Previous to this commit if any commands implemented in Python
implemented the complete method, and if there were any errors
encountered when calling that complete method, then GDB would silently
hide the error and continue as if there were no completions.
This makes is difficult to debug any errors encountered when writing
completion methods, and encourages the idea that Python extensions can
be broken, and GDB will just silently work around them.
I don't think this is a good idea. GDB should encourage extensions to
be written correctly, and robustly, and one way in which GDB can (I
think) support this, is by pointing out when an extension goes wrong.
In this commit I've gone through the Python command completion code,
and added calls to gdbpy_print_stack() or gdbpy_print_stack_or_quit()
in places where we were either clearing the Python error, or, in some
cases, just not handling the error at all.
One thing I have not changed is in cmdpy_completer (py-cmd.c) where we
process the list of completions returned from the Command.complete
method; this routine includes a call to gdbpy_is_string to check a
possible completion is a string, if not the completion is ignored.
I was tempted to remove this check, attempt to complete each result to
a string, and display an error if the conversion fails. After all,
returning anything but a string is surely a mistake by the extension
author.
However, the docs clearly say that only strings within the returned
list will be considered as completions. Anything else is ignored. As
such, and to avoid (what I think is pretty unlikely) breakage of
existing code, I've retained the gdbpy_is_string check.
After the gdbpy_is_string check we call python_string_to_host_string,
if this call fails then I do now print the error, where before we
ignored the error. I think this is OK; if GDB thinks something is a
string, but still can't convert it to a string, then I think it's OK
to display the error in that case.
Another case which I was a little unsure about was in
cmdpy_completer_helper, and the call to PyObject_CallMethodObjArgs,
which is when we actually call Command.complete. Previously, if this
call resulted in an exception then we would ignore this and just
pretend there were no completions.
Of all the changes, this is possibly the one with the biggest
potential for breaking existing scripts, but also, is, I think, the
most useful change. If the user code is wrong in some way, such that
an exception is raised, then previously the user would have no obvious
feedback about this breakage. Now GDB will print the exception for
them, making it, I think, much easier to debug their extension. But,
if there is user code in the wild that relies on raising an exception
as a means to indicate there are no completions .... well, that code
is going to break after this commit. I think we can live with this
though, the exceptions means no completions thing was never documented
behaviour.
I also added a new error() call if the PyObject_CallMethodObjArgs call
raises an exception. This causes the completion mechanism within GDB
to stop. Within GDB the completion code is called twice, the first
time to compute the work break characters, and then a second time to
compute the actual completions.
If PyObject_CallMethodObjArgs raises an exception when computing the
word break character, and we print it by calling
gdbpy_print_stack_or_quit(), but then carry on as if
PyObject_CallMethodObjArgs had returns no completions, GDB will
call the Python completion code again, which results in another call
to PyObject_CallMethodObjArgs, which might raise the same exception
again. This results in the Python exception being printed twice.
By throwing a C++ exception after the failed
PyObject_CallMethodObjArgs call, the completion mechanism is aborted,
and no completions are offered. But importantly, the Python exception
is only printed once. I think this gives a much better user
experience.
I've added some tests to cover this case, as I think this is the most
likely case that a user will run into.
Approved-By: Tom Tromey <tom@tromey.com>
2023-11-27 21:29:53 +00:00
|
|
|
|
{
|
|
|
|
|
|
if (PyErr_Occurred() != nullptr)
|
|
|
|
|
|
gdbpy_print_stack ();
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
2010-05-17 21:23:25 +00:00
|
|
|
|
|
2016-11-20 10:23:08 -07:00
|
|
|
|
if (! gdbpy_is_string (elt.get ()))
|
2009-02-06 21:33:59 +00:00
|
|
|
|
{
|
|
|
|
|
|
/* Skip problem elements. */
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
gdb/python: display errors from command completion
This commit makes the gdb.Command.complete methods more verbose when
it comes to error handling.
Previous to this commit if any commands implemented in Python
implemented the complete method, and if there were any errors
encountered when calling that complete method, then GDB would silently
hide the error and continue as if there were no completions.
This makes is difficult to debug any errors encountered when writing
completion methods, and encourages the idea that Python extensions can
be broken, and GDB will just silently work around them.
I don't think this is a good idea. GDB should encourage extensions to
be written correctly, and robustly, and one way in which GDB can (I
think) support this, is by pointing out when an extension goes wrong.
In this commit I've gone through the Python command completion code,
and added calls to gdbpy_print_stack() or gdbpy_print_stack_or_quit()
in places where we were either clearing the Python error, or, in some
cases, just not handling the error at all.
One thing I have not changed is in cmdpy_completer (py-cmd.c) where we
process the list of completions returned from the Command.complete
method; this routine includes a call to gdbpy_is_string to check a
possible completion is a string, if not the completion is ignored.
I was tempted to remove this check, attempt to complete each result to
a string, and display an error if the conversion fails. After all,
returning anything but a string is surely a mistake by the extension
author.
However, the docs clearly say that only strings within the returned
list will be considered as completions. Anything else is ignored. As
such, and to avoid (what I think is pretty unlikely) breakage of
existing code, I've retained the gdbpy_is_string check.
After the gdbpy_is_string check we call python_string_to_host_string,
if this call fails then I do now print the error, where before we
ignored the error. I think this is OK; if GDB thinks something is a
string, but still can't convert it to a string, then I think it's OK
to display the error in that case.
Another case which I was a little unsure about was in
cmdpy_completer_helper, and the call to PyObject_CallMethodObjArgs,
which is when we actually call Command.complete. Previously, if this
call resulted in an exception then we would ignore this and just
pretend there were no completions.
Of all the changes, this is possibly the one with the biggest
potential for breaking existing scripts, but also, is, I think, the
most useful change. If the user code is wrong in some way, such that
an exception is raised, then previously the user would have no obvious
feedback about this breakage. Now GDB will print the exception for
them, making it, I think, much easier to debug their extension. But,
if there is user code in the wild that relies on raising an exception
as a means to indicate there are no completions .... well, that code
is going to break after this commit. I think we can live with this
though, the exceptions means no completions thing was never documented
behaviour.
I also added a new error() call if the PyObject_CallMethodObjArgs call
raises an exception. This causes the completion mechanism within GDB
to stop. Within GDB the completion code is called twice, the first
time to compute the work break characters, and then a second time to
compute the actual completions.
If PyObject_CallMethodObjArgs raises an exception when computing the
word break character, and we print it by calling
gdbpy_print_stack_or_quit(), but then carry on as if
PyObject_CallMethodObjArgs had returns no completions, GDB will
call the Python completion code again, which results in another call
to PyObject_CallMethodObjArgs, which might raise the same exception
again. This results in the Python exception being printed twice.
By throwing a C++ exception after the failed
PyObject_CallMethodObjArgs call, the completion mechanism is aborted,
and no completions are offered. But importantly, the Python exception
is only printed once. I think this gives a much better user
experience.
I've added some tests to cover this case, as I think this is the most
likely case that a user will run into.
Approved-By: Tom Tromey <tom@tromey.com>
2023-11-27 21:29:53 +00:00
|
|
|
|
|
Use unique_xmalloc_ptr in Python code
This changes some utility functions in the Python code to return
unique_xmalloc_ptr, and then fixes up the callers.
I chose unique_xmalloc_ptr rather than std::string because at a few
call points the xmalloc'd string is released and ownership transferred
elsewhere.
This patch found a few existing memory leaks. For example,
py-unwind.c called gdbpy_obj_to_string but never freed the result.
Built and regression tested on the buildbot.
2016-11-09 Tom Tromey <tom@tromey.com>
* varobj.h (varobj_get_display_hint): Change return type.
* varobj.c (varobj_get_display_hint): Return unique_xmalloc_ptr.
(varobj_value_get_print_value): Update.
* python/python.c (gdbpy_before_prompt_hook, gdbpy_print_stack)
(gdbpy_apply_type_printers): Update.
* python/python-internal.h (unicode_to_target_string)
(python_string_to_target_string, python_string_to_host_string)
(gdbpy_obj_to_string, gdbpy_exception_to_string)
(gdbpy_get_display_hint): Change return types.
* python/py-varobj.c (py_varobj_iter_next): Update.
* python/py-value.c (valpy_getitem, convert_value_from_python):
Update.
* python/py-utils.c (unicode_to_encoded_string)
(unicode_to_target_string, python_string_to_target_string)
(python_string_to_host_string, gdbpy_obj_to_string)
(gdbpy_exception_to_string): Return unique_xmalloc_ptr.
* python/py-unwind.c (pyuw_parse_register_id): Update.
* python/py-type.c (typy_getitem): Update.
* python/py-prettyprint.c (gdbpy_get_display_hint)
(print_stack_unless_memory_error, print_children)
(gdbpy_apply_val_pretty_printer): Update.
* python/py-param.c (set_parameter_value): Update.
(get_doc_string, call_doc_function): Return unique_xmalloc_ptr.
(get_set_value, get_show_value, compute_enum_values, parmpy_init):
Update.
* python/py-infthread.c (thpy_set_name): Update.
* python/py-function.c (fnpy_call, fnpy_init): Update.
* python/py-framefilter.c (extract_sym): Change "name" to
unique_xmalloc_ptr.
(enumerate_args, enumerate_locals): Update.
(py_print_frame): Use unique_xmalloc_ptr.
* python/py-frame.c (frapy_read_var): Update. Remove cleanup.
* python/py-cmd.c (cmdpy_function, cmdpy_completer, cmdpy_init):
Update.
* python/py-breakpoint.c (bppy_set_condition): Use
unique_xmalloc_ptr.
(bppy_init): Likewise. Remove cleanup.
(local_setattro): Update.
* mi/mi-cmd-var.c (print_varobj, mi_cmd_var_list_children)
(varobj_update_one): Update.
2016-10-15 09:20:02 -06:00
|
|
|
|
gdb::unique_xmalloc_ptr<char>
|
2016-11-20 10:23:08 -07:00
|
|
|
|
item (python_string_to_host_string (elt.get ()));
|
* ada-lang.c (ada_make_symbol_completion_list): Return a VEC.
* breakpoint.c (catch_syscall_completer): Return a VEC.
* cli/cli-cmds.c (complete_command): Update.
* cli/cli-decode.c (complete_on_cmdlist): Return a VEC.
(complete_on_enum): Likewise.
* command.h: Include gdb_vecs.h.
(completer_ftype): Change return type.
(complete_on_cmdlist, complete_on_enum): Likewise.
* completer.c (noop_completer, filename_completer)
(location_completer): Return a VEC.
(add_struct_fields): Remove 'nextp' argument. Change 'output'
to a VEC.
(expression_completer, complete_line_internal, complete_line)
(command_completer): Return a VEC.
(gdb_completion_word_break_characters, line_completion_function):
Update.
* completer.h: Include gdb_vecs.h.
(complete_line, noop_completer, filename_completer)
(expression_completer, location_completer, command_completer):
Update.
* f-lang.c (f_word_break_characters): Return a VEC.
* interps.c (interpreter_completer): Return a VEC.
* language.h (struct language_defn)
<la_make_symbol_completion_list>: Return a VEC.
* python/py-cmd.c (cmdpy_completer): Return a VEC.
* symtab.c (free_completion_list): Take a VEC.
(return_val_size, return_val_index): Remove.
(return_val): Now a VEC.
(completion_list_add_name): Update.
(default_make_symbol_completion_list_break_on)
(default_make_symbol_completion_list, make_symbol_completion_list)
(make_symbol_completion_list_fn, make_file_symbol_completion_list):
Return a VEC.
(add_filename_to_list): Update.
(struct add_partial_filename_data) <list_used, list_alloced>: Remove.
<list>: Now a VEC.
(maybe_add_partial_symtab_filename): Update.
(make_source_files_completion_list): Return a VEC.
* symtab.h (default_make_symbol_completion_list_break_on)
(default_make_symbol_completion_list, make_symbol_completion_list)
(make_symbol_completion_list_fn, make_file_symbol_completion_list)
(make_source_files_completion_list): Update.
2012-06-13 15:47:16 +00:00
|
|
|
|
if (item == NULL)
|
2010-10-13 13:24:40 +00:00
|
|
|
|
{
|
gdb/python: display errors from command completion
This commit makes the gdb.Command.complete methods more verbose when
it comes to error handling.
Previous to this commit if any commands implemented in Python
implemented the complete method, and if there were any errors
encountered when calling that complete method, then GDB would silently
hide the error and continue as if there were no completions.
This makes is difficult to debug any errors encountered when writing
completion methods, and encourages the idea that Python extensions can
be broken, and GDB will just silently work around them.
I don't think this is a good idea. GDB should encourage extensions to
be written correctly, and robustly, and one way in which GDB can (I
think) support this, is by pointing out when an extension goes wrong.
In this commit I've gone through the Python command completion code,
and added calls to gdbpy_print_stack() or gdbpy_print_stack_or_quit()
in places where we were either clearing the Python error, or, in some
cases, just not handling the error at all.
One thing I have not changed is in cmdpy_completer (py-cmd.c) where we
process the list of completions returned from the Command.complete
method; this routine includes a call to gdbpy_is_string to check a
possible completion is a string, if not the completion is ignored.
I was tempted to remove this check, attempt to complete each result to
a string, and display an error if the conversion fails. After all,
returning anything but a string is surely a mistake by the extension
author.
However, the docs clearly say that only strings within the returned
list will be considered as completions. Anything else is ignored. As
such, and to avoid (what I think is pretty unlikely) breakage of
existing code, I've retained the gdbpy_is_string check.
After the gdbpy_is_string check we call python_string_to_host_string,
if this call fails then I do now print the error, where before we
ignored the error. I think this is OK; if GDB thinks something is a
string, but still can't convert it to a string, then I think it's OK
to display the error in that case.
Another case which I was a little unsure about was in
cmdpy_completer_helper, and the call to PyObject_CallMethodObjArgs,
which is when we actually call Command.complete. Previously, if this
call resulted in an exception then we would ignore this and just
pretend there were no completions.
Of all the changes, this is possibly the one with the biggest
potential for breaking existing scripts, but also, is, I think, the
most useful change. If the user code is wrong in some way, such that
an exception is raised, then previously the user would have no obvious
feedback about this breakage. Now GDB will print the exception for
them, making it, I think, much easier to debug their extension. But,
if there is user code in the wild that relies on raising an exception
as a means to indicate there are no completions .... well, that code
is going to break after this commit. I think we can live with this
though, the exceptions means no completions thing was never documented
behaviour.
I also added a new error() call if the PyObject_CallMethodObjArgs call
raises an exception. This causes the completion mechanism within GDB
to stop. Within GDB the completion code is called twice, the first
time to compute the work break characters, and then a second time to
compute the actual completions.
If PyObject_CallMethodObjArgs raises an exception when computing the
word break character, and we print it by calling
gdbpy_print_stack_or_quit(), but then carry on as if
PyObject_CallMethodObjArgs had returns no completions, GDB will
call the Python completion code again, which results in another call
to PyObject_CallMethodObjArgs, which might raise the same exception
again. This results in the Python exception being printed twice.
By throwing a C++ exception after the failed
PyObject_CallMethodObjArgs call, the completion mechanism is aborted,
and no completions are offered. But importantly, the Python exception
is only printed once. I think this gives a much better user
experience.
I've added some tests to cover this case, as I think this is the most
likely case that a user will run into.
Approved-By: Tom Tromey <tom@tromey.com>
2023-11-27 21:29:53 +00:00
|
|
|
|
gdbpy_print_stack ();
|
2010-10-13 13:24:40 +00:00
|
|
|
|
continue;
|
|
|
|
|
|
}
|
Introduce class completion_tracker & rewrite completion<->readline interaction
This patch reworks the whole completion machinery, and prepares it
for later enhancements.
Adds a new "completion_tracker" class that is meant to hold everything
about the state of the current completion operation.
This class now has the responsibility of tracking the list of
completion matches, and checking whether the max completions limit has
been reached. You can look at this as this patch starting out by
C++fying the existing "completion_tracker" in symtab.c (it's just an
htab_t typedef currently), moving it to completer.h/c, and then making
it a class/generalizing/enhancing it.
Unlike with the current tracking, completion_tracker now checks
whether the limit has been reached on each completion match list
insertion. This both simplifies the max-completions handling code
(maybe_add_completion_enum is gone, for example), and is a
prerequisite for follow up patches.
The current completion_tracker is only used for symbol completions,
and the symbol code gets at the current instance via globals. This
patch cleans that up by adding a completion_tracker reference to the
signature of the completion functions, and passing the tracker around
everywhere necessary.
Then, the patch changes how the completion match list is handed over
to readline. Currently, we're using the rl_completion_entry_function
readline entry point, and the patch switches to
rl_attempted_completion_function. A following patch will want to let
GDB itself decide the common completion prefix between all matches
(what readline calls the "lowest common denominator"), instead of
having readline compute it, and that's not possible with the
rl_completion_entry_function entry point. Also,
rl_attempted_completion_function lets GDB hand over the match list to
readline as an array in one go instead of passing down matches one by
one, so from that angle it's a nicer entry point anyway.
Lastly, the patch catches exceptions around the readline entry points,
because we can't let C++ exceptions cross readline. We handle that in
the readline input entry point, but the completion entry point isn't
guarded, so GDB can abort if completion throws. E.g., in current
master:
(gdb) b -function "fun<tab>
terminate called after throwing an instance of 'gdb_exception_RETURN_MASK_ERROR'
Aborted (core dumped)
This patch fixes that. This will be exercised in the new tests added
later on in the series.
gdb/ChangeLog:
2017-07-17 Pedro Alves <palves@redhat.com>
* ada-lang.c (symbol_completion_match): Adjust comments.
(symbol_completion_add): Replace vector parameter with
completion_tracker parameter. Use it.
(ada_make_symbol_completion_list): Rename to...
(ada_collect_symbol_completion_matches): ... this. Add
completion_tracker parameter and use it.
(ada_language_defn): Adjust.
* break-catch-syscall.c (catch_syscall_completer): Adjust
prototype and work with completion_tracker instead of VEC.
* breakpoint.c (condition_completer): Adjust prototype and work
with completion_tracker instead of VEC.
* c-lang.c (c_language_defn, cplus_language_defn)
(asm_language_defn, minimal_language_defn): Adjust to renames.
* cli/cli-cmds.c (complete_command): Rework using
completion_tracker. Catch exceptions when completing.
* cli/cli-decode.c (integer_unlimited_completer)
(complete_on_cmdlist, complete_on_enum): Adjust prototype and work
with completion_tracker instead of VEC.
* command.h (struct completion_tracker): Forward declare.
(completer_ftype, completer_handle_brkchars_ftype): Change
types.
(complete_on_cmdlist, complete_on_enum): Adjust.
* completer.c: Include <algorithm>.
(struct gdb_completer_state): New.
(current_completion): New global.
(readline_line_completion_function): Delete.
(noop_completer, filename_completer)
(filename_completer_handle_brkchars, complete_files_symbols)
(linespec_location_completer): Adjust to work with a
completion_tracker instead of a VEC.
(string_or_empty): New.
(collect_explicit_location_matches): Adjust to work with a
completion_tracker instead of a VEC.
(explicit_location_completer): Rename to ...
(complete_explicit_location): ... this and adjust to work with a
completion_tracker instead of a VEC.
(location_completer): Adjust to work with a completion_tracker
instead of a VEC.
(add_struct_fields): Adjust to work with a completion_list instead
of VEC.
(expression_completer): Rename to ...
(complete_expression): ... this and adjust to work with a
completion_tracker instead of a VEC. Use complete_files_symbols.
(expression_completer): Reimplement on top of complete_expression.
(symbol_completer): Adjust to work with a completion_tracker
instead of a VEC.
(enum complete_line_internal_reason): Add describing comments.
(complete_line_internal_normal_command): Adjust to work with a
completion_tracker instead of a VEC.
(complete_line_internal): Rename to ...
(complete_line_internal_1): ... this and adjust to work with a
completion_tracker instead of a VEC. Assert TEXT is NULL in the
handle_brkchars phase.
(new_completion_tracker): Delete.
(complete_line_internal): Reimplement as TRY/CATCH wrapper around
complete_line_internal_1.
(free_completion_tracker): Delete.
(INITIAL_COMPLETION_HTAB_SIZE): New.
(completion_tracker::completion_tracker)
(completion_tracker::~completion_tracker): New.
(maybe_add_completion): Delete.
(completion_tracker::maybe_add_completion)
(completion_tracker::add_completion)
(completion_tracker::add_completions): New.
(throw_max_completions_reached_error): Delete.
(complete_line): Adjust to work with a completion_tracker instead
of a VEC. Don't create a completion_tracker_t or check for max
completions here.
(command_completer, command_completer_handle_brkchars)
(signal_completer, reg_or_group_completer_1)
(reg_or_group_completer, default_completer_handle_brkchars):
Adjust to work with a completion_tracker.
(gdb_completion_word_break_characters_throw): New.
(gdb_completion_word_break_characters): Reimplement.
(line_completion_function): Delete.
(completion_tracker::recompute_lowest_common_denominator)
(expand_preserving_ws)
(completion_tracker::build_completion_result)
(completion_result::completion_result)
(completion_result::completion_result)
(completion_result::~completion_result)
(completion_result::completion_result)
(completion_result::release_match_list, compare_cstrings)
(completion_result::sort_match_list)
(completion_result::reset_match_list)
(gdb_rl_attempted_completion_function_throw)
(gdb_rl_attempted_completion_function): New.
* completer.h (completion_list, struct completion_result)
(class completion_tracker): New.
(complete_line): Add completion_tracker parameter.
(readline_line_completion_function): Delete.
(gdb_rl_attempted_completion_function): New.
(noop_completer, filename_completer, expression_completer)
(location_completer, symbol_completer, command_completer)
(signal_completer, reg_or_group_completer): Update prototypes.
(completion_tracker_t, new_completion_tracker)
(make_cleanup_free_completion_tracker): Delete.
(enum maybe_add_completion_enum): Delete.
(maybe_add_completion): Delete.
(throw_max_completions_reached_error): Delete.
* corefile.c (complete_set_gnutarget): Adjust to work with a
completion_tracker instead of a VEC.
* cp-abi.c (cp_abi_completer): Adjust to work with a
completion_tracker instead of a VEC.
* d-lang.c (d_language_defn): Adjust.
* disasm.c (disassembler_options_completer): Adjust to work with a
completion_tracker instead of a VEC.
* f-lang.c (f_make_symbol_completion_list): Rename to ...
(f_collect_symbol_completion_matches): ... this. Adjust to work
with a completion_tracker instead of a VEC.
(f_language_defn): Adjust.
* go-lang.c (go_language_defn): Adjust.
* guile/scm-cmd.c (cmdscm_add_completion, cmdscm_completer):
Adjust to work with a completion_tracker instead of a VEC.
* infrun.c (handle_completer): Likewise.
* interps.c (interpreter_completer): Likewise.
* interps.h (interpreter_completer): Likewise.
* language.c (unknown_language_defn, auto_language_defn)
(local_language_defn): Adjust.
* language.h (language_defn::la_make_symbol_completion_list):
Rename to ...
(language_defn::la_collect_symbol_completion_matches): ... this
and adjust to work with a completion_tracker instead of a VEC.
* m2-lang.c (m2_language_defn): Adjust.
* objc-lang.c (objc_language_defn): Adjust.
* opencl-lang.c (opencl_language_defn): Adjust.
* p-lang.c (pascal_language_defn): Adjust.
* python/py-cmd.c (cmdpy_completer_helper): Handle NULL word.
(cmdpy_completer_handle_brkchars, cmdpy_completer): Adjust to work
with a completion_tracker.
* rust-lang.c (rust_language_defn): Adjust.
* symtab.c (free_completion_list, do_free_completion_list)
(return_val, completion_tracker): Delete.
(completion_list_add_name, completion_list_add_symbol)
(completion_list_add_msymbol, completion_list_objc_symbol)
(completion_list_add_fields, add_symtab_completions): Add
completion_tracker parameter and use it.
(default_make_symbol_completion_list_break_on_1): Rename to...
(default_collect_symbol_completion_matches_break_on): ... this.
Add completion_tracker parameter and use it instead of allocating
a completion tracker here.
(default_make_symbol_completion_list_break_on): Delete old
implementation.
(default_make_symbol_completion_list): Delete.
(default_collect_symbol_completion_matches): New.
(make_symbol_completion_list): Delete.
(collect_symbol_completion_matches): New.
(make_symbol_completion_type): Rename to ...
(collect_symbol_completion_matches_type): ... this. Add
completion_tracker parameter and use it instead of VEC.
(make_file_symbol_completion_list_1): Rename to...
(collect_file_symbol_completion_matches): ... this. Add
completion_tracker parameter and use it instead of VEC.
(make_file_symbol_completion_list): Delete.
(add_filename_to_list): Use completion_list instead of a VEC.
(add_partial_filename_data::list): Now a completion_list.
(make_source_files_completion_list): Work with a completion_list
instead of a VEC.
* symtab.h: Include "completer.h".
(default_make_symbol_completion_list_break_on)
(default_make_symbol_completion_list, make_symbol_completion_list)
(make_symbol_completion_type, make_file_symbol_completion_list)
(make_source_files_completion_list): Delete.
(default_collect_symbol_completion_matches_break_on)
(default_collect_symbol_completion_matches)
(collect_symbol_completion_matches)
(collect_symbol_completion_matches_type)
(collect_file_symbol_completion_matches)
(make_source_files_completion_list): New.
* top.c (init_main): Don't install a rl_completion_entry_function
hook. Install a rl_attempted_completion_function hook instead.
* tui/tui-layout.c (layout_completer): Adjust to work with a
completion_tracker.
* tui/tui-regs.c (tui_reggroup_completer):
* tui/tui-win.c (window_name_completer, focus_completer)
(winheight_completer): Adjust to work with a completion_tracker.
* value.c: Include "completer.h".
(complete_internalvar): Adjust to work with a completion_tracker.
* value.h (complete_internalvar): Likewise.
2017-07-17 14:45:59 +01:00
|
|
|
|
tracker.add_completion (std::move (item));
|
2009-02-06 21:33:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Helper for cmdpy_init which locates the command list to use and
|
|
|
|
|
|
pulls out the command name.
|
2013-11-29 12:00:47 -08:00
|
|
|
|
|
2011-09-08 19:51:27 +00:00
|
|
|
|
NAME is the command name list. The final word in the list is the
|
2009-02-06 21:33:59 +00:00
|
|
|
|
name of the new command. All earlier words must be existing prefix
|
|
|
|
|
|
commands.
|
|
|
|
|
|
|
gdb/python/guile: fix segfault from nested prefix command creation
A commit I recently pushed:
commit 0b5023cc71d3af8b18e10e6599a3f9381bc15265
Date: Sat Apr 12 09:15:53 2025 +0100
gdb/python/guile: user created prefix commands get help list
can trigger a segfault if a user tries to create nested prefix
commands. For example, this will trigger a crash:
(gdb) python gdb.ParameterPrefix("prefix-1", gdb.COMMAND_NONE)
(gdb) python gdb.ParameterPrefix("prefix-1 prefix-2", gdb.COMMAND_NONE)
Fatal signal: Segmentation fault
... etc ...
If the user adds an actual parameter under 'prefix-1' before creating
'prefix-2', then everything is fine:
(gdb) python gdb.ParameterPrefix("prefix-1", gdb.COMMAND_NONE)
(gdb) python gdb.Parameter('prefix-1 param-1', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)
(gdb) python gdb.ParameterPrefix("prefix-1 prefix-2", gdb.COMMAND_NONE)
The mistake in the above patch is in how gdbpy_parse_command_name is
used. The BASE_LIST output argument from this function points to the
list of commands for the prefix, not to the prefix command itself.
So when gdbpy_parse_command_name is called for 'prefix-1 prefix-2',
BASE_LIST points to the list of commands associated with 'prefix-1',
not to the actual 'prefix-1' cmd_list_element.
Back in cmdpy_init, from where gdbpy_parse_command_name was called, I
was walking back from the first entry in BASE_LIST to figure out if
this was a "show" prefix command or not. However, if BASE_LIST is
empty then there is no first item, and this would trigger the
segfault.
The solution it to extend gdbpy_parse_command_name to also return the
prefix cmd_list_element in addition to the existing values. With this
done, and cmdpy_init updated, the segfault is now avoided.
There's a new test that would trigger the crash without the patch.
And, of course, the above commit also broke guile in the exact same
way. And the fix is exactly the same. And there's a guile test too.
NOTE: We should investigate possibly sharing some of this boiler plate
helper code between Python and Guile. But not in this commit.
Approved-By: Tom Tromey <tom@tromey.com>
2025-06-03 17:23:10 +01:00
|
|
|
|
*BASE_LIST is set to the final prefix command's list of sub-commands.
|
2013-11-29 12:00:47 -08:00
|
|
|
|
|
2010-04-29 15:45:57 +00:00
|
|
|
|
START_LIST is the list in which the search starts.
|
|
|
|
|
|
|
gdb/python/guile: fix segfault from nested prefix command creation
A commit I recently pushed:
commit 0b5023cc71d3af8b18e10e6599a3f9381bc15265
Date: Sat Apr 12 09:15:53 2025 +0100
gdb/python/guile: user created prefix commands get help list
can trigger a segfault if a user tries to create nested prefix
commands. For example, this will trigger a crash:
(gdb) python gdb.ParameterPrefix("prefix-1", gdb.COMMAND_NONE)
(gdb) python gdb.ParameterPrefix("prefix-1 prefix-2", gdb.COMMAND_NONE)
Fatal signal: Segmentation fault
... etc ...
If the user adds an actual parameter under 'prefix-1' before creating
'prefix-2', then everything is fine:
(gdb) python gdb.ParameterPrefix("prefix-1", gdb.COMMAND_NONE)
(gdb) python gdb.Parameter('prefix-1 param-1', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)
(gdb) python gdb.ParameterPrefix("prefix-1 prefix-2", gdb.COMMAND_NONE)
The mistake in the above patch is in how gdbpy_parse_command_name is
used. The BASE_LIST output argument from this function points to the
list of commands for the prefix, not to the prefix command itself.
So when gdbpy_parse_command_name is called for 'prefix-1 prefix-2',
BASE_LIST points to the list of commands associated with 'prefix-1',
not to the actual 'prefix-1' cmd_list_element.
Back in cmdpy_init, from where gdbpy_parse_command_name was called, I
was walking back from the first entry in BASE_LIST to figure out if
this was a "show" prefix command or not. However, if BASE_LIST is
empty then there is no first item, and this would trigger the
segfault.
The solution it to extend gdbpy_parse_command_name to also return the
prefix cmd_list_element in addition to the existing values. With this
done, and cmdpy_init updated, the segfault is now avoided.
There's a new test that would trigger the crash without the patch.
And, of course, the above commit also broke guile in the exact same
way. And the fix is exactly the same. And there's a guile test too.
NOTE: We should investigate possibly sharing some of this boiler plate
helper code between Python and Guile. But not in this commit.
Approved-By: Tom Tromey <tom@tromey.com>
2025-06-03 17:23:10 +01:00
|
|
|
|
When PREFIX_CMD is not NULL then *PREFIX_CMD is set to the prefix
|
|
|
|
|
|
command itself, or NULL, if there is no prefix command.
|
|
|
|
|
|
|
2021-05-12 13:50:05 -04:00
|
|
|
|
This function returns the name of the new command. On error sets the Python
|
|
|
|
|
|
error and returns NULL. */
|
2011-09-08 19:51:27 +00:00
|
|
|
|
|
2021-05-12 13:50:05 -04:00
|
|
|
|
gdb::unique_xmalloc_ptr<char>
|
2011-09-08 19:51:27 +00:00
|
|
|
|
gdbpy_parse_command_name (const char *name,
|
2010-04-29 15:45:57 +00:00
|
|
|
|
struct cmd_list_element ***base_list,
|
gdb/python/guile: fix segfault from nested prefix command creation
A commit I recently pushed:
commit 0b5023cc71d3af8b18e10e6599a3f9381bc15265
Date: Sat Apr 12 09:15:53 2025 +0100
gdb/python/guile: user created prefix commands get help list
can trigger a segfault if a user tries to create nested prefix
commands. For example, this will trigger a crash:
(gdb) python gdb.ParameterPrefix("prefix-1", gdb.COMMAND_NONE)
(gdb) python gdb.ParameterPrefix("prefix-1 prefix-2", gdb.COMMAND_NONE)
Fatal signal: Segmentation fault
... etc ...
If the user adds an actual parameter under 'prefix-1' before creating
'prefix-2', then everything is fine:
(gdb) python gdb.ParameterPrefix("prefix-1", gdb.COMMAND_NONE)
(gdb) python gdb.Parameter('prefix-1 param-1', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)
(gdb) python gdb.ParameterPrefix("prefix-1 prefix-2", gdb.COMMAND_NONE)
The mistake in the above patch is in how gdbpy_parse_command_name is
used. The BASE_LIST output argument from this function points to the
list of commands for the prefix, not to the prefix command itself.
So when gdbpy_parse_command_name is called for 'prefix-1 prefix-2',
BASE_LIST points to the list of commands associated with 'prefix-1',
not to the actual 'prefix-1' cmd_list_element.
Back in cmdpy_init, from where gdbpy_parse_command_name was called, I
was walking back from the first entry in BASE_LIST to figure out if
this was a "show" prefix command or not. However, if BASE_LIST is
empty then there is no first item, and this would trigger the
segfault.
The solution it to extend gdbpy_parse_command_name to also return the
prefix cmd_list_element in addition to the existing values. With this
done, and cmdpy_init updated, the segfault is now avoided.
There's a new test that would trigger the crash without the patch.
And, of course, the above commit also broke guile in the exact same
way. And the fix is exactly the same. And there's a guile test too.
NOTE: We should investigate possibly sharing some of this boiler plate
helper code between Python and Guile. But not in this commit.
Approved-By: Tom Tromey <tom@tromey.com>
2025-06-03 17:23:10 +01:00
|
|
|
|
struct cmd_list_element **start_list,
|
|
|
|
|
|
struct cmd_list_element **prefix_cmd)
|
2009-02-06 21:33:59 +00:00
|
|
|
|
{
|
|
|
|
|
|
struct cmd_list_element *elt;
|
2011-09-08 19:51:27 +00:00
|
|
|
|
int len = strlen (name);
|
2009-02-06 21:33:59 +00:00
|
|
|
|
int i, lastchar;
|
Constify strings in tracepoint.c, lookup_cmd and the completers.
This is sort of a continuation of Keith's parse_exp_1 constification
patch. It started out by undoing these bits:
@@ -754,9 +754,12 @@ validate_actionline (char **line, struct
tmp_p = p;
for (loc = t->base.loc; loc; loc = loc->next)
{
- p = tmp_p;
- exp = parse_exp_1 (&p, loc->address,
+ const char *q;
+
+ q = tmp_p;
+ exp = parse_exp_1 (&q, loc->address,
block_for_pc (loc->address), 1);
+ p = (char *) q;
and progressively making more things const upwards, fixing fallout,
rinse repeat, until GDB built again (--enable-targets=all).
That ended up constifying lookup_cmd/add_cmd and (lots of) friends,
and the completers.
I didn't try to constify the command hooks themselves, because I know
upfront there are commands that write to the command string argument,
and I think I managed to stop at a nice non-hacky split point already.
I think the only non-really-super-obvious changes are
tracepoint.c:validate_actionline, and tracepoint.c:trace_dump_actions.
The rest is just mostly about 'char *' => 'const char *', 'char **'=>
'const char **', and the occasional (e.g., deprecated_cmd_warning)
case of 'char **'=> 'const char *', where/when I noticed that nothing
actually cares about the pointer to pointer output.
Tested on x86_64 Fedora 17, native and gdbserver.
gdb/
2013-03-13 Pedro Alves <palves@redhat.com>
* ada-lang.c (struct add_partial_datum) <text, text0, word>: Make
fields const.
(ada_make_symbol_completion_list): Make "text0" parameter const.
* ax-gdb.c (agent_eval_command_one): Make "exp" parameter const.
* breakpoint.c (condition_completer): Make "text" and "word"
parameters const. Adjust.
(check_tracepoint_command): Adjust to validate_actionline
prototype change.
(catch_syscall_completer): Make "text" and "word" parameters
const.
* cli/cli-cmds.c (show_user): Make "comname" local const.
(valid_command_p): Make "command" parameter const.
(alias_command): Make "alias_prefix" and "command_prefix" locals
const.
* cli/cli-decode.c (add_cmd): Make "name" parameter const.
(add_alias_cmd): Make "name" and "oldname" parameters const.
Adjust. No longer make copy of OLDNAME.
(add_prefix_cmd, add_abbrev_prefix_cmd, add_set_or_show_cmd)
(add_setshow_cmd_full, add_setshow_enum_cmd)
(add_setshow_auto_boolean_cmd, add_setshow_boolean_cmd)
(add_setshow_filename_cmd, add_setshow_string_cmd)
(add_setshow_string_noescape_cmd)
(add_setshow_optional_filename_cmd, add_setshow_integer_cmd)
(add_setshow_uinteger_cmd, add_setshow_zinteger_cmd)
(add_setshow_zuinteger_unlimited_cmd, add_setshow_zuinteger_cmd)
(delete_cmd, add_info, add_info_alias, add_com, add_com_alias):
Make "name" parameter const.
(help_cmd): Rename "command" parameter to "arg". New const local
"command".
(find_cmd): Make "command" parameter const.
(lookup_cmd_1): Make "text" parameter pointer to const. Adjust to
deprecated_cmd_warning prototype change.
(undef_cmd_error): Make "cmdtype" parameter const.
(lookup_cmd): Make "line" parameter const.
(deprecated_cmd_warning): Change type of "text" parameter to
pointer to const char, from pointer to pointer to char. Adjust.
(lookup_cmd_composition): Make "text" parameter const.
(complete_on_cmdlist, complete_on_enum): Make "text" and "word"
parameters const.
* cli/cli-decode.h (struct cmd_list_element) <name>: Make field
const.
* cli/cli-script.c (validate_comname): Make "tem" local const.
(define_command): New const local "tem_c". Use it in calls to
lookup_cmd.
(document_command): Make "tem" and "comfull" locals const.
(show_user_1): Make "prefix" and "name" parameters const.
* cli-script.h (show_user_1): Make "prefix" and "name" parameters
const.
* command.h (add_cmd, add_alias_cmd, add_prefix_cmd)
(add_abbrev_prefix_cmd, completer_ftype, lookup_cmd, lookup_cmd_1)
(deprecated_cmd_warning, lookup_cmd_composition, add_com)
(add_com_alias, add_info, add_info_alias, complete_on_cmdlist)
(complete_on_enum, add_setshow_enum_cmd)
(add_setshow_auto_boolean_cmd, add_setshow_boolean_cmd)
(add_setshow_filename_cmd, add_setshow_string_cmd)
(add_setshow_string_noescape_cmd)
(add_setshow_optional_filename_cmd, add_setshow_integer_cmd)
(add_setshow_uinteger_cmd, add_setshow_zinteger_cmd)
(add_setshow_zuinteger_cmd, add_setshow_zuinteger_unlimited_cmd):
Change prototypes, constifying strings.
* completer.c (noop_completer, filename_completer): Make "text"
and "prefix" parameters const.
(location_completer, expression_completer)
(complete_line_internal): Make "text" and "prefix" parameters
const and adjust.
(command_completer, signal_completer): Make "text" and "prefix"
parameters const.
* completer.h (noop_completer, filename_completer)
(expression_completer, location_completer, command_completer)
(signal_completer): Change prototypes.
* corefile.c (complete_set_gnutarget): Make "text" and "word"
parameters const.
* cp-abi.c (cp_abi_completer): Likewise.
* expression.h (parse_expression_for_completion): Change
prototype.
* f-lang.c (f_make_symbol_completion_list): Make "text" and "word"
parameters const.
* infcmd.c (_initialize_infcmd): Make "cmd_name" local const.
* infrun.c (handle_completer): Make "text" and "word" parameters
const.
* interps.c (interpreter_completer): Make "text" and "word"
parameters const.
* language.h (struct language_defn)
<la_make_symbol_completion_list>: Make "text" and "word"
parameters const.
* parse.c (parse_exp_1): Move const hack to parse_exp_in_context.
(parse_exp_in_context): Rename to ...
(parse_exp_in_context_1): ... this.
(parse_exp_in_context): Reimplement, with const hack from
parse_exp_1.
(parse_expression_for_completion): Make "string" parameter const.
* printcmd.c (decode_format): Make "string_ptr" parameter pointer
to pointer to const char. Adjust.
(print_command_1): Make "exp" parameter const.
(output_command): Rename to ...
(output_command_const): ... this. Make "exp" parameter const.
(output_command): Reimplement.
(x_command): Adjust.
(display_command): Rename "exp" parameter to "arg". New "exp"
local, const version of "arg".
* python/py-auto-load.c (gdbpy_initialize_auto_load): Make
"cmd_name" local const.
* python/py-cmd.c (cmdpy_destroyer): Cast const away in xfree
call.
(cmdpy_completer): Make "text" and "word" parameters const.
(gdbpy_parse_command_name): Make "prefix_text2" local const.
* python/py-param.c (add_setshow_generic): Make "tmp_name" local
const.
* remote.c (_initialize_remote): Make "cmd_name" local const.
* symtab.c (language_search_unquoted_string): Make "text" and "p"
parameters const. Adjust.
(completion_list_add_fields): Make "sym_text", "text" and "word"
parameters const.
(struct add_name_data) <sym_text, text, word>: Make fields const.
(default_make_symbol_completion_list_break_on): Make "text" and
"word" parameters const. Adjust locals.
(default_make_symbol_completion_list)
(make_symbol_completion_list, make_symbol_completion_type)
(make_symbol_completion_list_fn): Make "text" and "word"
parameters const.
(make_file_symbol_completion_list): Make "text", "word" and
"srcfile" parameters const. Adjust locals.
(add_filename_to_list): Make "text" and "word" parameters const.
(struct add_partial_filename_data) <text, word>: Make fields
const.
(make_source_files_completion_list): Make "text" and "word"
parameters const.
* symtab.h (default_make_symbol_completion_list_break_on)
(default_make_symbol_completion_list, make_symbol_completion_list)
(make_symbol_completion_type enum type_code)
(make_symbol_completion_list_fn make_file_symbol_completion_list)
(make_source_files_completion_list): Change prototype.
* top.c (execute_command): Adjust to pass pointer to pointer to
const char to lookup_cmd, and to deprecated_cmd_warning prototype
change.
(set_verbose): Make "cmdname" local const.
* tracepoint.c (decode_agent_options): Make "exp" parameter const,
and adjust.
(validate_actionline): Make "line" parameter a pointer to const
char, and adjust.
(encode_actions_1): Make "action_exp" local const, and adjust.
(encode_actions): Adjust.
(replace_comma): Delete.
(trace_dump_actions): Make "action_exp" and "next_comma" locals
const, and adjust. Don't frob the action string while splitting
it at commas. Instead, make a copy of each split substring in
turn.
(trace_dump_command): Adjust to validate_actionline prototype
change.
* tracepoint.h (decode_agent_options, decode_agent_options)
(encode_actions, validate_actionline): Change prototypes.
* valprint.h (output_command): Delete declaration.
(output_command_const): Declare.
* value.c (function_destroyer): Cast const away in xfree call.
2013-03-13 18:34:55 +00:00
|
|
|
|
const char *prefix_text2;
|
2009-02-06 21:33:59 +00:00
|
|
|
|
|
gdb/python/guile: fix segfault from nested prefix command creation
A commit I recently pushed:
commit 0b5023cc71d3af8b18e10e6599a3f9381bc15265
Date: Sat Apr 12 09:15:53 2025 +0100
gdb/python/guile: user created prefix commands get help list
can trigger a segfault if a user tries to create nested prefix
commands. For example, this will trigger a crash:
(gdb) python gdb.ParameterPrefix("prefix-1", gdb.COMMAND_NONE)
(gdb) python gdb.ParameterPrefix("prefix-1 prefix-2", gdb.COMMAND_NONE)
Fatal signal: Segmentation fault
... etc ...
If the user adds an actual parameter under 'prefix-1' before creating
'prefix-2', then everything is fine:
(gdb) python gdb.ParameterPrefix("prefix-1", gdb.COMMAND_NONE)
(gdb) python gdb.Parameter('prefix-1 param-1', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)
(gdb) python gdb.ParameterPrefix("prefix-1 prefix-2", gdb.COMMAND_NONE)
The mistake in the above patch is in how gdbpy_parse_command_name is
used. The BASE_LIST output argument from this function points to the
list of commands for the prefix, not to the prefix command itself.
So when gdbpy_parse_command_name is called for 'prefix-1 prefix-2',
BASE_LIST points to the list of commands associated with 'prefix-1',
not to the actual 'prefix-1' cmd_list_element.
Back in cmdpy_init, from where gdbpy_parse_command_name was called, I
was walking back from the first entry in BASE_LIST to figure out if
this was a "show" prefix command or not. However, if BASE_LIST is
empty then there is no first item, and this would trigger the
segfault.
The solution it to extend gdbpy_parse_command_name to also return the
prefix cmd_list_element in addition to the existing values. With this
done, and cmdpy_init updated, the segfault is now avoided.
There's a new test that would trigger the crash without the patch.
And, of course, the above commit also broke guile in the exact same
way. And the fix is exactly the same. And there's a guile test too.
NOTE: We should investigate possibly sharing some of this boiler plate
helper code between Python and Guile. But not in this commit.
Approved-By: Tom Tromey <tom@tromey.com>
2025-06-03 17:23:10 +01:00
|
|
|
|
if (prefix_cmd != nullptr)
|
|
|
|
|
|
*prefix_cmd = nullptr;
|
|
|
|
|
|
|
2009-02-06 21:33:59 +00:00
|
|
|
|
/* Skip trailing whitespace. */
|
2011-09-08 19:51:27 +00:00
|
|
|
|
for (i = len - 1; i >= 0 && (name[i] == ' ' || name[i] == '\t'); --i)
|
2009-02-06 21:33:59 +00:00
|
|
|
|
;
|
|
|
|
|
|
if (i < 0)
|
|
|
|
|
|
{
|
2010-04-14 13:18:55 +00:00
|
|
|
|
PyErr_SetString (PyExc_RuntimeError, _("No command name found."));
|
2009-02-06 21:33:59 +00:00
|
|
|
|
return NULL;
|
|
|
|
|
|
}
|
|
|
|
|
|
lastchar = i;
|
|
|
|
|
|
|
|
|
|
|
|
/* Find first character of the final word. */
|
2019-09-08 21:54:18 +02:00
|
|
|
|
for (; i > 0 && valid_cmd_char_p (name[i - 1]); --i)
|
2009-02-06 21:33:59 +00:00
|
|
|
|
;
|
2021-05-12 13:50:05 -04:00
|
|
|
|
|
gdb/python/guile: remove some explicit calls to xmalloc
In gdbpy_parse_command_name (python/py-cmd.c) there is a call to
xmalloc that can easily be replaced with a call to
make_unique_xstrndup, which makes the code easier to read (I think).
In gdbscm_parse_command_name (guile/scm-cmd.c) the same fix can be
applied to remove an identical xmalloc call. And there is an
additional xmalloc call, which can also be replaced with
make_unique_xstrndup in the same way.
The second xmalloc call in gdbscm_parse_command_name was also present
in gdbpy_parse_command_name at one point, but was replaced with a use
of std::string by this commit:
commit 075c55e0cc0a68eeab777027213c2f545618e844
Date: Wed Dec 26 11:05:57 2018 -0700
Remove more calls to xfree from Python
I haven't changed the gdbscm_parse_command_name to use std::string
though, as that doesn't work well with the guile exception model.
Guile exceptions work by performing a longjmp from the function that
raises the exception, back to the guile run-time. The consequence of
this is that destructors are not run. For example, if
gdbscm_parse_command_name calls gdbscm_out_of_range_error, then any
function local objects in gdbscm_parse_command_name will not have
their destructors called.
What this means is that, for the existing `result` and `prefix_text`
locals, any allocated memory managed by these objects will be leaked
if an exception is called. However, fixing this is pretty easy, one
way is to just assign nullptr to these locals before raising the
exception, this would cause the allocated memory to be released.
But for std::string it is harder to ensure that the managed memory has
actually been released. We can call std::string::clear() and then
maybe std::string::shrink_to_fit(), but this is still not guaranteed
to release any managed memory. In fact, I believe the only way to
ensure all managed memory is released, is to call the std::string
destructor.
And so, for functions that can throw a guile exception, it is easier
to just avoid std::string.
As for the memory leak that I identify above; I'll fix that in a
follow on commit.
Approved-By: Tom Tromey <tom@tromey.com>
2025-06-04 19:54:01 +01:00
|
|
|
|
gdb::unique_xmalloc_ptr<char> result
|
|
|
|
|
|
= make_unique_xstrndup (&name[i], lastchar - i + 1);
|
2009-02-06 21:33:59 +00:00
|
|
|
|
|
|
|
|
|
|
/* Skip whitespace again. */
|
2011-09-08 19:51:27 +00:00
|
|
|
|
for (--i; i >= 0 && (name[i] == ' ' || name[i] == '\t'); --i)
|
2009-02-06 21:33:59 +00:00
|
|
|
|
;
|
|
|
|
|
|
if (i < 0)
|
|
|
|
|
|
{
|
2010-04-29 15:45:57 +00:00
|
|
|
|
*base_list = start_list;
|
2009-02-06 21:33:59 +00:00
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-12-26 11:05:57 -07:00
|
|
|
|
std::string prefix_text (name, i + 1);
|
2009-02-06 21:33:59 +00:00
|
|
|
|
|
2018-12-26 11:05:57 -07:00
|
|
|
|
prefix_text2 = prefix_text.c_str ();
|
default-args: allow to define default arguments for aliases
Currently, a user can define an alias, but cannot have default
arguments for this alias.
This patch modifies the 'alias' command so that default args can
be provided.
(gdb) h alias
Define a new command that is an alias of an existing command.
Usage: alias [-a] [--] ALIAS = COMMAND [DEFAULT-ARGS...]
ALIAS is the name of the alias command to create.
COMMAND is the command being aliased to.
Options:
-a
Specify that ALIAS is an abbreviation of COMMAND.
Abbreviations are not used in command completion..
GDB will automatically prepend the provided DEFAULT-ARGS to the list
of arguments explicitly provided when using ALIAS.
Use "help aliases" to list all user defined aliases and their default args.
Examples:
Make "spe" an alias of "set print elements":
alias spe set print elements
Make "elms" an alias of "elements" in the "set print" command:
alias -a set print elms set print elements
Make "btf" an alias of "backtrace -full -past-entry -past-main" :
alias btf = backtrace -full -past-entry -past-main
Make "wLapPeu" an alias of 2 nested "with":
alias wLapPeu = with language pascal -- with print elements unlimited --
(gdb)
The way 'default-args' is implemented makes it trivial to set default
args also for GDB commands (such as "backtrace") and for GDB pre-defined
aliases (such as "bt"). It was however deemed better to not allow to
define default arguments for pre-defined commands and aliases, to avoid
users believing that e.g. default args for "backtrace" would apply to "bt".
If needed, default-args could be allowed for GDB predefined commands
and aliases by adding a command
'set default-args GDB_COMMAND_OR_PREDEFINED_ALIAS [DEFAULT-ARGS...]'.
* 'alias' command now has a completer that helps to complete:
- ALIAS (if the user defines an alias after a prefix),
- the aliased COMMAND
- the possible options for the aliased COMMAND.
* Help and apropos commands show the definitions of the aliases
that have default arguments, e.g.
(gdb) help backtrace
backtrace, btf, where, bt
alias btf = backtrace -full -past-entry -past-main
Print backtrace of all stack frames, or innermost COUNT frames.
Usage: backtrace [OPTION]... [QUALIFIER]... [COUNT | -COUNT]
Options:
-entry-values no|only|preferred|if-needed|both|compact|default
Set printing of function arguments at function entry.
...
gdb/ChangeLog
2020-06-22 Philippe Waroquiers <philippe.waroquiers@skynet.be>
* cli/cli-cmds.c (lookup_cmd_for_default_args)
(alias_command_completer)
(make_alias_options_def_group): New functions.
(alias_opts, alias_option_defs): New struct and array.
(alias_usage_error): Update usage.
(alias_command): Handles optional DEFAULT-ARGS... arguments.
Use option framework.
(_initialize_cli_cmds): Update alias command help.
Update aliases command help.
(show_user):
Add NULL for new default_args lookup_cmd argument.
(valid_command_p): Rename to validate_aliased_command.
Add NULL for new default_args lookup_cmd argument. Verify that the
aliased_command has no default args.
* cli/cli-decode.c (help_cmd): Show aliases definitions.
(lookup_cmd_1, lookup_cmd): New argument default_args.
(add_alias_cmd):
Add NULL for new default_args lookup_cmd argument.
(print_help_for_command): Show default args under the layout
alias some_alias = some_aliased_cmd some_alias_default_arg.
* cli/cli-decode.h (struct cmd_list_element): New member default_args.
xfree default_args in destructor.
* cli/cli-script.c (process_next_line, do_define_command):
Add NULL for new default_args lookup_cmd argument.
* command.h: Declare new default_args argument in lookup_cmd
and lookup_cmd_1.
* completer.c (complete_line_internal_1):
Add NULL for new default_args lookup_cmd or lookup_cmd_1 argument.
* guile/scm-cmd.c (gdbscm_parse_command_name): Likewise.
* guile/scm-param.c (add_setshow_generic, pascm_parameter_defined_p):
Likewise.
* infcmd.c (_initialize_infcmd): Likewise.
* python/py-auto-load.c (gdbpy_initialize_auto_load): Likewise.
* python/py-cmd.c (gdbpy_parse_command_name): Likewise.
* python/py-param.c (add_setshow_generic): Likewise.
* remote.c (_initialize_remote): Likewise.
* top.c (execute_command): Prepend default_args if command has some.
(set_verbose):
Add NULL for new default_args lookup_cmd or lookup_cmd_1 argument.
* tracepoint.c (validate_actionline, encode_actions_1):
Add NULL for new default_args lookup_cmd or lookup_cmd_1 argument.
2019-06-19 12:49:55 +02:00
|
|
|
|
elt = lookup_cmd_1 (&prefix_text2, *start_list, NULL, NULL, 1);
|
gdb/python/guile: check for invalid prefixes in Command/Parameter creation
The manual for gdb.Parameter says:
If NAME consists of multiple words, and no prefix parameter group
can be found, an exception is raised.
This makes sense; we cannot create a parameter within a prefix group,
if the prefix doesn't exist. And this almost works, so:
(gdb) python gdb.Parameter("xxx foo", gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)
Python Exception <class 'RuntimeError'>: Could not find command prefix xxx.
Error occurred in Python: Could not find command prefix xxx.
The prefix 'xxx' doesn't exist, and we get an error. But, if we try
multiple levels of prefix:
(gdb) python gdb.Parameter("print xxx foo", gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)
This completes without error, however, we didn't get what we were
maybe expecting:
(gdb) show print xxx foo
Undefined show print command: "xxx foo". Try "help show print".
But we did get:
(gdb) show print foo
The current value of 'print foo' is "off".
GDB stopped scanning the prefix string at the unknown 'xxx', and just
created the parameter there. I don't think this makes sense, nor is
it inline with the manual.
An identical problem exists with gdb.Command creation; GDB stops
parsing the prefix at the first unknown prefix, and just creates the
command there. The manual for gdb.Command says:
NAME is the name of the command. If NAME consists of multiple
words, then the initial words are looked for as prefix commands.
In this case, if one of the prefix commands does not exist, an
exception is raised.
So again, the correct action is, I believe, to raise an exception.
The problem is in gdbpy_parse_command_name (python/py-cmd.c), GDB
calls lookup_cmd_1 to look through the prefix string and return the
last prefix group. If the very first prefix word is invalid then
lookup_cmd_1 returns NULL, and this case is handled. However, if
there is a valid prefix, followed by an invalid prefix, then
lookup_cmd_1 will return a pointer to the last valid prefix list, and
will update the input argument to point to the start of the invalid
prefix word. This final case, where the input is left pointing to an
unknown prefix, was previously not handled.
I've fixed gdbpy_parse_command_name, and added tests for command and
parameter creation to cover this case.
The exact same error is present in the guile API too. The guile
documentation for make-parameter and make-command says the same things
about unknown prefixes resulting in an exception, but the same error
is present in gdbscm_parse_command_name (guile/scm-cmd.c), so I've
fixed that too, and added some tests.
2025-04-11 16:01:02 +01:00
|
|
|
|
if (elt == nullptr || elt == CMD_LIST_AMBIGUOUS || *prefix_text2 != '\0')
|
2009-02-06 21:33:59 +00:00
|
|
|
|
{
|
2010-04-14 13:18:55 +00:00
|
|
|
|
PyErr_Format (PyExc_RuntimeError, _("Could not find command prefix %s."),
|
2018-12-26 11:05:57 -07:00
|
|
|
|
prefix_text.c_str ());
|
2009-02-06 21:33:59 +00:00
|
|
|
|
return NULL;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-05-14 15:38:49 -04:00
|
|
|
|
if (elt->is_prefix ())
|
2009-02-06 21:33:59 +00:00
|
|
|
|
{
|
2021-05-17 14:01:08 -04:00
|
|
|
|
*base_list = elt->subcommands;
|
gdb/python/guile: fix segfault from nested prefix command creation
A commit I recently pushed:
commit 0b5023cc71d3af8b18e10e6599a3f9381bc15265
Date: Sat Apr 12 09:15:53 2025 +0100
gdb/python/guile: user created prefix commands get help list
can trigger a segfault if a user tries to create nested prefix
commands. For example, this will trigger a crash:
(gdb) python gdb.ParameterPrefix("prefix-1", gdb.COMMAND_NONE)
(gdb) python gdb.ParameterPrefix("prefix-1 prefix-2", gdb.COMMAND_NONE)
Fatal signal: Segmentation fault
... etc ...
If the user adds an actual parameter under 'prefix-1' before creating
'prefix-2', then everything is fine:
(gdb) python gdb.ParameterPrefix("prefix-1", gdb.COMMAND_NONE)
(gdb) python gdb.Parameter('prefix-1 param-1', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)
(gdb) python gdb.ParameterPrefix("prefix-1 prefix-2", gdb.COMMAND_NONE)
The mistake in the above patch is in how gdbpy_parse_command_name is
used. The BASE_LIST output argument from this function points to the
list of commands for the prefix, not to the prefix command itself.
So when gdbpy_parse_command_name is called for 'prefix-1 prefix-2',
BASE_LIST points to the list of commands associated with 'prefix-1',
not to the actual 'prefix-1' cmd_list_element.
Back in cmdpy_init, from where gdbpy_parse_command_name was called, I
was walking back from the first entry in BASE_LIST to figure out if
this was a "show" prefix command or not. However, if BASE_LIST is
empty then there is no first item, and this would trigger the
segfault.
The solution it to extend gdbpy_parse_command_name to also return the
prefix cmd_list_element in addition to the existing values. With this
done, and cmdpy_init updated, the segfault is now avoided.
There's a new test that would trigger the crash without the patch.
And, of course, the above commit also broke guile in the exact same
way. And the fix is exactly the same. And there's a guile test too.
NOTE: We should investigate possibly sharing some of this boiler plate
helper code between Python and Guile. But not in this commit.
Approved-By: Tom Tromey <tom@tromey.com>
2025-06-03 17:23:10 +01:00
|
|
|
|
if (prefix_cmd != nullptr)
|
|
|
|
|
|
*prefix_cmd = elt;
|
2009-02-06 21:33:59 +00:00
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2010-04-14 13:18:55 +00:00
|
|
|
|
PyErr_Format (PyExc_RuntimeError, _("'%s' is not a prefix command."),
|
2018-12-26 11:05:57 -07:00
|
|
|
|
prefix_text.c_str ());
|
2009-02-06 21:33:59 +00:00
|
|
|
|
return NULL;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Object initializer; sets up gdb-side structures for command.
|
|
|
|
|
|
|
2009-03-21 03:13:02 +00:00
|
|
|
|
Use: __init__(NAME, COMMAND_CLASS [, COMPLETER_CLASS][, PREFIX]]).
|
2009-02-06 21:33:59 +00:00
|
|
|
|
|
|
|
|
|
|
NAME is the name of the command. It may consist of multiple words,
|
|
|
|
|
|
in which case the final word is the name of the new command, and
|
|
|
|
|
|
earlier words must be prefix commands.
|
|
|
|
|
|
|
2009-03-21 03:13:02 +00:00
|
|
|
|
COMMAND_CLASS is the kind of command. It should be one of the COMMAND_*
|
2009-02-06 21:33:59 +00:00
|
|
|
|
constants defined in the gdb module.
|
|
|
|
|
|
|
2009-03-21 03:13:02 +00:00
|
|
|
|
COMPLETER_CLASS is the kind of completer. If not given, the
|
2009-02-06 21:33:59 +00:00
|
|
|
|
"complete" method will be used. Otherwise, it should be one of the
|
|
|
|
|
|
COMPLETE_* constants defined in the gdb module.
|
|
|
|
|
|
|
|
|
|
|
|
If PREFIX is True, then this command is a prefix command.
|
|
|
|
|
|
|
|
|
|
|
|
The documentation for the command is taken from the doc string for
|
2011-09-08 19:51:27 +00:00
|
|
|
|
the python class. */
|
|
|
|
|
|
|
2009-02-06 21:33:59 +00:00
|
|
|
|
static int
|
2009-03-21 03:13:02 +00:00
|
|
|
|
cmdpy_init (PyObject *self, PyObject *args, PyObject *kw)
|
2009-02-06 21:33:59 +00:00
|
|
|
|
{
|
|
|
|
|
|
cmdpy_object *obj = (cmdpy_object *) self;
|
2011-06-24 19:47:37 +00:00
|
|
|
|
const char *name;
|
2009-02-06 21:33:59 +00:00
|
|
|
|
int cmdtype;
|
|
|
|
|
|
int completetype = -1;
|
|
|
|
|
|
struct cmd_list_element **cmd_list;
|
-Wwrite-strings: Add a PyArg_ParseTupleAndKeywords "const char *" overload
-Wwrite-strings flags code like:
static char *keywords[] = {"command", "from_tty", "to_string", NULL };
as needing "(char *)" casts, because string literals are "const char []".
We can get rid of the casts by changing the array type like this:
- static char *keywords[] = {"command", "from_tty", "to_string", NULL };
+ static const char *keywords[] = {"command", "from_tty", "to_string", NULL };
However, passing the such array to PyArg_ParseTupleAndKeywords no longer
works OOTB, because PyArg_ParseTupleAndKeywords expects a "char **":
PyArg_ParseTupleAndKeywords(PyObject *args, PyObject *kw,
const char *format,
char *keywords[], ...);
and "const char **" is not implicitly convertible to "char **". C++
is more tolerant that C here WRT aliasing, and a const_cast<char **>
is fine. However, to avoid having all callers do the cast themselves,
this commit defines a gdb_PyArg_ParseTupleAndKeywords function here
with a corresponding 'keywords' parameter type that does the cast in a
single place.
gdb/ChangeLog:
2017-04-05 Pedro Alves <palves@redhat.com>
* python/python-internal.h (gdb_PyArg_ParseTupleAndKeywords): New
static inline function.
* python/py-arch.c (archpy_disassemble): Constify 'keywords'
array and use gdb_PyArg_ParseTupleAndKeywords.
* python/py-cmd.c (cmdpy_init): Likewise.
* python/py-finishbreakpoint.c (bpfinishpy_init): Likewise.
* python/py-inferior.c (infpy_read_memory, infpy_write_memory)
(infpy_search_memory): Likewise.
* python/py-objfile.c (objfpy_add_separate_debug_file)
(gdbpy_lookup_objfile): Likewise.
* python/py-symbol.c (gdbpy_lookup_symbol)
(gdbpy_lookup_global_symbol): Likewise.
* python/py-type.c (gdbpy_lookup_type): Likewise.
* python/py-value.c (valpy_lazy_string, valpy_string): Likewise.
* python/python.c (execute_gdb_command, gdbpy_write, gdbpy_flush):
Likewise.
2017-04-05 19:21:36 +01:00
|
|
|
|
static const char *keywords[] = { "name", "command_class", "completer_class",
|
|
|
|
|
|
"prefix", NULL };
|
2021-05-12 11:19:22 +01:00
|
|
|
|
PyObject *is_prefix_obj = NULL;
|
|
|
|
|
|
bool is_prefix = false;
|
2009-02-06 21:33:59 +00:00
|
|
|
|
|
|
|
|
|
|
if (obj->command)
|
|
|
|
|
|
{
|
|
|
|
|
|
/* Note: this is apparently not documented in Python. We return
|
|
|
|
|
|
0 for success, -1 for failure. */
|
|
|
|
|
|
PyErr_Format (PyExc_RuntimeError,
|
2010-04-14 13:18:55 +00:00
|
|
|
|
_("Command object already initialized."));
|
2009-02-06 21:33:59 +00:00
|
|
|
|
return -1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
-Wwrite-strings: Add a PyArg_ParseTupleAndKeywords "const char *" overload
-Wwrite-strings flags code like:
static char *keywords[] = {"command", "from_tty", "to_string", NULL };
as needing "(char *)" casts, because string literals are "const char []".
We can get rid of the casts by changing the array type like this:
- static char *keywords[] = {"command", "from_tty", "to_string", NULL };
+ static const char *keywords[] = {"command", "from_tty", "to_string", NULL };
However, passing the such array to PyArg_ParseTupleAndKeywords no longer
works OOTB, because PyArg_ParseTupleAndKeywords expects a "char **":
PyArg_ParseTupleAndKeywords(PyObject *args, PyObject *kw,
const char *format,
char *keywords[], ...);
and "const char **" is not implicitly convertible to "char **". C++
is more tolerant that C here WRT aliasing, and a const_cast<char **>
is fine. However, to avoid having all callers do the cast themselves,
this commit defines a gdb_PyArg_ParseTupleAndKeywords function here
with a corresponding 'keywords' parameter type that does the cast in a
single place.
gdb/ChangeLog:
2017-04-05 Pedro Alves <palves@redhat.com>
* python/python-internal.h (gdb_PyArg_ParseTupleAndKeywords): New
static inline function.
* python/py-arch.c (archpy_disassemble): Constify 'keywords'
array and use gdb_PyArg_ParseTupleAndKeywords.
* python/py-cmd.c (cmdpy_init): Likewise.
* python/py-finishbreakpoint.c (bpfinishpy_init): Likewise.
* python/py-inferior.c (infpy_read_memory, infpy_write_memory)
(infpy_search_memory): Likewise.
* python/py-objfile.c (objfpy_add_separate_debug_file)
(gdbpy_lookup_objfile): Likewise.
* python/py-symbol.c (gdbpy_lookup_symbol)
(gdbpy_lookup_global_symbol): Likewise.
* python/py-type.c (gdbpy_lookup_type): Likewise.
* python/py-value.c (valpy_lazy_string, valpy_string): Likewise.
* python/python.c (execute_gdb_command, gdbpy_write, gdbpy_flush):
Likewise.
2017-04-05 19:21:36 +01:00
|
|
|
|
if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "si|iO",
|
|
|
|
|
|
keywords, &name, &cmdtype,
|
2021-05-12 11:19:22 +01:00
|
|
|
|
&completetype, &is_prefix_obj))
|
2009-02-06 21:33:59 +00:00
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
|
|
if (cmdtype != no_class && cmdtype != class_run
|
|
|
|
|
|
&& cmdtype != class_vars && cmdtype != class_stack
|
|
|
|
|
|
&& cmdtype != class_files && cmdtype != class_support
|
|
|
|
|
|
&& cmdtype != class_info && cmdtype != class_breakpoint
|
|
|
|
|
|
&& cmdtype != class_trace && cmdtype != class_obscure
|
2020-04-28 08:54:17 -06:00
|
|
|
|
&& cmdtype != class_maintenance && cmdtype != class_user
|
gdb: add "essential" command class
Currently, there is no way for a new user to have an idea of common
useful commands and behaviors from the GDB interface itself, without
checking the example session in the documentation. This command class
aims to close that gap by providing a set of quickstart commands that
allows for any simple debug session to happen without anything too
egregious missing.
The set of commands was chosen somewhat arbitrarily, based on what I
used or missed the most. The one overarching important thing, however,
is that the list is kept short, so as to not overwhelm new users. This
is confirmed by the newly introduced selftest, essential_command_count,
which ensures there are 20 or fewer essential commands.
Here's the reasoning for some of the choices:
* The command "start" was picked over "run" because combining it with
"continue" achieves the same effect, and I prefer it over needing to set
a breakpoint on main to stop at the start of the inferior.
* The command "ptype" is chosen because I believe it is important to
provide a way for the user to check a variable's type from inside GDB,
and ptype is a more complete command than the alternative, "whatis".
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
Approved-By: Tom Tromey <tom@tromey.com>
2025-09-19 08:44:35 -03:00
|
|
|
|
&& cmdtype != class_tui && cmdtype != class_essential)
|
2009-02-06 21:33:59 +00:00
|
|
|
|
{
|
2010-04-14 13:18:55 +00:00
|
|
|
|
PyErr_Format (PyExc_RuntimeError, _("Invalid command class argument."));
|
2009-02-06 21:33:59 +00:00
|
|
|
|
return -1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (completetype < -1 || completetype >= (int) N_COMPLETERS)
|
|
|
|
|
|
{
|
2011-01-06 00:57:05 +00:00
|
|
|
|
PyErr_Format (PyExc_RuntimeError,
|
|
|
|
|
|
_("Invalid completion type argument."));
|
2009-02-06 21:33:59 +00:00
|
|
|
|
return -1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
gdb/python/guile: fix segfault from nested prefix command creation
A commit I recently pushed:
commit 0b5023cc71d3af8b18e10e6599a3f9381bc15265
Date: Sat Apr 12 09:15:53 2025 +0100
gdb/python/guile: user created prefix commands get help list
can trigger a segfault if a user tries to create nested prefix
commands. For example, this will trigger a crash:
(gdb) python gdb.ParameterPrefix("prefix-1", gdb.COMMAND_NONE)
(gdb) python gdb.ParameterPrefix("prefix-1 prefix-2", gdb.COMMAND_NONE)
Fatal signal: Segmentation fault
... etc ...
If the user adds an actual parameter under 'prefix-1' before creating
'prefix-2', then everything is fine:
(gdb) python gdb.ParameterPrefix("prefix-1", gdb.COMMAND_NONE)
(gdb) python gdb.Parameter('prefix-1 param-1', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)
(gdb) python gdb.ParameterPrefix("prefix-1 prefix-2", gdb.COMMAND_NONE)
The mistake in the above patch is in how gdbpy_parse_command_name is
used. The BASE_LIST output argument from this function points to the
list of commands for the prefix, not to the prefix command itself.
So when gdbpy_parse_command_name is called for 'prefix-1 prefix-2',
BASE_LIST points to the list of commands associated with 'prefix-1',
not to the actual 'prefix-1' cmd_list_element.
Back in cmdpy_init, from where gdbpy_parse_command_name was called, I
was walking back from the first entry in BASE_LIST to figure out if
this was a "show" prefix command or not. However, if BASE_LIST is
empty then there is no first item, and this would trigger the
segfault.
The solution it to extend gdbpy_parse_command_name to also return the
prefix cmd_list_element in addition to the existing values. With this
done, and cmdpy_init updated, the segfault is now avoided.
There's a new test that would trigger the crash without the patch.
And, of course, the above commit also broke guile in the exact same
way. And the fix is exactly the same. And there's a guile test too.
NOTE: We should investigate possibly sharing some of this boiler plate
helper code between Python and Guile. But not in this commit.
Approved-By: Tom Tromey <tom@tromey.com>
2025-06-03 17:23:10 +01:00
|
|
|
|
cmd_list_element *prefix_cmd = nullptr;
|
2021-05-12 13:50:05 -04:00
|
|
|
|
gdb::unique_xmalloc_ptr<char> cmd_name
|
gdb/python/guile: fix segfault from nested prefix command creation
A commit I recently pushed:
commit 0b5023cc71d3af8b18e10e6599a3f9381bc15265
Date: Sat Apr 12 09:15:53 2025 +0100
gdb/python/guile: user created prefix commands get help list
can trigger a segfault if a user tries to create nested prefix
commands. For example, this will trigger a crash:
(gdb) python gdb.ParameterPrefix("prefix-1", gdb.COMMAND_NONE)
(gdb) python gdb.ParameterPrefix("prefix-1 prefix-2", gdb.COMMAND_NONE)
Fatal signal: Segmentation fault
... etc ...
If the user adds an actual parameter under 'prefix-1' before creating
'prefix-2', then everything is fine:
(gdb) python gdb.ParameterPrefix("prefix-1", gdb.COMMAND_NONE)
(gdb) python gdb.Parameter('prefix-1 param-1', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)
(gdb) python gdb.ParameterPrefix("prefix-1 prefix-2", gdb.COMMAND_NONE)
The mistake in the above patch is in how gdbpy_parse_command_name is
used. The BASE_LIST output argument from this function points to the
list of commands for the prefix, not to the prefix command itself.
So when gdbpy_parse_command_name is called for 'prefix-1 prefix-2',
BASE_LIST points to the list of commands associated with 'prefix-1',
not to the actual 'prefix-1' cmd_list_element.
Back in cmdpy_init, from where gdbpy_parse_command_name was called, I
was walking back from the first entry in BASE_LIST to figure out if
this was a "show" prefix command or not. However, if BASE_LIST is
empty then there is no first item, and this would trigger the
segfault.
The solution it to extend gdbpy_parse_command_name to also return the
prefix cmd_list_element in addition to the existing values. With this
done, and cmdpy_init updated, the segfault is now avoided.
There's a new test that would trigger the crash without the patch.
And, of course, the above commit also broke guile in the exact same
way. And the fix is exactly the same. And there's a guile test too.
NOTE: We should investigate possibly sharing some of this boiler plate
helper code between Python and Guile. But not in this commit.
Approved-By: Tom Tromey <tom@tromey.com>
2025-06-03 17:23:10 +01:00
|
|
|
|
= gdbpy_parse_command_name (name, &cmd_list, &cmdlist, &prefix_cmd);
|
2021-05-12 13:50:05 -04:00
|
|
|
|
if (cmd_name == nullptr)
|
2009-02-06 21:33:59 +00:00
|
|
|
|
return -1;
|
|
|
|
|
|
|
2021-05-12 11:19:22 +01:00
|
|
|
|
if (is_prefix_obj != NULL)
|
2009-02-06 21:33:59 +00:00
|
|
|
|
{
|
2021-05-12 11:19:22 +01:00
|
|
|
|
int cmp = PyObject_IsTrue (is_prefix_obj);
|
2021-05-12 13:50:05 -04:00
|
|
|
|
if (cmp < 0)
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
|
|
is_prefix = cmp > 0;
|
2009-02-06 21:33:59 +00:00
|
|
|
|
}
|
2021-05-12 11:19:22 +01:00
|
|
|
|
|
2022-05-14 10:55:59 +01:00
|
|
|
|
gdb::unique_xmalloc_ptr<char> docstring = nullptr;
|
2009-02-06 21:33:59 +00:00
|
|
|
|
if (PyObject_HasAttr (self, gdbpy_doc_cst))
|
|
|
|
|
|
{
|
Turn gdbpy_ref into a template
This turns gdbpy_ref into a template class, so that it can be used to
wrap subclasses of PyObject. The default argument remains PyObject;
and this necessitated renaming uses of "gdbpy_ref" to "gdbpy_ref<>".
gdb/ChangeLog
2017-02-10 Tom Tromey <tom@tromey.com>
* python/py-ref.h (gdbpy_ref_policy): Now a template.
(gdbpy_ref): Now a template; allow subclasses of PyObject to be
used.
* python/py-arch.c, python/py-bpevent.c, python/py-breakpoint.c,
python/py-cmd.c, python/py-continueevent.c, python/py-event.c,
python/py-exitedevent.c, python/py-finishbreakpoint.c,
python/py-framefilter.c, python/py-function.c,
python/py-inferior.c, python/py-infevents.c,
python/py-linetable.c, python/py-newobjfileevent.c,
python/py-param.c, python/py-prettyprint.c, python/py-ref.h,
python/py-signalevent.c, python/py-stopevent.c,
python/py-symbol.c, python/py-threadevent.c, python/py-type.c,
python/py-unwind.c, python/py-utils.c, python/py-value.c,
python/py-varobj.c, python/py-xmethods.c, python/python.c,
varobj.c: Change gdbpy_ref to gdbpy_ref<>.
2017-02-09 13:16:36 -07:00
|
|
|
|
gdbpy_ref<> ds_obj (PyObject_GetAttr (self, gdbpy_doc_cst));
|
2010-05-17 21:23:25 +00:00
|
|
|
|
|
2016-11-20 10:23:08 -07:00
|
|
|
|
if (ds_obj != NULL && gdbpy_is_string (ds_obj.get ()))
|
2010-10-13 13:24:40 +00:00
|
|
|
|
{
|
2022-05-14 10:55:59 +01:00
|
|
|
|
docstring = python_string_to_host_string (ds_obj.get ());
|
|
|
|
|
|
if (docstring == nullptr)
|
2021-05-12 13:50:05 -04:00
|
|
|
|
return -1;
|
gdb/python: improve formatting of help text for user defined commands
Consider this command defined in Python (in the file test-cmd.py):
class test_cmd (gdb.Command):
"""
This is the first line.
Indented second line.
This is the third line.
"""
def __init__ (self):
super ().__init__ ("test-cmd", gdb.COMMAND_OBSCURE)
def invoke (self, arg, from_tty):
print ("In test-cmd")
test_cmd()
Now, within a GDB session:
(gdb) source test-cmd.py
(gdb) help test-cmd
This is the first line.
Indented second line.
This is the third line.
(gdb)
I think there's three things wrong here:
1. The leading blank line,
2. The trailing blank line, and
3. Every line is indented from the left edge slightly.
The problem of course, is that GDB is using the Python doc string
verbatim as its help text. While the user has formatted the help text
so that it appears clear within the .py file, this means that the text
appear less well formatted when displayed in the "help" output.
The same problem can be observed for gdb.Parameter objects in their
set/show output.
In this commit I aim to improve the "help" output for commands and
parameters.
To do this I have added gdbpy_fix_doc_string_indentation, a new
function that rewrites the doc string text following the following
rules:
1. Leading blank lines are removed,
2. Trailing blank lines are removed, and
3. Leading whitespace is removed in a "smart" way such that the
relative indentation of lines is retained.
With this commit in place the above example now looks like this:
(gdb) source ~/tmp/test-cmd.py
(gdb) help test-cmd
This is the first line.
Indented second line.
This is the third line.
(gdb)
Which I think is much neater. Notice that the indentation of the
second line is retained. Any blank lines within the help text (not
leading or trailing) will be retained.
I've added a NEWS entry to note that there has been a change in
behaviour, but I didn't update the manual. The existing manual is
suitably vague about how the doc string is used, so I think the new
behaviour is covered just as well by the existing text.
2022-05-16 19:26:54 +01:00
|
|
|
|
docstring = gdbpy_fix_doc_string_indentation (std::move (docstring));
|
2010-10-13 13:24:40 +00:00
|
|
|
|
}
|
2009-02-06 21:33:59 +00:00
|
|
|
|
}
|
2022-05-14 10:55:59 +01:00
|
|
|
|
if (docstring == nullptr)
|
|
|
|
|
|
docstring = make_unique_xstrdup (_("This command is not documented."));
|
2009-02-06 21:33:59 +00:00
|
|
|
|
|
2018-12-27 11:53:20 -07:00
|
|
|
|
gdbpy_ref<> self_ref = gdbpy_ref<>::new_reference (self);
|
2009-02-06 21:33:59 +00:00
|
|
|
|
|
2019-04-03 16:02:42 -06:00
|
|
|
|
try
|
2009-02-06 21:33:59 +00:00
|
|
|
|
{
|
|
|
|
|
|
struct cmd_list_element *cmd;
|
|
|
|
|
|
|
2021-05-12 11:19:22 +01:00
|
|
|
|
if (is_prefix)
|
2009-02-06 21:33:59 +00:00
|
|
|
|
{
|
gdb/python/guile: user created prefix commands get help list
Consider GDB's builtin prefix set/show prefix sub-commands, if they
are invoked with no sub-command name then they work like this:
(gdb) show print
print address: Printing of addresses is on.
print array: Pretty formatting of arrays is off.
print array-indexes: Printing of array indexes is off.
print asm-demangle: Demangling of C++/ObjC names in disassembly listings is off.
... cut lots of lines ...
(gdb) set print
List of set print subcommands:
set print address -- Set printing of addresses.
set print array -- Set pretty formatting of arrays.
set print array-indexes -- Set printing of array indexes.
set print asm-demangle -- Set demangling of C++/ObjC names in disassembly listings.
... cut lots of lines ...
Type "help set print" followed by set print subcommand name for full documentation.
Type "apropos word" to search for commands related to "word".
Type "apropos -v word" for full documentation of commands related to "word".
Command name abbreviations are allowed if unambiguous.
(gdb)
That is 'show print' lists the values of all settings under the
'print' prefix, and 'set print' lists the help text for all settings
under the 'set print' prefix.
Now, if we try to create something similar using the Python API:
(gdb) python gdb.ParameterPrefix("my-prefix", gdb.COMMAND_NONE)
(gdb) python gdb.Parameter("my-prefix foo", gdb.COMMAND_OBSCURE, gdb.PARAM_BOOLEAN)
(gdb) show my-prefix
(gdb) set my-prefix
Neither 'show my-prefix' or 'set my-prefix' gives us the same details
relating to the sub-commands that we get with the builtin prefix
commands.
This commit aims to address this.
Currently, in cmdpy_init, when a new command is created, we always set
the commands callback function to cmdpy_function. It is within
cmdpy_function that we spot that the command is a prefix command, and
that there is no gdb.Command.invoke method, and so return early.
This commit changes things so that the rules are now:
1. For NON prefix commands, we continue to use cmdpy_function.
2. For prefix commands that do have a gdb.Command.invoke
method (i.e. can handle unknown sub-commands), continue to use
cmdpy_function.
3. For all other prefix commands, don't use cmdpy_function, instead
use GDB's normal callback function for set/show prefixes.
This requires splitting the current call to add_prefix_cmd into either
a call to add_prefix_cmd, add_show_prefix_cmd, or
add_basic_prefix_cmd, as appropriate.
After these changes, we now see this:
(gdb) python gdb.ParameterPrefix("my-prefix", gdb.COMMAND_NONE) │
(gdb) python gdb.Parameter("my-prefix foo", gdb.COMMAND_OBSCURE, gdb.PARAM_BOOLEAN)
(gdb) show my-prefix │
my-prefix foo: The current value of 'my-prefix foo' is "off".
(gdb) set my-prefix
List of "set my-prefix" subcommands:
set my-prefix foo -- Set the current value of 'my-prefix foo'.
Type "help set my-prefix" followed by subcommand name for full documentation.
Type "apropos word" to search for commands related to "word".
Type "apropos -v word" for full documentation of commands related to "word".
Command name abbreviations are allowed if unambiguous.
(gdb)
Which matches how a prefix defined within GDB would act.
I have made the same changes to the Guile API.
2025-04-12 09:15:53 +01:00
|
|
|
|
bool has_invoke = PyObject_HasAttr (self, invoke_cst) == 1;
|
|
|
|
|
|
if (has_invoke)
|
|
|
|
|
|
{
|
|
|
|
|
|
/* If there's an 'invoke' method, then create the prefix
|
|
|
|
|
|
command, but call cmdpy_function to dispatch to the invoke
|
|
|
|
|
|
method when the user runs the prefix with no sub-command. */
|
|
|
|
|
|
cmd = add_prefix_cmd (cmd_name.get (),
|
|
|
|
|
|
(enum command_class) cmdtype,
|
|
|
|
|
|
nullptr,
|
|
|
|
|
|
docstring.release (), &obj->sub_list,
|
|
|
|
|
|
1 /* allow_unknown */, cmd_list);
|
|
|
|
|
|
cmd->func = cmdpy_function;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
/* If there is no 'invoke' method, then create the prefix
|
|
|
|
|
|
using the standard prefix callbacks. This means that for
|
|
|
|
|
|
'set prefix' the user will get the help text listing all
|
|
|
|
|
|
of the sub-commands, and for 'show prefix', the user will
|
|
|
|
|
|
see all of the sub-command values. */
|
gdb/python/guile: fix segfault from nested prefix command creation
A commit I recently pushed:
commit 0b5023cc71d3af8b18e10e6599a3f9381bc15265
Date: Sat Apr 12 09:15:53 2025 +0100
gdb/python/guile: user created prefix commands get help list
can trigger a segfault if a user tries to create nested prefix
commands. For example, this will trigger a crash:
(gdb) python gdb.ParameterPrefix("prefix-1", gdb.COMMAND_NONE)
(gdb) python gdb.ParameterPrefix("prefix-1 prefix-2", gdb.COMMAND_NONE)
Fatal signal: Segmentation fault
... etc ...
If the user adds an actual parameter under 'prefix-1' before creating
'prefix-2', then everything is fine:
(gdb) python gdb.ParameterPrefix("prefix-1", gdb.COMMAND_NONE)
(gdb) python gdb.Parameter('prefix-1 param-1', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)
(gdb) python gdb.ParameterPrefix("prefix-1 prefix-2", gdb.COMMAND_NONE)
The mistake in the above patch is in how gdbpy_parse_command_name is
used. The BASE_LIST output argument from this function points to the
list of commands for the prefix, not to the prefix command itself.
So when gdbpy_parse_command_name is called for 'prefix-1 prefix-2',
BASE_LIST points to the list of commands associated with 'prefix-1',
not to the actual 'prefix-1' cmd_list_element.
Back in cmdpy_init, from where gdbpy_parse_command_name was called, I
was walking back from the first entry in BASE_LIST to figure out if
this was a "show" prefix command or not. However, if BASE_LIST is
empty then there is no first item, and this would trigger the
segfault.
The solution it to extend gdbpy_parse_command_name to also return the
prefix cmd_list_element in addition to the existing values. With this
done, and cmdpy_init updated, the segfault is now avoided.
There's a new test that would trigger the crash without the patch.
And, of course, the above commit also broke guile in the exact same
way. And the fix is exactly the same. And there's a guile test too.
NOTE: We should investigate possibly sharing some of this boiler plate
helper code between Python and Guile. But not in this commit.
Approved-By: Tom Tromey <tom@tromey.com>
2025-06-03 17:23:10 +01:00
|
|
|
|
if (prefix_cmd != nullptr)
|
|
|
|
|
|
{
|
|
|
|
|
|
while (prefix_cmd->prefix != nullptr)
|
|
|
|
|
|
prefix_cmd = prefix_cmd->prefix;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool is_show = (prefix_cmd != nullptr
|
|
|
|
|
|
&& prefix_cmd->subcommands == &showlist);
|
gdb/python/guile: user created prefix commands get help list
Consider GDB's builtin prefix set/show prefix sub-commands, if they
are invoked with no sub-command name then they work like this:
(gdb) show print
print address: Printing of addresses is on.
print array: Pretty formatting of arrays is off.
print array-indexes: Printing of array indexes is off.
print asm-demangle: Demangling of C++/ObjC names in disassembly listings is off.
... cut lots of lines ...
(gdb) set print
List of set print subcommands:
set print address -- Set printing of addresses.
set print array -- Set pretty formatting of arrays.
set print array-indexes -- Set printing of array indexes.
set print asm-demangle -- Set demangling of C++/ObjC names in disassembly listings.
... cut lots of lines ...
Type "help set print" followed by set print subcommand name for full documentation.
Type "apropos word" to search for commands related to "word".
Type "apropos -v word" for full documentation of commands related to "word".
Command name abbreviations are allowed if unambiguous.
(gdb)
That is 'show print' lists the values of all settings under the
'print' prefix, and 'set print' lists the help text for all settings
under the 'set print' prefix.
Now, if we try to create something similar using the Python API:
(gdb) python gdb.ParameterPrefix("my-prefix", gdb.COMMAND_NONE)
(gdb) python gdb.Parameter("my-prefix foo", gdb.COMMAND_OBSCURE, gdb.PARAM_BOOLEAN)
(gdb) show my-prefix
(gdb) set my-prefix
Neither 'show my-prefix' or 'set my-prefix' gives us the same details
relating to the sub-commands that we get with the builtin prefix
commands.
This commit aims to address this.
Currently, in cmdpy_init, when a new command is created, we always set
the commands callback function to cmdpy_function. It is within
cmdpy_function that we spot that the command is a prefix command, and
that there is no gdb.Command.invoke method, and so return early.
This commit changes things so that the rules are now:
1. For NON prefix commands, we continue to use cmdpy_function.
2. For prefix commands that do have a gdb.Command.invoke
method (i.e. can handle unknown sub-commands), continue to use
cmdpy_function.
3. For all other prefix commands, don't use cmdpy_function, instead
use GDB's normal callback function for set/show prefixes.
This requires splitting the current call to add_prefix_cmd into either
a call to add_prefix_cmd, add_show_prefix_cmd, or
add_basic_prefix_cmd, as appropriate.
After these changes, we now see this:
(gdb) python gdb.ParameterPrefix("my-prefix", gdb.COMMAND_NONE) │
(gdb) python gdb.Parameter("my-prefix foo", gdb.COMMAND_OBSCURE, gdb.PARAM_BOOLEAN)
(gdb) show my-prefix │
my-prefix foo: The current value of 'my-prefix foo' is "off".
(gdb) set my-prefix
List of "set my-prefix" subcommands:
set my-prefix foo -- Set the current value of 'my-prefix foo'.
Type "help set my-prefix" followed by subcommand name for full documentation.
Type "apropos word" to search for commands related to "word".
Type "apropos -v word" for full documentation of commands related to "word".
Command name abbreviations are allowed if unambiguous.
(gdb)
Which matches how a prefix defined within GDB would act.
I have made the same changes to the Guile API.
2025-04-12 09:15:53 +01:00
|
|
|
|
|
|
|
|
|
|
if (is_show)
|
|
|
|
|
|
cmd = add_show_prefix_cmd (cmd_name.get (),
|
|
|
|
|
|
(enum command_class) cmdtype,
|
|
|
|
|
|
docstring.release (),
|
|
|
|
|
|
&obj->sub_list,
|
|
|
|
|
|
0 /* allow_unknown */, cmd_list);
|
|
|
|
|
|
else
|
|
|
|
|
|
cmd = add_basic_prefix_cmd (cmd_name.get (),
|
|
|
|
|
|
(enum command_class) cmdtype,
|
|
|
|
|
|
docstring.release (),
|
|
|
|
|
|
&obj->sub_list,
|
|
|
|
|
|
0 /* allow_unknown */, cmd_list);
|
|
|
|
|
|
}
|
2009-02-06 21:33:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
else
|
gdb/python/guile: user created prefix commands get help list
Consider GDB's builtin prefix set/show prefix sub-commands, if they
are invoked with no sub-command name then they work like this:
(gdb) show print
print address: Printing of addresses is on.
print array: Pretty formatting of arrays is off.
print array-indexes: Printing of array indexes is off.
print asm-demangle: Demangling of C++/ObjC names in disassembly listings is off.
... cut lots of lines ...
(gdb) set print
List of set print subcommands:
set print address -- Set printing of addresses.
set print array -- Set pretty formatting of arrays.
set print array-indexes -- Set printing of array indexes.
set print asm-demangle -- Set demangling of C++/ObjC names in disassembly listings.
... cut lots of lines ...
Type "help set print" followed by set print subcommand name for full documentation.
Type "apropos word" to search for commands related to "word".
Type "apropos -v word" for full documentation of commands related to "word".
Command name abbreviations are allowed if unambiguous.
(gdb)
That is 'show print' lists the values of all settings under the
'print' prefix, and 'set print' lists the help text for all settings
under the 'set print' prefix.
Now, if we try to create something similar using the Python API:
(gdb) python gdb.ParameterPrefix("my-prefix", gdb.COMMAND_NONE)
(gdb) python gdb.Parameter("my-prefix foo", gdb.COMMAND_OBSCURE, gdb.PARAM_BOOLEAN)
(gdb) show my-prefix
(gdb) set my-prefix
Neither 'show my-prefix' or 'set my-prefix' gives us the same details
relating to the sub-commands that we get with the builtin prefix
commands.
This commit aims to address this.
Currently, in cmdpy_init, when a new command is created, we always set
the commands callback function to cmdpy_function. It is within
cmdpy_function that we spot that the command is a prefix command, and
that there is no gdb.Command.invoke method, and so return early.
This commit changes things so that the rules are now:
1. For NON prefix commands, we continue to use cmdpy_function.
2. For prefix commands that do have a gdb.Command.invoke
method (i.e. can handle unknown sub-commands), continue to use
cmdpy_function.
3. For all other prefix commands, don't use cmdpy_function, instead
use GDB's normal callback function for set/show prefixes.
This requires splitting the current call to add_prefix_cmd into either
a call to add_prefix_cmd, add_show_prefix_cmd, or
add_basic_prefix_cmd, as appropriate.
After these changes, we now see this:
(gdb) python gdb.ParameterPrefix("my-prefix", gdb.COMMAND_NONE) │
(gdb) python gdb.Parameter("my-prefix foo", gdb.COMMAND_OBSCURE, gdb.PARAM_BOOLEAN)
(gdb) show my-prefix │
my-prefix foo: The current value of 'my-prefix foo' is "off".
(gdb) set my-prefix
List of "set my-prefix" subcommands:
set my-prefix foo -- Set the current value of 'my-prefix foo'.
Type "help set my-prefix" followed by subcommand name for full documentation.
Type "apropos word" to search for commands related to "word".
Type "apropos -v word" for full documentation of commands related to "word".
Command name abbreviations are allowed if unambiguous.
(gdb)
Which matches how a prefix defined within GDB would act.
I have made the same changes to the Guile API.
2025-04-12 09:15:53 +01:00
|
|
|
|
{
|
|
|
|
|
|
/* For non-prefix commands, arrange to call cmdpy_function, which
|
|
|
|
|
|
invokes the Python 'invoke' method, or raises an exception if
|
|
|
|
|
|
the 'invoke' method is missing. */
|
|
|
|
|
|
cmd = add_cmd (cmd_name.get (), (enum command_class) cmdtype,
|
|
|
|
|
|
docstring.release (), cmd_list);
|
|
|
|
|
|
cmd->func = cmdpy_function;
|
|
|
|
|
|
}
|
2009-02-06 21:33:59 +00:00
|
|
|
|
|
2021-05-12 13:50:05 -04:00
|
|
|
|
/* If successful, the above takes ownership of the name, since we set
|
2023-03-09 14:56:09 -05:00
|
|
|
|
name_allocated, so release it. */
|
2021-05-12 13:50:05 -04:00
|
|
|
|
cmd_name.release ();
|
|
|
|
|
|
|
gdb/python/guile: user created prefix commands get help list
Consider GDB's builtin prefix set/show prefix sub-commands, if they
are invoked with no sub-command name then they work like this:
(gdb) show print
print address: Printing of addresses is on.
print array: Pretty formatting of arrays is off.
print array-indexes: Printing of array indexes is off.
print asm-demangle: Demangling of C++/ObjC names in disassembly listings is off.
... cut lots of lines ...
(gdb) set print
List of set print subcommands:
set print address -- Set printing of addresses.
set print array -- Set pretty formatting of arrays.
set print array-indexes -- Set printing of array indexes.
set print asm-demangle -- Set demangling of C++/ObjC names in disassembly listings.
... cut lots of lines ...
Type "help set print" followed by set print subcommand name for full documentation.
Type "apropos word" to search for commands related to "word".
Type "apropos -v word" for full documentation of commands related to "word".
Command name abbreviations are allowed if unambiguous.
(gdb)
That is 'show print' lists the values of all settings under the
'print' prefix, and 'set print' lists the help text for all settings
under the 'set print' prefix.
Now, if we try to create something similar using the Python API:
(gdb) python gdb.ParameterPrefix("my-prefix", gdb.COMMAND_NONE)
(gdb) python gdb.Parameter("my-prefix foo", gdb.COMMAND_OBSCURE, gdb.PARAM_BOOLEAN)
(gdb) show my-prefix
(gdb) set my-prefix
Neither 'show my-prefix' or 'set my-prefix' gives us the same details
relating to the sub-commands that we get with the builtin prefix
commands.
This commit aims to address this.
Currently, in cmdpy_init, when a new command is created, we always set
the commands callback function to cmdpy_function. It is within
cmdpy_function that we spot that the command is a prefix command, and
that there is no gdb.Command.invoke method, and so return early.
This commit changes things so that the rules are now:
1. For NON prefix commands, we continue to use cmdpy_function.
2. For prefix commands that do have a gdb.Command.invoke
method (i.e. can handle unknown sub-commands), continue to use
cmdpy_function.
3. For all other prefix commands, don't use cmdpy_function, instead
use GDB's normal callback function for set/show prefixes.
This requires splitting the current call to add_prefix_cmd into either
a call to add_prefix_cmd, add_show_prefix_cmd, or
add_basic_prefix_cmd, as appropriate.
After these changes, we now see this:
(gdb) python gdb.ParameterPrefix("my-prefix", gdb.COMMAND_NONE) │
(gdb) python gdb.Parameter("my-prefix foo", gdb.COMMAND_OBSCURE, gdb.PARAM_BOOLEAN)
(gdb) show my-prefix │
my-prefix foo: The current value of 'my-prefix foo' is "off".
(gdb) set my-prefix
List of "set my-prefix" subcommands:
set my-prefix foo -- Set the current value of 'my-prefix foo'.
Type "help set my-prefix" followed by subcommand name for full documentation.
Type "apropos word" to search for commands related to "word".
Type "apropos -v word" for full documentation of commands related to "word".
Command name abbreviations are allowed if unambiguous.
(gdb)
Which matches how a prefix defined within GDB would act.
I have made the same changes to the Guile API.
2025-04-12 09:15:53 +01:00
|
|
|
|
/* There appears to be no API to set these member variables. */
|
2009-02-06 21:33:59 +00:00
|
|
|
|
cmd->destroyer = cmdpy_destroyer;
|
2019-11-15 16:41:12 -07:00
|
|
|
|
cmd->doc_allocated = 1;
|
2019-11-15 16:56:20 -07:00
|
|
|
|
cmd->name_allocated = 1;
|
2009-02-06 21:33:59 +00:00
|
|
|
|
|
|
|
|
|
|
obj->command = cmd;
|
2021-06-25 21:35:40 -04:00
|
|
|
|
cmd->set_context (self_ref.release ());
|
2009-02-06 21:33:59 +00:00
|
|
|
|
set_cmd_completer (cmd, ((completetype == -1) ? cmdpy_completer
|
|
|
|
|
|
: completers[completetype].completer));
|
PR python/16699: GDB Python command completion with overriden complete vs. completer class
This PR came from a Red Hat bug that was filed recently. I checked and
it still exists on HEAD, so here's a proposed fix. Although this is
marked as a Python backend bug, this is really about the completion
mechanism used by GDB. Since this code reminds me of my first attempt
to make a good noodle, it took me quite some time to fix it in a
non-intrusive way.
The problem is triggered when one registers a completion method inside a
class in a Python script, rather than registering the command using a
completer class directly. For example, consider the following script:
class MyFirstCommand(gdb.Command):
def __init__(self):
gdb.Command.__init__(self,'myfirstcommand',gdb.COMMAND_USER,gdb.COMPLETE_FILENAME)
def invoke(self,argument,from_tty):
raise gdb.GdbError('not implemented')
class MySecondCommand(gdb.Command):
def __init__(self):
gdb.Command.__init__(self,'mysecondcommand',gdb.COMMAND_USER)
def invoke(self,argument,from_tty):
raise gdb.GdbError('not implemented')
def complete(self,text,word):
return gdb.COMPLETE_FILENAME
MyFirstCommand ()
MySecondCommand ()
When one loads this into GDB and tries to complete filenames for both
myfirstcommand and mysecondcommand, she gets:
(gdb) myfirstcommand /hom<TAB>
(gdb) myfirstcommand /home/
^
...
(gdb) mysecondcommand /hom<TAB>
(gdb) mysecondcommand /home
^
(The "^" marks the final position of the cursor after the TAB).
So we see that myfirstcommand honors the COMPLETE_FILENAME class (as
specified in the command creation), but mysecondcommand does not. After
some investigation, I found that the problem lies with the set of word
break characters that is used for each case. The set should be the same
for both commands, but it is not.
During the process of deciding which type of completion should be used,
the code in gdb/completer.c:complete_line_internal analyses the command
that requested the completion and tries to determine the type of
completion wanted by checking which completion function will be called
(e.g., filename_completer for filenames, location_completer for
locations, etc.).
This all works fine for myfirstcommand, because immediately after the
command registration the Python backend already sets its completion
function to filename_completer (which then causes the
complete_line_internal function to choose the right set of word break
chars). However, for mysecondcommand, this decision is postponed to
when the completer function is evaluated, and the Python backend uses an
internal completer (called cmdpy_completer). complete_line_internal
doesn't know about this internal completer, and can't choose the right
set of word break chars in time, which then leads to a bad decision when
completing the "/hom" word.
So, after a few attempts, I decided to create another callback in
"struct cmd_list_element" that will be responsible for handling the case
when there is an unknown completer function for complete_line_internal
to work with. So far, only the Python backend uses this callback, and
only when the user provides a completer method instead of registering
the command directly with a completer class. I think this is the best
option because it not very intrusive (all the other commands will still
work normally), but especially because the whole completion code is so
messy that it would be hard to fix this without having to redesign
things.
I have regtested this on Fedora 18 x86_64, without regressions. I also
included a testcase.
gdb/ChangeLog:
2014-09-03 Sergio Durigan Junior <sergiodj@redhat.com>
PR python/16699
* cli/cli-decode.c (set_cmd_completer_handle_brkchars): New
function.
(add_cmd): Set "completer_handle_brkchars" to NULL.
* cli/cli-decode.h (struct cmd_list_element)
<completer_handle_brkchars>: New field.
* command.h (completer_ftype_void): New typedef.
(set_cmd_completer_handle_brkchars): New prototype.
* completer.c (set_gdb_completion_word_break_characters): New
function.
(complete_line_internal): Call "completer_handle_brkchars"
callback from command.
* completer.h: Include "command.h".
(set_gdb_completion_word_break_characters): New prototype.
* python/py-cmd.c (cmdpy_completer_helper): New function.
(cmdpy_completer_handle_brkchars): New function.
(cmdpy_completer): Adjust to use cmdpy_completer_helper.
(cmdpy_init): Set completer_handle_brkchars to
cmdpy_completer_handle_brkchars.
gdb/testsuite/ChangeLog:
2014-09-03 Sergio Durigan Junior <sergiodj@redhat.com>
PR python/16699
* gdb.python/py-completion.exp: New file.
* gdb.python/py-completion.py: Likewise.
2014-09-03 16:30:28 -04:00
|
|
|
|
if (completetype == -1)
|
|
|
|
|
|
set_cmd_completer_handle_brkchars (cmd,
|
|
|
|
|
|
cmdpy_completer_handle_brkchars);
|
2009-02-06 21:33:59 +00:00
|
|
|
|
}
|
2019-04-03 15:59:07 -06:00
|
|
|
|
catch (const gdb_exception &except)
|
2009-02-06 21:33:59 +00:00
|
|
|
|
{
|
2024-09-24 13:06:32 +02:00
|
|
|
|
return gdbpy_handle_gdb_exception (-1, except);
|
2009-02-06 21:33:59 +00:00
|
|
|
|
}
|
Split TRY_CATCH into TRY + CATCH
This patch splits the TRY_CATCH macro into three, so that we go from
this:
~~~
volatile gdb_exception ex;
TRY_CATCH (ex, RETURN_MASK_ERROR)
{
}
if (ex.reason < 0)
{
}
~~~
to this:
~~~
TRY
{
}
CATCH (ex, RETURN_MASK_ERROR)
{
}
END_CATCH
~~~
Thus, we'll be getting rid of the local volatile exception object, and
declaring the caught exception in the catch block.
This allows reimplementing TRY/CATCH in terms of C++ exceptions when
building in C++ mode, while still allowing to build GDB in C mode
(using setjmp/longjmp), as a transition step.
TBC, after this patch, is it _not_ valid to have code between the TRY
and the CATCH blocks, like:
TRY
{
}
// some code here.
CATCH (ex, RETURN_MASK_ERROR)
{
}
END_CATCH
Just like it isn't valid to do that with C++'s native try/catch.
By switching to creating the exception object inside the CATCH block
scope, we can get rid of all the explicitly allocated volatile
exception objects all over the tree, and map the CATCH block more
directly to C++'s catch blocks.
The majority of the TRY_CATCH -> TRY+CATCH+END_CATCH conversion was
done with a script, rerun from scratch at every rebase, no manual
editing involved. After the mechanical conversion, a few places
needed manual intervention, to fix preexisting cases where we were
using the exception object outside of the TRY_CATCH block, and cases
where we were using "else" after a 'if (ex.reason) < 0)' [a CATCH
after this patch]. The result was folded into this patch so that GDB
still builds at each incremental step.
END_CATCH is necessary for two reasons:
First, because we name the exception object in the CATCH block, which
requires creating a scope, which in turn must be closed somewhere.
Declaring the exception variable in the initializer field of a for
block, like:
#define CATCH(EXCEPTION, mask) \
for (struct gdb_exception EXCEPTION; \
exceptions_state_mc_catch (&EXCEPTION, MASK); \
EXCEPTION = exception_none)
would avoid needing END_CATCH, but alas, in C mode, we build with C90,
which doesn't allow mixed declarations and code.
Second, because when TRY/CATCH are wired to real C++ try/catch, as
long as we need to handle cleanup chains, even if there's no CATCH
block that wants to catch the exception, we need for stop at every
frame in the unwind chain and run cleanups, then rethrow. That will
be done in END_CATCH.
After we require C++, we'll still need TRY/CATCH/END_CATCH until
cleanups are completely phased out -- TRY/CATCH in C++ mode will
save/restore the current cleanup chain, like in C mode, and END_CATCH
catches otherwise uncaugh exceptions, runs cleanups and rethrows, so
that C++ cleanups and exceptions can coexist.
IMO, this still makes the TRY/CATCH code look a bit more like a
newcomer would expect, so IMO worth it even if we weren't considering
C++.
gdb/ChangeLog.
2015-03-07 Pedro Alves <palves@redhat.com>
* common/common-exceptions.c (struct catcher) <exception>: No
longer a pointer to volatile exception. Now an exception value.
<mask>: Delete field.
(exceptions_state_mc_init): Remove all parameters. Adjust.
(exceptions_state_mc): No longer pop the catcher here.
(exceptions_state_mc_catch): New function.
(throw_exception): Adjust.
* common/common-exceptions.h (exceptions_state_mc_init): Remove
all parameters.
(exceptions_state_mc_catch): Declare.
(TRY_CATCH): Rename to ...
(TRY): ... this. Remove EXCEPTION and MASK parameters.
(CATCH, END_CATCH): New.
All callers adjusted.
gdb/gdbserver/ChangeLog:
2015-03-07 Pedro Alves <palves@redhat.com>
Adjust all callers of TRY_CATCH to use TRY/CATCH/END_CATCH
instead.
2015-03-07 15:14:14 +00:00
|
|
|
|
|
2009-02-06 21:33:59 +00:00
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Initialize the 'commands' code. */
|
2011-09-08 19:51:27 +00:00
|
|
|
|
|
2025-10-21 10:00:20 -06:00
|
|
|
|
static int
|
|
|
|
|
|
gdbpy_initialize_commands ()
|
2009-02-06 21:33:59 +00:00
|
|
|
|
{
|
|
|
|
|
|
int i;
|
|
|
|
|
|
|
2011-08-05 14:24:10 +00:00
|
|
|
|
cmdpy_object_type.tp_new = PyType_GenericNew;
|
2024-09-11 10:35:20 -06:00
|
|
|
|
if (gdbpy_type_ready (&cmdpy_object_type) < 0)
|
* python/py-arch.c (gdbpy_initialize_arch): Return 'int'.
Check errors.
* python/py-auto-load.c (gdbpy_initialize_auto_load): Return 'int'.
* python/py-block.c (gdbpy_initialize_blocks): Return 'int'.
Check errors.
* python/py-breakpoint.c (gdbpy_initialize_breakpoints): Return 'int'.
Check errors.
* python/py-cmd.c (gdbpy_initialize_commands): Return 'int'.
Check errors.
* python/py-event.c (gdbpy_initialize_event): Return 'int'.
Check errors.
* python/py-event.h (GDBPY_NEW_EVENT_TYPE): Change generated
init function to return 'int'.
* python/py-evtregistry.c (gdbpy_initialize_eventregistry):
Return 'int'. Check errors.
* python/py-evts.c (gdbpy_initialize_py_events): Return 'int'.
Check errors.
* python/py-finishbreakpoint.c (gdbpy_initialize_finishbreakpoints):
Return 'int'. Check errors.
* python/py-frame.c (gdbpy_initialize_frames): Return 'int'.
Check errors.
* python/py-function.c (gdbpy_initialize_functions): Return 'int'.
Check errors.
* python/py-gdb-readline.c (gdbpy_initialize_gdb_readline):
Check errors.
* python/py-inferior.c (gdbpy_initialize_inferior): Return 'int'.
Check errors.
* python/py-infthread.c (gdbpy_initialize_thread): Return 'int'.
Check errors.
* python/py-lazy-string.c (gdbpy_initialize_lazy_string): Return 'int'.
Check errors.
* python/py-objfile.c (gdbpy_initialize_objfile): Return 'int'.
Check errors.
* python/py-param.c (gdbpy_initialize_parameters): Return 'int'.
Check errors.
* python/py-progspace.c (gdbpy_initialize_pspace): Return 'int'.
Check errors.
* python/py-symbol.c (gdbpy_initialize_symbols): Return 'int'.
Check errors.
* python/py-symtab.c (gdbpy_initialize_symtabs): Return 'int'.
Check errors.
* python/py-type.c (gdbpy_initialize_types): Return 'int'.
Check errors.
* python/py-value.c (gdbpy_initialize_values): Return 'int'.
Check errors.
* python/python-internal.h (gdbpy_initialize_auto_load,
gdbpy_initialize_values, gdbpy_initialize_frames,
gdbpy_initialize_symtabs, gdbpy_initialize_commands,
gdbpy_initialize_symbols, gdbpy_initialize_symtabs,
gdbpy_initialize_blocks, gdbpy_initialize_types,
gdbpy_initialize_functions, gdbpy_initialize_pspace,
gdbpy_initialize_objfile, gdbpy_initialize_breakpoints,
gdbpy_initialize_finishbreakpoints,
gdbpy_initialize_lazy_string, gdbpy_initialize_parameters,
gdbpy_initialize_thread, gdbpy_initialize_inferior,
gdbpy_initialize_eventregistry, gdbpy_initialize_event,
gdbpy_initialize_py_events, gdbpy_initialize_stop_event,
gdbpy_initialize_signal_event,
gdbpy_initialize_breakpoint_event,
gdbpy_initialize_continue_event,
gdbpy_initialize_exited_event, gdbpy_initialize_thread_event,
gdbpy_initialize_new_objfile_event, gdbpy_initialize_arch):
Update. Use CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION.
* python/python.c (gdb_python_initialized): New global.
(gdbpy_initialize_events): Return 'int'. Check errors.
(_initialize_python): Check errors. Set
gdb_python_initialized.
2013-05-20 20:28:52 +00:00
|
|
|
|
return -1;
|
2009-02-06 21:33:59 +00:00
|
|
|
|
|
2020-04-28 08:54:17 -06:00
|
|
|
|
/* Note: alias and user are special. */
|
2009-02-06 21:33:59 +00:00
|
|
|
|
if (PyModule_AddIntConstant (gdb_module, "COMMAND_NONE", no_class) < 0
|
|
|
|
|
|
|| PyModule_AddIntConstant (gdb_module, "COMMAND_RUNNING", class_run) < 0
|
|
|
|
|
|
|| PyModule_AddIntConstant (gdb_module, "COMMAND_DATA", class_vars) < 0
|
|
|
|
|
|
|| PyModule_AddIntConstant (gdb_module, "COMMAND_STACK", class_stack) < 0
|
|
|
|
|
|
|| PyModule_AddIntConstant (gdb_module, "COMMAND_FILES", class_files) < 0
|
|
|
|
|
|
|| PyModule_AddIntConstant (gdb_module, "COMMAND_SUPPORT",
|
|
|
|
|
|
class_support) < 0
|
|
|
|
|
|
|| PyModule_AddIntConstant (gdb_module, "COMMAND_STATUS", class_info) < 0
|
|
|
|
|
|
|| PyModule_AddIntConstant (gdb_module, "COMMAND_BREAKPOINTS",
|
|
|
|
|
|
class_breakpoint) < 0
|
|
|
|
|
|
|| PyModule_AddIntConstant (gdb_module, "COMMAND_TRACEPOINTS",
|
|
|
|
|
|
class_trace) < 0
|
|
|
|
|
|
|| PyModule_AddIntConstant (gdb_module, "COMMAND_OBSCURE",
|
|
|
|
|
|
class_obscure) < 0
|
|
|
|
|
|
|| PyModule_AddIntConstant (gdb_module, "COMMAND_MAINTENANCE",
|
2012-03-01 19:30:25 +00:00
|
|
|
|
class_maintenance) < 0
|
2020-04-28 08:54:17 -06:00
|
|
|
|
|| PyModule_AddIntConstant (gdb_module, "COMMAND_USER", class_user) < 0
|
gdb: add "essential" command class
Currently, there is no way for a new user to have an idea of common
useful commands and behaviors from the GDB interface itself, without
checking the example session in the documentation. This command class
aims to close that gap by providing a set of quickstart commands that
allows for any simple debug session to happen without anything too
egregious missing.
The set of commands was chosen somewhat arbitrarily, based on what I
used or missed the most. The one overarching important thing, however,
is that the list is kept short, so as to not overwhelm new users. This
is confirmed by the newly introduced selftest, essential_command_count,
which ensures there are 20 or fewer essential commands.
Here's the reasoning for some of the choices:
* The command "start" was picked over "run" because combining it with
"continue" achieves the same effect, and I prefer it over needing to set
a breakpoint on main to stop at the start of the inferior.
* The command "ptype" is chosen because I believe it is important to
provide a way for the user to check a variable's type from inside GDB,
and ptype is a more complete command than the alternative, "whatis".
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
Approved-By: Tom Tromey <tom@tromey.com>
2025-09-19 08:44:35 -03:00
|
|
|
|
|| PyModule_AddIntConstant (gdb_module, "COMMAND_ESSENTIAL",
|
|
|
|
|
|
class_essential) < 0
|
2020-04-28 08:54:17 -06:00
|
|
|
|
|| PyModule_AddIntConstant (gdb_module, "COMMAND_TUI", class_tui) < 0)
|
* python/py-arch.c (gdbpy_initialize_arch): Return 'int'.
Check errors.
* python/py-auto-load.c (gdbpy_initialize_auto_load): Return 'int'.
* python/py-block.c (gdbpy_initialize_blocks): Return 'int'.
Check errors.
* python/py-breakpoint.c (gdbpy_initialize_breakpoints): Return 'int'.
Check errors.
* python/py-cmd.c (gdbpy_initialize_commands): Return 'int'.
Check errors.
* python/py-event.c (gdbpy_initialize_event): Return 'int'.
Check errors.
* python/py-event.h (GDBPY_NEW_EVENT_TYPE): Change generated
init function to return 'int'.
* python/py-evtregistry.c (gdbpy_initialize_eventregistry):
Return 'int'. Check errors.
* python/py-evts.c (gdbpy_initialize_py_events): Return 'int'.
Check errors.
* python/py-finishbreakpoint.c (gdbpy_initialize_finishbreakpoints):
Return 'int'. Check errors.
* python/py-frame.c (gdbpy_initialize_frames): Return 'int'.
Check errors.
* python/py-function.c (gdbpy_initialize_functions): Return 'int'.
Check errors.
* python/py-gdb-readline.c (gdbpy_initialize_gdb_readline):
Check errors.
* python/py-inferior.c (gdbpy_initialize_inferior): Return 'int'.
Check errors.
* python/py-infthread.c (gdbpy_initialize_thread): Return 'int'.
Check errors.
* python/py-lazy-string.c (gdbpy_initialize_lazy_string): Return 'int'.
Check errors.
* python/py-objfile.c (gdbpy_initialize_objfile): Return 'int'.
Check errors.
* python/py-param.c (gdbpy_initialize_parameters): Return 'int'.
Check errors.
* python/py-progspace.c (gdbpy_initialize_pspace): Return 'int'.
Check errors.
* python/py-symbol.c (gdbpy_initialize_symbols): Return 'int'.
Check errors.
* python/py-symtab.c (gdbpy_initialize_symtabs): Return 'int'.
Check errors.
* python/py-type.c (gdbpy_initialize_types): Return 'int'.
Check errors.
* python/py-value.c (gdbpy_initialize_values): Return 'int'.
Check errors.
* python/python-internal.h (gdbpy_initialize_auto_load,
gdbpy_initialize_values, gdbpy_initialize_frames,
gdbpy_initialize_symtabs, gdbpy_initialize_commands,
gdbpy_initialize_symbols, gdbpy_initialize_symtabs,
gdbpy_initialize_blocks, gdbpy_initialize_types,
gdbpy_initialize_functions, gdbpy_initialize_pspace,
gdbpy_initialize_objfile, gdbpy_initialize_breakpoints,
gdbpy_initialize_finishbreakpoints,
gdbpy_initialize_lazy_string, gdbpy_initialize_parameters,
gdbpy_initialize_thread, gdbpy_initialize_inferior,
gdbpy_initialize_eventregistry, gdbpy_initialize_event,
gdbpy_initialize_py_events, gdbpy_initialize_stop_event,
gdbpy_initialize_signal_event,
gdbpy_initialize_breakpoint_event,
gdbpy_initialize_continue_event,
gdbpy_initialize_exited_event, gdbpy_initialize_thread_event,
gdbpy_initialize_new_objfile_event, gdbpy_initialize_arch):
Update. Use CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION.
* python/python.c (gdb_python_initialized): New global.
(gdbpy_initialize_events): Return 'int'. Check errors.
(_initialize_python): Check errors. Set
gdb_python_initialized.
2013-05-20 20:28:52 +00:00
|
|
|
|
return -1;
|
2009-02-06 21:33:59 +00:00
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < N_COMPLETERS; ++i)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (PyModule_AddIntConstant (gdb_module, completers[i].name, i) < 0)
|
* python/py-arch.c (gdbpy_initialize_arch): Return 'int'.
Check errors.
* python/py-auto-load.c (gdbpy_initialize_auto_load): Return 'int'.
* python/py-block.c (gdbpy_initialize_blocks): Return 'int'.
Check errors.
* python/py-breakpoint.c (gdbpy_initialize_breakpoints): Return 'int'.
Check errors.
* python/py-cmd.c (gdbpy_initialize_commands): Return 'int'.
Check errors.
* python/py-event.c (gdbpy_initialize_event): Return 'int'.
Check errors.
* python/py-event.h (GDBPY_NEW_EVENT_TYPE): Change generated
init function to return 'int'.
* python/py-evtregistry.c (gdbpy_initialize_eventregistry):
Return 'int'. Check errors.
* python/py-evts.c (gdbpy_initialize_py_events): Return 'int'.
Check errors.
* python/py-finishbreakpoint.c (gdbpy_initialize_finishbreakpoints):
Return 'int'. Check errors.
* python/py-frame.c (gdbpy_initialize_frames): Return 'int'.
Check errors.
* python/py-function.c (gdbpy_initialize_functions): Return 'int'.
Check errors.
* python/py-gdb-readline.c (gdbpy_initialize_gdb_readline):
Check errors.
* python/py-inferior.c (gdbpy_initialize_inferior): Return 'int'.
Check errors.
* python/py-infthread.c (gdbpy_initialize_thread): Return 'int'.
Check errors.
* python/py-lazy-string.c (gdbpy_initialize_lazy_string): Return 'int'.
Check errors.
* python/py-objfile.c (gdbpy_initialize_objfile): Return 'int'.
Check errors.
* python/py-param.c (gdbpy_initialize_parameters): Return 'int'.
Check errors.
* python/py-progspace.c (gdbpy_initialize_pspace): Return 'int'.
Check errors.
* python/py-symbol.c (gdbpy_initialize_symbols): Return 'int'.
Check errors.
* python/py-symtab.c (gdbpy_initialize_symtabs): Return 'int'.
Check errors.
* python/py-type.c (gdbpy_initialize_types): Return 'int'.
Check errors.
* python/py-value.c (gdbpy_initialize_values): Return 'int'.
Check errors.
* python/python-internal.h (gdbpy_initialize_auto_load,
gdbpy_initialize_values, gdbpy_initialize_frames,
gdbpy_initialize_symtabs, gdbpy_initialize_commands,
gdbpy_initialize_symbols, gdbpy_initialize_symtabs,
gdbpy_initialize_blocks, gdbpy_initialize_types,
gdbpy_initialize_functions, gdbpy_initialize_pspace,
gdbpy_initialize_objfile, gdbpy_initialize_breakpoints,
gdbpy_initialize_finishbreakpoints,
gdbpy_initialize_lazy_string, gdbpy_initialize_parameters,
gdbpy_initialize_thread, gdbpy_initialize_inferior,
gdbpy_initialize_eventregistry, gdbpy_initialize_event,
gdbpy_initialize_py_events, gdbpy_initialize_stop_event,
gdbpy_initialize_signal_event,
gdbpy_initialize_breakpoint_event,
gdbpy_initialize_continue_event,
gdbpy_initialize_exited_event, gdbpy_initialize_thread_event,
gdbpy_initialize_new_objfile_event, gdbpy_initialize_arch):
Update. Use CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION.
* python/python.c (gdb_python_initialized): New global.
(gdbpy_initialize_events): Return 'int'. Check errors.
(_initialize_python): Check errors. Set
gdb_python_initialized.
2013-05-20 20:28:52 +00:00
|
|
|
|
return -1;
|
2009-02-06 21:33:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2022-03-21 10:07:41 -04:00
|
|
|
|
invoke_cst = PyUnicode_FromString ("invoke");
|
* python/py-arch.c (gdbpy_initialize_arch): Return 'int'.
Check errors.
* python/py-auto-load.c (gdbpy_initialize_auto_load): Return 'int'.
* python/py-block.c (gdbpy_initialize_blocks): Return 'int'.
Check errors.
* python/py-breakpoint.c (gdbpy_initialize_breakpoints): Return 'int'.
Check errors.
* python/py-cmd.c (gdbpy_initialize_commands): Return 'int'.
Check errors.
* python/py-event.c (gdbpy_initialize_event): Return 'int'.
Check errors.
* python/py-event.h (GDBPY_NEW_EVENT_TYPE): Change generated
init function to return 'int'.
* python/py-evtregistry.c (gdbpy_initialize_eventregistry):
Return 'int'. Check errors.
* python/py-evts.c (gdbpy_initialize_py_events): Return 'int'.
Check errors.
* python/py-finishbreakpoint.c (gdbpy_initialize_finishbreakpoints):
Return 'int'. Check errors.
* python/py-frame.c (gdbpy_initialize_frames): Return 'int'.
Check errors.
* python/py-function.c (gdbpy_initialize_functions): Return 'int'.
Check errors.
* python/py-gdb-readline.c (gdbpy_initialize_gdb_readline):
Check errors.
* python/py-inferior.c (gdbpy_initialize_inferior): Return 'int'.
Check errors.
* python/py-infthread.c (gdbpy_initialize_thread): Return 'int'.
Check errors.
* python/py-lazy-string.c (gdbpy_initialize_lazy_string): Return 'int'.
Check errors.
* python/py-objfile.c (gdbpy_initialize_objfile): Return 'int'.
Check errors.
* python/py-param.c (gdbpy_initialize_parameters): Return 'int'.
Check errors.
* python/py-progspace.c (gdbpy_initialize_pspace): Return 'int'.
Check errors.
* python/py-symbol.c (gdbpy_initialize_symbols): Return 'int'.
Check errors.
* python/py-symtab.c (gdbpy_initialize_symtabs): Return 'int'.
Check errors.
* python/py-type.c (gdbpy_initialize_types): Return 'int'.
Check errors.
* python/py-value.c (gdbpy_initialize_values): Return 'int'.
Check errors.
* python/python-internal.h (gdbpy_initialize_auto_load,
gdbpy_initialize_values, gdbpy_initialize_frames,
gdbpy_initialize_symtabs, gdbpy_initialize_commands,
gdbpy_initialize_symbols, gdbpy_initialize_symtabs,
gdbpy_initialize_blocks, gdbpy_initialize_types,
gdbpy_initialize_functions, gdbpy_initialize_pspace,
gdbpy_initialize_objfile, gdbpy_initialize_breakpoints,
gdbpy_initialize_finishbreakpoints,
gdbpy_initialize_lazy_string, gdbpy_initialize_parameters,
gdbpy_initialize_thread, gdbpy_initialize_inferior,
gdbpy_initialize_eventregistry, gdbpy_initialize_event,
gdbpy_initialize_py_events, gdbpy_initialize_stop_event,
gdbpy_initialize_signal_event,
gdbpy_initialize_breakpoint_event,
gdbpy_initialize_continue_event,
gdbpy_initialize_exited_event, gdbpy_initialize_thread_event,
gdbpy_initialize_new_objfile_event, gdbpy_initialize_arch):
Update. Use CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION.
* python/python.c (gdb_python_initialized): New global.
(gdbpy_initialize_events): Return 'int'. Check errors.
(_initialize_python): Check errors. Set
gdb_python_initialized.
2013-05-20 20:28:52 +00:00
|
|
|
|
if (invoke_cst == NULL)
|
|
|
|
|
|
return -1;
|
2022-03-21 10:07:41 -04:00
|
|
|
|
complete_cst = PyUnicode_FromString ("complete");
|
* python/py-arch.c (gdbpy_initialize_arch): Return 'int'.
Check errors.
* python/py-auto-load.c (gdbpy_initialize_auto_load): Return 'int'.
* python/py-block.c (gdbpy_initialize_blocks): Return 'int'.
Check errors.
* python/py-breakpoint.c (gdbpy_initialize_breakpoints): Return 'int'.
Check errors.
* python/py-cmd.c (gdbpy_initialize_commands): Return 'int'.
Check errors.
* python/py-event.c (gdbpy_initialize_event): Return 'int'.
Check errors.
* python/py-event.h (GDBPY_NEW_EVENT_TYPE): Change generated
init function to return 'int'.
* python/py-evtregistry.c (gdbpy_initialize_eventregistry):
Return 'int'. Check errors.
* python/py-evts.c (gdbpy_initialize_py_events): Return 'int'.
Check errors.
* python/py-finishbreakpoint.c (gdbpy_initialize_finishbreakpoints):
Return 'int'. Check errors.
* python/py-frame.c (gdbpy_initialize_frames): Return 'int'.
Check errors.
* python/py-function.c (gdbpy_initialize_functions): Return 'int'.
Check errors.
* python/py-gdb-readline.c (gdbpy_initialize_gdb_readline):
Check errors.
* python/py-inferior.c (gdbpy_initialize_inferior): Return 'int'.
Check errors.
* python/py-infthread.c (gdbpy_initialize_thread): Return 'int'.
Check errors.
* python/py-lazy-string.c (gdbpy_initialize_lazy_string): Return 'int'.
Check errors.
* python/py-objfile.c (gdbpy_initialize_objfile): Return 'int'.
Check errors.
* python/py-param.c (gdbpy_initialize_parameters): Return 'int'.
Check errors.
* python/py-progspace.c (gdbpy_initialize_pspace): Return 'int'.
Check errors.
* python/py-symbol.c (gdbpy_initialize_symbols): Return 'int'.
Check errors.
* python/py-symtab.c (gdbpy_initialize_symtabs): Return 'int'.
Check errors.
* python/py-type.c (gdbpy_initialize_types): Return 'int'.
Check errors.
* python/py-value.c (gdbpy_initialize_values): Return 'int'.
Check errors.
* python/python-internal.h (gdbpy_initialize_auto_load,
gdbpy_initialize_values, gdbpy_initialize_frames,
gdbpy_initialize_symtabs, gdbpy_initialize_commands,
gdbpy_initialize_symbols, gdbpy_initialize_symtabs,
gdbpy_initialize_blocks, gdbpy_initialize_types,
gdbpy_initialize_functions, gdbpy_initialize_pspace,
gdbpy_initialize_objfile, gdbpy_initialize_breakpoints,
gdbpy_initialize_finishbreakpoints,
gdbpy_initialize_lazy_string, gdbpy_initialize_parameters,
gdbpy_initialize_thread, gdbpy_initialize_inferior,
gdbpy_initialize_eventregistry, gdbpy_initialize_event,
gdbpy_initialize_py_events, gdbpy_initialize_stop_event,
gdbpy_initialize_signal_event,
gdbpy_initialize_breakpoint_event,
gdbpy_initialize_continue_event,
gdbpy_initialize_exited_event, gdbpy_initialize_thread_event,
gdbpy_initialize_new_objfile_event, gdbpy_initialize_arch):
Update. Use CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION.
* python/python.c (gdb_python_initialized): New global.
(gdbpy_initialize_events): Return 'int'. Check errors.
(_initialize_python): Check errors. Set
gdb_python_initialized.
2013-05-20 20:28:52 +00:00
|
|
|
|
if (complete_cst == NULL)
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
2009-02-06 21:33:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
gdb/python: add mechanism to manage Python initialization functions
Currently, when we add a new python sub-system to GDB,
e.g. py-inferior.c, we end up having to create a new function like
gdbpy_initialize_inferior, which then has to be called from the
function do_start_initialization in python.c.
In some cases (py-micmd.c and py-tui.c), we have two functions
gdbpy_initialize_*, and gdbpy_finalize_*, with the second being called
from finalize_python which is also in python.c.
This commit proposes a mechanism to manage these initialization and
finalization calls, this means that adding a new Python subsystem will
no longer require changes to python.c or python-internal.h, instead,
the initialization and finalization functions will be registered
directly from the sub-system file, e.g. py-inferior.c, or py-micmd.c.
The initialization and finalization functions are managed through a
new class gdbpy_initialize_file in python-internal.h. This class
contains a single global vector of all the initialization and
finalization functions.
In each Python sub-system we create a new gdbpy_initialize_file
object, the object constructor takes care of registering the two
callback functions.
Now from python.c we can call static functions on the
gdbpy_initialize_file class which take care of walking the callback
list and invoking each callback in turn.
To slightly simplify the Python sub-system files I added a new macro
GDBPY_INITIALIZE_FILE, which hides the need to create an object. We
can now just do this:
GDBPY_INITIALIZE_FILE (gdbpy_initialize_registers);
One possible problem with this change is that there is now no
guaranteed ordering of how the various sub-systems are initialized (or
finalized). To try and avoid dependencies creeping in I have added a
use of the environment variable GDB_REVERSE_INIT_FUNCTIONS, this is
the same environment variable used in the generated init.c file.
Just like with init.c, when this environment variable is set we
reverse the list of Python initialization (and finalization)
functions. As there is already a test that starts GDB with the
environment variable set then this should offer some level of
protection against dependencies creeping in - though for full
protection I guess we'd need to run all gdb.python/*.exp tests with
the variable set.
I have tested this patch with the environment variable set, and saw no
regressions, so I think we are fine right now.
One other change of note was for gdbpy_initialize_gdb_readline, this
function previously returned void. In order to make this function
have the correct signature I've updated its return type to int, and we
now return 0 to indicate success.
All of the other initialize (and finalize) functions have been made
static within their respective sub-system files.
There should be no user visible changes after this commit.
2022-09-16 16:08:17 +01:00
|
|
|
|
GDBPY_INITIALIZE_FILE (gdbpy_initialize_commands);
|
|
|
|
|
|
|
2009-02-06 21:33:59 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static PyMethodDef cmdpy_object_methods[] =
|
|
|
|
|
|
{
|
|
|
|
|
|
{ "dont_repeat", cmdpy_dont_repeat, METH_NOARGS,
|
|
|
|
|
|
"Prevent command repetition when user enters empty line." },
|
|
|
|
|
|
|
|
|
|
|
|
{ 0 }
|
|
|
|
|
|
};
|
|
|
|
|
|
|
Fix redefinition errors in C++ mode
In C, we can forward declare static structure instances. That doesn't
work in C++ though. C++ treats these as definitions. So then the
compiler complains about symbol redefinition, like:
src/gdb/elfread.c:1569:29: error: redefinition of ‘const sym_fns elf_sym_fns_lazy_psyms’
src/gdb/elfread.c:53:29: error: ‘const sym_fns elf_sym_fns_lazy_psyms’ previously declared here
The intent of static here is naturally to avoid making these objects
visible outside the compilation unit. The equivalent in C++ would be
to instead define the objects in the anonymous namespace. But given
that it's desirable to leave the codebase compiling as both C and C++
for a while, this just makes the objects extern.
(base_breakpoint_ops is already declared in breakpoint.h, so we can
just remove the forward declare from breakpoint.c)
gdb/ChangeLog:
2015-02-11 Tom Tromey <tromey@redhat.com>
Pedro Alves <palves@redhat.com>
* breakpoint.c (base_breakpoint_ops): Delete.
* dwarf2loc.c (dwarf_expr_ctx_funcs): Make extern.
* elfread.c (elf_sym_fns_gdb_index, elf_sym_fns_lazy_psyms): Make extern.
* guile/guile.c (guile_extension_script_ops, guile_extension_ops): Make extern.
* ppcnbsd-tdep.c (ppcnbsd2_sigtramp): Make extern.
* python/py-arch.c (arch_object_type): Make extern.
* python/py-block.c (block_syms_iterator_object_type): Make extern.
* python/py-bpevent.c (breakpoint_event_object_type): Make extern.
* python/py-cmd.c (cmdpy_object_type): Make extern.
* python/py-continueevent.c (continue_event_object_type)
* python/py-event.h (GDBPY_NEW_EVENT_TYPE): Remove 'qual'
parameter. Update all callers.
* python/py-evtregistry.c (eventregistry_object_type): Make extern.
* python/py-exitedevent.c (exited_event_object_type): Make extern.
* python/py-finishbreakpoint.c (finish_breakpoint_object_type): Make extern.
* python/py-function.c (fnpy_object_type): Make extern.
* python/py-inferior.c (inferior_object_type, membuf_object_type): Make extern.
* python/py-infevents.c (call_pre_event_object_type)
(inferior_call_post_event_object_type).
(memory_changed_event_object_type): Make extern.
* python/py-infthread.c (thread_object_type): Make extern.
* python/py-lazy-string.c (lazy_string_object_type): Make extern.
* python/py-linetable.c (linetable_entry_object_type)
(linetable_object_type, ltpy_iterator_object_type): Make extern.
* python/py-newobjfileevent.c (new_objfile_event_object_type)
(clear_objfiles_event_object_type): Make extern.
* python/py-objfile.c (objfile_object_type): Make extern.
* python/py-param.c (parmpy_object_type): Make extern.
* python/py-progspace.c (pspace_object_type): Make extern.
* python/py-signalevent.c (signal_event_object_type): Make extern.
* python/py-symtab.c (symtab_object_type, sal_object_type): Make extern.
* python/py-type.c (type_object_type, field_object_type)
(type_iterator_object_type): Make extern.
* python/python.c (python_extension_script_ops)
(python_extension_ops): Make extern.
* stap-probe.c (stap_probe_ops): Make extern.
2015-02-11 11:20:21 +00:00
|
|
|
|
PyTypeObject cmdpy_object_type =
|
2009-02-06 21:33:59 +00:00
|
|
|
|
{
|
2012-12-12 16:47:30 +00:00
|
|
|
|
PyVarObject_HEAD_INIT (NULL, 0)
|
2009-02-06 21:33:59 +00:00
|
|
|
|
"gdb.Command", /*tp_name*/
|
|
|
|
|
|
sizeof (cmdpy_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 command object", /* tp_doc */
|
|
|
|
|
|
0, /* tp_traverse */
|
|
|
|
|
|
0, /* tp_clear */
|
|
|
|
|
|
0, /* tp_richcompare */
|
|
|
|
|
|
0, /* tp_weaklistoffset */
|
|
|
|
|
|
0, /* tp_iter */
|
|
|
|
|
|
0, /* tp_iternext */
|
|
|
|
|
|
cmdpy_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 */
|
|
|
|
|
|
cmdpy_init, /* tp_init */
|
|
|
|
|
|
0, /* tp_alloc */
|
|
|
|
|
|
};
|
2010-05-25 15:27:17 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Utility to build a buildargv-like result from ARGS.
|
|
|
|
|
|
This intentionally parses arguments the way libiberty/argv.c:buildargv
|
|
|
|
|
|
does. It splits up arguments in a reasonable way, and we want a standard
|
|
|
|
|
|
way of parsing arguments. Several gdb commands use buildargv to parse their
|
|
|
|
|
|
arguments. Plus we want to be able to write compatible python
|
|
|
|
|
|
implementations of gdb commands. */
|
|
|
|
|
|
|
|
|
|
|
|
PyObject *
|
|
|
|
|
|
gdbpy_string_to_argv (PyObject *self, PyObject *args)
|
|
|
|
|
|
{
|
2011-06-24 19:47:37 +00:00
|
|
|
|
const char *input;
|
2010-05-25 15:27:17 +00:00
|
|
|
|
|
|
|
|
|
|
if (!PyArg_ParseTuple (args, "s", &input))
|
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
Turn gdbpy_ref into a template
This turns gdbpy_ref into a template class, so that it can be used to
wrap subclasses of PyObject. The default argument remains PyObject;
and this necessitated renaming uses of "gdbpy_ref" to "gdbpy_ref<>".
gdb/ChangeLog
2017-02-10 Tom Tromey <tom@tromey.com>
* python/py-ref.h (gdbpy_ref_policy): Now a template.
(gdbpy_ref): Now a template; allow subclasses of PyObject to be
used.
* python/py-arch.c, python/py-bpevent.c, python/py-breakpoint.c,
python/py-cmd.c, python/py-continueevent.c, python/py-event.c,
python/py-exitedevent.c, python/py-finishbreakpoint.c,
python/py-framefilter.c, python/py-function.c,
python/py-inferior.c, python/py-infevents.c,
python/py-linetable.c, python/py-newobjfileevent.c,
python/py-param.c, python/py-prettyprint.c, python/py-ref.h,
python/py-signalevent.c, python/py-stopevent.c,
python/py-symbol.c, python/py-threadevent.c, python/py-type.c,
python/py-unwind.c, python/py-utils.c, python/py-value.c,
python/py-varobj.c, python/py-xmethods.c, python/python.c,
varobj.c: Change gdbpy_ref to gdbpy_ref<>.
2017-02-09 13:16:36 -07:00
|
|
|
|
gdbpy_ref<> py_argv (PyList_New (0));
|
2013-05-20 20:14:51 +00:00
|
|
|
|
if (py_argv == NULL)
|
|
|
|
|
|
return NULL;
|
2010-05-25 15:27:17 +00:00
|
|
|
|
|
|
|
|
|
|
/* buildargv uses NULL to represent an empty argument list, but we can't use
|
|
|
|
|
|
that in Python. Instead, if ARGS is "" then return an empty list.
|
|
|
|
|
|
This undoes the NULL -> "" conversion that cmdpy_function does. */
|
|
|
|
|
|
|
|
|
|
|
|
if (*input != '\0')
|
|
|
|
|
|
{
|
Introduce gdb_argv, a class wrapper for buildargv
This introduces gdb_argv, a class wrapping an "argv" pointer; that is,
a pointer to a NULL-terminated array of char*, where both the array
and each non-NULL element in the array are xmalloc'd.
This patch then changes most users of gdb_buildargv to use gdb_argv
instead.
ChangeLog
2017-08-03 Tom Tromey <tom@tromey.com>
* utils.h (struct gdb_argv_deleter): New.
(gdb_argv): New class.
* utils.c (gdb_argv::reset): New method.
* tracepoint.c (delete_trace_variable_command): Use gdb_argv.
* tracefile.c (tsave_command): Use gdb_argv.
* top.c (new_ui_command): Use gdb_argv.
* symmisc.c (maintenance_print_symbols)
(maintenance_print_msymbols, maintenance_expand_symtabs): Use gdb_argv.
* symfile.c (symbol_file_command, generic_load)
(remove_symbol_file_command): Use gdb_argv.
* stack.c (backtrace_command): Use gdb_argv.
* source.c (add_path, show_substitute_path_command)
(unset_substitute_path_command, set_substitute_path_command):
Use gdb_argv.
* skip.c (skip_command): Use gdb_argv. Use gdb_buildargv.
* ser-mingw.c (pipe_windows_open): Use gdb_argv.
* remote.c (extended_remote_run, remote_put_command)
(remote_get_command, remote_delete_command): Use gdb_argv.
* remote-sim.c (gdbsim_load, gdbsim_create_inferior)
(gdbsim_open): Use gdb_argv.
* python/py-cmd.c (gdbpy_string_to_argv): Use gdb_argv.
* psymtab.c (maintenance_print_psymbols): Use gdb_argv.
* procfs.c (procfs_info_proc): Use gdb_argv.
* interps.c (interpreter_exec_cmd): Use gdb_argv.
* infrun.c (handle_command): Use gdb_argv.
* inferior.c (add_inferior_command, clone_inferior_command):
Use gdb_argv.
* guile/scm-string.c (gdbscm_string_to_argv): Use gdb_argv.
* exec.c (exec_file_command): Use gdb_argv.
* cli/cli-cmds.c (alias_command): Use gdb_argv.
* compile/compile.c (build_argc_argv): Use gdb_argv.
2017-04-30 23:02:30 -06:00
|
|
|
|
gdb_argv c_argv (input);
|
2010-05-25 15:27:17 +00:00
|
|
|
|
|
Introduce gdb_argv, a class wrapper for buildargv
This introduces gdb_argv, a class wrapping an "argv" pointer; that is,
a pointer to a NULL-terminated array of char*, where both the array
and each non-NULL element in the array are xmalloc'd.
This patch then changes most users of gdb_buildargv to use gdb_argv
instead.
ChangeLog
2017-08-03 Tom Tromey <tom@tromey.com>
* utils.h (struct gdb_argv_deleter): New.
(gdb_argv): New class.
* utils.c (gdb_argv::reset): New method.
* tracepoint.c (delete_trace_variable_command): Use gdb_argv.
* tracefile.c (tsave_command): Use gdb_argv.
* top.c (new_ui_command): Use gdb_argv.
* symmisc.c (maintenance_print_symbols)
(maintenance_print_msymbols, maintenance_expand_symtabs): Use gdb_argv.
* symfile.c (symbol_file_command, generic_load)
(remove_symbol_file_command): Use gdb_argv.
* stack.c (backtrace_command): Use gdb_argv.
* source.c (add_path, show_substitute_path_command)
(unset_substitute_path_command, set_substitute_path_command):
Use gdb_argv.
* skip.c (skip_command): Use gdb_argv. Use gdb_buildargv.
* ser-mingw.c (pipe_windows_open): Use gdb_argv.
* remote.c (extended_remote_run, remote_put_command)
(remote_get_command, remote_delete_command): Use gdb_argv.
* remote-sim.c (gdbsim_load, gdbsim_create_inferior)
(gdbsim_open): Use gdb_argv.
* python/py-cmd.c (gdbpy_string_to_argv): Use gdb_argv.
* psymtab.c (maintenance_print_psymbols): Use gdb_argv.
* procfs.c (procfs_info_proc): Use gdb_argv.
* interps.c (interpreter_exec_cmd): Use gdb_argv.
* infrun.c (handle_command): Use gdb_argv.
* inferior.c (add_inferior_command, clone_inferior_command):
Use gdb_argv.
* guile/scm-string.c (gdbscm_string_to_argv): Use gdb_argv.
* exec.c (exec_file_command): Use gdb_argv.
* cli/cli-cmds.c (alias_command): Use gdb_argv.
* compile/compile.c (build_argc_argv): Use gdb_argv.
2017-04-30 23:02:30 -06:00
|
|
|
|
for (char *arg : c_argv)
|
2010-05-25 15:27:17 +00:00
|
|
|
|
{
|
2022-03-21 10:07:41 -04:00
|
|
|
|
gdbpy_ref<> argp (PyUnicode_FromString (arg));
|
2010-05-25 15:27:17 +00:00
|
|
|
|
|
|
|
|
|
|
if (argp == NULL
|
2016-11-06 21:10:18 -07:00
|
|
|
|
|| PyList_Append (py_argv.get (), argp.get ()) < 0)
|
Introduce gdb_argv, a class wrapper for buildargv
This introduces gdb_argv, a class wrapping an "argv" pointer; that is,
a pointer to a NULL-terminated array of char*, where both the array
and each non-NULL element in the array are xmalloc'd.
This patch then changes most users of gdb_buildargv to use gdb_argv
instead.
ChangeLog
2017-08-03 Tom Tromey <tom@tromey.com>
* utils.h (struct gdb_argv_deleter): New.
(gdb_argv): New class.
* utils.c (gdb_argv::reset): New method.
* tracepoint.c (delete_trace_variable_command): Use gdb_argv.
* tracefile.c (tsave_command): Use gdb_argv.
* top.c (new_ui_command): Use gdb_argv.
* symmisc.c (maintenance_print_symbols)
(maintenance_print_msymbols, maintenance_expand_symtabs): Use gdb_argv.
* symfile.c (symbol_file_command, generic_load)
(remove_symbol_file_command): Use gdb_argv.
* stack.c (backtrace_command): Use gdb_argv.
* source.c (add_path, show_substitute_path_command)
(unset_substitute_path_command, set_substitute_path_command):
Use gdb_argv.
* skip.c (skip_command): Use gdb_argv. Use gdb_buildargv.
* ser-mingw.c (pipe_windows_open): Use gdb_argv.
* remote.c (extended_remote_run, remote_put_command)
(remote_get_command, remote_delete_command): Use gdb_argv.
* remote-sim.c (gdbsim_load, gdbsim_create_inferior)
(gdbsim_open): Use gdb_argv.
* python/py-cmd.c (gdbpy_string_to_argv): Use gdb_argv.
* psymtab.c (maintenance_print_psymbols): Use gdb_argv.
* procfs.c (procfs_info_proc): Use gdb_argv.
* interps.c (interpreter_exec_cmd): Use gdb_argv.
* infrun.c (handle_command): Use gdb_argv.
* inferior.c (add_inferior_command, clone_inferior_command):
Use gdb_argv.
* guile/scm-string.c (gdbscm_string_to_argv): Use gdb_argv.
* exec.c (exec_file_command): Use gdb_argv.
* cli/cli-cmds.c (alias_command): Use gdb_argv.
* compile/compile.c (build_argc_argv): Use gdb_argv.
2017-04-30 23:02:30 -06:00
|
|
|
|
return NULL;
|
2010-05-25 15:27:17 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-11-06 21:10:18 -07:00
|
|
|
|
return py_argv.release ();
|
2010-05-25 15:27:17 +00:00
|
|
|
|
}
|