/* Connect to the remote target. */ enum mi_cmd_result mi_cmd_target_select (char *args, int from_tty) { char *run; struct cleanup *old_cleanups = NULL; run = xstrprintf ("target %s", args); old_cleanups = make_cleanup (xfree, run); /* target-select is always synchronous. once the call has returned we know that we are connected. */ /* NOTE: At present all targets that are connected are also (implicitly) talking to a halted target. In the future this may change. */ execute_command (run, from_tty); do_cleanups (old_cleanups); /* Issue the completion message here. */ if (last_async_command) fputs_unfiltered (last_async_command, raw_stdout); fputs_unfiltered ("^connected", raw_stdout); mi_out_put (uiout, raw_stdout); mi_out_rewind (uiout); fputs_unfiltered ("\n", raw_stdout); do_exec_cleanups (ALL_CLEANUPS); return MI_CMD_QUIET; }
void mi_execute_command (char *cmd, int from_tty) { struct mi_parse *command; struct captured_mi_execute_command_args args; struct ui_out *saved_uiout = uiout; /* This is to handle EOF (^D). We just quit gdb. */ /* FIXME: we should call some API function here. */ if (cmd == 0) quit_force (NULL, from_tty); command = mi_parse (cmd); if (command != NULL) { struct gdb_exception result; if (do_timings) { command->cmd_start = (struct mi_timestamp *) xmalloc (sizeof (struct mi_timestamp)); timestamp (command->cmd_start); } /* FIXME: cagney/1999-11-04: Can this use of catch_exceptions either be pushed even further down or even eliminated? */ args.command = command; result = catch_exception (uiout, captured_mi_execute_command, &args, RETURN_MASK_ALL); exception_print (gdb_stderr, result); if (args.action == EXECUTE_COMMAND_SUPRESS_PROMPT) { /* The command is executing synchronously. Bail out early suppressing the finished prompt. */ mi_parse_free (command); return; } if (result.reason < 0) { /* The command execution failed and error() was called somewhere. */ fputs_unfiltered (command->token, raw_stdout); fputs_unfiltered ("^error,msg=\"", raw_stdout); if (result.message == NULL) fputs_unfiltered ("unknown error", raw_stdout); else fputstr_unfiltered (result.message, '"', raw_stdout); fputs_unfiltered ("\"\n", raw_stdout); mi_out_rewind (uiout); } mi_parse_free (command); } fputs_unfiltered ("(gdb) \n", raw_stdout); gdb_flush (raw_stdout); /* Print any buffered hook code. */ /* ..... */ }
static void mi_on_normal_stop (struct bpstats *bs, int print_frame) { /* Since this can be called when CLI command is executing, using cli interpreter, be sure to use MI uiout for output, not the current one. */ struct ui_out *mi_uiout = interp_ui_out (top_level_interpreter ()); if (print_frame) { int core; if (current_uiout != mi_uiout) { /* The normal_stop function has printed frame information into CLI uiout, or some other non-MI uiout. There's no way we can extract proper fields from random uiout object, so we print the frame again. In practice, this can only happen when running a CLI command in MI. */ struct ui_out *saved_uiout = current_uiout; struct target_waitstatus last; ptid_t last_ptid; current_uiout = mi_uiout; get_last_target_status (&last_ptid, &last); bpstat_print (bs, last.kind); print_stack_frame (get_selected_frame (NULL), 0, SRC_AND_LOC, 1); current_uiout = saved_uiout; } ui_out_field_int (mi_uiout, "thread-id", pid_to_thread_id (inferior_ptid)); if (non_stop) { struct cleanup *back_to = make_cleanup_ui_out_list_begin_end (mi_uiout, "stopped-threads"); ui_out_field_int (mi_uiout, NULL, pid_to_thread_id (inferior_ptid)); do_cleanups (back_to); } else ui_out_field_string (mi_uiout, "stopped-threads", "all"); core = target_core_of_thread (inferior_ptid); if (core != -1) ui_out_field_int (mi_uiout, "core", core); } fputs_unfiltered ("*stopped", raw_stdout); mi_out_put (mi_uiout, raw_stdout); mi_out_rewind (mi_uiout); mi_print_timing_maybe (); fputs_unfiltered ("\n", raw_stdout); gdb_flush (raw_stdout); }
static void ser_base_read_error_fd (struct serial *scb, int close_fd) { if (scb->error_fd != -1) { ssize_t s; char buf[GDB_MI_MSG_WIDTH + 1]; for (;;) { char *current; char *newline; int to_read = GDB_MI_MSG_WIDTH; int num_bytes = -1; if (scb->ops->avail) num_bytes = (scb->ops->avail)(scb, scb->error_fd); if (num_bytes != -1) to_read = (num_bytes < to_read) ? num_bytes : to_read; if (to_read == 0) break; s = read (scb->error_fd, &buf, to_read); if ((s == -1) || (s == 0 && !close_fd)) break; if (s == 0 && close_fd) { /* End of file. */ if (serial_is_async_p (scb)) delete_file_handler (scb->error_fd); close (scb->error_fd); scb->error_fd = -1; break; } /* In theory, embedded newlines are not a problem. But for MI, we want each output line to have just one newline for legibility. So output things in newline chunks. */ gdb_assert (s > 0 && s <= GDB_MI_MSG_WIDTH); buf[s] = '\0'; current = buf; while ((newline = strstr (current, "\n")) != NULL) { *newline = '\0'; fputs_unfiltered (current, gdb_stderr); fputs_unfiltered ("\n", gdb_stderr); current = newline + 1; } fputs_unfiltered (current, gdb_stderr); } } }
enum mi_cmd_result mi_cmd_gdb_exit (char *command, char **argv, int argc) { /* We have to print everything right here because we never return */ if (last_async_command) fputs_unfiltered (last_async_command, raw_stdout); fputs_unfiltered ("^exit\n", raw_stdout); mi_out_put (uiout, raw_stdout); /* FIXME: The function called is not yet a formal libgdb function */ quit_force (NULL, FROM_TTY); return MI_CMD_DONE; }
void mi_exec_async_cli_cmd_continuation (struct continuation_arg *arg) { if (last_async_command) fputs_unfiltered (last_async_command, raw_stdout); fputs_unfiltered ("*stopped", raw_stdout); mi_out_put (uiout, raw_stdout); fputs_unfiltered ("\n", raw_stdout); fputs_unfiltered ("(gdb) \n", raw_stdout); gdb_flush (raw_stdout); do_exec_cleanups (ALL_CLEANUPS); }
void mi_execute_command (char *cmd, int from_tty) { struct mi_parse *command; struct captured_mi_execute_command_args args; struct ui_out *saved_uiout = uiout; int result; /* This is to handle EOF (^D). We just quit gdb. */ /* FIXME: we should call some API function here. */ if (cmd == 0) quit_force (NULL, from_tty); command = mi_parse (cmd); if (command != NULL) { /* FIXME: cagney/1999-11-04: Can this use of catch_exceptions either be pushed even further down or even eliminated? */ args.command = command; result = catch_exceptions (uiout, captured_mi_execute_command, &args, "", RETURN_MASK_ALL); if (args.action == EXECUTE_COMMAND_SUPRESS_PROMPT) { /* The command is executing synchronously. Bail out early suppressing the finished prompt. */ mi_parse_free (command); return; } if (args.action == EXECUTE_COMMAND_DISPLAY_ERROR || result < 0) { char *msg = error_last_message (); struct cleanup *cleanup = make_cleanup (xfree, msg); /* The command execution failed and error() was called somewhere */ fputs_unfiltered (command->token, raw_stdout); fputs_unfiltered ("^error,msg=\"", raw_stdout); fputstr_unfiltered (msg, '"', raw_stdout); fputs_unfiltered ("\"\n", raw_stdout); } mi_parse_free (command); } fputs_unfiltered ("(gdb) \n", raw_stdout); gdb_flush (raw_stdout); /* print any buffered hook code */ /* ..... */ }
void mi_ui_out::do_field_fmt (int fldno, int width, ui_align align, const char *fldname, const char *format, va_list args) { ui_file *stream = m_streams.back (); field_separator (); if (fldname) fprintf_unfiltered (stream, "%s=\"", fldname); else fputs_unfiltered ("\"", stream); vfprintf_unfiltered (stream, format, args); fputs_unfiltered ("\"", stream); }
void serial_log_command (struct target_ops *self, const char *cmd) { if (!serial_logfp) return; serial_current_type = 'c'; fputs_unfiltered ("\nc ", serial_logfp); fputs_unfiltered (cmd, serial_logfp); /* Make sure that the log file is as up-to-date as possible, in case we are getting ready to dump core or something. */ gdb_flush (serial_logfp); }
static void gdbtk_command_loop (void) { extern FILE *instream; /* We no longer want to use stdin as the command input stream */ instream = NULL; if (Tcl_Eval (gdbtk_interp, "gdbtk_tcl_preloop") != TCL_OK) { const char *msg; /* Force errorInfo to be set up propertly. */ Tcl_AddErrorInfo (gdbtk_interp, ""); msg = Tcl_GetVar (gdbtk_interp, "errorInfo", TCL_GLOBAL_ONLY); #ifdef _WIN32 MessageBox (NULL, msg, NULL, MB_OK | MB_ICONERROR | MB_TASKMODAL); #else fputs_unfiltered (msg, gdb_stderr); #endif } #ifdef _WIN32 close_bfds (); #endif Tk_MainLoop (); }
void gdbtk_interp::pre_command_loop () { /* We no longer want to use stdin as the command input stream: disable events from stdin. */ main_ui->input_fd = -1; if (Tcl_Eval (gdbtk_tcl_interp, "gdbtk_tcl_preloop") != TCL_OK) { const char *msg; /* Force errorInfo to be set up propertly. */ Tcl_AddErrorInfo (gdbtk_tcl_interp, ""); msg = Tcl_GetVar (gdbtk_tcl_interp, "errorInfo", TCL_GLOBAL_ONLY); #ifdef _WIN32 MessageBox (NULL, msg, NULL, MB_OK | MB_ICONERROR | MB_TASKMODAL); #else fputs_unfiltered (msg, gdb_stderr); #endif } #ifdef _WIN32 close_bfds (); #endif }
static void mi_execute_command_input_handler (char *cmd) { mi_execute_command_wrapper (cmd); fputs_unfiltered ("(gdb) \n", raw_stdout); gdb_flush (raw_stdout); }
enum tui_status tui_alloc_source_buffer (struct tui_win_info *win_info) { char *src_line_buf; int i, line_width, max_lines; enum tui_status ret = TUI_FAILURE; max_lines = win_info->generic.height; /* less the highlight box */ line_width = win_info->generic.width - 1; /* ** Allocate the buffer for the source lines. Do this only once since they ** will be re-used for all source displays. The only other time this will ** be done is when a window's size changes. */ if (win_info->generic.content == NULL) { src_line_buf = (char *) xmalloc ((max_lines * line_width) * sizeof (char)); if (src_line_buf == (char *) NULL) fputs_unfiltered ( "Unable to Allocate Memory for Source or Disassembly Display.\n", gdb_stderr); else { /* allocate the content list */ if ((win_info->generic.content = (void **) tui_alloc_content (max_lines, SRC_WIN)) == NULL) { xfree (src_line_buf); src_line_buf = (char *) NULL; fputs_unfiltered ( "Unable to Allocate Memory for Source or Disassembly Display.\n", gdb_stderr); } } for (i = 0; i < max_lines; i++) ((struct tui_win_element *) win_info->generic.content[i])->which_element.source.line = src_line_buf + (line_width * i); ret = TUI_SUCCESS; } else ret = TUI_SUCCESS; return ret; }
void mi_field_fmt (struct ui_out *uiout, int fldno, int width, enum ui_align align, const char *fldname, const char *format, va_list args) { struct ui_out_data *data = ui_out_data (uiout); if (data->suppress_output) return; field_separator (uiout); if (fldname) fprintf_unfiltered (data->buffer, "%s=\"", fldname); else fputs_unfiltered ("\"", data->buffer); vfprintf_unfiltered (data->buffer, format, args); fputs_unfiltered ("\"", data->buffer); }
static char * explicit_to_string_internal (int as_linespec, const struct explicit_location *explicit_loc) { struct ui_file *buf; char space, *result; int need_space = 0; struct cleanup *cleanup; space = as_linespec ? ':' : ' '; buf = mem_fileopen (); cleanup = make_cleanup_ui_file_delete (buf); if (explicit_loc->source_filename != NULL) { if (!as_linespec) fputs_unfiltered ("-source ", buf); fputs_unfiltered (explicit_loc->source_filename, buf); need_space = 1; } if (explicit_loc->function_name != NULL) { if (need_space) fputc_unfiltered (space, buf); if (!as_linespec) fputs_unfiltered ("-function ", buf); fputs_unfiltered (explicit_loc->function_name, buf); need_space = 1; } if (explicit_loc->label_name != NULL) { if (need_space) fputc_unfiltered (space, buf); if (!as_linespec) fputs_unfiltered ("-label ", buf); fputs_unfiltered (explicit_loc->label_name, buf); need_space = 1; } if (explicit_loc->line_offset.sign != LINE_OFFSET_UNKNOWN) { if (need_space) fputc_unfiltered (space, buf); if (!as_linespec) fputs_unfiltered ("-line ", buf); fprintf_filtered (buf, "%s%d", (explicit_loc->line_offset.sign == LINE_OFFSET_NONE ? "" : (explicit_loc->line_offset.sign == LINE_OFFSET_PLUS ? "+" : "-")), explicit_loc->line_offset.offset); } result = ui_file_xstrdup (buf, NULL); do_cleanups (cleanup); return result; }
static void mi_command_loop (int mi_version) { /* Turn off 8 bit strings in quoted output. Any character with the high bit set is printed using C's octal format. */ sevenbit_strings = 1; /* Tell the world that we're alive */ fputs_unfiltered ("(gdb) \n", raw_stdout); gdb_flush (raw_stdout); start_event_loop (); }
/* VARARGS */ static void out_field_fmt (struct ui_out *uiout, int fldno, char *fldname, char *format,...) { struct ui_out_data *data = ui_out_data (uiout); va_list args; field_separator (uiout); if (fldname) fprintf_unfiltered (data->buffer, "%s=\"", fldname); else fputs_unfiltered ("\"", data->buffer); va_start (args, format); vfprintf_unfiltered (data->buffer, format, args); fputs_unfiltered ("\"", data->buffer); va_end (args); }
static void mi_on_sync_execution_done (void) { /* If MI is sync, then output the MI prompt now, indicating we're ready for further input. */ if (!mi_async_p ()) { fputs_unfiltered ("(gdb) \n", raw_stdout); gdb_flush (raw_stdout); } }
enum tui_status tui_alloc_source_buffer (struct tui_win_info *win_info) { char *src_line_buf; int i, line_width, max_lines; max_lines = win_info->generic.height; /* Less the highlight box. */ line_width = win_info->generic.width - 1; /* * Allocate the buffer for the source lines. Do this only once * since they will be re-used for all source displays. The only * other time this will be done is when a window's size changes. */ if (win_info->generic.content == NULL) { src_line_buf = (char *) xmalloc ((max_lines * line_width) * sizeof (char)); if (src_line_buf == (char *) NULL) { fputs_unfiltered ("Unable to Allocate Memory for " "Source or Disassembly Display.\n", gdb_stderr); return TUI_FAILURE; } /* Allocate the content list. */ win_info->generic.content = tui_alloc_content (max_lines, SRC_WIN); if (win_info->generic.content == NULL) { xfree (src_line_buf); fputs_unfiltered ("Unable to Allocate Memory for " "Source or Disassembly Display.\n", gdb_stderr); return TUI_FAILURE; } for (i = 0; i < max_lines; i++) win_info->generic.content[i]->which_element.source.line = src_line_buf + (line_width * i); } return TUI_SUCCESS; }
static void add_code_header (enum compile_i_scope_types type, struct ui_file *buf) { switch (type) { case COMPILE_I_SIMPLE_SCOPE: fputs_unfiltered ("void " GCC_FE_WRAPPER_FUNCTION " (struct " COMPILE_I_SIMPLE_REGISTER_STRUCT_TAG " *" COMPILE_I_SIMPLE_REGISTER_ARG_NAME ") {\n", buf); break; case COMPILE_I_PRINT_ADDRESS_SCOPE: case COMPILE_I_PRINT_VALUE_SCOPE: /* <string.h> is needed for a memcpy call below. */ fputs_unfiltered ("#include <string.h>\n" "void " GCC_FE_WRAPPER_FUNCTION " (struct " COMPILE_I_SIMPLE_REGISTER_STRUCT_TAG " *" COMPILE_I_SIMPLE_REGISTER_ARG_NAME ", " COMPILE_I_PRINT_OUT_ARG_TYPE " " COMPILE_I_PRINT_OUT_ARG ") {\n", buf); break; case COMPILE_I_RAW_SCOPE: break; default: gdb_assert_not_reached (_("Unknown compiler scope reached.")); } }
/* Interrupt the execution of the target. Note how we must play around with the token varialbes, in order to display the current token in the result of the interrupt command, and the previous execution token when the target finally stops. See comments in mi_cmd_execute. */ enum mi_cmd_result mi_cmd_exec_interrupt (char *args, int from_tty) { if (!target_executing) { mi_error_message = xstrprintf ("mi_cmd_exec_interrupt: Inferior not executing."); return MI_CMD_ERROR; } interrupt_target_command (args, from_tty); if (last_async_command) fputs_unfiltered (last_async_command, raw_stdout); fputs_unfiltered ("^done", raw_stdout); xfree (last_async_command); if (previous_async_command) last_async_command = xstrdup (previous_async_command); xfree (previous_async_command); previous_async_command = NULL; mi_out_put (uiout, raw_stdout); mi_out_rewind (uiout); fputs_unfiltered ("\n", raw_stdout); return MI_CMD_QUIET; }
static void do_serial_close (struct serial *scb, int really_close) { struct serial *tmp_scb; last_serial_opened = NULL; if (serial_logfp) { fputs_unfiltered ("\nEnd of log\n", serial_logfp); serial_current_type = 0; /* XXX - What if serial_logfp == gdb_stdout or gdb_stderr? */ ui_file_delete (serial_logfp); serial_logfp = NULL; } /* This is bogus. It's not our fault if you pass us a bad scb...! Rob, you should fix your code instead. */ if (!scb) return; scb->refcnt--; if (scb->refcnt > 0) return; /* ensure that the FD has been taken out of async mode */ if (scb->async_handler != NULL) serial_async (scb, NULL, NULL); if (really_close) scb->ops->close (scb); if (scb->name) xfree (scb->name); if (scb_base == scb) scb_base = scb_base->next; else for (tmp_scb = scb_base; tmp_scb; tmp_scb = tmp_scb->next) { if (tmp_scb->next != scb) continue; tmp_scb->next = tmp_scb->next->next; break; } xfree (scb); }
static int gdb_os_write_stderr (host_callback *p, const char *buf, int len) { int i; char b[2]; for (i = 0; i < len; i++) { b[0] = buf[i]; b[1] = 0; fputs_unfiltered (b, gdb_stdtargerr); } return len; }
static void add_code_footer (enum compile_i_scope_types type, struct ui_file *buf) { switch (type) { case COMPILE_I_SIMPLE_SCOPE: case COMPILE_I_PRINT_ADDRESS_SCOPE: case COMPILE_I_PRINT_VALUE_SCOPE: fputs_unfiltered ("}\n", buf); break; case COMPILE_I_RAW_SCOPE: break; default: gdb_assert_not_reached (_("Unknown compiler scope reached.")); } }
static void mi_execute_command_input_handler (char *cmd) { mi_execute_command_wrapper (cmd); /* Print a prompt, indicating we're ready for further input, unless we just started a synchronous command. In that case, we're about to go back to the event loop and will output the prompt in the 'synchronous_command_done' observer when the target next stops. */ if (!sync_execution) { fputs_unfiltered ("(gdb) \n", raw_stdout); gdb_flush (raw_stdout); } }
static void mi_on_sync_execution_done (void) { /* MI generally prints a prompt after a command, indicating it's ready for further input. However, due to an historical wart, if MI async, and a (CLI) synchronous command was issued, then we will print the prompt right after printing "^running", even if we cannot actually accept any input until the target stops. See mi_on_resume. However, if the target is async but MI is sync, then we need to output the MI prompt now, to replicate gdb's behavior when neither the target nor MI are async. (Note this observer is only called by the asynchronous target event handling code.) */ if (!mi_async_p ()) { fputs_unfiltered ("(gdb) \n", raw_stdout); gdb_flush (raw_stdout); } }
static void do_serial_close (struct serial *scb, int really_close) { struct serial *tmp_scb; if (serial_logfp) { fputs_unfiltered ("\nEnd of log\n", serial_logfp); serial_current_type = 0; /* XXX - What if serial_logfp == gdb_stdout or gdb_stderr? */ ui_file_delete (serial_logfp); serial_logfp = NULL; } /* ensure that the FD has been taken out of async mode. */ if (scb->async_handler != NULL) serial_async (scb, NULL, NULL); if (really_close) scb->ops->close (scb); if (scb->name) xfree (scb->name); /* For serial_is_open. */ scb->bufp = NULL; if (scb_base == scb) scb_base = scb_base->next; else for (tmp_scb = scb_base; tmp_scb; tmp_scb = tmp_scb->next) { if (tmp_scb->next != scb) continue; tmp_scb->next = tmp_scb->next->next; break; } serial_unref (scb); }
static void mi_execute_command_input_handler (char *cmd) { mi_execute_command_wrapper (cmd); /* MI generally prints a prompt after a command, indicating it's ready for further input. However, due to an historical wart, if MI is async, and a synchronous command was issued, then we will print the prompt right after printing "^running", even if we cannot actually accept any input until the target stops. See mi_on_resume. If MI is not async, then we print the prompt when the command finishes. If the target is sync, that means output the prompt now, as in that case executing a command doesn't return until the command is done. However, if the target is async, we go back to the event loop and output the prompt in the 'synchronous_command_done' observer. */ if (!target_is_async_p () || !sync_execution) { fputs_unfiltered ("(gdb) \n", raw_stdout); gdb_flush (raw_stdout); } }
void display_gdb_prompt (char *new_prompt) { char *actual_gdb_prompt = NULL; struct cleanup *old_chain; annotate_display_prompt (); /* Reset the nesting depth used when trace-commands is set. */ reset_command_nest_depth (); /* Each interpreter has its own rules on displaying the command prompt. */ if (!current_interp_display_prompt_p ()) return; old_chain = make_cleanup (free_current_contents, &actual_gdb_prompt); /* Do not call the python hook on an explicit prompt change as passed to this function, as this forms a secondary/local prompt, IE, displayed but not set. */ if (! new_prompt) { if (sync_execution) { /* This is to trick readline into not trying to display the prompt. Even though we display the prompt using this function, readline still tries to do its own display if we don't call rl_callback_handler_install and rl_callback_handler_remove (which readline detects because a global variable is not set). If readline did that, it could mess up gdb signal handlers for SIGINT. Readline assumes that between calls to rl_set_signals and rl_clear_signals gdb doesn't do anything with the signal handlers. Well, that's not the case, because when the target executes we change the SIGINT signal handler. If we allowed readline to display the prompt, the signal handler change would happen exactly between the calls to the above two functions. Calling rl_callback_handler_remove(), does the job. */ rl_callback_handler_remove (); do_cleanups (old_chain); return; } else { /* Display the top level prompt. */ actual_gdb_prompt = top_level_prompt (); } } else actual_gdb_prompt = xstrdup (new_prompt); if (async_command_editing_p) { rl_callback_handler_remove (); rl_callback_handler_install (actual_gdb_prompt, input_handler); } /* new_prompt at this point can be the top of the stack or the one passed in. It can't be NULL. */ else { /* Don't use a _filtered function here. It causes the assumed character position to be off, since the newline we read from the user is not accounted for. */ fputs_unfiltered (actual_gdb_prompt, gdb_stdout); gdb_flush (gdb_stdout); } do_cleanups (old_chain); }
void do_setshow_command(char *arg, int from_tty, struct cmd_list_element *c) { if (c->type == set_cmd) { switch (c->var_type) { case var_string: { char *newstr; char *p; char *q; int ch; if (arg == NULL) arg = ""; newstr = (char *)xmalloc(strlen(arg) + 2); p = arg; q = newstr; while ((ch = *p++) != '\000') { if (ch == '\\') { /* \ at end of argument is used after spaces so they won't be lost. */ /* This is obsolete now that we no longer strip trailing whitespace and actually, the backslash didn't get here in my test, readline or something did something funky with a backslash right before a newline. */ if (*p == 0) break; ch = parse_escape(&p); if (ch == 0) break; /* C loses */ else if (ch > 0) *q++ = ch; } else *q++ = ch; } #if 0 if (*(p - 1) != '\\') *q++ = ' '; #endif /* 0 */ *q++ = '\0'; newstr = (char *)xrealloc(newstr, (q - newstr)); if (*(char **)c->var != NULL) xfree(*(char **)c->var); *(char **)c->var = newstr; } break; case var_string_noescape: if (arg == NULL) arg = ""; if (*(char **)c->var != NULL) xfree(*(char **)c->var); *(char **)c->var = savestring(arg, strlen(arg)); break; case var_optional_filename: if (arg == NULL) arg = ""; if (*(char **)c->var != NULL) xfree(*(char **)c->var); *(char **)c->var = savestring(arg, strlen(arg)); break; case var_filename: if (arg == NULL) error_no_arg(_("filename to set it to.")); if (*(char **)c->var != NULL) xfree (*(char **)c->var); *(char **)c->var = tilde_expand(arg); break; case var_boolean: *(int *)c->var = parse_binary_operation(arg); break; case var_auto_boolean: *(enum auto_boolean *)c->var = parse_auto_binary_operation(arg); break; case var_uinteger: if (arg == NULL) error_no_arg(_("integer to set it to.")); *(unsigned int *)c->var = (unsigned int)parse_and_eval_long(arg); if (*(unsigned int *)c->var == 0) *(unsigned int *)c->var = UINT_MAX; break; case var_integer: { unsigned int val; if (arg == NULL) error_no_arg(_("integer to set it to.")); val = (unsigned int)parse_and_eval_long(arg); if (val == 0) *(int *)c->var = INT_MAX; else if (val >= INT_MAX) error(_("integer %u out of range"), val); else *(int *)c->var = val; break; } case var_zinteger: if (arg == NULL) error_no_arg(_("integer to set it to.")); *(int *)c->var = (int)parse_and_eval_long(arg); break; case var_enum: { int i; int len; int nmatches = 0; const char *match = NULL; char *p; /* APPLE LOCAL: Give the valid options for all error messages for enum type commands. */ /* If an argument was supplied, parse it. */ if (arg != NULL) { p = strchr(arg, ' '); if (p) len = (p - arg); else len = strlen(arg); nmatches = 0; for (i = 0; c->enums[i]; i++) if (strncmp(arg, c->enums[i], len) == 0) { if (c->enums[i][len] == '\0') { match = c->enums[i]; nmatches = 1; break; /* exact match. */ } else { match = c->enums[i]; nmatches++; } } } if (nmatches == 1) *(const char **)c->var = match; else { /* If there was an error, print an informative error message. */ struct ui_file *tmp_error_stream = mem_fileopen(); make_cleanup_ui_file_delete (tmp_error_stream); if (arg == NULL) fprintf_unfiltered(tmp_error_stream, "Requires an argument."); else if (nmatches <= 0) fprintf_unfiltered(tmp_error_stream, "Undefined item: \"%s\".", arg); else if (nmatches > 1) fprintf_unfiltered(tmp_error_stream, "Ambiguous item \"%s\".", arg); fprintf_unfiltered(tmp_error_stream, " Valid arguments are "); for (i = 0; c->enums[i]; i++) { if (i != 0) fprintf_unfiltered(tmp_error_stream, ", "); fputs_unfiltered(c->enums[i], tmp_error_stream); } fprintf_unfiltered(tmp_error_stream, "."); error_stream(tmp_error_stream); } /* END APPLE LOCAL */ } break; default: error(_("gdb internal error: bad var_type in do_setshow_command")); } } else if (c->type == show_cmd) { struct cleanup *old_chain; struct ui_stream *stb; stb = ui_out_stream_new(uiout); old_chain = make_cleanup_ui_out_stream_delete(stb); /* Possibly call the pre hook: */ if (c->pre_show_hook) (c->pre_show_hook)(c); switch (c->var_type) { case var_string: { if (*(unsigned char **)c->var) fputstr_filtered(*(char **)c->var, '"', stb->stream); } break; case var_string_noescape: case var_optional_filename: case var_filename: case var_enum: if (*(char **)c->var) fputs_filtered(*(char **)c->var, stb->stream); break; case var_boolean: fputs_filtered(*(int *)c->var ? "on" : "off", stb->stream); break; case var_auto_boolean: switch (*(enum auto_boolean*)c->var) { case AUTO_BOOLEAN_TRUE: fputs_filtered("on", stb->stream); break; case AUTO_BOOLEAN_FALSE: fputs_filtered("off", stb->stream); break; case AUTO_BOOLEAN_AUTO: fputs_filtered("auto", stb->stream); break; default: internal_error(__FILE__, __LINE__, _("do_setshow_command: invalid var_auto_boolean")); break; } break; case var_uinteger: if (*(unsigned int *)c->var == UINT_MAX) { fputs_filtered("unlimited", stb->stream); break; } /* else fall through */ case var_zinteger: fprintf_filtered(stb->stream, "%u", *(unsigned int *)c->var); break; case var_integer: if (*(int *)c->var == INT_MAX) { fputs_filtered("unlimited", stb->stream); } else fprintf_filtered(stb->stream, "%d", *(int *)c->var); break; default: error(_("gdb internal error: bad var_type in do_setshow_command")); } /* FIXME: cagney/2005-02-10: Need to split this in half: code to convert the value into a string (esentially the above); and code to print the value out. For the latter there should be MI and CLI specific versions. */ if (ui_out_is_mi_like_p(uiout)) ui_out_field_stream(uiout, "value", stb); else { long length; char *value = ui_file_xstrdup(stb->stream, &length); make_cleanup(xfree, value); if (c->show_value_func != NULL) c->show_value_func(gdb_stdout, from_tty, c, value); else deprecated_show_value_hack(gdb_stdout, from_tty, c, value); } do_cleanups(old_chain); } else error(_("gdb internal error: bad cmd_type in do_setshow_command")); c->func(c, NULL, from_tty); if ((c->type == set_cmd) && deprecated_set_hook) deprecated_set_hook(c); }