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.
This changes the users of do_restore_instream_cleanup to use a
scoped_restore instead. This patch is broken out because it warrants
some additional attention: in particular it's unclear to me whether
current_ui can change in the body of these functions -- but if it can,
then the cleanup would have modified a different UI's instream member.
ChangeLog
2017-08-03 Tom Tromey <tom@tromey.com>
* top.h (do_restore_instream_cleanup): Remove.
* top.c (do_restore_instream_cleanup): Remove.
(read_command_file): Use scoped_restore.
* cli/cli-script.c (execute_user_command): Use scoped_restore.
While working on the next patch in this series, I found that the
global in_user_command is not used. This patch removes it. (I didn't
think to check Insight until submitting this series; and it's not very
convenient to do so, so if someone has it checked out and could look
at it, that would be nice.)
ChangeLog
2017-08-03 Tom Tromey <tom@tromey.com>
* top.h (in_user_command): Remove.
* top.c (in_user_command): Remove.
* cli/cli-script.c (do_restore_user_call_depth)
(execute_user_command): Update.
This changes open_terminal_stream to return a gdb_file_up, eliminating
another use of make_cleanup_fclose. Arguably perhaps new_ui should
take ownership of the files using a move, but there is at least one
spot where this isn't appropriate (or at least not currently done), so
I elected to use a more minimal approach.
ChangeLog
2017-08-03 Tom Tromey <tom@tromey.com>
* top.c (open_terminal_stream): Return gdb_file_up.
(new_ui_command): Update.
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.
This commit moves a few bits responsible for dealing with inferior job
control from GDB to common/, which makes them available to gdbserver.
This is necessary for the upcoming patches that will share
fork_inferior et al between GDB and gdbserver.
We move some parts of gdb/terminal.h to gdb/common/common-terminal.h,
especifically the code that checks terminal features and that are used
to set job_control accordingly.
After sharing parts of gdb/terminal.h, we also to share the two
functions on gdb/inflow.c that are going to be needed by the
fork_inferior rework. They are 'gdb_setpgid' and the new
'have_job_control'. I've also taken the opportunity to give a more
meaningful name to "inflow.c" on common/. Now it is called
"job-control.c" (thanks Pedro for the suggestion).
gdb/ChangeLog:
2017-06-07 Sergio Durigan Junior <sergiodj@redhat.com>
* Makefile.in (SFILES): Add "common/job-control.c".
(HFILES_NO_SRCDIR): Add "common/job-control.h".
(COMMON_OBS): Add "job-control.o".
* common/job-control.c: New file, with contents from
"gdb/inflow.c".
* common/job-control.h: New file, with contents from "terminal.h".
* fork-child.c: Include "job-control.h".
* inflow.c: Include "job-control.h".
(gdb_setpgid): Move to "common/common-inflow.c".
(_initialize_inflow): Move setting of "job_control" to
"handle_job_control".
* terminal.h (job_control): Moved to "common/common-terminal.h".
(gdb_setpgid): Likewise.
* top.c: Include "job_control.h".
* utils.c: Likewise.
(job_control): Moved to "job-control.c".
gdb/gdbserver/ChangeLog:
2017-06-07 Sergio Durigan Junior <sergiodj@redhat.com>
* Makefile.in (SFILE): Add "common/job-control.c".
(OBS): Add "job-control.o".
-Wwrite-strings flags several cases of missing casts around
initializations like:
static char *gdb_completer_command_word_break_characters =
" \t\n!@#$%^&*()+=|~`}{[]\"';:?/>.<,";
Obviously these could/should be const. However, while at it, there's
no need for these variables to be pointers instead of arrays. They
are never changed to point to anything else.
Unfortunately, readline's rl_completer_word_break_characters is
"char *", not "const char *". So we always need a cast somewhere. The
approach taken here is to add a new
set_rl_completer_word_break_characters function that becomes the only
place that writes to rl_completer_word_break_characters, and thus the
single place that needs the cast.
gdb/ChangeLog:
2017-04-05 Pedro Alves <palves@redhat.com>
* ada-lang.c (ada_completer_word_break_characters): Now a const
array.
(ada_get_gdb_completer_word_break_characters): Constify.
* completer.c (gdb_completer_command_word_break_characters)
(gdb_completer_file_name_break_characters)
(gdb_completer_quote_characters): Now const arrays.
(get_gdb_completer_quote_characters): Constify.
(set_rl_completer_word_break_characters): New function.
(set_gdb_completion_word_break_characters)
(complete_line_internal): Use it.
* completer.h (get_gdb_completer_quote_characters): Constify.
(set_rl_completer_word_break_characters): Declare.
* f-lang.c (f_word_break_characters): Constify.
* language.c (default_word_break_characters): Constify.
* language.h (language_defn::la_word_break_characters): Constify.
(default_word_break_characters): Constify.
* top.c (init_main): Use set_rl_completer_word_break_characters.
With commit 3b12939dfc ("Replace the sync_execution global with a
new enum prompt_state tristate"), GDB started aborting if you try
splitting an input line with a continuation char (backslash) while in
a multi-line command:
(gdb) commands
Type commands for breakpoint(s) 1, one per line.
End with a line saying just "end".
>print \
(gdb) 1 # note "(gdb)" incorrectly printed here.
>end
readline: readline_callback_read_char() called with no handler!
$
That abort is actually a symptom of an old problem introduced when
gdb_readline_wrapper was rewritten to use asynchronous readline, back
in 2007. Note how the "(gdb)" prompt is printed above in the "(gdb)
1" line. Clearly it shouldn't be there, but it already was before the
commit mentioned above. Fixing that also fixes the readline abort
shown above.
The problem starts when command_line_input passes a NULL prompt to
gdb_readline_wrapper when it finds previous incomplete input due to a
backslash, trying to fetch more input without printing another ">"
secondary prompt. That itself should not be a problem, because
passing NULL to gdb_readline_wrapper has the same meaning as passing a
pointer to empty string, since gdb_readline_wrapper exposes the same
interface as 'readline(char *)'. However, gdb_readline_wrapper passes
the prompt argument directly to display_gdb_prompt, and for the
latter, a NULL prompt argument has a different meaning - it requests
printing the primary prompt.
Before commit 782a7b8ef9c096 (which rewrote gdb_readline_wrapper to
use asynchronous readline), GDB behaved like this:
(gdb) commands
[....]
>print \
1
>end
(gdb)
The above is what this commit restores GDB back to.
New test included.
gdb/ChangeLog:
2017-03-08 Pedro Alves <palves@redhat.com>
PR cli/21218
* top.c (gdb_readline_wrapper): Avoid passing NULL to
display_gdb_prompt.
(command_line_input): Add comment.
gdb/testsuite/ChangeLog:
2017-03-08 Pedro Alves <palves@redhat.com>
Jan Kratochvil <jan.kratochvil@redhat.com>
PR cli/21218
* gdb.base/commands.exp (backslash_in_multi_line_command_test):
New proc.
(top level): Call it.
This patch starts from the desire to eliminate
make_cleanup_ui_file_delete, but then goes beyond. It makes ui_file &
friends a real C++ class hierarchy, and switches temporary
ui_file-like objects to stack-based allocation.
- mem_fileopen -> string_file
mem_fileopen is replaced with a new string_file class that is treated
as a value class created on the stack. This alone eliminates most
make_cleanup_ui_file_delete calls, and, simplifies code a whole lot
(diffstat shows around 1k loc dropped.)
string_file's internal buffer is a std::string, thus the "string" in
the name. This simplifies the implementation much, compared to
mem_fileopen, which managed growing its internal buffer manually.
- ui_file_as_string, ui_file_strdup, ui_file_obsavestring all gone
The new string_file class has a string() method that provides direct
writable access to the internal std::string buffer. This replaced
ui_file_as_string, which forced a copy of the same data the stream had
inside. With direct access via a writable reference, we can instead
move the string out of the string_stream, avoiding deep string
copying.
Related, ui_file_xstrdup calls are replaced with xstrdup'ping the
stream's string, and ui_file_obsavestring is replaced by
obstack_copy0.
With all those out of the way, getting rid of the weird ui_file_put
mechanism was possible.
- New ui_file::printf, ui_file::puts, etc. methods
These simplify / clarify client code. I considered splitting
client-code changes, like these, e.g.:
- stb = mem_fileopen ();
- fprintf_unfiltered (stb, "%s%s%s",
- _("The valid values are:\n"),
- regdesc,
- _("The default is \"std\"."));
+ string_file stb;
+ stb.printf ("%s%s%s",
+ _("The valid values are:\n"),
+ regdesc,
+ _("The default is \"std\"."));
In two steps, with the first step leaving fprintf_unfiltered (etc.)
calls in place, and only afterwards do a pass to change all those to
call stb.printf etc.. I didn't do that split, because (when I tried),
it turned out to be pointless make-work: the first pass would have to
touch the fprintf_unfiltered line anyway, to replace "stb" with
"&stb".
- gdb_fopen replaced with stack-based objects
This avoids the need for cleanups or unique_ptr's. I.e., this:
struct ui_file *file = gdb_fopen (filename, "w");
if (filename == NULL)
perror_with_name (filename);
cleanups = make_cleanup_ui_file_delete (file);
// use file.
do_cleanups (cleanups);
is replaced with this:
stdio_file file;
if (!file.open (filename, "w"))
perror_with_name (filename);
// use file.
- odd contorsions in null_file_write / null_file_fputs around when to
call to_fputs / to_write eliminated.
- Global null_stream object
A few places that were allocating a ui_file in order to print to
"nowhere" are adjusted to instead refer to a new 'null_stream' global
stream.
- TUI's tui_sfileopen eliminated. TUI's ui_file much simplified
The TUI's ui_file was serving a dual purpose. It supported being used
as string buffer, and supported being backed by a stdio FILE. The
string buffer part is gone, replaced by using of string_file. The
'FILE *' support is now much simplified, by making the TUI's ui_file
inherit from stdio_file.
gdb/ChangeLog:
2017-02-02 Pedro Alves <palves@redhat.com>
* ada-lang.c (type_as_string): Use string_file.
* ada-valprint.c (ada_print_floating): Use string_file.
* ada-varobj.c (ada_varobj_scalar_image)
(ada_varobj_get_value_image): Use string_file.
* aix-thread.c (aix_thread_extra_thread_info): Use string_file.
* arm-tdep.c (_initialize_arm_tdep): Use string_printf.
* breakpoint.c (update_inserted_breakpoint_locations)
(insert_breakpoint_locations, reattach_breakpoints)
(print_breakpoint_location, print_one_detail_ranged_breakpoint)
(print_it_watchpoint): Use string_file.
(save_breakpoints): Use stdio_file.
* c-exp.y (oper): Use string_file.
* cli/cli-logging.c (set_logging_redirect): Use ui_file_up and
tee_file.
(pop_output_files): Use delete.
(handle_redirections): Use stdio_file and tee_file.
* cli/cli-setshow.c (do_show_command): Use string_file.
* compile/compile-c-support.c (c_compute_program): Use
string_file.
* compile/compile-c-symbols.c (generate_vla_size): Take a
'string_file &' instead of a 'ui_file *'.
(generate_c_for_for_one_variable): Take a 'string_file &' instead
of a 'ui_file *'. Use string_file.
(generate_c_for_variable_locations): Take a 'string_file &'
instead of a 'ui_file *'.
* compile/compile-internal.h (generate_c_for_for_one_variable):
Take a 'string_file &' instead of a 'ui_file *'.
* compile/compile-loc2c.c (push, pushf, unary, binary)
(print_label, pushf_register_address, pushf_register)
(do_compile_dwarf_expr_to_c): Take a 'string_file &' instead of a
'ui_file *'. Adjust.
* compile/compile.c (compile_to_object): Use string_file.
* compile/compile.h (compile_dwarf_expr_to_c)
(compile_dwarf_bounds_to_c): Take a 'string_file &' instead of a
'ui_file *'.
* cp-support.c (inspect_type): Use string_file and obstack_copy0.
(replace_typedefs_qualified_name): Use string_file and
obstack_copy0.
* disasm.c (gdb_pretty_print_insn): Use string_file.
(gdb_disassembly): Adjust reference the null_stream global.
(do_ui_file_delete): Delete.
(gdb_insn_length): Use null_stream.
* dummy-frame.c (maintenance_print_dummy_frames): Use stdio_file.
* dwarf2loc.c (dwarf2_compile_property_to_c)
(locexpr_generate_c_location, loclist_generate_c_location): Take a
'string_file &' instead of a 'ui_file *'.
* dwarf2loc.h (dwarf2_compile_property_to_c): Likewise.
* dwarf2read.c (do_ui_file_peek_last): Delete.
(dwarf2_compute_name): Use string_file.
* event-top.c (gdb_setup_readline): Use stdio_file.
* gdbarch.sh (verify_gdbarch): Use string_file.
* gdbtypes.c (safe_parse_type): Use null_stream.
* guile/scm-breakpoint.c (gdbscm_breakpoint_commands): Use
string_file.
* guile/scm-disasm.c (gdbscm_print_insn_from_port): Take a
'string_file *' instead of a 'ui_file *'.
(gdbscm_arch_disassemble): Use string_file.
* guile/scm-frame.c (frscm_print_frame_smob): Use string_file.
* guile/scm-ports.c (class ioscm_file_port): Now a class that
inherits from ui_file.
(ioscm_file_port_delete, ioscm_file_port_rewind)
(ioscm_file_port_put): Delete.
(ioscm_file_port_write): Rename to ...
(ioscm_file_port::write): ... this. Remove file_port_magic
checks.
(ioscm_file_port_new): Delete.
(ioscm_with_output_to_port_worker): Use ioscm_file_port and
ui_file_up.
* guile/scm-type.c (tyscm_type_name): Use string_file.
* guile/scm-value.c (vlscm_print_value_smob, gdbscm_value_print):
Use string_file.
* infcmd.c (print_return_value_1): Use string_file.
* infrun.c (print_target_wait_results): Use string_file.
* language.c (add_language): Use string_file.
* location.c (explicit_to_string_internal): Use string_file.
* main.c (captured_main_1): Use null_file.
* maint.c (maintenance_print_architecture): Use stdio_file.
* mi/mi-cmd-stack.c (list_arg_or_local): Use string_file.
* mi/mi-common.h (struct mi_interp) <out, err, log, targ,
event_channel>: Change type to mi_console_file pointer.
* mi/mi-console.c (mi_console_file_fputs, mi_console_file_flush)
(mi_console_file_delete): Delete.
(struct mi_console_file): Delete.
(mi_console_file_magic): Delete.
(mi_console_file_new): Delete.
(mi_console_file::mi_console_file): New.
(mi_console_file_delete): Delete.
(mi_console_file_fputs): Delete.
(mi_console_file::write): New.
(mi_console_raw_packet): Delete.
(mi_console_file::flush): New.
(mi_console_file_flush): Delete.
(mi_console_set_raw): Rename to ...
(mi_console_file::set_raw): ... this.
* mi/mi-console.h (class mi_console_file): New class.
(mi_console_file_new, mi_console_set_raw): Delete.
* mi/mi-interp.c (mi_interpreter_init): Use mi_console_file.
(mi_set_logging): Use delete and tee_file. Adjust.
* mi/mi-main.c (output_register): Use string_file.
(mi_cmd_data_evaluate_expression): Use string_file.
(mi_cmd_data_read_memory): Use string_file.
(mi_cmd_execute, print_variable_or_computed): Use string_file.
* mi/mi-out.c (mi_ui_out::main_stream): New.
(mi_ui_out::rewind): Use main_stream and
string_file.
(mi_ui_out::put): Use main_stream and string_file.
(mi_ui_out::mi_ui_out): Remove 'stream' parameter.
Allocate a 'string_file' instead.
(mi_out_new): Don't allocate a mem_fileopen stream here.
* mi/mi-out.h (mi_ui_out::mi_ui_out): Remove 'stream' parameter.
(mi_ui_out::main_stream): Declare method.
* printcmd.c (eval_command): Use string_file.
* psymtab.c (maintenance_print_psymbols): Use stdio_file.
* python/py-arch.c (archpy_disassemble): Use string_file.
* python/py-breakpoint.c (bppy_get_commands): Use string_file.
* python/py-frame.c (frapy_str): Use string_file.
* python/py-framefilter.c (py_print_type, py_print_single_arg):
Use string_file.
* python/py-type.c (typy_str): Use string_file.
* python/py-unwind.c (unwind_infopy_str): Use string_file.
* python/py-value.c (valpy_str): Use string_file.
* record-btrace.c (btrace_insn_history): Use string_file.
* regcache.c (regcache_print): Use stdio_file.
* reggroups.c (maintenance_print_reggroups): Use stdio_file.
* remote.c (escape_buffer): Use string_file.
* rust-lang.c (rust_get_disr_info): Use string_file.
* serial.c (serial_open_ops_1): Use stdio_file.
(do_serial_close): Use delete.
* stack.c (print_frame_arg): Use string_file.
(print_frame_args): Remove local mem_fileopen stream, not used.
(print_frame): Use string_file.
* symmisc.c (maintenance_print_symbols): Use stdio_file.
* symtab.h (struct symbol_computed_ops) <generate_c_location>:
Take a 'string_file *' instead of a 'ui_file *'.
* top.c (new_ui): Use stdio_file and stderr_file.
(free_ui): Use delete.
(execute_command_to_string): Use string_file.
(quit_confirm): Use string_file.
* tracepoint.c (collection_list::append_exp): Use string_file.
* tui/tui-disasm.c (tui_disassemble): Use string_file.
* tui/tui-file.c: Don't include "ui-file.h".
(enum streamtype, struct tui_stream): Delete.
(tui_file_new, tui_file_delete, tui_fileopen, tui_sfileopen)
(tui_file_isatty, tui_file_rewind, tui_file_put): Delete.
(tui_file::tui_file): New method.
(tui_file_fputs): Delete.
(tui_file_get_strbuf): Delete.
(tui_file::puts): New method.
(tui_file_adjust_strbuf): Delete.
(tui_file_flush): Delete.
(tui_file::flush): New method.
* tui/tui-file.h: Tweak intro comment.
Include ui-file.h.
(tui_fileopen, tui_sfileopen, tui_file_get_strbuf)
(tui_file_adjust_strbuf): Delete declarations.
(class tui_file): New class.
* tui/tui-io.c (tui_initialize_io): Use tui_file.
* tui/tui-regs.c (tui_restore_gdbout): Use delete.
(tui_register_format): Use string_stream.
* tui/tui-stack.c (tui_make_status_line): Use string_file.
(tui_get_function_from_frame): Use string_file.
* typeprint.c (type_to_string): Use string_file.
* ui-file.c (struct ui_file, ui_file_magic, ui_file_new): Delete.
(null_stream): New global.
(ui_file_delete): Delete.
(ui_file::ui_file): New.
(null_file_isatty): Delete.
(ui_file::~ui_file): New.
(null_file_rewind): Delete.
(ui_file::printf): New.
(null_file_put): Delete.
(null_file_flush): Delete.
(ui_file::putstr): New.
(null_file_write): Delete.
(ui_file::putstrn): New.
(null_file_read): Delete.
(ui_file::putc): New.
(null_file_fputs): Delete.
(null_file_write_async_safe): Delete.
(ui_file::vprintf): New.
(null_file_delete): Delete.
(null_file::write): New.
(null_file_fseek): Delete.
(null_file::puts): New.
(ui_file_data): Delete.
(null_file::write_async_safe): New.
(gdb_flush, ui_file_isatty): Adjust.
(ui_file_put, ui_file_rewind): Delete.
(ui_file_write): Adjust.
(ui_file_write_for_put): Delete.
(ui_file_write_async_safe, ui_file_read): Adjust.
(ui_file_fseek): Delete.
(fputs_unfiltered): Adjust.
(set_ui_file_flush, set_ui_file_isatty, set_ui_file_rewind)
(set_ui_file_put, set_ui_file_write, set_ui_file_write_async_safe)
(set_ui_file_read, set_ui_file_fputs, set_ui_file_fseek)
(set_ui_file_data): Delete.
(string_file::~string_file, string_file::write)
(struct accumulated_ui_file, do_ui_file_xstrdup, ui_file_xstrdup)
(do_ui_file_as_string, ui_file_as_string): Delete.
(do_ui_file_obsavestring, ui_file_obsavestring): Delete.
(struct mem_file): Delete.
(mem_file_new): Delete.
(stdio_file::stdio_file): New.
(mem_file_delete): Delete.
(stdio_file::stdio_file): New.
(mem_fileopen): Delete.
(stdio_file::~stdio_file): New.
(mem_file_rewind): Delete.
(stdio_file::set_stream): New.
(mem_file_put): Delete.
(stdio_file::open): New.
(mem_file_write): Delete.
(stdio_file_magic, struct stdio_file): Delete.
(stdio_file_new, stdio_file_delete, stdio_file_flush): Delete.
(stdio_file::flush): New.
(stdio_file_read): Rename to ...
(stdio_file::read): ... this. Adjust.
(stdio_file_write): Rename to ...
(stdio_file::write): ... this. Adjust.
(stdio_file_write_async_safe): Rename to ...
(stdio_file::write_async_safe) ... this. Adjust.
(stdio_file_fputs): Rename to ...
(stdio_file::puts) ... this. Adjust.
(stdio_file_isatty): Delete.
(stdio_file_fseek): Delete.
(stdio_file::isatty): New.
(stderr_file_write): Rename to ...
(stderr_file::write) ... this. Adjust.
(stderr_file_fputs): Rename to ...
(stderr_file::puts) ... this. Adjust.
(stderr_fileopen, stdio_fileopen, gdb_fopen): Delete.
(stderr_file::stderr_file): New.
(tee_file_magic): Delete.
(struct tee_file): Delete.
(tee_file::tee_file): New.
(tee_file_new): Delete.
(tee_file::~tee_file): New.
(tee_file_delete): Delete.
(tee_file_flush): Rename to ...
(tee_file::flush): ... this. Adjust.
(tee_file_write): Rename to ...
(tee_file::write): ... this. Adjust.
(tee_file::write_async_safe): New.
(tee_file_fputs): Rename to ...
(tee_file::puts): ... this. Adjust.
(tee_file_isatty): Rename to ...
(tee_file::isatty): ... this. Adjust.
* ui-file.h (struct obstack, struct ui_file): Don't
forward-declare.
(ui_file_new, ui_file_flush_ftype, set_ui_file_flush)
(ui_file_write_ftype)
(set_ui_file_write, ui_file_fputs_ftype, set_ui_file_fputs)
(ui_file_write_async_safe_ftype, set_ui_file_write_async_safe)
(ui_file_read_ftype, set_ui_file_read, ui_file_isatty_ftype)
(set_ui_file_isatty, ui_file_rewind_ftype, set_ui_file_rewind)
(ui_file_put_method_ftype, ui_file_put_ftype, set_ui_file_put)
(ui_file_delete_ftype, set_ui_file_data, ui_file_fseek_ftype)
(set_ui_file_fseek): Delete.
(ui_file_data, ui_file_delete, ui_file_rewind)
(struct ui_file): New.
(ui_file_up): New.
(class null_file): New.
(null_stream): Declare.
(ui_file_write_for_put, ui_file_put): Delete.
(ui_file_xstrdup, ui_file_as_string, ui_file_obsavestring):
Delete.
(ui_file_fseek, mem_fileopen, stdio_fileopen, stderr_fileopen)
(gdb_fopen, tee_file_new): Delete.
(struct string_file): New.
(struct stdio_file): New.
(stdio_file_up): New.
(struct stderr_file): New.
(class tee_file): New.
* ui-out.c (ui_out::field_stream): Take a 'string_file &' instead
of a 'ui_file *'. Adjust.
* ui-out.h (class ui_out) <field_stream>: Likewise.
* utils.c (do_ui_file_delete, make_cleanup_ui_file_delete)
(null_stream): Delete.
(error_stream): Take a 'string_file &' instead of a 'ui_file *'.
Adjust.
* utils.h (struct ui_file): Delete forward declaration..
(make_cleanup_ui_file_delete, null_stream): Delete declarations.
(error_stream): Take a 'string_file &' instead of a
'ui_file *'.
* varobj.c (varobj_value_get_print_value): Use string_file.
* xtensa-tdep.c (xtensa_verify_config): Use string_file.
* gdbarch.c: Regenerate.
This replaces a cleanup in execute_gdb_command with an instance of
std::string.
Testing showed that this originally missed a cleanup that was returned
by prevent_dont_repeat. This version of the patch changes
prevent_dont_repeat to return a scoped_restore rather than a cleanup.
2017-01-10 Tom Tromey <tom@tromey.com>
* top.c (prevent_dont_repeat): Change return type.
* python/python.c (execute_gdb_command): Use std::string.
Update.
* guile/guile.c (gdbscm_execute_gdb_command): Update.
* command.h (prevent_dont_repeat): Change return type.
* breakpoint.c (bpstat_do_actions_1): Update.
All implementations of redirect/do_redirect in the ui_out subsystem
always return 0 (success). We can therefore clean it up and make them
return void.
gdb/ChangeLog:
* cli-out.c (cli_ui_out::do_redirect): Change return type to
void.
* cli-out.h (cli_ui_out::do_redirect): Likewise.
* mi/mi-out.c (mi_ui_out::do_redirect): Likewise.
* mi/mi-out.h (mi_ui_out::do_redirect): Likewise.
* ui-out.c (ui_out::redirect): Likewise.
* ui-out.h (ui_out::redirect, ui_out::do_redirect): Likewise.
* cli/cli-logging.c (set_logging_redirect): Update call site of
ui_out::redirect.
(handle_redirections): Likewise.
* scm-ports.c (ioscm_with_output_to_port_worker): Likewise.
* top.c (execute_command_to_string): Likewise.
* utils.c (do_ui_out_redirect_pop): Likewise.
This applies the second part of GDB's End of Year Procedure, which
updates the copyright year range in all of GDB's files.
gdb/ChangeLog:
Update copyright year range in all GDB files.
Yet another cleanup is eliminated.
gdb/ChangeLog:
2016-11-08 Pedro Alves <palves@redhat.com>
* top.c (quit_confirm): Use ui_file_as_string and std::string.
... and then return std::string and adjust all callers.
gdb/ChangeLog:
2016-11-08 Pedro Alves <palves@redhat.com>
* gdbcmd.h (execute_command_to_string): Now returns std::string.
(lookup_struct_elt_type): Adjust to use std::string.
* top.c (execute_command_to_string): Use ui_file_as_string and
return std::string.
* guile/guile.c (gdbscm_execute_gdb_command): Adjust to use
std::string.
* python/python.c (execute_gdb_command): Adjust to use
std::string.
gdb 7.12 doesn't compile as C++ (tried with g++ 4.9) on Solaris (tried
10 and 12, sparc and x86). The following patch (relative to the 7.12
release, though I expect most if not all issues to be present on trunk,
too) fixes this.
Only a few of the changes bear explanation:
* Initially, compilation failed whereever defs.h. was included:
In file included from /vol/src/gnu/gdb/gdb-7.12/gdb/gdb.c:19:0:
/vol/src/gnu/gdb/gdb-7.12/gdb/defs.h:630:33: error: 'double atof(const char*)' conflicts with a previous declaration
extern double atof (const char *); /* X3.159-1989 4.10.1.1 */
^
In file included from /usr/include/stdlib.h:17:0,
from build-gnulib/import/stdlib.h:36,
from /vol/src/gnu/gdb/gdb-7.12/gdb/common/common-defs.h:32,
from /vol/src/gnu/gdb/gdb-7.12/gdb/defs.h:28,
from /vol/src/gnu/gdb/gdb-7.12/gdb/gdb.c:19:
/vol/gcc-4.9/lib/gcc/i386-pc-solaris2.10/4.9.0/include-fixed/iso/stdlib_iso.h:119:15: note: previous declaration 'double std::atof(const char*)'
extern double atof(const char *);
^
This is due to this gem in gdb/defs.h which seems to have been present
like forever:
#ifndef atof
extern double atof (const char *); /* X3.159-1989 4.10.1.1 */
#endif
In the Solaris headers, the appropriate functions are in namespace std,
thus the conflict. I've wrapped the defs.h declaration in !__cplusplus
to avoid this; perhaps it can go completely instead.
* All the casts are necessary to appease g++ and should be pretty
obvious.
* The sol-thread.c changes are here to handle
/vol/src/gnu/gdb/gdb-7.12/gdb/sol-thread.c: In function 'void _initialize_sol_thread()':
/vol/src/gnu/gdb/gdb-7.12/gdb/sol-thread.c:1252:36: error: invalid conversion from 'void*' to 'void (*)(int)' [-fpermissive]
if (!(p_##X = dlsym (dlhandle, #X))) \
^
/vol/src/gnu/gdb/gdb-7.12/gdb/sol-thread.c:1255:3: note: in expansion of macro 'resolve'
resolve (td_log);
^
and are modeled after linux-thread-db.c (try_thread_db_load_1).
The patch allowed both 32 and 64-bit C++ builds on sparc-sun-solaris2.10
and i386-pc-solaris2.10 to complete. The resulting binary hasn't seen
more than a smoke test (invoke it on itself, b main, run) yet.
When investigating the failure to detect -static-libstdc++
support (more below), I found two more issues which only show up with
-Werror:
/vol/src/gnu/gdb/gdb/local/gdb/procfs.c: In function 'ssd* proc_get_LDT_entry(procinfo*, int)':
/vol/src/gnu/gdb/gdb/local/gdb/procfs.c:2487:19: error: variable 'old_chain' set but not used [-Werror=unused-but-set-variable]
struct cleanup *old_chain = NULL;
^
Unless I'm mistaken, you need to run do_cleanups on every return from
the function.
Afterwards, I ran a 32-bit compilation, which (after adding
--disable-largefile to avoid
In file included from /usr/include/sys/procfs.h:28:0,
from /vol/src/gnu/gdb/gdb/local/gdb/i386-sol2-nat.c:23:
/usr/include/sys/old_procfs.h:39:2: error: #error "Cannot use procfs in the large file compilation environment"
#error "Cannot use procfs in the large file compilation environment"
^
and two more instances) revealed
/vol/src/gnu/gdb/gdb/local/gdb/top.c: In function 'void gdb_safe_append_history()':
/vol/src/gnu/gdb/gdb/local/gdb/top.c:1170:59: error: format '%d' expects argument of type 'int', but argument 3 has type 'pid_t {aka long int}' [-Werror=format=]
= xstrprintf ("%s-gdb%d~", history_filename, getpid ());
^
Fixed by casting pid_t to long and printing it as such.
This changes most uses of make_cleanup_restore_current_ui to use
scoped_restore. The use in switch_thru_all_uis_init still remains;
that is dealt with in a later patch by replacing this iterator with a
real class.
2016-10-21 Tom Tromey <tom@tromey.com>
* top.c (new_ui_command, wait_sync_command_done)
(gdb_readline_wrapper): Use scoped_restore.
* infrun.c (fetch_inferior_event): Use scoped_restore.
* infcall.c (call_thread_fsm_should_stop): Use scoped_restore.
This replaces all the uses of make_cleanup_restore_ui_file with
scoped_restore.
2016-10-21 Tom Tromey <tom@tromey.com>
* utils.c (make_cleanup_restore_ui_file, do_restore_ui_file)
(struct restore_ui_file_closure): Remove.
* utils.h (make_cleanup_restore_ui_file): Don't declare.
* guile/scm-ports.c (ioscm_with_output_to_port_worker): Use
scoped_restore.
* top.c (execute_command_to_string): Use scoped_restore.
This patch replaces many (but not all) uses of
make_cleanup_restore_integer with a simple RAII-based template class.
It also removes the similar restore_execution_direction cleanup in
favor of this new class. Subsequent patches will replace other
similar cleanups with this class.
The class is typically instantiated using make_scoped_restore. This
allows for template argument deduction.
2016-10-21 Tom Tromey <tom@tromey.com>
* common/scoped_restore.h: New file.
* utils.h: Include scoped_restore.h.
* top.c (execute_command_to_string): Use scoped_restore.
* python/python.c (python_interactive_command): Use
scoped_restore.
(python_command, execute_gdb_command): Likewise.
* printcmd.c (do_one_display): Use scoped_restore.
* mi/mi-main.c (exec_continue): Use scoped_restore.
* mi/mi-cmd-var.c (mi_cmd_var_assign): Use scoped_restore.
* linux-fork.c (checkpoint_command): Use scoped_restore.
* infrun.c (restore_execution_direction): Remove.
(fetch_inferior_event): Use scoped_restore.
* compile/compile.c (compile_file_command): Use
scoped_restore.
(compile_code_command, compile_print_command): Likewise.
* cli/cli-script.c (execute_user_command): Use
scoped_restore.
(while_command, if_command, script_from_file): Likewise.
* arm-tdep.c (arm_insert_single_step_breakpoint): Use
scoped_restore.
This fixes PR gdb/20604. The bug here is that passing an invalid
expression to "quit" -- e.g., "quit()" -- causes gdb to enter a
non-functioning state.
The immediate problem is that quit_force resets the terminal before
evaluating the expression. However, it seemed to me that it doesn't
really make sense to pass the quit_force argument to kill_or_detach
(which passes it to to_detach), first because conflating the exit
status for "quit" and the signal to pass when detaching doesn't make
sense, and second because to_detach implementations generally only
accept a constant here, while "quit" accepts an expression. So, I
removed that.
As an aside, I think the "detach SIGNO" functionality is not
documented.
Built and regtested on x86-64 Fedora 24.
2016-09-21 Tom Tromey <tom@tromey.com>
PR gdb/20604:
* top.h (quit_force): Update.
* top.c (quit_force): Changed type of first argument. Don't
evaluate expression. Pass NULL to kill_or_detach.
* cli/cli-cmds.c (quit_command): Evaluate "args".
2016-09-21 Tom Tromey <tom@tromey.com>
PR gdb/20604:
* gdb.base/quit.exp: New file.
I noticed that if input is already pending on the new-ui TTY, gdb
internal-errors.
E.g., create /dev/pts/2, and type anything there (even just <return>
is sufficient).
Now start GDB creating a new UI on that TTY, while at the same time,
running a synchronous execution command. Something like:
$ gdb program -ex "new-ui console /dev/pts/2" -ex "start"
Back on /dev/pts/2, we get:
(gdb) .../src/gdb/event-top.c:360: internal-error: double prompt
A problem internal to GDB has been detected,
further debugging may prove unreliable.
While the main UI was waiting for "start" to finish, gdb kepts pumping
events, including the input fd of the extra console. The problem is
that stdin_event_handler doesn't restore the current UI back to what
it was, assuming that it's only ever called from the top level event
loop. However, in this case, it's being called from the nested event
loop from within maybe_wait_sync_command_done.
When finally the "start" command is done, we reach the code that
prints the prompt in the main UI, just before starting the main event
loop. Since now the current UI is pointing at the extra console (by
mistake), we find ourselves printing a double prompt on the extra
console. This is caught by the assertion that fails, as shown above.
Since other event handlers also don't restore the UI (e.g., signal
event handlers), I think it's better if whatever is pumping events to
take care to restore the UI, if it cares. That's what this patch
does. New test included.
gdb/ChangeLog:
2016-09-06 Pedro Alves <palves@redhat.com>
* top.c (wait_sync_command_done): Don't assume current_ui doesn't
change across events. Restore the current UI before returning.
(gdb_readline_wrapper): Restore the current UI before returning.
gdb/testsuite/ChangeLog:
2016-09-06 Pedro Alves <palves@redhat.com>
* gdb.base/new-ui-pending-input.c: New file.
* gdb.base/new-ui-pending-input.exp: New file.
* gdb.exp (clear_gdb_spawn_id): New procedure.
(with_spawn_id): Check whether gdb_spawn_id exists before
referencing it. If gdb_spawn_id didn't exist on entry, clear it
on exit.
Just a tidy, no functional changes.
gdb/ChangeLog:
2016-09-06 Pedro Alves <palves@redhat.com>
* event-top.c (restore_ui_cleanup): Now static.
(make_cleanup_restore_current_ui): New function.
(switch_thru_all_uis_init): Use it.
* infcall.c (call_thread_fsm_should_stop): Use it.
* infrun.c (fetch_inferior_event): Use it.
* top.c (new_ui_command): Use it.
* top.h (restore_ui_cleanup): Delete declaration.
(make_cleanup_restore_current_ui): New declaration.
This patch fixes a problem that problem triggers if you start an
inferior, e.g., with the "start" command, in a UI created with the
new-ui command, and then run a foreground execution command in the
main UI. Once the program stops for the latter command, typing in the
main UI no longer echoes back to the user.
The problem revolves around this:
- gdb_has_a_terminal computes its result lazily, on first call.
that is what saves gdb's initial main UI terminal state (the UI
associated with stdin):
our_terminal_info.ttystate = serial_get_tty_state (stdin_serial);
This is the state that target_terminal_ours() restores.
- In this scenario, the gdb_has_a_terminal function happens to be
first ever called from within the target_terminal_init call in
startup_inferior:
(top-gdb) bt
#0 gdb_has_a_terminal () at src/gdb/inflow.c:157
#1 0x000000000079db22 in child_terminal_init_with_pgrp () at src/gdb/inflow.c:217
[...]
#4 0x000000000065bacb in target_terminal_init () at src/gdb/target.c:456
#5 0x00000000004676d2 in startup_inferior () at src/gdb/fork-child.c:531
[...]
#7 0x000000000046b168 in linux_nat_create_inferior () at src/gdb/linux-nat.c:1112
[...]
#9 0x00000000005f20c9 in start_command (args=0x0, from_tty=1) at src/gdb/infcmd.c:657
If the command to start the inferior is issued on the main UI, then
readline will have deprepped the terminal when we reach the above, and
the problem doesn't appear.
If however the command is issued on a non-main UI, then when we reach
that gdb_has_a_terminal call, the main UI's terminal state is still
set to whatever readline has sets it to in rl_prep_terminal, which
happens to have echo disabled. Later, when the following synchronous
execution command finishes, we'll call target_terminal_ours to restore
gdb's the main UI's terminal settings, and that restores the terminal
state with echo disabled...
Conceptually, the fix is to move the gdb_has_a_terminal call earlier,
to someplace during GDB initialization, before readline/ncurses have
had a chance to change terminal settings. Turns out that
"set_initial_gdb_ttystate" is exactly such a place.
I say conceptually, because the fix actually inlines the
gdb_has_a_terminal part that saves the terminal state in
set_initial_gdb_ttystate and then simplifies gdb_has_a_terminal, since
there's no point in making gdb_has_a_terminal do lazy computation.
gdb/ChangeLog:
2016-08-23 Pedro Alves <palves@redhat.com>
PR gdb/20494
* inflow.c (our_terminal_info, initial_gdb_ttystate): Update
comments.
(enum gdb_has_a_terminal_flag_enum, gdb_has_a_terminal_flag):
Delete.
(set_initial_gdb_ttystate): Record our_terminal_info here too,
instead of ...
(gdb_has_a_terminal): ... here. Reimplement in terms of
initial_gdb_ttystate. Make static.
* terminal.h (gdb_has_a_terminal): Delete declaration.
(set_initial_gdb_ttystate): Add comment.
* top.c (show_interactive_mode): Use input_interactive_p instead
of gdb_has_a_terminal.
gdb/testsuite/ChangeLog:
2016-08-23 Pedro Alves <palves@redhat.com>
PR gdb/20494
* gdb.base/new-ui-echo.c: New file.
* gdb.base/new-ui-echo.exp: New file.
When a bad interpreter name is passed to new-ui, such as:
(gdb) new-ui bloop /dev/pts/10
A partially created UI is left in the UI list, with interp set to NULL.
Trying to do anything that will print on this UI (such as "start") will
cause a segmentation fault.
Changes in v2:
- Use with_test_prefix to namespace test procedures
- Give an explicit stable test name
- Add a "bad terminal path" test
- Remove useless runto_main
- Add missing intro comments
I did not factor out the pty spawn, as there is some magic involved I
don't quite understand. But it wouldn't bring that much anyway.
gdb/ChangeLog:
* top.h (make_delete_ui_cleanup): New declaration.
* top.c (delete_ui_cleanup): New function.
(make_delete_ui_cleanup): New function.
(new_ui_command): Create restore_ui cleanup earlier, create a
delete_ui cleanup and discard it on success.
gdb/testsuite/ChangeLog:
* gdb.base/new-ui.exp (do_test_invalid_args): New
procedure.
- A few missing casts required by C++, resulting in:
../../src/gdb/ser-go32.c:795:21: error: invalid conversion from 'const void*' to 'const char*' [-fpermissive]
etc.
- dos_noop has an incompatible prototype with struct serial_ops's
setparity, resulting in:
../../src/gdb/ser-go32.c:874:1: error: invalid conversion from 'int (*)(serial*)' to 'int (*)(serial*, int)' [-fpermissive]
(I thought of calling the ser-base.c default methods, but djgpp
doesn't include ser-base.c in the build.)
gdb/ChangeLog:
2016-07-21 Pedro Alves <palves@redhat.com>
* go32-nat.c (go32_create_inferior): Add cast.
* ser-go32.c (dos_noop): Delete.
(dos_flush_output, dos_setparity, dos_drain_output): New
functions.
(dos_write): Add cast.
(dos_ops): Use dos_flush_output, dos_setparity and
dos_drain_output.
* top.c (do_chdir_cleanup): Add cast.
With all the previous plumbing in place, it's now easy to add a
command that actually creates a new console/mi UI.
The intended use case is to make it possible and easy for MI frontends
to provide a fully featured GDB console to users, with readline
support, command line editing, history, etc., just like if gdb was
started on the command line. Currently MI frontends have to try to
implement all of that theirselves and make use of "-interpreter-exec
console ...", which is far from perfect. If you ever tried Eclipse's
gdb console window, you'll know what I mean...
Instead of trying to multiplex console through MI, this command let's
just leverage all the built in readline/editing support already inside
gdb.
The plan is for the MI frontend to start GDB in regular console mode,
running inside a terminal emulator widget embedded in Eclipse (which
already exists, for supporting the shell widget; other frontends have
similar widgets), and then tell GDB to run a full MI interpreter on an
specified input/output device, independent of the console.
My original prototype planned to do things the other way around --
start GDB in MI mode, and then start an extra CLI console on separate
tty. I handed over that prototype to Marc Khouzam @ Eclipse CDT, and
after experimentation and discussion, we ended up concluding that
starting GDB in CLI mode instead was both easier and actually also
supported an interesting use case -- connect an Eclipse frontend to a
GDB that is already running outside Eclipse.
The current usage is "new-ui <interpreter> <tty>".
E.g., on a terminal run this scriplet:
$ cat gdb-client
#!/bin/bash
reset
tty
tail -f /dev/null
$ gdb-client
/dev/pts/15
Now run gdb on another terminal, and tell it to start a MI interpreter
on the tty of the other terminal:
...
(gdb) new-ui mi /dev/pts/15
New UI allocated
Now back to the the gdb-client terminal, we'll get an MI prompt, ready
for MI input:
/dev/pts/15
=thread-group-added,id="i1"
(gdb)
You can also start a new UI running a CLI, with:
(gdb) new-ui console /dev/pts/15
Though note that this console won't support readline command editing.
It works as if "set editing off" was entered.
gdb/ChangeLog:
2016-06-21 Pedro Alves <palves@redhat.com>
* interps.c (set_top_level_interpreter): New function, factored
out from captured_main.
(interpreter_completer): Make extern.
* interps.h (set_top_level_interpreter, interpreter_completer):
New declarations.
(captured_main): Use set_top_level_interpreter.
* top.c [!O_NOCTTY] (O_NOCTTY): Define as 0.
(open_terminal_stream, new_ui_command): New functions.
(init_main): Install the "new-ui" command.
This commit makes each UI have its own "stdin" stream pointer. This
is used to determine whether the "from_tty" argument to
execute_command, etc. should be true.
Related, this commit makes input_from_terminal_p take an UI parameter,
and then avoids the gdb_has_a_terminal in it. gdb_has_a_terminal only
returns info on gdb's own main/primary terminal (the real stdin).
However, the places that call input_from_terminal_p really want to
know is whether the command came from an interactive tty. This patch
thus renames input_from_terminal_p to input_interactive_p for clarity,
and then makes input_interactive_p check for "set interactive" itself,
along with ISATTY, instead of calling gdb_has_a_terminal. Actually,
quit_force wants to call input_interactive_p _after_ stdin is closed,
we can't call ISATTY that late. So instead we save the result of
ISATTY in a field of the UI.
gdb/ChangeLog:
2016-06-21 Pedro Alves <palves@redhat.com>
* cli/cli-script.c (read_next_line): Adjust to per-UI stdin.
(read_command_lines): Use input_interactive_p instead of
input_from_terminal_p.
* defs.h (struct ui): Forward declare.
(input_from_terminal_p): Rename to ...
(input_interactive_p): ... this.
* event-top.c (stdin_event_handler): Pass 0 as from_tty argument
to quit_command.
(command_handler): Adjust to per-UI stdin.
(handle_line_of_input): Adjust to per-UI stdin and use
input_interactive_p instead of ISATTY and input_from_terminal_p.
(gdb_readline_no_editing_callback): Adjust to per-UI stdin.
(command_line_handler): Always pass true as "from_tty" parameter
of handle_line_of_input and execute_command.
(async_sigterm_handler): Pass 0 as from_tty argument to
quit_command.
* inflow.c (interactive_mode, show_interactive_mode): Moved to ...
(gdb_has_a_terminal): Don't check interactive_mode here.
(_initialize_inflow): Don't install "set interactive-mode" here.
* main.c (captured_command_loop): Adjust to per-UI stdin.
* mi/mi-interp.c (mi_execute_command_wrapper): Adjust to per-UI
stdin.
* top.c (new_ui): Save the stdin stream and whether it's a tty.
(dont_repeat): Adjust to per-UI stdin.
(command_line_input): Adjust to per-UI stdin and to use
input_interactive_p.
(quit_force): Write history if any UI supports interactive input.
(interactive_mode, show_interactive_mode): Move here, from
inflow.c.
(input_from_terminal_p): Rename to ...
(input_interactive_p): ... this, and check the "interactive_mode"
global instead of calling gdb_has_a_terminal.
(_initialize_top): Install "set interactive-mode" here.
* top.h (struct ui) <stdin_stream, input_interactive_p>: New
fields.
* utils.c (quit): Pass 0 as from_tty argument to quit_force.
(defaulted_query): Adjust to per-UI stdin and to use
input_interactive_p.
Without this, GDB exits if a secondary UIs terminal/input stream is
closed:
$ ./gdb -ex "new-ui mi /dev/pts/6"
New UI allocated
<<< close /dev/pts/6
(gdb) Error detected on fd 9
$
We want that for the main UI, but not secondary UIs.
gdb/ChangeLog:
2016-06-21 Pedro Alves <palves@redhat.com>
* event-top.c (stdin_event_handler): Don't quit gdb if it was a
secondary UI's input stream that closed. Instead, just delete the
UI.
This is preparation for being able to create more than one UI object.
The change to gdb_main to stop using catch_errors is necessary because
catch_errors references current_uiout, which expands to
current_ui->m_current_ui, which would crash because current_ui is not
initialized yet at that point. It didn't trigger earlier in the
series because before this patch, main_ui/current_ui always start out
non-NULL.
gdb/ChangeLog:
2016-06-21 Pedro Alves <palves@redhat.com>
* event-top.c (main_ui_): Delete.
(main_ui, current_ui, ui_list): No longer initialize here.
* main.c (captured_main): UI initialization code factored out to
new new_ui function.
(gdb_main): Wrap captured_main with TRY/CATCH instead of
catch_errors.
* top.c (highest_ui_num): New global.
(new_ui): New function.
* top.h (struct ui) <num>: New field.
(new_ui): New declaration.
When sync_execution (a boolean) is true, it means we're running a
foreground command -- we hide the prompt stop listening to input, give
the inferior the terminal, then go to the event loop waiting for the
target to stop.
With multiple independent UIs, we need to track whether each UI is
synchronously blocked waiting for the target. IOW, if you do
"continue" in one console, that console stops accepting commands, but
you should still be free to type other commands in the others
consoles.
Just simply making sync_execution be per-UI alone not sufficient,
because of this in fetch_inferior_event:
/* If the inferior was in sync execution mode, and now isn't,
restore the prompt (a synchronous execution command has finished,
and we're ready for input). */
if (current_ui->async && was_sync && !sync_execution)
observer_notify_sync_execution_done ();
We'd have to record at entry the "was_sync" state for each UI, not
just of the current UI.
This patch instead replaces the sync_execution flag by a per-UI
tristate flag indicating the command line prompt state:
enum prompt_state
{
/* The command line is blocked simulating synchronous execution.
This is used to implement the foreground execution commands
('run', 'continue', etc.). We won't display the prompt and
accept further commands until the execution is actually over. */
PROMPT_BLOCKED,
/* The command finished; display the prompt before returning back to
the top level. */
PROMPT_NEEDED,
/* We've displayed the prompt already, ready for input. */
PROMPTED,
;
I think the end result is _much_ clearer than the current code, and,
it addresses the original motivation too.
gdb/ChangeLog:
2016-06-21 Pedro Alves <palves@redhat.com>
* annotate.c: Include top.h.
(async_background_execution_p): Delete.
(print_value_flags): Check the UI's prompt state rather then
async_background_execution_p.
* event-loop.c (start_event_loop): Set the prompt state to
PROMPT_NEEDED.
* event-top.c (display_gdb_prompt, async_enable_stdin)
(async_disable_stdin): Check the current UI's prompt state instead
of the sync_execution global.
(command_line_handler): Set the prompt state to PROMPT_NEEDED
before running a command, and display the prompt if still needed
afterwards.
* infcall.c (struct call_thread_fsm) <waiting_ui>: New field.
(new_call_thread_fsm): New parameter 'waiting_ui'. Store it.
(call_thread_fsm_should_stop): Set the prompt state to
PROMPT_NEEDED.
(run_inferior_call): Adjust to temporarily set the prompt state to
PROMPT_BLOCKED instead of using the sync_execution global.
(call_function_by_hand_dummy): Pass the current UI to
new_call_thread_fsm.
* infcmd.c: Include top.h.
(continue_1): Check the current UI's prompt state instead of the
sync_execution global.
(continue_command): Validate global execution state before calling
prepare_execution_command.
(step_1): Call all_uis_check_sync_execution_done.
(attach_post_wait): Don't call async_enable_stdin here. Remove
reference to sync_execution.
* infrun.c (sync_execution): Delete global.
(follow_fork_inferior)
(reinstall_readline_callback_handler_cleanup): Check the current
UI's prompt state instead of the sync_execution global.
(check_curr_ui_sync_execution_done)
(all_uis_check_sync_execution_done): New functions.
(fetch_inferior_event): Call all_uis_check_sync_execution_done
instead of trying to determine whether the global sync execution
changed.
(handle_no_resumed): Check the prompt state of all UIs.
(normal_stop): Emit the no unwait-for even to all PROMPT_BLOCKED
UIs. Emit the "Switching to" notification to all UIs. Enable
stdin in all UIs.
* infrun.h (sync_execution): Delete.
(all_uis_check_sync_execution_done): Declare.
* main.c (captured_command_loop): Don't call
interp_pre_command_loop if the prompt is blocked.
(catch_command_errors, catch_command_errors_const): Adjust.
(captured_main): Set the initial prompt state to PROMPT_NEEDED.
* mi/mi-interp.c (display_mi_prompt): Set the prompt state to
PROMPTED.
(mi_interpreter_resume): Don't clear sync_execution. Remove hack
comment.
(mi_execute_command_input_handler): Set the prompt state to
PROMPT_NEEDED before executing the command, and only display the
prompt if the prompt state is PROMPT_NEEDED afterwards.
(mi_on_resume_1): Adjust to check the prompt state.
* target.c (target_terminal_inferior): Adjust to check the prompt
state.
* top.c (wait_sync_command_done, maybe_wait_sync_command_done)
(execute_command): Check the current UI's prompt state instead of
sync_execution.
* top.h (enum prompt_state): New.
(struct ui) <prompt_state>: New field.
(ALL_UIS): New macro.
Due to the way that readline's API works (based on globals), we can
only have one instance of readline in a process. So the goal of this
patch is to only allow editing in the main UI, and make sure that only
one UI calls into readline. Some MI paths touch readline variables
currently, which is bad as that is changing variables that matter for
the main console UI. This patch fixes those.
This actually fixes a nasty bug -- starting gdb in MI mode ("gdb
-i=mi"), and then doing "set editing on" crashes GDB, because MI is
not prepared to use readline:
set editing on
&"set editing on\n"
=cmd-param-changed,param="editing",value="on"
^done
(gdb)
p 1
readline: readline_callback_read_char() called with no handler!
Aborted (core dumped)
The fix for that was to add an interp_proc method to query the
interpreter whether it actually supports editing. New test included.
gdb/ChangeLog:
2016-06-21 Pedro Alves <palves@redhat.com>
PR mi/20034
* cli/cli-interp.c: Include cli-interp.h and event-top.h.
(cli_interpreter_resume): Pass 1 to gdb_setup_readline. Set the
UI's input_handler here.
(cli_interpreter_supports_command_editing): New function.
(cli_interp_procs): Install it.
* cli/cli-interp.h: New file.
* event-top.c (async_command_editing_p): Rename to ...
(set_editing_cmd_var): ... this.
(change_line_handler): Add parameter 'editing', and use it. Bail
early if the interpreter doesn't support editing. Don't touch
readline state if editing is off.
(gdb_rl_callback_handler_remove, gdb_rl_callback_handler_install)
(gdb_rl_callback_handler_reinstall): Assert the current UI is the
main UI.
(display_gdb_prompt): Don't call gdb_rl_callback_handler_remove if
not using readline. Check whether the current UI is using command
editing instead of checking the async_command_editing_p global.
(set_async_editing_command): Delete.
(gdb_setup_readline): Add 'editing' parameter. Only allow editing
on the main UI. Don't touch readline state if editing is off.
(gdb_disable_readline): Don't touch readline state if editing is
off.
* event-top.h (gdb_setup_readline): Add 'int' parameter.
(set_async_editing_command): Delete declaration.
(change_line_handler, command_line_handler): Declare.
(async_command_editing_p): Rename to ...
(set_editing_cmd_var): ... this.
* infrun.c (reinstall_readline_callback_handler_cleanup): Check
whether the current UI has editing enabled rather than checking
the async_command_editing_p global.
* interps.c (interp_supports_command_editing): New function.
* interps.h (interp_supports_command_editing_ftype): New typedef.
(struct interp_procs) <supports_command_editing_proc>: New field.
(interp_supports_command_editing): Declare.
* mi/mi-interp.c (mi_interpreter_resume): Pass 0 to
gdb_setup_readline. Don't clear the async_command_editing_p
global. Update comments.
* top.c (gdb_readline_wrapper_line, gdb_readline_wrapper): Check
whether the current UI has editing enabled rather than checking
the async_command_editing_p global. Don't touch readline state if
editing is off.
(undo_terminal_modifications_before_exit): Switch to the main UI.
Unconditionally call gdb_disable_readline.
(set_editing): New function.
(show_async_command_editing_p): Rename to ...
(show_editing): ... this. Show the state of the current UI.
(_initialize_top): Adjust.
* top.h (struct ui) <command_editing>: New field.
* tui/tui-interp.c: Include cli/cli-interp.h.
(tui_resume): Pass 1 to gdb_setup_readline. Set the UI's
input_handler.
(tui_interp_procs): Install
cli_interpreter_supports_command_editing.
* tui/tui-io.c (tui_getc): Check whether the current UI has
editing enabled rather than checking the async_command_editing_p
global.
gdb/testsuite/ChangeLog:
2016-06-21 Pedro Alves <palves@redhat.com>
PR mi/20034
* gdb.mi/mi-editing.exp: New file.
Make each UI have its own interpreter list, top level interpreter,
current interpreter, etc. The "interpreter_async" global is not
really specific to an struct interp (it crosses interpreter-exec ...),
so I moved it to "struct ui" directly, while the other globals were
left hidden in interps.c, opaque to the rest of GDB.
gdb/ChangeLog:
2016-06-21 Pedro Alves <palves@redhat.com>
* breakpoint.c (bpstat_do_actions_1): Access the current UI's
async field instead of the interpreter_async global.
* cli/cli-script.c (execute_user_command, while_command)
(if_command, script_from_file): Likewise.
* compile/compile.c: Include top.h instead of interps.h.
(compile_file_command, compile_code_command)
(compile_print_command): Access the current UI's async field
instead of the interpreter_async global.
* guile/guile.c: Include top.h instead of interps.h.
(guile_repl_command, guile_command, gdbscm_execute_gdb_command):
Access the current UI's async field instead of the
interpreter_async global.
* guile/scm-ports.c: Include top.h instead of interps.h.
(ioscm_with_output_to_port_worker): Access the current UI's async
field instead of the interpreter_async global.
* inf-loop.c (inferior_event_handler): Likewise.
* infcall.c (run_inferior_call): Likewise.
* infrun.c (reinstall_readline_callback_handler_cleanup)
(fetch_inferior_event): Likewise.
* interps.c (interpreter_async): Delete.
(struct ui_interp_info): New.
(get_current_interp_info): New function.
(interp_list, current_interpreter, top_level_interpreter_ptr):
Delete.
(interp_add, interp_set, interp_lookup, interp_ui_out)
(current_interp_set_logging, interp_set_temp)
(current_interp_named_p): Adjust to per-UI interpreters.
(command_interpreter): Delete.
(command_interp, current_interp_command_loop, interp_quiet_p)
(interp_exec, interpreter_exec_cmd, interpreter_completer)
(top_level_interpreter, top_level_interpreter_data): Adjust to
per-UI interpreters.
* interps.h (interpreter_async): Delete.
* main.c (captured_command_loop): Access the current UI's async
field instead of the interpreter_async global.
* python/python.c (python_interactive_command, python_command)
(execute_gdb_command): Likewise.
* top.c (maybe_wait_sync_command_done, execute_command_to_string):
Access the current UI's async field instead of the
interpreter_async global.
* top.h (struct tl_interp_info): Forward declare.
(struct ui) <interp_info, async>: New fields.
We need to have these send output to the proper UI.
However, this patch still make them look like globals. Kind of like
__thread variables, if you will. Changing everything throughout to
write something like current_ui->gdb_stdout instead would be massive
overkill, IMNSHO.
This leaves gdb_stdtargin/stdtarg/stdtargerr global, but maybe that was a
mistake, I'm not sure -- IIRC, MI formats target I/O differently, so
if we have a separate MI channel, then I guess target output should go
there instead of to gdb's stdout. OTOH, maybe GDB should send that
instead to "set inferior-tty", instead of multiplexing it over MI. We
can always fix those later when it gets clearer where they should go.
gdb/ChangeLog:
2016-06-21 Pedro Alves <palves@redhat.com>
* main.c (gdb_stdout, gdb_stderr, gdb_stdlog, gdb_stdin): Delete
globals.
(gen_ret_current_ui_field_ptr): New macro. Use it to generate
wrappers for gdb_stdout, gdb_stderr, gdb_stdlog and gdb_stdin.
* top.h (struct ui) <m_gdb_stdout, m_gdb_stdin, m_gdb_stderr,
m_gdb_stdlog>: New fields.
(current_ui_gdb_stdout_ptr, current_ui_gdb_stdin_ptr)
(current_ui_gdb_stderr_ptr, current_ui_gdb_stdlog_ptr): Declare.
(gdb_stdout, gdb_stdin, gdb_stderr, gdb_stdlog): Reimplement as
macros.
This is a step towards supporting multiple consoles/MIs, each on its
own stdio streams / terminal.
See intro comment in top.h.
(I've had trouble picking a name for this object. I've started out
with "struct console" originally. But then this is about MI as well,
and there's "interpreter-exec console", which is specifically about
the CLI...
So I changed to "struct terminal", but, then we have a terminal object
that works when the input is not a terminal as well ...
Then I sort of gave up and renamed it to "struct top_level". But it
then gets horribly confusing when we talk about the "top level
interpreter that's running on the current top level".
In the end, I realized we're already sort of calling this "ui", in
struct ui_out, struct ui_file, and a few coments here and there.)
gdb/ChangeLog:
2016-06-21 Pedro Alves <palves@redhat.com>
* event-top.c: Update readline-related comments.
(input_handler, call_readline): Delete globals.
(gdb_rl_callback_handler): Call the current UI's input_handler
method.
(change_line_handler): Adjust to set current UI's properties
instead of globals.
(current_ui_, current_ui): New globals.
(get_command_line_buffer): Rewrite to refer to the current UI.
(stdin_event_handler): Adjust to call the call_readline method of
the current UI.
(gdb_readline_no_editing_callback): Adjust to call the current UI's
input_handler method.
(gdb_setup_readline): Adjust to set current UI's properties
instead of globals.
* event-top.h (call_readline, input_handler): Delete declarations.
* mi/mi-interp.c (mi_interpreter_resume): Adjust to set current
UI's properties instead of globals.
* top.c (gdb_readline_wrapper_cleanup): Adjust to set current UI's
properties instead of globals.
(gdb_readline_wrapper): Adjust to call and set current UI's
methods instead of globals.
* top.h: Include buffer.h and event-loop.h.
(struct ui): New struct.
(current_ui): New declaration.
We have places where we call a blocking gdb_select expecting that a
Ctrl-C will unblock it. However, if the Ctrl-C is pressed just before
gdb_select, the SIGINT handler runs before gdb_select, and thus
gdb_select won't return.
For example gdb_readline_no_editing:
QUIT;
/* Wait until at least one byte of data is available. Control-C
can interrupt gdb_select, but not fgetc. */
FD_ZERO (&readfds);
FD_SET (fd, &readfds);
if (gdb_select (fd + 1, &readfds, NULL, NULL, NULL) == -1)
and stdio_file_read:
/* For the benefit of Windows, call gdb_select before reading from
the file. Wait until at least one byte of data is available.
Control-C can interrupt gdb_select, but not read. */
{
fd_set readfds;
FD_ZERO (&readfds);
FD_SET (stdio->fd, &readfds);
if (gdb_select (stdio->fd + 1, &readfds, NULL, NULL, NULL) == -1)
return -1;
}
return read (stdio->fd, buf, length_buf);
This is a race classically fixed with either the self-pipe trick, or
by blocking SIGINT and then using pselect instead of select.
Blocking SIGINT most of the time would mean that check_quit_flag (and
thus QUIT) would need to do a syscall every time it is called, which
sounds best avoided, since QUIT is called in many loops. Thus we take
the self-pipe trick route (wrapped in a serial event).
Instead of having all places that need this manually add an extra file
descriptor to the set of gdb_select's watched file descriptors, we
introduce a wrapper, interruptible_select, that does that.
The Windows version of gdb_select actually does not suffer from this,
because mingw-hdep.c:gdb_call_async_signal_handler sets a Windows
event that gdb_select always waits on. So this patch can be seen as
generalization of that technique. We can't remove that extra event
from mingw-hdep.c until we get rid of immediate_quit though.
gdb/ChangeLog:
2016-04-12 Pedro Alves <palves@redhat.com>
* defs.h: Extend QUIT-related comments to mention
interruptible_select.
(quit_serial_event_set, quit_serial_event_clear): Declare.
* event-top.c: Include "ser-event.h" and "gdb_select.h".
(quit_serial_event): New global.
(async_init_signals): Make quit_serial_event.
(quit_serial_event_set, quit_serial_event_clear)
(quit_serial_event_fd, interruptible_select): New functions.
* extension.c (set_quit_flag): Set the quit serial event.
(check_quit_flag): Clear the quit serial event.
* gdb_select.h (interruptible_select): New declaration.
* guile/scm-ports.c (ioscm_input_waiting): Use
interruptible_select instead of gdb_select.
* top.c (gdb_readline_no_editing): Likewise.
* ui-file.c (stdio_file_read): Likewise.
read_command_line is the only caller, and here we can assume we're
reading a regular file, not stdin.
gdb/ChangeLog:
2016-04-12 Pedro Alves <palves@redhat.com>
* top.c (read_command_file): Inline command_loop here.
(command_loop): Delete.
AFAICS, immediate_quit was only needed here nowdays to be able to
interrupt gdb_readline_no_editing.
command_line_input can also take the gdb_readline_wrapper path, but
since that is built on top of the event loop (gdb_select / poll and
asynchronous signal handlers), it can be interrupted.
gdb/ChangeLog:
2016-04-12 Pedro Alves <palves@redhat.com>
* top.c: Include "gdb_select.h".
(gdb_readline_no_editing): Wait for input with gdb_select instead
of blocking in fgetc.
(command_line_input): Don't set immediate_quit.
I didn't manage to usefully split this further into smaller
independent pieces, so:
- Use "struct buffer" more.
- Split out the responsibility of composing a complete command line
from multiple input lines split with backslash
(
E.g.:
(gdb) print \
1 + \
2
$1 = 3
(gdb)
)
to a separate function. Note we don't need the separate
readline_input_state and more_to_come globals at all. They were
just obfuscating the logic.
- Factor out the tricky mostly duplicated code in
command_line_handler and command_line_input.
gdb/ChangeLog
2016-03-09 Pedro Alves <palves@redhat.com>
* event-top.c (more_to_come): Delete.
(struct readline_input_state): Delete.
(readline_input_state): Delete.
(get_command_line_buffer): New function.
(command_handler): Update comments. Don't handle NULL commands
here. Do not execute commented lines.
(command_line_append_input_line): New function.
(handle_line_of_input): New function, partly based on
command_line_handler and command_line_input.
(command_line_handler): Rewrite.
* event-top.h (command_handler): New declaration.
(command_loop): Defer command execution to command_handler.
(command_line_input): Update comments. Simplify, using struct
buffer and handle_line_of_input.
* top.h (struct buffer): New forward declaration.
(handle_line_of_input): New declaration.
There doesn't seem to be much point in trying to reuse this buffer.
Prefer simplicity instead.
(In case you're wondering whether this fixes an off-by-one: linelength
is misnamed; it's really a size including terminating null char.)
gdb/ChangeLog:
2016-03-09 Pedro Alves <palves@redhat.com>
* event-top.c (command_line_handler): Use xfree + xstrdup instead
of xrealloc + strcpy.
* main.c (captured_main): Use xstrdup instead of xmalloc plus
manual clear.
* top.c (saved_command_line): Rewrite comment.
(saved_command_line_size): Delete.
(command_line_input): Use xfree + xstrdup instead of xrealloc +
strcpy.
* top.h (saved_command_line_size): Delete declaration.
gdb/ChangeLog:
2016-03-09 Pedro Alves <palves@redhat.com>
* common/buffer.h (buffer_grow_char): New function.
* top.c: Include buffer.h.
(gdb_readline_no_editing): Rename 'prompt_arg' parameter to
'prompt'. Use struct buffer instead of xrealloc.
Name this such that it's clearer that this is not a wrapper for the
real readline, but instead a replacement that provides no command line
editing features.
gdb/ChangeLog:
2016-03-09 Pedro Alves <palves@redhat.com>
* defs.h (gdb_readline): Delete declaration.
* top.c (gdb_readline): Rename to ...
(gdb_readline_no_editing): ... this, and make static.
The comments and existence of this global are a bit of misleading
obfuscation, since this is only ever used to print the prompt
annotation, and never changes. Just hardcode "prompt" where
necessary, as done for most other annotations.
gdb/ChangeLog:
2016-03-09 Pedro Alves <palves@redhat.com>
* event-top.c (async_annotation_suffix): Delete.
(top_level_prompt, command_line_handler): Don't use
'async_annotation_suffix' and simplify.
* event-top.h (async_annotation_suffix): Delete declaration.
(init_main): Remove reference to 'async_annotation_suffix'.
I checked, and Insight doesn't set this.
gdb/ChangeLog:
2016-03-09 Pedro Alves <palves@redhat.com>
* top.c (window_hook): Delete.
(command_loop): Remove references to window_hook.
gdb/ChangeLog:
* top.c (print_gdb_version): Change copyright year in version
message.
gdb/gdbserver/ChangeLog:
* gdbreplay.c (gdbreplay_version): Change copyright year in
version message.
* server.c (gdbserver_version): Likewise.
2015-12-18 Sandra Loosemore <sandra@codesourcery.com>
gdb/
* event-top.c (command_handler): Don't require stdin to be a tty
for call to reinitialize_more_filter.
* top.c (command_loop): Likewise.