xref: /dragonfly/contrib/gdb-7/gdb/mi/mi-main.c (revision 74a8b0f5)
15796c8dcSSimon Schubert /* MI Command Set.
25796c8dcSSimon Schubert 
3a45ae5f8SJohn Marino    Copyright (C) 2000-2013 Free Software Foundation, Inc.
45796c8dcSSimon Schubert 
55796c8dcSSimon Schubert    Contributed by Cygnus Solutions (a Red Hat company).
65796c8dcSSimon Schubert 
75796c8dcSSimon Schubert    This file is part of GDB.
85796c8dcSSimon Schubert 
95796c8dcSSimon Schubert    This program is free software; you can redistribute it and/or modify
105796c8dcSSimon Schubert    it under the terms of the GNU General Public License as published by
115796c8dcSSimon Schubert    the Free Software Foundation; either version 3 of the License, or
125796c8dcSSimon Schubert    (at your option) any later version.
135796c8dcSSimon Schubert 
145796c8dcSSimon Schubert    This program is distributed in the hope that it will be useful,
155796c8dcSSimon Schubert    but WITHOUT ANY WARRANTY; without even the implied warranty of
165796c8dcSSimon Schubert    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
175796c8dcSSimon Schubert    GNU General Public License for more details.
185796c8dcSSimon Schubert 
195796c8dcSSimon Schubert    You should have received a copy of the GNU General Public License
205796c8dcSSimon Schubert    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
215796c8dcSSimon Schubert 
225796c8dcSSimon Schubert #include "defs.h"
235796c8dcSSimon Schubert #include "arch-utils.h"
245796c8dcSSimon Schubert #include "target.h"
255796c8dcSSimon Schubert #include "inferior.h"
265796c8dcSSimon Schubert #include "gdb_string.h"
275796c8dcSSimon Schubert #include "exceptions.h"
285796c8dcSSimon Schubert #include "top.h"
295796c8dcSSimon Schubert #include "gdbthread.h"
305796c8dcSSimon Schubert #include "mi-cmds.h"
315796c8dcSSimon Schubert #include "mi-parse.h"
325796c8dcSSimon Schubert #include "mi-getopt.h"
335796c8dcSSimon Schubert #include "mi-console.h"
345796c8dcSSimon Schubert #include "ui-out.h"
355796c8dcSSimon Schubert #include "mi-out.h"
365796c8dcSSimon Schubert #include "interps.h"
375796c8dcSSimon Schubert #include "event-loop.h"
385796c8dcSSimon Schubert #include "event-top.h"
395796c8dcSSimon Schubert #include "gdbcore.h"		/* For write_memory().  */
405796c8dcSSimon Schubert #include "value.h"
415796c8dcSSimon Schubert #include "regcache.h"
425796c8dcSSimon Schubert #include "gdb.h"
435796c8dcSSimon Schubert #include "frame.h"
445796c8dcSSimon Schubert #include "mi-main.h"
455796c8dcSSimon Schubert #include "mi-common.h"
465796c8dcSSimon Schubert #include "language.h"
475796c8dcSSimon Schubert #include "valprint.h"
485796c8dcSSimon Schubert #include "inferior.h"
495796c8dcSSimon Schubert #include "osdata.h"
505796c8dcSSimon Schubert #include "splay-tree.h"
515796c8dcSSimon Schubert #include "tracepoint.h"
52cf7f2e2dSJohn Marino #include "ada-lang.h"
53cf7f2e2dSJohn Marino #include "linespec.h"
54a45ae5f8SJohn Marino 
55a45ae5f8SJohn Marino #include <ctype.h>
565796c8dcSSimon Schubert #include <sys/time.h>
575796c8dcSSimon Schubert 
585796c8dcSSimon Schubert #if defined HAVE_SYS_RESOURCE_H
595796c8dcSSimon Schubert #include <sys/resource.h>
605796c8dcSSimon Schubert #endif
615796c8dcSSimon Schubert 
625796c8dcSSimon Schubert #ifdef HAVE_GETRUSAGE
635796c8dcSSimon Schubert struct rusage rusage;
645796c8dcSSimon Schubert #endif
655796c8dcSSimon Schubert 
665796c8dcSSimon Schubert enum
675796c8dcSSimon Schubert   {
685796c8dcSSimon Schubert     FROM_TTY = 0
695796c8dcSSimon Schubert   };
705796c8dcSSimon Schubert 
715796c8dcSSimon Schubert int mi_debug_p;
725796c8dcSSimon Schubert 
735796c8dcSSimon Schubert struct ui_file *raw_stdout;
745796c8dcSSimon Schubert 
755796c8dcSSimon Schubert /* This is used to pass the current command timestamp down to
765796c8dcSSimon Schubert    continuation routines.  */
775796c8dcSSimon Schubert static struct mi_timestamp *current_command_ts;
785796c8dcSSimon Schubert 
795796c8dcSSimon Schubert static int do_timings = 0;
805796c8dcSSimon Schubert 
815796c8dcSSimon Schubert char *current_token;
825796c8dcSSimon Schubert /* Few commands would like to know if options like --thread-group were
83cf7f2e2dSJohn Marino    explicitly specified.  This variable keeps the current parsed
84cf7f2e2dSJohn Marino    command including all option, and make it possible.  */
85cf7f2e2dSJohn Marino static struct mi_parse *current_context;
86cf7f2e2dSJohn Marino 
87cf7f2e2dSJohn Marino int running_result_record_printed = 1;
885796c8dcSSimon Schubert 
895796c8dcSSimon Schubert /* Flag indicating that the target has proceeded since the last
905796c8dcSSimon Schubert    command was issued.  */
915796c8dcSSimon Schubert int mi_proceeded;
925796c8dcSSimon Schubert 
935796c8dcSSimon Schubert extern void _initialize_mi_main (void);
945796c8dcSSimon Schubert static void mi_cmd_execute (struct mi_parse *parse);
955796c8dcSSimon Schubert 
965796c8dcSSimon Schubert static void mi_execute_cli_command (const char *cmd, int args_p,
975796c8dcSSimon Schubert 				    const char *args);
985796c8dcSSimon Schubert static void mi_execute_async_cli_command (char *cli_command,
995796c8dcSSimon Schubert 					  char **argv, int argc);
1005796c8dcSSimon Schubert static int register_changed_p (int regnum, struct regcache *,
1015796c8dcSSimon Schubert 			       struct regcache *);
1025796c8dcSSimon Schubert static void get_register (struct frame_info *, int regnum, int format);
1035796c8dcSSimon Schubert 
1045796c8dcSSimon Schubert /* Command implementations.  FIXME: Is this libgdb?  No.  This is the MI
1055796c8dcSSimon Schubert    layer that calls libgdb.  Any operation used in the below should be
1065796c8dcSSimon Schubert    formalized.  */
1075796c8dcSSimon Schubert 
1085796c8dcSSimon Schubert static void timestamp (struct mi_timestamp *tv);
1095796c8dcSSimon Schubert 
1105796c8dcSSimon Schubert static void print_diff_now (struct mi_timestamp *start);
1115796c8dcSSimon Schubert static void print_diff (struct mi_timestamp *start, struct mi_timestamp *end);
1125796c8dcSSimon Schubert 
1135796c8dcSSimon Schubert void
mi_cmd_gdb_exit(char * command,char ** argv,int argc)1145796c8dcSSimon Schubert mi_cmd_gdb_exit (char *command, char **argv, int argc)
1155796c8dcSSimon Schubert {
1165796c8dcSSimon Schubert   /* We have to print everything right here because we never return.  */
1175796c8dcSSimon Schubert   if (current_token)
1185796c8dcSSimon Schubert     fputs_unfiltered (current_token, raw_stdout);
1195796c8dcSSimon Schubert   fputs_unfiltered ("^exit\n", raw_stdout);
1205796c8dcSSimon Schubert   mi_out_put (current_uiout, raw_stdout);
121a45ae5f8SJohn Marino   gdb_flush (raw_stdout);
122cf7f2e2dSJohn Marino   /* FIXME: The function called is not yet a formal libgdb function.  */
1235796c8dcSSimon Schubert   quit_force (NULL, FROM_TTY);
1245796c8dcSSimon Schubert }
1255796c8dcSSimon Schubert 
1265796c8dcSSimon Schubert void
mi_cmd_exec_next(char * command,char ** argv,int argc)1275796c8dcSSimon Schubert mi_cmd_exec_next (char *command, char **argv, int argc)
1285796c8dcSSimon Schubert {
1295796c8dcSSimon Schubert   /* FIXME: Should call a libgdb function, not a cli wrapper.  */
1305796c8dcSSimon Schubert   if (argc > 0 && strcmp(argv[0], "--reverse") == 0)
131cf7f2e2dSJohn Marino     mi_execute_async_cli_command ("reverse-next", argv + 1, argc - 1);
132cf7f2e2dSJohn Marino   else
133cf7f2e2dSJohn Marino     mi_execute_async_cli_command ("next", argv, argc);
1345796c8dcSSimon Schubert }
1355796c8dcSSimon Schubert 
1365796c8dcSSimon Schubert void
mi_cmd_exec_next_instruction(char * command,char ** argv,int argc)1375796c8dcSSimon Schubert mi_cmd_exec_next_instruction (char *command, char **argv, int argc)
1385796c8dcSSimon Schubert {
1395796c8dcSSimon Schubert   /* FIXME: Should call a libgdb function, not a cli wrapper.  */
1405796c8dcSSimon Schubert   if (argc > 0 && strcmp(argv[0], "--reverse") == 0)
141cf7f2e2dSJohn Marino     mi_execute_async_cli_command ("reverse-nexti", argv + 1, argc - 1);
142cf7f2e2dSJohn Marino   else
143cf7f2e2dSJohn Marino     mi_execute_async_cli_command ("nexti", argv, argc);
1445796c8dcSSimon Schubert }
1455796c8dcSSimon Schubert 
1465796c8dcSSimon Schubert void
mi_cmd_exec_step(char * command,char ** argv,int argc)1475796c8dcSSimon Schubert mi_cmd_exec_step (char *command, char **argv, int argc)
1485796c8dcSSimon Schubert {
1495796c8dcSSimon Schubert   /* FIXME: Should call a libgdb function, not a cli wrapper.  */
1505796c8dcSSimon Schubert   if (argc > 0 && strcmp(argv[0], "--reverse") == 0)
151cf7f2e2dSJohn Marino     mi_execute_async_cli_command ("reverse-step", argv + 1, argc - 1);
152cf7f2e2dSJohn Marino   else
153cf7f2e2dSJohn Marino     mi_execute_async_cli_command ("step", argv, argc);
1545796c8dcSSimon Schubert }
1555796c8dcSSimon Schubert 
1565796c8dcSSimon Schubert void
mi_cmd_exec_step_instruction(char * command,char ** argv,int argc)1575796c8dcSSimon Schubert mi_cmd_exec_step_instruction (char *command, char **argv, int argc)
1585796c8dcSSimon Schubert {
1595796c8dcSSimon Schubert   /* FIXME: Should call a libgdb function, not a cli wrapper.  */
1605796c8dcSSimon Schubert   if (argc > 0 && strcmp(argv[0], "--reverse") == 0)
161cf7f2e2dSJohn Marino     mi_execute_async_cli_command ("reverse-stepi", argv + 1, argc - 1);
162cf7f2e2dSJohn Marino   else
163cf7f2e2dSJohn Marino     mi_execute_async_cli_command ("stepi", argv, argc);
1645796c8dcSSimon Schubert }
1655796c8dcSSimon Schubert 
1665796c8dcSSimon Schubert void
mi_cmd_exec_finish(char * command,char ** argv,int argc)1675796c8dcSSimon Schubert mi_cmd_exec_finish (char *command, char **argv, int argc)
1685796c8dcSSimon Schubert {
1695796c8dcSSimon Schubert   /* FIXME: Should call a libgdb function, not a cli wrapper.  */
1705796c8dcSSimon Schubert   if (argc > 0 && strcmp(argv[0], "--reverse") == 0)
171cf7f2e2dSJohn Marino     mi_execute_async_cli_command ("reverse-finish", argv + 1, argc - 1);
172cf7f2e2dSJohn Marino   else
173cf7f2e2dSJohn Marino     mi_execute_async_cli_command ("finish", argv, argc);
1745796c8dcSSimon Schubert }
1755796c8dcSSimon Schubert 
1765796c8dcSSimon Schubert void
mi_cmd_exec_return(char * command,char ** argv,int argc)1775796c8dcSSimon Schubert mi_cmd_exec_return (char *command, char **argv, int argc)
1785796c8dcSSimon Schubert {
1795796c8dcSSimon Schubert   /* This command doesn't really execute the target, it just pops the
1805796c8dcSSimon Schubert      specified number of frames.  */
1815796c8dcSSimon Schubert   if (argc)
1825796c8dcSSimon Schubert     /* Call return_command with from_tty argument equal to 0 so as to
1835796c8dcSSimon Schubert        avoid being queried.  */
1845796c8dcSSimon Schubert     return_command (*argv, 0);
1855796c8dcSSimon Schubert   else
1865796c8dcSSimon Schubert     /* Call return_command with from_tty argument equal to 0 so as to
1875796c8dcSSimon Schubert        avoid being queried.  */
1885796c8dcSSimon Schubert     return_command (NULL, 0);
1895796c8dcSSimon Schubert 
1905796c8dcSSimon Schubert   /* Because we have called return_command with from_tty = 0, we need
1915796c8dcSSimon Schubert      to print the frame here.  */
1925796c8dcSSimon Schubert   print_stack_frame (get_selected_frame (NULL), 1, LOC_AND_ADDRESS);
1935796c8dcSSimon Schubert }
1945796c8dcSSimon Schubert 
1955796c8dcSSimon Schubert void
mi_cmd_exec_jump(char * args,char ** argv,int argc)1965796c8dcSSimon Schubert mi_cmd_exec_jump (char *args, char **argv, int argc)
1975796c8dcSSimon Schubert {
1985796c8dcSSimon Schubert   /* FIXME: Should call a libgdb function, not a cli wrapper.  */
1995796c8dcSSimon Schubert   mi_execute_async_cli_command ("jump", argv, argc);
200cf7f2e2dSJohn Marino }
2015796c8dcSSimon Schubert 
2025796c8dcSSimon Schubert static void
proceed_thread(struct thread_info * thread,int pid)203cf7f2e2dSJohn Marino proceed_thread (struct thread_info *thread, int pid)
204cf7f2e2dSJohn Marino {
205cf7f2e2dSJohn Marino   if (!is_stopped (thread->ptid))
206cf7f2e2dSJohn Marino     return;
207cf7f2e2dSJohn Marino 
208cf7f2e2dSJohn Marino   if (pid != 0 && PIDGET (thread->ptid) != pid)
209cf7f2e2dSJohn Marino     return;
210cf7f2e2dSJohn Marino 
211cf7f2e2dSJohn Marino   switch_to_thread (thread->ptid);
212cf7f2e2dSJohn Marino   clear_proceed_status ();
213cf7f2e2dSJohn Marino   proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT, 0);
214cf7f2e2dSJohn Marino }
215cf7f2e2dSJohn Marino 
216cf7f2e2dSJohn Marino static int
proceed_thread_callback(struct thread_info * thread,void * arg)217cf7f2e2dSJohn Marino proceed_thread_callback (struct thread_info *thread, void *arg)
2185796c8dcSSimon Schubert {
2195796c8dcSSimon Schubert   int pid = *(int *)arg;
2205796c8dcSSimon Schubert 
2215796c8dcSSimon Schubert   proceed_thread (thread, pid);
2225796c8dcSSimon Schubert   return 0;
223cf7f2e2dSJohn Marino }
2245796c8dcSSimon Schubert 
225cf7f2e2dSJohn Marino static void
exec_continue(char ** argv,int argc)2265796c8dcSSimon Schubert exec_continue (char **argv, int argc)
227cf7f2e2dSJohn Marino {
228cf7f2e2dSJohn Marino   if (non_stop)
229cf7f2e2dSJohn Marino     {
230cf7f2e2dSJohn Marino       /* In non-stop mode, 'resume' always resumes a single thread.
231cf7f2e2dSJohn Marino 	 Therefore, to resume all threads of the current inferior, or
232cf7f2e2dSJohn Marino 	 all threads in all inferiors, we need to iterate over
233cf7f2e2dSJohn Marino 	 threads.
234cf7f2e2dSJohn Marino 
2355796c8dcSSimon Schubert 	 See comment on infcmd.c:proceed_thread_callback for rationale.  */
236cf7f2e2dSJohn Marino       if (current_context->all || current_context->thread_group != -1)
237cf7f2e2dSJohn Marino 	{
238cf7f2e2dSJohn Marino 	  int pid = 0;
239cf7f2e2dSJohn Marino 	  struct cleanup *back_to = make_cleanup_restore_current_thread ();
240cf7f2e2dSJohn Marino 
241cf7f2e2dSJohn Marino 	  if (!current_context->all)
242cf7f2e2dSJohn Marino 	    {
243cf7f2e2dSJohn Marino 	      struct inferior *inf
244c50c785cSJohn Marino 		= find_inferior_id (current_context->thread_group);
245c50c785cSJohn Marino 
246c50c785cSJohn Marino 	      pid = inf->pid;
247cf7f2e2dSJohn Marino 	    }
248cf7f2e2dSJohn Marino 	  iterate_over_threads (proceed_thread_callback, &pid);
249cf7f2e2dSJohn Marino 	  do_cleanups (back_to);
250cf7f2e2dSJohn Marino 	}
251cf7f2e2dSJohn Marino       else
252cf7f2e2dSJohn Marino 	{
253cf7f2e2dSJohn Marino 	  continue_1 (0);
254cf7f2e2dSJohn Marino 	}
255cf7f2e2dSJohn Marino     }
256cf7f2e2dSJohn Marino   else
257cf7f2e2dSJohn Marino     {
258cf7f2e2dSJohn Marino       struct cleanup *back_to = make_cleanup_restore_integer (&sched_multi);
259cf7f2e2dSJohn Marino 
260cf7f2e2dSJohn Marino       if (current_context->all)
261cf7f2e2dSJohn Marino 	{
262cf7f2e2dSJohn Marino 	  sched_multi = 1;
263cf7f2e2dSJohn Marino 	  continue_1 (0);
264cf7f2e2dSJohn Marino 	}
265cf7f2e2dSJohn Marino       else
266cf7f2e2dSJohn Marino 	{
267cf7f2e2dSJohn Marino 	  /* In all-stop mode, -exec-continue traditionally resumed
268cf7f2e2dSJohn Marino 	     either all threads, or one thread, depending on the
269cf7f2e2dSJohn Marino 	     'scheduler-locking' variable.  Let's continue to do the
270cf7f2e2dSJohn Marino 	     same.  */
271cf7f2e2dSJohn Marino 	  continue_1 (1);
272cf7f2e2dSJohn Marino 	}
273cf7f2e2dSJohn Marino       do_cleanups (back_to);
274cf7f2e2dSJohn Marino     }
275cf7f2e2dSJohn Marino }
276cf7f2e2dSJohn Marino 
277cf7f2e2dSJohn Marino static void
exec_direction_forward(void * notused)278cf7f2e2dSJohn Marino exec_direction_forward (void *notused)
279cf7f2e2dSJohn Marino {
280cf7f2e2dSJohn Marino   execution_direction = EXEC_FORWARD;
281cf7f2e2dSJohn Marino }
282cf7f2e2dSJohn Marino 
283cf7f2e2dSJohn Marino static void
exec_reverse_continue(char ** argv,int argc)284cf7f2e2dSJohn Marino exec_reverse_continue (char **argv, int argc)
285cf7f2e2dSJohn Marino {
286cf7f2e2dSJohn Marino   enum exec_direction_kind dir = execution_direction;
287cf7f2e2dSJohn Marino   struct cleanup *old_chain;
288cf7f2e2dSJohn Marino 
289cf7f2e2dSJohn Marino   if (dir == EXEC_REVERSE)
290cf7f2e2dSJohn Marino     error (_("Already in reverse mode."));
291cf7f2e2dSJohn Marino 
292cf7f2e2dSJohn Marino   if (!target_can_execute_reverse)
293cf7f2e2dSJohn Marino     error (_("Target %s does not support this command."), target_shortname);
294cf7f2e2dSJohn Marino 
295cf7f2e2dSJohn Marino   old_chain = make_cleanup (exec_direction_forward, NULL);
296cf7f2e2dSJohn Marino   execution_direction = EXEC_REVERSE;
297cf7f2e2dSJohn Marino   exec_continue (argv, argc);
298cf7f2e2dSJohn Marino   do_cleanups (old_chain);
2995796c8dcSSimon Schubert }
3005796c8dcSSimon Schubert 
3015796c8dcSSimon Schubert void
mi_cmd_exec_continue(char * command,char ** argv,int argc)3025796c8dcSSimon Schubert mi_cmd_exec_continue (char *command, char **argv, int argc)
3035796c8dcSSimon Schubert {
304cf7f2e2dSJohn Marino   if (argc > 0 && strcmp (argv[0], "--reverse") == 0)
305cf7f2e2dSJohn Marino     exec_reverse_continue (argv + 1, argc - 1);
3065796c8dcSSimon Schubert   else
307cf7f2e2dSJohn Marino     exec_continue (argv, argc);
3085796c8dcSSimon Schubert }
3095796c8dcSSimon Schubert 
3105796c8dcSSimon Schubert static int
interrupt_thread_callback(struct thread_info * thread,void * arg)3115796c8dcSSimon Schubert interrupt_thread_callback (struct thread_info *thread, void *arg)
3125796c8dcSSimon Schubert {
3135796c8dcSSimon Schubert   int pid = *(int *)arg;
3145796c8dcSSimon Schubert 
3155796c8dcSSimon Schubert   if (!is_running (thread->ptid))
3165796c8dcSSimon Schubert     return 0;
3175796c8dcSSimon Schubert 
3185796c8dcSSimon Schubert   if (PIDGET (thread->ptid) != pid)
3195796c8dcSSimon Schubert     return 0;
3205796c8dcSSimon Schubert 
3215796c8dcSSimon Schubert   target_stop (thread->ptid);
3225796c8dcSSimon Schubert   return 0;
3235796c8dcSSimon Schubert }
3245796c8dcSSimon Schubert 
3255796c8dcSSimon Schubert /* Interrupt the execution of the target.  Note how we must play
3265796c8dcSSimon Schubert    around with the token variables, in order to display the current
3275796c8dcSSimon Schubert    token in the result of the interrupt command, and the previous
3285796c8dcSSimon Schubert    execution token when the target finally stops.  See comments in
3295796c8dcSSimon Schubert    mi_cmd_execute.  */
3305796c8dcSSimon Schubert 
3315796c8dcSSimon Schubert void
mi_cmd_exec_interrupt(char * command,char ** argv,int argc)3325796c8dcSSimon Schubert mi_cmd_exec_interrupt (char *command, char **argv, int argc)
333cf7f2e2dSJohn Marino {
334cf7f2e2dSJohn Marino   /* In all-stop mode, everything stops, so we don't need to try
335cf7f2e2dSJohn Marino      anything specific.  */
3365796c8dcSSimon Schubert   if (!non_stop)
3375796c8dcSSimon Schubert     {
338cf7f2e2dSJohn Marino       interrupt_target_1 (0);
3395796c8dcSSimon Schubert       return;
3405796c8dcSSimon Schubert     }
341cf7f2e2dSJohn Marino 
342cf7f2e2dSJohn Marino   if (current_context->all)
343cf7f2e2dSJohn Marino     {
3445796c8dcSSimon Schubert       /* This will interrupt all threads in all inferiors.  */
3455796c8dcSSimon Schubert       interrupt_target_1 (1);
346cf7f2e2dSJohn Marino     }
3475796c8dcSSimon Schubert   else if (current_context->thread_group != -1)
348cf7f2e2dSJohn Marino     {
3495796c8dcSSimon Schubert       struct inferior *inf = find_inferior_id (current_context->thread_group);
350cf7f2e2dSJohn Marino 
3515796c8dcSSimon Schubert       iterate_over_threads (interrupt_thread_callback, &inf->pid);
3525796c8dcSSimon Schubert     }
353cf7f2e2dSJohn Marino   else
354cf7f2e2dSJohn Marino     {
355cf7f2e2dSJohn Marino       /* Interrupt just the current thread -- either explicitly
356cf7f2e2dSJohn Marino 	 specified via --thread or whatever was current before
357cf7f2e2dSJohn Marino 	 MI command was sent.  */
3585796c8dcSSimon Schubert       interrupt_target_1 (0);
359cf7f2e2dSJohn Marino     }
360cf7f2e2dSJohn Marino }
361cf7f2e2dSJohn Marino 
362cf7f2e2dSJohn Marino static int
run_one_inferior(struct inferior * inf,void * arg)363cf7f2e2dSJohn Marino run_one_inferior (struct inferior *inf, void *arg)
364*74a8b0f5SJohn Marino {
365cf7f2e2dSJohn Marino   if (inf->pid != 0)
366cf7f2e2dSJohn Marino     {
367cf7f2e2dSJohn Marino       if (inf->pid != ptid_get_pid (inferior_ptid))
368cf7f2e2dSJohn Marino 	{
369cf7f2e2dSJohn Marino 	  struct thread_info *tp;
370cf7f2e2dSJohn Marino 
371cf7f2e2dSJohn Marino 	  tp = any_thread_of_process (inf->pid);
372cf7f2e2dSJohn Marino 	  if (!tp)
373cf7f2e2dSJohn Marino 	    error (_("Inferior has no threads."));
374cf7f2e2dSJohn Marino 
375cf7f2e2dSJohn Marino 	  switch_to_thread (tp->ptid);
376cf7f2e2dSJohn Marino 	}
377cf7f2e2dSJohn Marino     }
378cf7f2e2dSJohn Marino   else
379cf7f2e2dSJohn Marino     {
380cf7f2e2dSJohn Marino       set_current_inferior (inf);
381cf7f2e2dSJohn Marino       switch_to_thread (null_ptid);
382cf7f2e2dSJohn Marino       set_current_program_space (inf->pspace);
383cf7f2e2dSJohn Marino     }
384cf7f2e2dSJohn Marino   mi_execute_cli_command ("run", target_can_async_p (),
385cf7f2e2dSJohn Marino 			  target_can_async_p () ? "&" : NULL);
386cf7f2e2dSJohn Marino   return 0;
387cf7f2e2dSJohn Marino }
388cf7f2e2dSJohn Marino 
389cf7f2e2dSJohn Marino void
mi_cmd_exec_run(char * command,char ** argv,int argc)390cf7f2e2dSJohn Marino mi_cmd_exec_run (char *command, char **argv, int argc)
391cf7f2e2dSJohn Marino {
392cf7f2e2dSJohn Marino   if (current_context->all)
393cf7f2e2dSJohn Marino     {
394cf7f2e2dSJohn Marino       struct cleanup *back_to = save_current_space_and_thread ();
395cf7f2e2dSJohn Marino 
396cf7f2e2dSJohn Marino       iterate_over_inferiors (run_one_inferior, NULL);
397cf7f2e2dSJohn Marino       do_cleanups (back_to);
398cf7f2e2dSJohn Marino     }
399cf7f2e2dSJohn Marino   else
400cf7f2e2dSJohn Marino     {
401cf7f2e2dSJohn Marino       mi_execute_cli_command ("run", target_can_async_p (),
402cf7f2e2dSJohn Marino 			      target_can_async_p () ? "&" : NULL);
403cf7f2e2dSJohn Marino     }
404cf7f2e2dSJohn Marino }
4055796c8dcSSimon Schubert 
4065796c8dcSSimon Schubert 
4075796c8dcSSimon Schubert static int
find_thread_of_process(struct thread_info * ti,void * p)4085796c8dcSSimon Schubert find_thread_of_process (struct thread_info *ti, void *p)
4095796c8dcSSimon Schubert {
410cf7f2e2dSJohn Marino   int pid = *(int *)p;
4115796c8dcSSimon Schubert 
4125796c8dcSSimon Schubert   if (PIDGET (ti->ptid) == pid && !is_exited (ti->ptid))
4135796c8dcSSimon Schubert     return 1;
4145796c8dcSSimon Schubert 
4155796c8dcSSimon Schubert   return 0;
4165796c8dcSSimon Schubert }
4175796c8dcSSimon Schubert 
4185796c8dcSSimon Schubert void
mi_cmd_target_detach(char * command,char ** argv,int argc)4195796c8dcSSimon Schubert mi_cmd_target_detach (char *command, char **argv, int argc)
4205796c8dcSSimon Schubert {
421c50c785cSJohn Marino   if (argc != 0 && argc != 1)
4225796c8dcSSimon Schubert     error (_("Usage: -target-detach [pid | thread-group]"));
4235796c8dcSSimon Schubert 
4245796c8dcSSimon Schubert   if (argc == 1)
4255796c8dcSSimon Schubert     {
4265796c8dcSSimon Schubert       struct thread_info *tp;
427c50c785cSJohn Marino       char *end = argv[0];
428c50c785cSJohn Marino       int pid;
429c50c785cSJohn Marino 
430c50c785cSJohn Marino       /* First see if we are dealing with a thread-group id.  */
431c50c785cSJohn Marino       if (*argv[0] == 'i')
432c50c785cSJohn Marino 	{
433c50c785cSJohn Marino 	  struct inferior *inf;
434cf7f2e2dSJohn Marino 	  int id = strtoul (argv[0] + 1, &end, 0);
4355796c8dcSSimon Schubert 
436c50c785cSJohn Marino 	  if (*end != '\0')
437c50c785cSJohn Marino 	    error (_("Invalid syntax of thread-group id '%s'"), argv[0]);
438c50c785cSJohn Marino 
439c50c785cSJohn Marino 	  inf = find_inferior_id (id);
440c50c785cSJohn Marino 	  if (!inf)
441c50c785cSJohn Marino 	    error (_("Non-existent thread-group id '%d'"), id);
442c50c785cSJohn Marino 
443c50c785cSJohn Marino 	  pid = inf->pid;
444c50c785cSJohn Marino 	}
445c50c785cSJohn Marino       else
446c50c785cSJohn Marino 	{
447c50c785cSJohn Marino 	  /* We must be dealing with a pid.  */
448c50c785cSJohn Marino 	  pid = strtol (argv[0], &end, 10);
449c50c785cSJohn Marino 
450c50c785cSJohn Marino 	  if (*end != '\0')
451c50c785cSJohn Marino 	    error (_("Invalid identifier '%s'"), argv[0]);
4525796c8dcSSimon Schubert 	}
4535796c8dcSSimon Schubert 
454c50c785cSJohn Marino       /* Pick any thread in the desired process.  Current
4555796c8dcSSimon Schubert 	 target_detach detaches from the parent of inferior_ptid.  */
4565796c8dcSSimon Schubert       tp = iterate_over_threads (find_thread_of_process, &pid);
4575796c8dcSSimon Schubert       if (!tp)
4585796c8dcSSimon Schubert 	error (_("Thread group is empty"));
4595796c8dcSSimon Schubert 
4605796c8dcSSimon Schubert       switch_to_thread (tp->ptid);
4615796c8dcSSimon Schubert     }
4625796c8dcSSimon Schubert 
4635796c8dcSSimon Schubert   detach_command (NULL, 0);
4645796c8dcSSimon Schubert }
4655796c8dcSSimon Schubert 
4665796c8dcSSimon Schubert void
mi_cmd_thread_select(char * command,char ** argv,int argc)4675796c8dcSSimon Schubert mi_cmd_thread_select (char *command, char **argv, int argc)
4685796c8dcSSimon Schubert {
4695796c8dcSSimon Schubert   enum gdb_rc rc;
4705796c8dcSSimon Schubert   char *mi_error_message;
4715796c8dcSSimon Schubert 
472c50c785cSJohn Marino   if (argc != 1)
4735796c8dcSSimon Schubert     error (_("-thread-select: USAGE: threadnum."));
474a45ae5f8SJohn Marino 
4755796c8dcSSimon Schubert   rc = gdb_thread_select (current_uiout, argv[0], &mi_error_message);
4765796c8dcSSimon Schubert 
4775796c8dcSSimon Schubert   if (rc == GDB_RC_FAIL)
4785796c8dcSSimon Schubert     {
4795796c8dcSSimon Schubert       make_cleanup (xfree, mi_error_message);
4805796c8dcSSimon Schubert       error ("%s", mi_error_message);
4815796c8dcSSimon Schubert     }
4825796c8dcSSimon Schubert }
4835796c8dcSSimon Schubert 
4845796c8dcSSimon Schubert void
mi_cmd_thread_list_ids(char * command,char ** argv,int argc)4855796c8dcSSimon Schubert mi_cmd_thread_list_ids (char *command, char **argv, int argc)
4865796c8dcSSimon Schubert {
4875796c8dcSSimon Schubert   enum gdb_rc rc;
4885796c8dcSSimon Schubert   char *mi_error_message;
4895796c8dcSSimon Schubert 
490c50c785cSJohn Marino   if (argc != 0)
4915796c8dcSSimon Schubert     error (_("-thread-list-ids: No arguments required."));
492a45ae5f8SJohn Marino 
4935796c8dcSSimon Schubert   rc = gdb_list_thread_ids (current_uiout, &mi_error_message);
4945796c8dcSSimon Schubert 
4955796c8dcSSimon Schubert   if (rc == GDB_RC_FAIL)
4965796c8dcSSimon Schubert     {
4975796c8dcSSimon Schubert       make_cleanup (xfree, mi_error_message);
4985796c8dcSSimon Schubert       error ("%s", mi_error_message);
4995796c8dcSSimon Schubert     }
5005796c8dcSSimon Schubert }
5015796c8dcSSimon Schubert 
5025796c8dcSSimon Schubert void
mi_cmd_thread_info(char * command,char ** argv,int argc)5035796c8dcSSimon Schubert mi_cmd_thread_info (char *command, char **argv, int argc)
5045796c8dcSSimon Schubert {
505c50c785cSJohn Marino   if (argc != 0 && argc != 1)
5065796c8dcSSimon Schubert     error (_("Invalid MI command"));
507a45ae5f8SJohn Marino 
5085796c8dcSSimon Schubert   print_thread_info (current_uiout, argv[0], -1);
5095796c8dcSSimon Schubert }
510cf7f2e2dSJohn Marino 
5115796c8dcSSimon Schubert DEF_VEC_I(int);
512cf7f2e2dSJohn Marino 
5135796c8dcSSimon Schubert struct collect_cores_data
514cf7f2e2dSJohn Marino {
515cf7f2e2dSJohn Marino   int pid;
5165796c8dcSSimon Schubert 
517cf7f2e2dSJohn Marino   VEC (int) *cores;
518cf7f2e2dSJohn Marino };
519cf7f2e2dSJohn Marino 
520cf7f2e2dSJohn Marino static int
collect_cores(struct thread_info * ti,void * xdata)521cf7f2e2dSJohn Marino collect_cores (struct thread_info *ti, void *xdata)
522cf7f2e2dSJohn Marino {
523cf7f2e2dSJohn Marino   struct collect_cores_data *data = xdata;
524cf7f2e2dSJohn Marino 
525cf7f2e2dSJohn Marino   if (ptid_get_pid (ti->ptid) == data->pid)
526cf7f2e2dSJohn Marino     {
527cf7f2e2dSJohn Marino       int core = target_core_of_thread (ti->ptid);
528cf7f2e2dSJohn Marino 
529cf7f2e2dSJohn Marino       if (core != -1)
5305796c8dcSSimon Schubert 	VEC_safe_push (int, data->cores, core);
5315796c8dcSSimon Schubert     }
5325796c8dcSSimon Schubert 
533cf7f2e2dSJohn Marino   return 0;
534cf7f2e2dSJohn Marino }
5355796c8dcSSimon Schubert 
536cf7f2e2dSJohn Marino static int *
unique(int * b,int * e)5375796c8dcSSimon Schubert unique (int *b, int *e)
538cf7f2e2dSJohn Marino {
539cf7f2e2dSJohn Marino   int *d = b;
540cf7f2e2dSJohn Marino 
541cf7f2e2dSJohn Marino   while (++b != e)
5425796c8dcSSimon Schubert     if (*d != *b)
5435796c8dcSSimon Schubert       *++d = *b;
544cf7f2e2dSJohn Marino   return ++d;
5455796c8dcSSimon Schubert }
546cf7f2e2dSJohn Marino 
547cf7f2e2dSJohn Marino struct print_one_inferior_data
548cf7f2e2dSJohn Marino {
549cf7f2e2dSJohn Marino   int recurse;
550cf7f2e2dSJohn Marino   VEC (int) *inferiors;
551cf7f2e2dSJohn Marino };
552cf7f2e2dSJohn Marino 
553cf7f2e2dSJohn Marino static int
print_one_inferior(struct inferior * inferior,void * xdata)554a45ae5f8SJohn Marino print_one_inferior (struct inferior *inferior, void *xdata)
555cf7f2e2dSJohn Marino {
556cf7f2e2dSJohn Marino   struct print_one_inferior_data *top_data = xdata;
557cf7f2e2dSJohn Marino   struct ui_out *uiout = current_uiout;
558cf7f2e2dSJohn Marino 
559cf7f2e2dSJohn Marino   if (VEC_empty (int, top_data->inferiors)
560cf7f2e2dSJohn Marino       || bsearch (&(inferior->pid), VEC_address (int, top_data->inferiors),
561cf7f2e2dSJohn Marino 		  VEC_length (int, top_data->inferiors), sizeof (int),
562cf7f2e2dSJohn Marino 		  compare_positive_ints))
563cf7f2e2dSJohn Marino     {
564cf7f2e2dSJohn Marino       struct collect_cores_data data;
565cf7f2e2dSJohn Marino       struct cleanup *back_to
566cf7f2e2dSJohn Marino 	= make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
567*74a8b0f5SJohn Marino 
568cf7f2e2dSJohn Marino       ui_out_field_fmt (uiout, "id", "i%d", inferior->num);
569cf7f2e2dSJohn Marino       ui_out_field_string (uiout, "type", "process");
570cf7f2e2dSJohn Marino       if (inferior->pid != 0)
571cf7f2e2dSJohn Marino 	ui_out_field_int (uiout, "pid", inferior->pid);
572cf7f2e2dSJohn Marino 
573cf7f2e2dSJohn Marino       if (inferior->pspace->pspace_exec_filename != NULL)
5745796c8dcSSimon Schubert 	{
575cf7f2e2dSJohn Marino 	  ui_out_field_string (uiout, "executable",
576cf7f2e2dSJohn Marino 			       inferior->pspace->pspace_exec_filename);
577*74a8b0f5SJohn Marino 	}
578cf7f2e2dSJohn Marino 
579cf7f2e2dSJohn Marino       data.cores = 0;
580cf7f2e2dSJohn Marino       if (inferior->pid != 0)
581cf7f2e2dSJohn Marino 	{
582cf7f2e2dSJohn Marino 	  data.pid = inferior->pid;
583cf7f2e2dSJohn Marino 	  iterate_over_threads (collect_cores, &data);
584cf7f2e2dSJohn Marino 	}
585cf7f2e2dSJohn Marino 
586cf7f2e2dSJohn Marino       if (!VEC_empty (int, data.cores))
587cf7f2e2dSJohn Marino 	{
588cf7f2e2dSJohn Marino 	  int *b, *e;
589cf7f2e2dSJohn Marino 	  struct cleanup *back_to_2 =
590cf7f2e2dSJohn Marino 	    make_cleanup_ui_out_list_begin_end (uiout, "cores");
591cf7f2e2dSJohn Marino 
592cf7f2e2dSJohn Marino 	  qsort (VEC_address (int, data.cores),
593cf7f2e2dSJohn Marino 		 VEC_length (int, data.cores), sizeof (int),
594cf7f2e2dSJohn Marino 		 compare_positive_ints);
595cf7f2e2dSJohn Marino 
596cf7f2e2dSJohn Marino 	  b = VEC_address (int, data.cores);
597cf7f2e2dSJohn Marino 	  e = b + VEC_length (int, data.cores);
598cf7f2e2dSJohn Marino 	  e = unique (b, e);
599cf7f2e2dSJohn Marino 
600cf7f2e2dSJohn Marino 	  for (; b != e; ++b)
601cf7f2e2dSJohn Marino 	    ui_out_field_int (uiout, NULL, *b);
602cf7f2e2dSJohn Marino 
603cf7f2e2dSJohn Marino 	  do_cleanups (back_to_2);
604c50c785cSJohn Marino 	}
605cf7f2e2dSJohn Marino 
606cf7f2e2dSJohn Marino       if (top_data->recurse)
607cf7f2e2dSJohn Marino 	print_thread_info (uiout, NULL, inferior->pid);
608cf7f2e2dSJohn Marino 
609cf7f2e2dSJohn Marino       do_cleanups (back_to);
610cf7f2e2dSJohn Marino     }
611cf7f2e2dSJohn Marino 
612cf7f2e2dSJohn Marino   return 0;
613cf7f2e2dSJohn Marino }
614cf7f2e2dSJohn Marino 
615cf7f2e2dSJohn Marino /* Output a field named 'cores' with a list as the value.  The
616cf7f2e2dSJohn Marino    elements of the list are obtained by splitting 'cores' on
617cf7f2e2dSJohn Marino    comma.  */
618cf7f2e2dSJohn Marino 
619cf7f2e2dSJohn Marino static void
output_cores(struct ui_out * uiout,const char * field_name,const char * xcores)620cf7f2e2dSJohn Marino output_cores (struct ui_out *uiout, const char *field_name, const char *xcores)
621cf7f2e2dSJohn Marino {
622cf7f2e2dSJohn Marino   struct cleanup *back_to = make_cleanup_ui_out_list_begin_end (uiout,
623cf7f2e2dSJohn Marino 								field_name);
624cf7f2e2dSJohn Marino   char *cores = xstrdup (xcores);
625cf7f2e2dSJohn Marino   char *p = cores;
626cf7f2e2dSJohn Marino 
627cf7f2e2dSJohn Marino   make_cleanup (xfree, cores);
628cf7f2e2dSJohn Marino 
629cf7f2e2dSJohn Marino   for (p = strtok (p, ","); p;  p = strtok (NULL, ","))
630cf7f2e2dSJohn Marino     ui_out_field_string (uiout, NULL, p);
631cf7f2e2dSJohn Marino 
632cf7f2e2dSJohn Marino   do_cleanups (back_to);
633cf7f2e2dSJohn Marino }
634cf7f2e2dSJohn Marino 
635cf7f2e2dSJohn Marino static void
free_vector_of_ints(void * xvector)636cf7f2e2dSJohn Marino free_vector_of_ints (void *xvector)
637cf7f2e2dSJohn Marino {
638cf7f2e2dSJohn Marino   VEC (int) **vector = xvector;
639cf7f2e2dSJohn Marino 
640cf7f2e2dSJohn Marino   VEC_free (int, *vector);
641cf7f2e2dSJohn Marino }
642cf7f2e2dSJohn Marino 
643cf7f2e2dSJohn Marino static void
do_nothing(splay_tree_key k)644cf7f2e2dSJohn Marino do_nothing (splay_tree_key k)
645cf7f2e2dSJohn Marino {
646cf7f2e2dSJohn Marino }
647cf7f2e2dSJohn Marino 
648cf7f2e2dSJohn Marino static void
free_vector_of_osdata_items(splay_tree_value xvalue)649cf7f2e2dSJohn Marino free_vector_of_osdata_items (splay_tree_value xvalue)
650cf7f2e2dSJohn Marino {
651cf7f2e2dSJohn Marino   VEC (osdata_item_s) *value = (VEC (osdata_item_s) *) xvalue;
652cf7f2e2dSJohn Marino 
653cf7f2e2dSJohn Marino   /* We don't free the items itself, it will be done separately.  */
654cf7f2e2dSJohn Marino   VEC_free (osdata_item_s, value);
655cf7f2e2dSJohn Marino }
656cf7f2e2dSJohn Marino 
657cf7f2e2dSJohn Marino static int
splay_tree_int_comparator(splay_tree_key xa,splay_tree_key xb)658cf7f2e2dSJohn Marino splay_tree_int_comparator (splay_tree_key xa, splay_tree_key xb)
659cf7f2e2dSJohn Marino {
660cf7f2e2dSJohn Marino   int a = xa;
661cf7f2e2dSJohn Marino   int b = xb;
662cf7f2e2dSJohn Marino 
663cf7f2e2dSJohn Marino   return a - b;
664cf7f2e2dSJohn Marino }
665cf7f2e2dSJohn Marino 
666cf7f2e2dSJohn Marino static void
free_splay_tree(void * xt)667cf7f2e2dSJohn Marino free_splay_tree (void *xt)
668cf7f2e2dSJohn Marino {
669cf7f2e2dSJohn Marino   splay_tree t = xt;
670cf7f2e2dSJohn Marino   splay_tree_delete (t);
6715796c8dcSSimon Schubert }
6725796c8dcSSimon Schubert 
6735796c8dcSSimon Schubert static void
list_available_thread_groups(VEC (int)* ids,int recurse)6745796c8dcSSimon Schubert list_available_thread_groups (VEC (int) *ids, int recurse)
675a45ae5f8SJohn Marino {
6765796c8dcSSimon Schubert   struct osdata *data;
677cf7f2e2dSJohn Marino   struct osdata_item *item;
678cf7f2e2dSJohn Marino   int ix_items;
679cf7f2e2dSJohn Marino   struct ui_out *uiout = current_uiout;
680cf7f2e2dSJohn Marino 
681cf7f2e2dSJohn Marino   /* This keeps a map from integer (pid) to VEC (struct osdata_item *)*
682cf7f2e2dSJohn Marino      The vector contains information about all threads for the given pid.
683cf7f2e2dSJohn Marino      This is assigned an initial value to avoid "may be used uninitialized"
6845796c8dcSSimon Schubert      warning from gcc.  */
6855796c8dcSSimon Schubert   splay_tree tree = NULL;
6865796c8dcSSimon Schubert 
687cf7f2e2dSJohn Marino   /* get_osdata will throw if it cannot return data.  */
688cf7f2e2dSJohn Marino   data = get_osdata ("processes");
689cf7f2e2dSJohn Marino   make_cleanup_osdata_free (data);
690cf7f2e2dSJohn Marino 
691cf7f2e2dSJohn Marino   if (recurse)
692cf7f2e2dSJohn Marino     {
693cf7f2e2dSJohn Marino       struct osdata *threads = get_osdata ("threads");
694cf7f2e2dSJohn Marino 
695cf7f2e2dSJohn Marino       make_cleanup_osdata_free (threads);
696cf7f2e2dSJohn Marino       tree = splay_tree_new (splay_tree_int_comparator,
697cf7f2e2dSJohn Marino 			     do_nothing,
698cf7f2e2dSJohn Marino 			     free_vector_of_osdata_items);
699cf7f2e2dSJohn Marino       make_cleanup (free_splay_tree, tree);
700cf7f2e2dSJohn Marino 
701cf7f2e2dSJohn Marino       for (ix_items = 0;
702cf7f2e2dSJohn Marino 	   VEC_iterate (osdata_item_s, threads->items,
703cf7f2e2dSJohn Marino 			ix_items, item);
704cf7f2e2dSJohn Marino 	   ix_items++)
705cf7f2e2dSJohn Marino 	{
706cf7f2e2dSJohn Marino 	  const char *pid = get_osdata_column (item, "pid");
707cf7f2e2dSJohn Marino 	  int pid_i = strtoul (pid, NULL, 0);
708cf7f2e2dSJohn Marino 	  VEC (osdata_item_s) *vec = 0;
709cf7f2e2dSJohn Marino 
710cf7f2e2dSJohn Marino 	  splay_tree_node n = splay_tree_lookup (tree, pid_i);
711cf7f2e2dSJohn Marino 	  if (!n)
712cf7f2e2dSJohn Marino 	    {
713cf7f2e2dSJohn Marino 	      VEC_safe_push (osdata_item_s, vec, item);
714cf7f2e2dSJohn Marino 	      splay_tree_insert (tree, pid_i, (splay_tree_value)vec);
715cf7f2e2dSJohn Marino 	    }
716cf7f2e2dSJohn Marino 	  else
717cf7f2e2dSJohn Marino 	    {
718cf7f2e2dSJohn Marino 	      vec = (VEC (osdata_item_s) *) n->value;
719cf7f2e2dSJohn Marino 	      VEC_safe_push (osdata_item_s, vec, item);
720cf7f2e2dSJohn Marino 	      n->value = (splay_tree_value) vec;
7215796c8dcSSimon Schubert 	    }
7225796c8dcSSimon Schubert 	}
7235796c8dcSSimon Schubert     }
7245796c8dcSSimon Schubert 
7255796c8dcSSimon Schubert   make_cleanup_ui_out_list_begin_end (uiout, "groups");
7265796c8dcSSimon Schubert 
7275796c8dcSSimon Schubert   for (ix_items = 0;
728cf7f2e2dSJohn Marino        VEC_iterate (osdata_item_s, data->items,
7295796c8dcSSimon Schubert 		    ix_items, item);
7305796c8dcSSimon Schubert        ix_items++)
7315796c8dcSSimon Schubert     {
7325796c8dcSSimon Schubert       struct cleanup *back_to;
733cf7f2e2dSJohn Marino 
734cf7f2e2dSJohn Marino       const char *pid = get_osdata_column (item, "pid");
735cf7f2e2dSJohn Marino       const char *cmd = get_osdata_column (item, "command");
736cf7f2e2dSJohn Marino       const char *user = get_osdata_column (item, "user");
737cf7f2e2dSJohn Marino       const char *cores = get_osdata_column (item, "cores");
738cf7f2e2dSJohn Marino 
739cf7f2e2dSJohn Marino       int pid_i = strtoul (pid, NULL, 0);
740cf7f2e2dSJohn Marino 
741cf7f2e2dSJohn Marino       /* At present, the target will return all available processes
742cf7f2e2dSJohn Marino 	 and if information about specific ones was required, we filter
743cf7f2e2dSJohn Marino 	 undesired processes here.  */
744cf7f2e2dSJohn Marino       if (ids && bsearch (&pid_i, VEC_address (int, ids),
745cf7f2e2dSJohn Marino 			  VEC_length (int, ids),
746cf7f2e2dSJohn Marino 			  sizeof (int), compare_positive_ints) == NULL)
7475796c8dcSSimon Schubert 	continue;
7485796c8dcSSimon Schubert 
7495796c8dcSSimon Schubert 
7505796c8dcSSimon Schubert       back_to = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
7515796c8dcSSimon Schubert 
7525796c8dcSSimon Schubert       ui_out_field_fmt (uiout, "id", "%s", pid);
7535796c8dcSSimon Schubert       ui_out_field_string (uiout, "type", "process");
754cf7f2e2dSJohn Marino       if (cmd)
755cf7f2e2dSJohn Marino 	ui_out_field_string (uiout, "description", cmd);
756cf7f2e2dSJohn Marino       if (user)
757cf7f2e2dSJohn Marino 	ui_out_field_string (uiout, "user", user);
758cf7f2e2dSJohn Marino       if (cores)
759cf7f2e2dSJohn Marino 	output_cores (uiout, "cores", cores);
760cf7f2e2dSJohn Marino 
761cf7f2e2dSJohn Marino       if (recurse)
762cf7f2e2dSJohn Marino 	{
763cf7f2e2dSJohn Marino 	  splay_tree_node n = splay_tree_lookup (tree, pid_i);
764cf7f2e2dSJohn Marino 	  if (n)
765cf7f2e2dSJohn Marino 	    {
766cf7f2e2dSJohn Marino 	      VEC (osdata_item_s) *children = (VEC (osdata_item_s) *) n->value;
767cf7f2e2dSJohn Marino 	      struct osdata_item *child;
768cf7f2e2dSJohn Marino 	      int ix_child;
769cf7f2e2dSJohn Marino 
770cf7f2e2dSJohn Marino 	      make_cleanup_ui_out_list_begin_end (uiout, "threads");
771cf7f2e2dSJohn Marino 
772cf7f2e2dSJohn Marino 	      for (ix_child = 0;
773cf7f2e2dSJohn Marino 		   VEC_iterate (osdata_item_s, children, ix_child, child);
774cf7f2e2dSJohn Marino 		   ++ix_child)
775cf7f2e2dSJohn Marino 		{
776cf7f2e2dSJohn Marino 		  struct cleanup *back_to_2 =
777cf7f2e2dSJohn Marino 		    make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
778cf7f2e2dSJohn Marino 		  const char *tid = get_osdata_column (child, "tid");
779cf7f2e2dSJohn Marino 		  const char *tcore = get_osdata_column (child, "core");
780cf7f2e2dSJohn Marino 
781cf7f2e2dSJohn Marino 		  ui_out_field_string (uiout, "id", tid);
782cf7f2e2dSJohn Marino 		  if (tcore)
783cf7f2e2dSJohn Marino 		    ui_out_field_string (uiout, "core", tcore);
784cf7f2e2dSJohn Marino 
7855796c8dcSSimon Schubert 		  do_cleanups (back_to_2);
7865796c8dcSSimon Schubert 		}
7875796c8dcSSimon Schubert 	    }
7885796c8dcSSimon Schubert 	}
789cf7f2e2dSJohn Marino 
790cf7f2e2dSJohn Marino       do_cleanups (back_to);
791cf7f2e2dSJohn Marino     }
7925796c8dcSSimon Schubert }
793a45ae5f8SJohn Marino 
794cf7f2e2dSJohn Marino void
mi_cmd_list_thread_groups(char * command,char ** argv,int argc)795cf7f2e2dSJohn Marino mi_cmd_list_thread_groups (char *command, char **argv, int argc)
796cf7f2e2dSJohn Marino {
797cf7f2e2dSJohn Marino   struct ui_out *uiout = current_uiout;
798cf7f2e2dSJohn Marino   struct cleanup *back_to;
799cf7f2e2dSJohn Marino   int available = 0;
800cf7f2e2dSJohn Marino   int recurse = 0;
801cf7f2e2dSJohn Marino   VEC (int) *ids = 0;
802cf7f2e2dSJohn Marino 
803a45ae5f8SJohn Marino   enum opt
804cf7f2e2dSJohn Marino   {
805cf7f2e2dSJohn Marino     AVAILABLE_OPT, RECURSE_OPT
806cf7f2e2dSJohn Marino   };
807cf7f2e2dSJohn Marino   static const struct mi_opt opts[] =
808cf7f2e2dSJohn Marino     {
809cf7f2e2dSJohn Marino       {"-available", AVAILABLE_OPT, 0},
810cf7f2e2dSJohn Marino       {"-recurse", RECURSE_OPT, 1},
811cf7f2e2dSJohn Marino       { 0, 0, 0 }
812cf7f2e2dSJohn Marino     };
813cf7f2e2dSJohn Marino 
814cf7f2e2dSJohn Marino   int oind = 0;
815cf7f2e2dSJohn Marino   char *oarg;
816cf7f2e2dSJohn Marino 
817cf7f2e2dSJohn Marino   while (1)
818cf7f2e2dSJohn Marino     {
819cf7f2e2dSJohn Marino       int opt = mi_getopt ("-list-thread-groups", argc, argv, opts,
820cf7f2e2dSJohn Marino 			   &oind, &oarg);
821cf7f2e2dSJohn Marino 
822cf7f2e2dSJohn Marino       if (opt < 0)
823cf7f2e2dSJohn Marino 	break;
824cf7f2e2dSJohn Marino       switch ((enum opt) opt)
825cf7f2e2dSJohn Marino 	{
826cf7f2e2dSJohn Marino 	case AVAILABLE_OPT:
827cf7f2e2dSJohn Marino 	  available = 1;
828cf7f2e2dSJohn Marino 	  break;
829cf7f2e2dSJohn Marino 	case RECURSE_OPT:
830cf7f2e2dSJohn Marino 	  if (strcmp (oarg, "0") == 0)
831c50c785cSJohn Marino 	    ;
832c50c785cSJohn Marino 	  else if (strcmp (oarg, "1") == 0)
833cf7f2e2dSJohn Marino 	    recurse = 1;
834cf7f2e2dSJohn Marino 	  else
835cf7f2e2dSJohn Marino 	    error (_("only '0' and '1' are valid values "
836cf7f2e2dSJohn Marino 		     "for the '--recurse' option"));
837cf7f2e2dSJohn Marino 	  break;
838cf7f2e2dSJohn Marino 	}
839cf7f2e2dSJohn Marino     }
840cf7f2e2dSJohn Marino 
841cf7f2e2dSJohn Marino   for (; oind < argc; ++oind)
842cf7f2e2dSJohn Marino     {
843c50c785cSJohn Marino       char *end;
844cf7f2e2dSJohn Marino       int inf;
845cf7f2e2dSJohn Marino 
846cf7f2e2dSJohn Marino       if (*(argv[oind]) != 'i')
847cf7f2e2dSJohn Marino 	error (_("invalid syntax of group id '%s'"), argv[oind]);
848c50c785cSJohn Marino 
849cf7f2e2dSJohn Marino       inf = strtoul (argv[oind] + 1, &end, 0);
850cf7f2e2dSJohn Marino 
851cf7f2e2dSJohn Marino       if (*end != '\0')
852cf7f2e2dSJohn Marino 	error (_("invalid syntax of group id '%s'"), argv[oind]);
853cf7f2e2dSJohn Marino       VEC_safe_push (int, ids, inf);
854cf7f2e2dSJohn Marino     }
855cf7f2e2dSJohn Marino   if (VEC_length (int, ids) > 1)
856cf7f2e2dSJohn Marino     qsort (VEC_address (int, ids),
857cf7f2e2dSJohn Marino 	   VEC_length (int, ids),
858cf7f2e2dSJohn Marino 	   sizeof (int), compare_positive_ints);
859cf7f2e2dSJohn Marino 
860cf7f2e2dSJohn Marino   back_to = make_cleanup (free_vector_of_ints, &ids);
861cf7f2e2dSJohn Marino 
862cf7f2e2dSJohn Marino   if (available)
863cf7f2e2dSJohn Marino     {
864cf7f2e2dSJohn Marino       list_available_thread_groups (ids, recurse);
865cf7f2e2dSJohn Marino     }
866cf7f2e2dSJohn Marino   else if (VEC_length (int, ids) == 1)
867cf7f2e2dSJohn Marino     {
868cf7f2e2dSJohn Marino       /* Local thread groups, single id.  */
869c50c785cSJohn Marino       int id = *VEC_address (int, ids);
870cf7f2e2dSJohn Marino       struct inferior *inf = find_inferior_id (id);
871c50c785cSJohn Marino 
8725796c8dcSSimon Schubert       if (!inf)
8735796c8dcSSimon Schubert 	error (_("Non-existent thread group id '%d'"), id);
8745796c8dcSSimon Schubert 
875cf7f2e2dSJohn Marino       print_thread_info (uiout, NULL, inf->pid);
876cf7f2e2dSJohn Marino     }
877cf7f2e2dSJohn Marino   else
878cf7f2e2dSJohn Marino     {
879cf7f2e2dSJohn Marino       struct print_one_inferior_data data;
880cf7f2e2dSJohn Marino 
881cf7f2e2dSJohn Marino       data.recurse = recurse;
882cf7f2e2dSJohn Marino       data.inferiors = ids;
883cf7f2e2dSJohn Marino 
8845796c8dcSSimon Schubert       /* Local thread groups.  Either no explicit ids -- and we
885cf7f2e2dSJohn Marino 	 print everything, or several explicit ids.  In both cases,
886cf7f2e2dSJohn Marino 	 we print more than one group, and have to use 'groups'
8875796c8dcSSimon Schubert 	 as the top-level element.  */
8885796c8dcSSimon Schubert       make_cleanup_ui_out_list_begin_end (uiout, "groups");
8895796c8dcSSimon Schubert       update_thread_list ();
8905796c8dcSSimon Schubert       iterate_over_inferiors (print_one_inferior, &data);
8915796c8dcSSimon Schubert     }
8925796c8dcSSimon Schubert 
8935796c8dcSSimon Schubert   do_cleanups (back_to);
8945796c8dcSSimon Schubert }
8955796c8dcSSimon Schubert 
896a45ae5f8SJohn Marino void
mi_cmd_data_list_register_names(char * command,char ** argv,int argc)8975796c8dcSSimon Schubert mi_cmd_data_list_register_names (char *command, char **argv, int argc)
8985796c8dcSSimon Schubert {
8995796c8dcSSimon Schubert   struct gdbarch *gdbarch;
9005796c8dcSSimon Schubert   struct ui_out *uiout = current_uiout;
9015796c8dcSSimon Schubert   int regnum, numregs;
9025796c8dcSSimon Schubert   int i;
9035796c8dcSSimon Schubert   struct cleanup *cleanup;
9045796c8dcSSimon Schubert 
9055796c8dcSSimon Schubert   /* Note that the test for a valid register must include checking the
9065796c8dcSSimon Schubert      gdbarch_register_name because gdbarch_num_regs may be allocated
907cf7f2e2dSJohn Marino      for the union of the register sets within a family of related
9085796c8dcSSimon Schubert      processors.  In this case, some entries of gdbarch_register_name
9095796c8dcSSimon Schubert      will change depending upon the particular processor being
9105796c8dcSSimon Schubert      debugged.  */
9115796c8dcSSimon Schubert 
9125796c8dcSSimon Schubert   gdbarch = get_current_arch ();
9135796c8dcSSimon Schubert   numregs = gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch);
9145796c8dcSSimon Schubert 
9155796c8dcSSimon Schubert   cleanup = make_cleanup_ui_out_list_begin_end (uiout, "register-names");
9165796c8dcSSimon Schubert 
9175796c8dcSSimon Schubert   if (argc == 0)		/* No args, just do all the regs.  */
9185796c8dcSSimon Schubert     {
9195796c8dcSSimon Schubert       for (regnum = 0;
9205796c8dcSSimon Schubert 	   regnum < numregs;
9215796c8dcSSimon Schubert 	   regnum++)
9225796c8dcSSimon Schubert 	{
9235796c8dcSSimon Schubert 	  if (gdbarch_register_name (gdbarch, regnum) == NULL
9245796c8dcSSimon Schubert 	      || *(gdbarch_register_name (gdbarch, regnum)) == '\0')
9255796c8dcSSimon Schubert 	    ui_out_field_string (uiout, NULL, "");
9265796c8dcSSimon Schubert 	  else
9275796c8dcSSimon Schubert 	    ui_out_field_string (uiout, NULL,
9285796c8dcSSimon Schubert 				 gdbarch_register_name (gdbarch, regnum));
9295796c8dcSSimon Schubert 	}
9305796c8dcSSimon Schubert     }
9315796c8dcSSimon Schubert 
932c50c785cSJohn Marino   /* Else, list of register #s, just do listed regs.  */
9335796c8dcSSimon Schubert   for (i = 0; i < argc; i++)
9345796c8dcSSimon Schubert     {
9355796c8dcSSimon Schubert       regnum = atoi (argv[i]);
9365796c8dcSSimon Schubert       if (regnum < 0 || regnum >= numregs)
9375796c8dcSSimon Schubert 	error (_("bad register number"));
9385796c8dcSSimon Schubert 
9395796c8dcSSimon Schubert       if (gdbarch_register_name (gdbarch, regnum) == NULL
9405796c8dcSSimon Schubert 	  || *(gdbarch_register_name (gdbarch, regnum)) == '\0')
9415796c8dcSSimon Schubert 	ui_out_field_string (uiout, NULL, "");
9425796c8dcSSimon Schubert       else
9435796c8dcSSimon Schubert 	ui_out_field_string (uiout, NULL,
9445796c8dcSSimon Schubert 			     gdbarch_register_name (gdbarch, regnum));
9455796c8dcSSimon Schubert     }
9465796c8dcSSimon Schubert   do_cleanups (cleanup);
9475796c8dcSSimon Schubert }
948a45ae5f8SJohn Marino 
9495796c8dcSSimon Schubert void
mi_cmd_data_list_changed_registers(char * command,char ** argv,int argc)9505796c8dcSSimon Schubert mi_cmd_data_list_changed_registers (char *command, char **argv, int argc)
9515796c8dcSSimon Schubert {
9525796c8dcSSimon Schubert   static struct regcache *this_regs = NULL;
9535796c8dcSSimon Schubert   struct ui_out *uiout = current_uiout;
9545796c8dcSSimon Schubert   struct regcache *prev_regs;
9555796c8dcSSimon Schubert   struct gdbarch *gdbarch;
9565796c8dcSSimon Schubert   int regnum, numregs, changed;
9575796c8dcSSimon Schubert   int i;
9585796c8dcSSimon Schubert   struct cleanup *cleanup;
9595796c8dcSSimon Schubert 
9605796c8dcSSimon Schubert   /* The last time we visited this function, the current frame's
9615796c8dcSSimon Schubert      register contents were saved in THIS_REGS.  Move THIS_REGS over
9625796c8dcSSimon Schubert      to PREV_REGS, and refresh THIS_REGS with the now-current register
9635796c8dcSSimon Schubert      contents.  */
9645796c8dcSSimon Schubert 
9655796c8dcSSimon Schubert   prev_regs = this_regs;
9665796c8dcSSimon Schubert   this_regs = frame_save_as_regcache (get_selected_frame (NULL));
9675796c8dcSSimon Schubert   cleanup = make_cleanup_regcache_xfree (prev_regs);
9685796c8dcSSimon Schubert 
9695796c8dcSSimon Schubert   /* Note that the test for a valid register must include checking the
9705796c8dcSSimon Schubert      gdbarch_register_name because gdbarch_num_regs may be allocated
9715796c8dcSSimon Schubert      for the union of the register sets within a family of related
9725796c8dcSSimon Schubert      processors.  In this case, some entries of gdbarch_register_name
9735796c8dcSSimon Schubert      will change depending upon the particular processor being
9745796c8dcSSimon Schubert      debugged.  */
9755796c8dcSSimon Schubert 
9765796c8dcSSimon Schubert   gdbarch = get_regcache_arch (this_regs);
9775796c8dcSSimon Schubert   numregs = gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch);
9785796c8dcSSimon Schubert 
9795796c8dcSSimon Schubert   make_cleanup_ui_out_list_begin_end (uiout, "changed-registers");
9805796c8dcSSimon Schubert 
9815796c8dcSSimon Schubert   if (argc == 0)
9825796c8dcSSimon Schubert     {
9835796c8dcSSimon Schubert       /* No args, just do all the regs.  */
9845796c8dcSSimon Schubert       for (regnum = 0;
985c50c785cSJohn Marino 	   regnum < numregs;
986c50c785cSJohn Marino 	   regnum++)
9875796c8dcSSimon Schubert 	{
9885796c8dcSSimon Schubert 	  if (gdbarch_register_name (gdbarch, regnum) == NULL
9895796c8dcSSimon Schubert 	      || *(gdbarch_register_name (gdbarch, regnum)) == '\0')
9905796c8dcSSimon Schubert 	    continue;
9915796c8dcSSimon Schubert 	  changed = register_changed_p (regnum, prev_regs, this_regs);
9925796c8dcSSimon Schubert 	  if (changed < 0)
9935796c8dcSSimon Schubert 	    error (_("-data-list-changed-registers: "
9945796c8dcSSimon Schubert 		     "Unable to read register contents."));
9955796c8dcSSimon Schubert 	  else if (changed)
9965796c8dcSSimon Schubert 	    ui_out_field_int (uiout, NULL, regnum);
9975796c8dcSSimon Schubert 	}
9985796c8dcSSimon Schubert     }
9995796c8dcSSimon Schubert 
10005796c8dcSSimon Schubert   /* Else, list of register #s, just do listed regs.  */
10015796c8dcSSimon Schubert   for (i = 0; i < argc; i++)
10025796c8dcSSimon Schubert     {
10035796c8dcSSimon Schubert       regnum = atoi (argv[i]);
1004c50c785cSJohn Marino 
1005c50c785cSJohn Marino       if (regnum >= 0
10065796c8dcSSimon Schubert 	  && regnum < numregs
10075796c8dcSSimon Schubert 	  && gdbarch_register_name (gdbarch, regnum) != NULL
10085796c8dcSSimon Schubert 	  && *gdbarch_register_name (gdbarch, regnum) != '\000')
10095796c8dcSSimon Schubert 	{
1010c50c785cSJohn Marino 	  changed = register_changed_p (regnum, prev_regs, this_regs);
10115796c8dcSSimon Schubert 	  if (changed < 0)
10125796c8dcSSimon Schubert 	    error (_("-data-list-changed-registers: "
10135796c8dcSSimon Schubert 		     "Unable to read register contents."));
10145796c8dcSSimon Schubert 	  else if (changed)
10155796c8dcSSimon Schubert 	    ui_out_field_int (uiout, NULL, regnum);
10165796c8dcSSimon Schubert 	}
10175796c8dcSSimon Schubert       else
10185796c8dcSSimon Schubert 	error (_("bad register number"));
10195796c8dcSSimon Schubert     }
10205796c8dcSSimon Schubert   do_cleanups (cleanup);
10215796c8dcSSimon Schubert }
1022c50c785cSJohn Marino 
1023c50c785cSJohn Marino static int
register_changed_p(int regnum,struct regcache * prev_regs,struct regcache * this_regs)10245796c8dcSSimon Schubert register_changed_p (int regnum, struct regcache *prev_regs,
1025c50c785cSJohn Marino 		    struct regcache *this_regs)
1026c50c785cSJohn Marino {
1027c50c785cSJohn Marino   struct gdbarch *gdbarch = get_regcache_arch (this_regs);
10285796c8dcSSimon Schubert   gdb_byte prev_buffer[MAX_REGISTER_SIZE];
10295796c8dcSSimon Schubert   gdb_byte this_buffer[MAX_REGISTER_SIZE];
10305796c8dcSSimon Schubert   enum register_status prev_status;
1031c50c785cSJohn Marino   enum register_status this_status;
1032c50c785cSJohn Marino 
10335796c8dcSSimon Schubert   /* First time through or after gdbarch change consider all registers
1034c50c785cSJohn Marino      as changed.  */
1035c50c785cSJohn Marino   if (!prev_regs || get_regcache_arch (prev_regs) != gdbarch)
1036c50c785cSJohn Marino     return 1;
10375796c8dcSSimon Schubert 
10385796c8dcSSimon Schubert   /* Get register contents and compare.  */
1039c50c785cSJohn Marino   prev_status = regcache_cooked_read (prev_regs, regnum, prev_buffer);
1040c50c785cSJohn Marino   this_status = regcache_cooked_read (this_regs, regnum, this_buffer);
10415796c8dcSSimon Schubert 
10425796c8dcSSimon Schubert   if (this_status != prev_status)
10435796c8dcSSimon Schubert     return 1;
10445796c8dcSSimon Schubert   else if (this_status == REG_VALID)
10455796c8dcSSimon Schubert     return memcmp (prev_buffer, this_buffer,
10465796c8dcSSimon Schubert 		   register_size (gdbarch, regnum)) != 0;
10475796c8dcSSimon Schubert   else
10485796c8dcSSimon Schubert     return 0;
10495796c8dcSSimon Schubert }
10505796c8dcSSimon Schubert 
10515796c8dcSSimon Schubert /* Return a list of register number and value pairs.  The valid
10525796c8dcSSimon Schubert    arguments expected are: a letter indicating the format in which to
1053a45ae5f8SJohn Marino    display the registers contents.  This can be one of: x
10545796c8dcSSimon Schubert    (hexadecimal), d (decimal), N (natural), t (binary), o (octal), r
10555796c8dcSSimon Schubert    (raw).  After the format argument there can be a sequence of
10565796c8dcSSimon Schubert    numbers, indicating which registers to fetch the content of.  If
10575796c8dcSSimon Schubert    the format is the only argument, a list of all the registers with
10585796c8dcSSimon Schubert    their values is returned.  */
10595796c8dcSSimon Schubert 
10605796c8dcSSimon Schubert void
mi_cmd_data_list_register_values(char * command,char ** argv,int argc)10615796c8dcSSimon Schubert mi_cmd_data_list_register_values (char *command, char **argv, int argc)
10625796c8dcSSimon Schubert {
10635796c8dcSSimon Schubert   struct ui_out *uiout = current_uiout;
10645796c8dcSSimon Schubert   struct frame_info *frame;
10655796c8dcSSimon Schubert   struct gdbarch *gdbarch;
10665796c8dcSSimon Schubert   int regnum, numregs, format;
1067c50c785cSJohn Marino   int i;
1068c50c785cSJohn Marino   struct cleanup *list_cleanup, *tuple_cleanup;
10695796c8dcSSimon Schubert 
10705796c8dcSSimon Schubert   /* Note that the test for a valid register must include checking the
10715796c8dcSSimon Schubert      gdbarch_register_name because gdbarch_num_regs may be allocated
10725796c8dcSSimon Schubert      for the union of the register sets within a family of related
10735796c8dcSSimon Schubert      processors.  In this case, some entries of gdbarch_register_name
10745796c8dcSSimon Schubert      will change depending upon the particular processor being
10755796c8dcSSimon Schubert      debugged.  */
10765796c8dcSSimon Schubert 
10775796c8dcSSimon Schubert   if (argc == 0)
10785796c8dcSSimon Schubert     error (_("-data-list-register-values: Usage: "
10795796c8dcSSimon Schubert 	     "-data-list-register-values <format> [<regnum1>...<regnumN>]"));
10805796c8dcSSimon Schubert 
10815796c8dcSSimon Schubert   format = (int) argv[0][0];
10825796c8dcSSimon Schubert 
10835796c8dcSSimon Schubert   frame = get_selected_frame (NULL);
10845796c8dcSSimon Schubert   gdbarch = get_frame_arch (frame);
10855796c8dcSSimon Schubert   numregs = gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch);
10865796c8dcSSimon Schubert 
10875796c8dcSSimon Schubert   list_cleanup = make_cleanup_ui_out_list_begin_end (uiout, "register-values");
10885796c8dcSSimon Schubert 
10895796c8dcSSimon Schubert   if (argc == 1)
10905796c8dcSSimon Schubert     {
10915796c8dcSSimon Schubert       /* No args, beside the format: do all the regs.  */
10925796c8dcSSimon Schubert       for (regnum = 0;
10935796c8dcSSimon Schubert 	   regnum < numregs;
10945796c8dcSSimon Schubert 	   regnum++)
10955796c8dcSSimon Schubert 	{
10965796c8dcSSimon Schubert 	  if (gdbarch_register_name (gdbarch, regnum) == NULL
10975796c8dcSSimon Schubert 	      || *(gdbarch_register_name (gdbarch, regnum)) == '\0')
10985796c8dcSSimon Schubert 	    continue;
10995796c8dcSSimon Schubert 	  tuple_cleanup = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
11005796c8dcSSimon Schubert 	  ui_out_field_int (uiout, "number", regnum);
11015796c8dcSSimon Schubert 	  get_register (frame, regnum, format);
11025796c8dcSSimon Schubert 	  do_cleanups (tuple_cleanup);
11035796c8dcSSimon Schubert 	}
11045796c8dcSSimon Schubert     }
11055796c8dcSSimon Schubert 
11065796c8dcSSimon Schubert   /* Else, list of register #s, just do listed regs.  */
11075796c8dcSSimon Schubert   for (i = 1; i < argc; i++)
11085796c8dcSSimon Schubert     {
11095796c8dcSSimon Schubert       regnum = atoi (argv[i]);
1110c50c785cSJohn Marino 
11115796c8dcSSimon Schubert       if (regnum >= 0
11125796c8dcSSimon Schubert 	  && regnum < numregs
11135796c8dcSSimon Schubert 	  && gdbarch_register_name (gdbarch, regnum) != NULL
11145796c8dcSSimon Schubert 	  && *gdbarch_register_name (gdbarch, regnum) != '\000')
11155796c8dcSSimon Schubert 	{
11165796c8dcSSimon Schubert 	  tuple_cleanup = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
11175796c8dcSSimon Schubert 	  ui_out_field_int (uiout, "number", regnum);
11185796c8dcSSimon Schubert 	  get_register (frame, regnum, format);
11195796c8dcSSimon Schubert 	  do_cleanups (tuple_cleanup);
1120a45ae5f8SJohn Marino 	}
11215796c8dcSSimon Schubert       else
11225796c8dcSSimon Schubert 	error (_("bad register number"));
1123a45ae5f8SJohn Marino     }
1124c50c785cSJohn Marino   do_cleanups (list_cleanup);
11255796c8dcSSimon Schubert }
11265796c8dcSSimon Schubert 
11275796c8dcSSimon Schubert /* Output one register's contents in the desired format.  */
11285796c8dcSSimon Schubert 
11295796c8dcSSimon Schubert static void
get_register(struct frame_info * frame,int regnum,int format)11305796c8dcSSimon Schubert get_register (struct frame_info *frame, int regnum, int format)
1131c50c785cSJohn Marino {
11325796c8dcSSimon Schubert   struct gdbarch *gdbarch = get_frame_arch (frame);
1133c50c785cSJohn Marino   struct ui_out *uiout = current_uiout;
1134c50c785cSJohn Marino   struct value *val;
11355796c8dcSSimon Schubert 
11365796c8dcSSimon Schubert   if (format == 'N')
11375796c8dcSSimon Schubert     format = 0;
11385796c8dcSSimon Schubert 
11395796c8dcSSimon Schubert   val = get_frame_register_value (frame, regnum);
1140c50c785cSJohn Marino 
11415796c8dcSSimon Schubert   if (value_optimized_out (val))
11425796c8dcSSimon Schubert     error (_("Optimized out"));
11435796c8dcSSimon Schubert 
11445796c8dcSSimon Schubert   if (format == 'r')
11455796c8dcSSimon Schubert     {
11465796c8dcSSimon Schubert       int j;
11475796c8dcSSimon Schubert       char *ptr, buf[1024];
1148cf7f2e2dSJohn Marino       const gdb_byte *valaddr = value_contents_for_printing (val);
1149c50c785cSJohn Marino 
11505796c8dcSSimon Schubert       strcpy (buf, "0x");
11515796c8dcSSimon Schubert       ptr = buf + 2;
11525796c8dcSSimon Schubert       for (j = 0; j < register_size (gdbarch, regnum); j++)
11535796c8dcSSimon Schubert 	{
11545796c8dcSSimon Schubert 	  int idx = gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG ?
11555796c8dcSSimon Schubert 		    j : register_size (gdbarch, regnum) - 1 - j;
11565796c8dcSSimon Schubert 
11575796c8dcSSimon Schubert 	  sprintf (ptr, "%02x", (unsigned char) valaddr[idx]);
1158cf7f2e2dSJohn Marino 	  ptr += 2;
11595796c8dcSSimon Schubert 	}
11605796c8dcSSimon Schubert       ui_out_field_string (uiout, "value", buf);
1161c50c785cSJohn Marino     }
1162c50c785cSJohn Marino   else
1163c50c785cSJohn Marino     {
1164c50c785cSJohn Marino       struct value_print_options opts;
11655796c8dcSSimon Schubert       struct ui_file *stb;
11665796c8dcSSimon Schubert       struct cleanup *old_chain;
11675796c8dcSSimon Schubert 
11685796c8dcSSimon Schubert       stb = mem_fileopen ();
11695796c8dcSSimon Schubert       old_chain = make_cleanup_ui_file_delete (stb);
11705796c8dcSSimon Schubert 
11715796c8dcSSimon Schubert       get_formatted_print_options (&opts, format);
1172c50c785cSJohn Marino       opts.deref_ref = 1;
1173c50c785cSJohn Marino       val_print (value_type (val),
11745796c8dcSSimon Schubert 		 value_contents_for_printing (val),
11755796c8dcSSimon Schubert 		 value_embedded_offset (val), 0,
11765796c8dcSSimon Schubert 		 stb, 0, val, &opts, current_language);
11775796c8dcSSimon Schubert       ui_out_field_stream (uiout, "value", stb);
11785796c8dcSSimon Schubert       do_cleanups (old_chain);
11795796c8dcSSimon Schubert     }
11805796c8dcSSimon Schubert }
11815796c8dcSSimon Schubert 
11825796c8dcSSimon Schubert /* Write given values into registers. The registers and values are
11835796c8dcSSimon Schubert    given as pairs.  The corresponding MI command is
11845796c8dcSSimon Schubert    -data-write-register-values <format>
11855796c8dcSSimon Schubert                                [<regnum1> <value1>...<regnumN> <valueN>] */
11865796c8dcSSimon Schubert void
mi_cmd_data_write_register_values(char * command,char ** argv,int argc)11875796c8dcSSimon Schubert mi_cmd_data_write_register_values (char *command, char **argv, int argc)
11885796c8dcSSimon Schubert {
11895796c8dcSSimon Schubert   struct regcache *regcache;
11905796c8dcSSimon Schubert   struct gdbarch *gdbarch;
11915796c8dcSSimon Schubert   int numregs, i;
11925796c8dcSSimon Schubert 
1193c50c785cSJohn Marino   /* Note that the test for a valid register must include checking the
1194c50c785cSJohn Marino      gdbarch_register_name because gdbarch_num_regs may be allocated
11955796c8dcSSimon Schubert      for the union of the register sets within a family of related
11965796c8dcSSimon Schubert      processors.  In this case, some entries of gdbarch_register_name
11975796c8dcSSimon Schubert      will change depending upon the particular processor being
11985796c8dcSSimon Schubert      debugged.  */
1199c50c785cSJohn Marino 
12005796c8dcSSimon Schubert   regcache = get_current_regcache ();
12015796c8dcSSimon Schubert   gdbarch = get_regcache_arch (regcache);
1202c50c785cSJohn Marino   numregs = gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch);
12035796c8dcSSimon Schubert 
12045796c8dcSSimon Schubert   if (argc == 0)
1205c50c785cSJohn Marino     error (_("-data-write-register-values: Usage: -data-write-register-"
1206c50c785cSJohn Marino 	     "values <format> [<regnum1> <value1>...<regnumN> <valueN>]"));
12075796c8dcSSimon Schubert 
12085796c8dcSSimon Schubert   if (!target_has_registers)
12095796c8dcSSimon Schubert     error (_("-data-write-register-values: No registers."));
12105796c8dcSSimon Schubert 
12115796c8dcSSimon Schubert   if (!(argc - 1))
12125796c8dcSSimon Schubert     error (_("-data-write-register-values: No regs and values specified."));
12135796c8dcSSimon Schubert 
12145796c8dcSSimon Schubert   if ((argc - 1) % 2)
12155796c8dcSSimon Schubert     error (_("-data-write-register-values: "
12165796c8dcSSimon Schubert 	     "Regs and vals are not in pairs."));
12175796c8dcSSimon Schubert 
12185796c8dcSSimon Schubert   for (i = 1; i < argc; i = i + 2)
12195796c8dcSSimon Schubert     {
12205796c8dcSSimon Schubert       int regnum = atoi (argv[i]);
12215796c8dcSSimon Schubert 
12225796c8dcSSimon Schubert       if (regnum >= 0 && regnum < numregs
12235796c8dcSSimon Schubert 	  && gdbarch_register_name (gdbarch, regnum)
12245796c8dcSSimon Schubert 	  && *gdbarch_register_name (gdbarch, regnum))
1225c50c785cSJohn Marino 	{
12265796c8dcSSimon Schubert 	  LONGEST value;
12275796c8dcSSimon Schubert 
12285796c8dcSSimon Schubert 	  /* Get the value as a number.  */
12295796c8dcSSimon Schubert 	  value = parse_and_eval_address (argv[i + 1]);
12305796c8dcSSimon Schubert 
12315796c8dcSSimon Schubert 	  /* Write it down.  */
12325796c8dcSSimon Schubert 	  regcache_cooked_write_signed (regcache, regnum, value);
12335796c8dcSSimon Schubert 	}
12345796c8dcSSimon Schubert       else
12355796c8dcSSimon Schubert 	error (_("bad register number"));
12365796c8dcSSimon Schubert     }
12375796c8dcSSimon Schubert }
12385796c8dcSSimon Schubert 
12395796c8dcSSimon Schubert /* Evaluate the value of the argument.  The argument is an
1240a45ae5f8SJohn Marino    expression. If the expression contains spaces it needs to be
12415796c8dcSSimon Schubert    included in double quotes.  */
12425796c8dcSSimon Schubert 
12435796c8dcSSimon Schubert void
mi_cmd_data_evaluate_expression(char * command,char ** argv,int argc)12445796c8dcSSimon Schubert mi_cmd_data_evaluate_expression (char *command, char **argv, int argc)
12455796c8dcSSimon Schubert {
12465796c8dcSSimon Schubert   struct expression *expr;
1247c50c785cSJohn Marino   struct cleanup *old_chain;
1248c50c785cSJohn Marino   struct value *val;
12495796c8dcSSimon Schubert   struct ui_file *stb;
12505796c8dcSSimon Schubert   struct value_print_options opts;
12515796c8dcSSimon Schubert   struct ui_out *uiout = current_uiout;
12525796c8dcSSimon Schubert 
12535796c8dcSSimon Schubert   stb = mem_fileopen ();
12545796c8dcSSimon Schubert   old_chain = make_cleanup_ui_file_delete (stb);
12555796c8dcSSimon Schubert 
12565796c8dcSSimon Schubert   if (argc != 1)
12575796c8dcSSimon Schubert     error (_("-data-evaluate-expression: "
12585796c8dcSSimon Schubert 	     "Usage: -data-evaluate-expression expression"));
12595796c8dcSSimon Schubert 
1260cf7f2e2dSJohn Marino   expr = parse_expression (argv[0]);
12615796c8dcSSimon Schubert 
12625796c8dcSSimon Schubert   make_cleanup (free_current_contents, &expr);
12635796c8dcSSimon Schubert 
12645796c8dcSSimon Schubert   val = evaluate_expression (expr);
12655796c8dcSSimon Schubert 
12665796c8dcSSimon Schubert   /* Print the result of the expression evaluation.  */
12675796c8dcSSimon Schubert   get_user_print_options (&opts);
12685796c8dcSSimon Schubert   opts.deref_ref = 0;
12695796c8dcSSimon Schubert   common_val_print (val, stb, 0, &opts, current_language);
12705796c8dcSSimon Schubert 
12715796c8dcSSimon Schubert   ui_out_field_stream (uiout, "value", stb);
12725796c8dcSSimon Schubert 
12735796c8dcSSimon Schubert   do_cleanups (old_chain);
12745796c8dcSSimon Schubert }
12755796c8dcSSimon Schubert 
12765796c8dcSSimon Schubert /* This is the -data-read-memory command.
12775796c8dcSSimon Schubert 
12785796c8dcSSimon Schubert    ADDR: start address of data to be dumped.
12795796c8dcSSimon Schubert    WORD-FORMAT: a char indicating format for the ``word''.  See
12805796c8dcSSimon Schubert    the ``x'' command.
12815796c8dcSSimon Schubert    WORD-SIZE: size of each ``word''; 1,2,4, or 8 bytes.
12825796c8dcSSimon Schubert    NR_ROW: Number of rows.
12835796c8dcSSimon Schubert    NR_COL: The number of colums (words per row).
12845796c8dcSSimon Schubert    ASCHAR: (OPTIONAL) Append an ascii character dump to each row.  Use
12855796c8dcSSimon Schubert    ASCHAR for unprintable characters.
12865796c8dcSSimon Schubert 
12875796c8dcSSimon Schubert    Reads SIZE*NR_ROW*NR_COL bytes starting at ADDR from memory and
12885796c8dcSSimon Schubert    displayes them.  Returns:
12895796c8dcSSimon Schubert 
12905796c8dcSSimon Schubert    {addr="...",rowN={wordN="..." ,... [,ascii="..."]}, ...}
1291a45ae5f8SJohn Marino 
12925796c8dcSSimon Schubert    Returns:
12935796c8dcSSimon Schubert    The number of bytes read is SIZE*ROW*COL.  */
12945796c8dcSSimon Schubert 
12955796c8dcSSimon Schubert void
mi_cmd_data_read_memory(char * command,char ** argv,int argc)12965796c8dcSSimon Schubert mi_cmd_data_read_memory (char *command, char **argv, int argc)
12975796c8dcSSimon Schubert {
12985796c8dcSSimon Schubert   struct gdbarch *gdbarch = get_current_arch ();
12995796c8dcSSimon Schubert   struct ui_out *uiout = current_uiout;
13005796c8dcSSimon Schubert   struct cleanup *cleanups = make_cleanup (null_cleanup, NULL);
13015796c8dcSSimon Schubert   CORE_ADDR addr;
13025796c8dcSSimon Schubert   long total_bytes, nr_cols, nr_rows;
13035796c8dcSSimon Schubert   char word_format;
13045796c8dcSSimon Schubert   struct type *word_type;
13055796c8dcSSimon Schubert   long word_size;
13065796c8dcSSimon Schubert   char word_asize;
13075796c8dcSSimon Schubert   char aschar;
13085796c8dcSSimon Schubert   gdb_byte *mbuf;
13095796c8dcSSimon Schubert   int nr_bytes;
13105796c8dcSSimon Schubert   long offset = 0;
1311a45ae5f8SJohn Marino   int oind = 0;
13125796c8dcSSimon Schubert   char *oarg;
13135796c8dcSSimon Schubert   enum opt
13145796c8dcSSimon Schubert   {
13155796c8dcSSimon Schubert     OFFSET_OPT
13165796c8dcSSimon Schubert   };
13175796c8dcSSimon Schubert   static const struct mi_opt opts[] =
13185796c8dcSSimon Schubert     {
1319c50c785cSJohn Marino       {"o", OFFSET_OPT, 1},
13205796c8dcSSimon Schubert       { 0, 0, 0 }
1321cf7f2e2dSJohn Marino     };
13225796c8dcSSimon Schubert 
13235796c8dcSSimon Schubert   while (1)
13245796c8dcSSimon Schubert     {
13255796c8dcSSimon Schubert       int opt = mi_getopt ("-data-read-memory", argc, argv, opts,
13265796c8dcSSimon Schubert 			   &oind, &oarg);
13275796c8dcSSimon Schubert 
13285796c8dcSSimon Schubert       if (opt < 0)
13295796c8dcSSimon Schubert 	break;
13305796c8dcSSimon Schubert       switch ((enum opt) opt)
13315796c8dcSSimon Schubert 	{
13325796c8dcSSimon Schubert 	case OFFSET_OPT:
13335796c8dcSSimon Schubert 	  offset = atol (oarg);
13345796c8dcSSimon Schubert 	  break;
1335c50c785cSJohn Marino 	}
1336c50c785cSJohn Marino     }
13375796c8dcSSimon Schubert   argv += oind;
13385796c8dcSSimon Schubert   argc -= oind;
13395796c8dcSSimon Schubert 
13405796c8dcSSimon Schubert   if (argc < 5 || argc > 6)
13415796c8dcSSimon Schubert     error (_("-data-read-memory: Usage: "
13425796c8dcSSimon Schubert 	     "ADDR WORD-FORMAT WORD-SIZE NR-ROWS NR-COLS [ASCHAR]."));
13435796c8dcSSimon Schubert 
13445796c8dcSSimon Schubert   /* Extract all the arguments. */
13455796c8dcSSimon Schubert 
13465796c8dcSSimon Schubert   /* Start address of the memory dump.  */
13475796c8dcSSimon Schubert   addr = parse_and_eval_address (argv[0]) + offset;
13485796c8dcSSimon Schubert   /* The format character to use when displaying a memory word.  See
13495796c8dcSSimon Schubert      the ``x'' command.  */
13505796c8dcSSimon Schubert   word_format = argv[1][0];
13515796c8dcSSimon Schubert   /* The size of the memory word.  */
13525796c8dcSSimon Schubert   word_size = atol (argv[2]);
13535796c8dcSSimon Schubert   switch (word_size)
13545796c8dcSSimon Schubert     {
13555796c8dcSSimon Schubert     case 1:
13565796c8dcSSimon Schubert       word_type = builtin_type (gdbarch)->builtin_int8;
13575796c8dcSSimon Schubert       word_asize = 'b';
13585796c8dcSSimon Schubert       break;
13595796c8dcSSimon Schubert     case 2:
13605796c8dcSSimon Schubert       word_type = builtin_type (gdbarch)->builtin_int16;
13615796c8dcSSimon Schubert       word_asize = 'h';
13625796c8dcSSimon Schubert       break;
13635796c8dcSSimon Schubert     case 4:
13645796c8dcSSimon Schubert       word_type = builtin_type (gdbarch)->builtin_int32;
13655796c8dcSSimon Schubert       word_asize = 'w';
13665796c8dcSSimon Schubert       break;
13675796c8dcSSimon Schubert     case 8:
13685796c8dcSSimon Schubert       word_type = builtin_type (gdbarch)->builtin_int64;
13695796c8dcSSimon Schubert       word_asize = 'g';
13705796c8dcSSimon Schubert       break;
13715796c8dcSSimon Schubert     default:
1372c50c785cSJohn Marino       word_type = builtin_type (gdbarch)->builtin_int8;
13735796c8dcSSimon Schubert       word_asize = 'b';
13745796c8dcSSimon Schubert     }
13755796c8dcSSimon Schubert   /* The number of rows.  */
13765796c8dcSSimon Schubert   nr_rows = atol (argv[3]);
1377c50c785cSJohn Marino   if (nr_rows <= 0)
13785796c8dcSSimon Schubert     error (_("-data-read-memory: invalid number of rows."));
13795796c8dcSSimon Schubert 
13805796c8dcSSimon Schubert   /* Number of bytes per row.  */
13815796c8dcSSimon Schubert   nr_cols = atol (argv[4]);
13825796c8dcSSimon Schubert   if (nr_cols <= 0)
13835796c8dcSSimon Schubert     error (_("-data-read-memory: invalid number of columns."));
13845796c8dcSSimon Schubert 
13855796c8dcSSimon Schubert   /* The un-printable character when printing ascii.  */
13865796c8dcSSimon Schubert   if (argc == 6)
13875796c8dcSSimon Schubert     aschar = *argv[5];
13885796c8dcSSimon Schubert   else
13895796c8dcSSimon Schubert     aschar = 0;
13905796c8dcSSimon Schubert 
13915796c8dcSSimon Schubert   /* Create a buffer and read it in.  */
1392c50c785cSJohn Marino   total_bytes = word_size * nr_rows * nr_cols;
13935796c8dcSSimon Schubert   mbuf = xcalloc (total_bytes, 1);
13945796c8dcSSimon Schubert   make_cleanup (xfree, mbuf);
13955796c8dcSSimon Schubert 
1396c50c785cSJohn Marino   /* Dispatch memory reads to the topmost target, not the flattened
13975796c8dcSSimon Schubert      current_target.  */
13985796c8dcSSimon Schubert   nr_bytes = target_read (current_target.beneath,
13995796c8dcSSimon Schubert 			  TARGET_OBJECT_MEMORY, NULL, mbuf,
14005796c8dcSSimon Schubert 			  addr, total_bytes);
14015796c8dcSSimon Schubert   if (nr_bytes <= 0)
14025796c8dcSSimon Schubert     error (_("Unable to read memory."));
14035796c8dcSSimon Schubert 
14045796c8dcSSimon Schubert   /* Output the header information.  */
14055796c8dcSSimon Schubert   ui_out_field_core_addr (uiout, "addr", gdbarch, addr);
14065796c8dcSSimon Schubert   ui_out_field_int (uiout, "nr-bytes", nr_bytes);
14075796c8dcSSimon Schubert   ui_out_field_int (uiout, "total-bytes", total_bytes);
14085796c8dcSSimon Schubert   ui_out_field_core_addr (uiout, "next-row",
14095796c8dcSSimon Schubert 			  gdbarch, addr + word_size * nr_cols);
14105796c8dcSSimon Schubert   ui_out_field_core_addr (uiout, "prev-row",
14115796c8dcSSimon Schubert 			  gdbarch, addr - word_size * nr_cols);
14125796c8dcSSimon Schubert   ui_out_field_core_addr (uiout, "next-page", gdbarch, addr + total_bytes);
14135796c8dcSSimon Schubert   ui_out_field_core_addr (uiout, "prev-page", gdbarch, addr - total_bytes);
14145796c8dcSSimon Schubert 
1415cf7f2e2dSJohn Marino   /* Build the result as a two dimentional table.  */
14165796c8dcSSimon Schubert   {
14175796c8dcSSimon Schubert     struct ui_file *stream;
14185796c8dcSSimon Schubert     struct cleanup *cleanup_stream;
14195796c8dcSSimon Schubert     int row;
14205796c8dcSSimon Schubert     int row_byte;
14215796c8dcSSimon Schubert 
14225796c8dcSSimon Schubert     stream = mem_fileopen ();
14235796c8dcSSimon Schubert     cleanup_stream = make_cleanup_ui_file_delete (stream);
14245796c8dcSSimon Schubert 
14255796c8dcSSimon Schubert     make_cleanup_ui_out_list_begin_end (uiout, "memory");
14265796c8dcSSimon Schubert     for (row = 0, row_byte = 0;
14275796c8dcSSimon Schubert 	 row < nr_rows;
14285796c8dcSSimon Schubert 	 row++, row_byte += nr_cols * word_size)
1429c50c785cSJohn Marino       {
1430c50c785cSJohn Marino 	int col;
14315796c8dcSSimon Schubert 	int col_byte;
14325796c8dcSSimon Schubert 	struct cleanup *cleanup_tuple;
14335796c8dcSSimon Schubert 	struct cleanup *cleanup_list_data;
14345796c8dcSSimon Schubert 	struct value_print_options opts;
14355796c8dcSSimon Schubert 
14365796c8dcSSimon Schubert 	cleanup_tuple = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
14375796c8dcSSimon Schubert 	ui_out_field_core_addr (uiout, "addr", gdbarch, addr + row_byte);
14385796c8dcSSimon Schubert 	/* ui_out_field_core_addr_symbolic (uiout, "saddr", addr +
14395796c8dcSSimon Schubert 	   row_byte); */
14405796c8dcSSimon Schubert 	cleanup_list_data = make_cleanup_ui_out_list_begin_end (uiout, "data");
14415796c8dcSSimon Schubert 	get_formatted_print_options (&opts, word_format);
14425796c8dcSSimon Schubert 	for (col = 0, col_byte = row_byte;
14435796c8dcSSimon Schubert 	     col < nr_cols;
14445796c8dcSSimon Schubert 	     col++, col_byte += word_size)
14455796c8dcSSimon Schubert 	  {
14465796c8dcSSimon Schubert 	    if (col_byte + word_size > nr_bytes)
14475796c8dcSSimon Schubert 	      {
14485796c8dcSSimon Schubert 		ui_out_field_string (uiout, NULL, "N/A");
14495796c8dcSSimon Schubert 	      }
14505796c8dcSSimon Schubert 	    else
14515796c8dcSSimon Schubert 	      {
14525796c8dcSSimon Schubert 		ui_file_rewind (stream);
1453cf7f2e2dSJohn Marino 		print_scalar_formatted (mbuf + col_byte, word_type, &opts,
14545796c8dcSSimon Schubert 					word_asize, stream);
1455c50c785cSJohn Marino 		ui_out_field_stream (uiout, NULL, stream);
1456c50c785cSJohn Marino 	      }
14575796c8dcSSimon Schubert 	  }
14585796c8dcSSimon Schubert 	do_cleanups (cleanup_list_data);
14595796c8dcSSimon Schubert 	if (aschar)
14605796c8dcSSimon Schubert 	  {
14615796c8dcSSimon Schubert 	    int byte;
14625796c8dcSSimon Schubert 
14635796c8dcSSimon Schubert 	    ui_file_rewind (stream);
14645796c8dcSSimon Schubert 	    for (byte = row_byte;
14655796c8dcSSimon Schubert 		 byte < row_byte + word_size * nr_cols; byte++)
14665796c8dcSSimon Schubert 	      {
14675796c8dcSSimon Schubert 		if (byte >= nr_bytes)
14685796c8dcSSimon Schubert 		  fputc_unfiltered ('X', stream);
14695796c8dcSSimon Schubert 		else if (mbuf[byte] < 32 || mbuf[byte] > 126)
14705796c8dcSSimon Schubert 		  fputc_unfiltered (aschar, stream);
14715796c8dcSSimon Schubert 		else
14725796c8dcSSimon Schubert 		  fputc_unfiltered (mbuf[byte], stream);
14735796c8dcSSimon Schubert 	      }
14745796c8dcSSimon Schubert 	    ui_out_field_stream (uiout, "ascii", stream);
14755796c8dcSSimon Schubert 	  }
14765796c8dcSSimon Schubert 	do_cleanups (cleanup_tuple);
14775796c8dcSSimon Schubert       }
14785796c8dcSSimon Schubert     do_cleanups (cleanup_stream);
1479c50c785cSJohn Marino   }
1480c50c785cSJohn Marino   do_cleanups (cleanups);
1481c50c785cSJohn Marino }
1482c50c785cSJohn Marino 
1483a45ae5f8SJohn Marino void
mi_cmd_data_read_memory_bytes(char * command,char ** argv,int argc)1484c50c785cSJohn Marino mi_cmd_data_read_memory_bytes (char *command, char **argv, int argc)
1485c50c785cSJohn Marino {
1486c50c785cSJohn Marino   struct gdbarch *gdbarch = get_current_arch ();
1487c50c785cSJohn Marino   struct ui_out *uiout = current_uiout;
1488c50c785cSJohn Marino   struct cleanup *cleanups;
1489c50c785cSJohn Marino   CORE_ADDR addr;
1490c50c785cSJohn Marino   LONGEST length;
1491c50c785cSJohn Marino   memory_read_result_s *read_result;
1492c50c785cSJohn Marino   int ix;
1493c50c785cSJohn Marino   VEC(memory_read_result_s) *result;
1494c50c785cSJohn Marino   long offset = 0;
1495c50c785cSJohn Marino   int oind = 0;
1496c50c785cSJohn Marino   char *oarg;
1497a45ae5f8SJohn Marino   enum opt
1498c50c785cSJohn Marino   {
1499c50c785cSJohn Marino     OFFSET_OPT
1500c50c785cSJohn Marino   };
1501c50c785cSJohn Marino   static const struct mi_opt opts[] =
1502c50c785cSJohn Marino     {
1503c50c785cSJohn Marino       {"o", OFFSET_OPT, 1},
1504c50c785cSJohn Marino       { 0, 0, 0 }
1505c50c785cSJohn Marino     };
1506c50c785cSJohn Marino 
1507c50c785cSJohn Marino   while (1)
1508c50c785cSJohn Marino     {
1509c50c785cSJohn Marino       int opt = mi_getopt ("-data-read-memory-bytes", argc, argv, opts,
1510c50c785cSJohn Marino 			   &oind, &oarg);
1511c50c785cSJohn Marino       if (opt < 0)
1512c50c785cSJohn Marino 	break;
1513c50c785cSJohn Marino       switch ((enum opt) opt)
1514c50c785cSJohn Marino 	{
1515c50c785cSJohn Marino 	case OFFSET_OPT:
1516c50c785cSJohn Marino 	  offset = atol (oarg);
1517c50c785cSJohn Marino 	  break;
1518c50c785cSJohn Marino 	}
1519c50c785cSJohn Marino     }
1520c50c785cSJohn Marino   argv += oind;
1521c50c785cSJohn Marino   argc -= oind;
1522c50c785cSJohn Marino 
1523c50c785cSJohn Marino   if (argc != 2)
1524c50c785cSJohn Marino     error (_("Usage: [ -o OFFSET ] ADDR LENGTH."));
1525c50c785cSJohn Marino 
1526c50c785cSJohn Marino   addr = parse_and_eval_address (argv[0]) + offset;
1527c50c785cSJohn Marino   length = atol (argv[1]);
1528c50c785cSJohn Marino 
1529c50c785cSJohn Marino   result = read_memory_robust (current_target.beneath, addr, length);
1530c50c785cSJohn Marino 
1531c50c785cSJohn Marino   cleanups = make_cleanup (free_memory_read_result_vector, result);
1532c50c785cSJohn Marino 
1533c50c785cSJohn Marino   if (VEC_length (memory_read_result_s, result) == 0)
1534c50c785cSJohn Marino     error (_("Unable to read memory."));
1535c50c785cSJohn Marino 
1536c50c785cSJohn Marino   make_cleanup_ui_out_list_begin_end (uiout, "memory");
1537c50c785cSJohn Marino   for (ix = 0;
1538c50c785cSJohn Marino        VEC_iterate (memory_read_result_s, result, ix, read_result);
1539c50c785cSJohn Marino        ++ix)
1540c50c785cSJohn Marino     {
1541c50c785cSJohn Marino       struct cleanup *t = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
1542c50c785cSJohn Marino       char *data, *p;
1543c50c785cSJohn Marino       int i;
1544c50c785cSJohn Marino 
1545c50c785cSJohn Marino       ui_out_field_core_addr (uiout, "begin", gdbarch, read_result->begin);
1546c50c785cSJohn Marino       ui_out_field_core_addr (uiout, "offset", gdbarch, read_result->begin
1547c50c785cSJohn Marino 			      - addr);
1548c50c785cSJohn Marino       ui_out_field_core_addr (uiout, "end", gdbarch, read_result->end);
1549c50c785cSJohn Marino 
1550c50c785cSJohn Marino       data = xmalloc ((read_result->end - read_result->begin) * 2 + 1);
1551c50c785cSJohn Marino 
1552c50c785cSJohn Marino       for (i = 0, p = data;
1553c50c785cSJohn Marino 	   i < (read_result->end - read_result->begin);
1554c50c785cSJohn Marino 	   ++i, p += 2)
1555c50c785cSJohn Marino 	{
1556c50c785cSJohn Marino 	  sprintf (p, "%02x", read_result->data[i]);
1557c50c785cSJohn Marino 	}
1558c50c785cSJohn Marino       ui_out_field_string (uiout, "contents", data);
1559c50c785cSJohn Marino       xfree (data);
1560c50c785cSJohn Marino       do_cleanups (t);
1561c50c785cSJohn Marino     }
15625796c8dcSSimon Schubert   do_cleanups (cleanups);
15635796c8dcSSimon Schubert }
1564a45ae5f8SJohn Marino 
15655796c8dcSSimon Schubert /* Implementation of the -data-write_memory command.
15665796c8dcSSimon Schubert 
15675796c8dcSSimon Schubert    COLUMN_OFFSET: optional argument. Must be preceded by '-o'. The
15685796c8dcSSimon Schubert    offset from the beginning of the memory grid row where the cell to
15695796c8dcSSimon Schubert    be written is.
15705796c8dcSSimon Schubert    ADDR: start address of the row in the memory grid where the memory
15715796c8dcSSimon Schubert    cell is, if OFFSET_COLUMN is specified.  Otherwise, the address of
15725796c8dcSSimon Schubert    the location to write to.
15735796c8dcSSimon Schubert    FORMAT: a char indicating format for the ``word''.  See
15745796c8dcSSimon Schubert    the ``x'' command.
15755796c8dcSSimon Schubert    WORD_SIZE: size of each ``word''; 1,2,4, or 8 bytes
15765796c8dcSSimon Schubert    VALUE: value to be written into the memory address.
15775796c8dcSSimon Schubert 
15785796c8dcSSimon Schubert    Writes VALUE into ADDR + (COLUMN_OFFSET * WORD_SIZE).
15795796c8dcSSimon Schubert 
15805796c8dcSSimon Schubert    Prints nothing.  */
15815796c8dcSSimon Schubert 
15825796c8dcSSimon Schubert void
mi_cmd_data_write_memory(char * command,char ** argv,int argc)15835796c8dcSSimon Schubert mi_cmd_data_write_memory (char *command, char **argv, int argc)
15845796c8dcSSimon Schubert {
15855796c8dcSSimon Schubert   struct gdbarch *gdbarch = get_current_arch ();
15865796c8dcSSimon Schubert   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
15875796c8dcSSimon Schubert   CORE_ADDR addr;
15885796c8dcSSimon Schubert   long word_size;
15895796c8dcSSimon Schubert   /* FIXME: ezannoni 2000-02-17 LONGEST could possibly not be big
15905796c8dcSSimon Schubert      enough when using a compiler other than GCC.  */
15915796c8dcSSimon Schubert   LONGEST value;
15925796c8dcSSimon Schubert   void *buffer;
15935796c8dcSSimon Schubert   struct cleanup *old_chain;
15945796c8dcSSimon Schubert   long offset = 0;
15955796c8dcSSimon Schubert   int oind = 0;
15965796c8dcSSimon Schubert   char *oarg;
15975796c8dcSSimon Schubert   enum opt
1598a45ae5f8SJohn Marino   {
15995796c8dcSSimon Schubert     OFFSET_OPT
16005796c8dcSSimon Schubert   };
16015796c8dcSSimon Schubert   static const struct mi_opt opts[] =
16025796c8dcSSimon Schubert     {
16035796c8dcSSimon Schubert       {"o", OFFSET_OPT, 1},
16045796c8dcSSimon Schubert       { 0, 0, 0 }
16055796c8dcSSimon Schubert     };
1606c50c785cSJohn Marino 
16075796c8dcSSimon Schubert   while (1)
1608cf7f2e2dSJohn Marino     {
16095796c8dcSSimon Schubert       int opt = mi_getopt ("-data-write-memory", argc, argv, opts,
16105796c8dcSSimon Schubert 			   &oind, &oarg);
16115796c8dcSSimon Schubert 
16125796c8dcSSimon Schubert       if (opt < 0)
16135796c8dcSSimon Schubert 	break;
16145796c8dcSSimon Schubert       switch ((enum opt) opt)
16155796c8dcSSimon Schubert 	{
16165796c8dcSSimon Schubert 	case OFFSET_OPT:
16175796c8dcSSimon Schubert 	  offset = atol (oarg);
16185796c8dcSSimon Schubert 	  break;
16195796c8dcSSimon Schubert 	}
16205796c8dcSSimon Schubert     }
16215796c8dcSSimon Schubert   argv += oind;
1622c50c785cSJohn Marino   argc -= oind;
1623c50c785cSJohn Marino 
16245796c8dcSSimon Schubert   if (argc != 4)
16255796c8dcSSimon Schubert     error (_("-data-write-memory: Usage: "
16265796c8dcSSimon Schubert 	     "[-o COLUMN_OFFSET] ADDR FORMAT WORD-SIZE VALUE."));
16275796c8dcSSimon Schubert 
16285796c8dcSSimon Schubert   /* Extract all the arguments.  */
16295796c8dcSSimon Schubert   /* Start address of the memory dump.  */
16305796c8dcSSimon Schubert   addr = parse_and_eval_address (argv[0]);
16315796c8dcSSimon Schubert   /* The size of the memory word.  */
16325796c8dcSSimon Schubert   word_size = atol (argv[2]);
16335796c8dcSSimon Schubert 
16345796c8dcSSimon Schubert   /* Calculate the real address of the write destination.  */
16355796c8dcSSimon Schubert   addr += (offset * word_size);
16365796c8dcSSimon Schubert 
16375796c8dcSSimon Schubert   /* Get the value as a number.  */
16385796c8dcSSimon Schubert   value = parse_and_eval_address (argv[3]);
16395796c8dcSSimon Schubert   /* Get the value into an array.  */
16405796c8dcSSimon Schubert   buffer = xmalloc (word_size);
16415796c8dcSSimon Schubert   old_chain = make_cleanup (xfree, buffer);
16425796c8dcSSimon Schubert   store_signed_integer (buffer, word_size, byte_order, value);
16435796c8dcSSimon Schubert   /* Write it down to memory.  */
16445796c8dcSSimon Schubert   write_memory_with_notification (addr, buffer, word_size);
16455796c8dcSSimon Schubert   /* Free the buffer.  */
16465796c8dcSSimon Schubert   do_cleanups (old_chain);
16475796c8dcSSimon Schubert }
16485796c8dcSSimon Schubert 
1649c50c785cSJohn Marino /* Implementation of the -data-write-memory-bytes command.
1650c50c785cSJohn Marino 
1651c50c785cSJohn Marino    ADDR: start address
1652c50c785cSJohn Marino    DATA: string of bytes to write at that address
1653c50c785cSJohn Marino    COUNT: number of bytes to be filled (decimal integer).  */
1654c50c785cSJohn Marino 
1655c50c785cSJohn Marino void
mi_cmd_data_write_memory_bytes(char * command,char ** argv,int argc)1656c50c785cSJohn Marino mi_cmd_data_write_memory_bytes (char *command, char **argv, int argc)
1657c50c785cSJohn Marino {
1658c50c785cSJohn Marino   CORE_ADDR addr;
1659c50c785cSJohn Marino   char *cdata;
1660c50c785cSJohn Marino   gdb_byte *data;
1661c50c785cSJohn Marino   gdb_byte *databuf;
1662c50c785cSJohn Marino   size_t len, i, steps, remainder;
1663c50c785cSJohn Marino   long int count, j;
1664c50c785cSJohn Marino   struct cleanup *back_to;
1665c50c785cSJohn Marino 
1666c50c785cSJohn Marino   if (argc != 2 && argc != 3)
1667c50c785cSJohn Marino     error (_("Usage: ADDR DATA [COUNT]."));
1668c50c785cSJohn Marino 
1669c50c785cSJohn Marino   addr = parse_and_eval_address (argv[0]);
1670c50c785cSJohn Marino   cdata = argv[1];
1671c50c785cSJohn Marino   if (strlen (cdata) % 2)
1672c50c785cSJohn Marino     error (_("Hex-encoded '%s' must have an even number of characters."),
1673c50c785cSJohn Marino 	   cdata);
1674c50c785cSJohn Marino 
1675c50c785cSJohn Marino   len = strlen (cdata)/2;
1676c50c785cSJohn Marino   if (argc == 3)
1677c50c785cSJohn Marino     count = strtoul (argv[2], NULL, 10);
1678c50c785cSJohn Marino   else
1679c50c785cSJohn Marino     count = len;
1680c50c785cSJohn Marino 
1681c50c785cSJohn Marino   databuf = xmalloc (len * sizeof (gdb_byte));
1682c50c785cSJohn Marino   back_to = make_cleanup (xfree, databuf);
1683c50c785cSJohn Marino 
1684c50c785cSJohn Marino   for (i = 0; i < len; ++i)
1685c50c785cSJohn Marino     {
1686c50c785cSJohn Marino       int x;
16875796c8dcSSimon Schubert       if (sscanf (cdata + i * 2, "%02x", &x) != 1)
16885796c8dcSSimon Schubert         error (_("Invalid argument"));
16895796c8dcSSimon Schubert       databuf[i] = (gdb_byte) x;
16905796c8dcSSimon Schubert     }
16915796c8dcSSimon Schubert 
16925796c8dcSSimon Schubert   if (len < count)
16935796c8dcSSimon Schubert     {
16945796c8dcSSimon Schubert       /* Pattern is made of less bytes than count:
16955796c8dcSSimon Schubert          repeat pattern to fill memory.  */
16965796c8dcSSimon Schubert       data = xmalloc (count);
16975796c8dcSSimon Schubert       make_cleanup (xfree, data);
16985796c8dcSSimon Schubert 
16995796c8dcSSimon Schubert       steps = count / len;
17005796c8dcSSimon Schubert       remainder = count % len;
17015796c8dcSSimon Schubert       for (j = 0; j < steps; j++)
17025796c8dcSSimon Schubert         memcpy (data + j * len, databuf, len);
17035796c8dcSSimon Schubert 
17045796c8dcSSimon Schubert       if (remainder > 0)
17055796c8dcSSimon Schubert         memcpy (data + steps * len, databuf, remainder);
17065796c8dcSSimon Schubert     }
1707c50c785cSJohn Marino   else
17085796c8dcSSimon Schubert     {
17095796c8dcSSimon Schubert       /* Pattern is longer than or equal to count:
17105796c8dcSSimon Schubert          just copy len bytes.  */
17115796c8dcSSimon Schubert       data = databuf;
17125796c8dcSSimon Schubert     }
17135796c8dcSSimon Schubert 
17145796c8dcSSimon Schubert   write_memory_with_notification (addr, data, count);
17155796c8dcSSimon Schubert 
1716a45ae5f8SJohn Marino   do_cleanups (back_to);
17175796c8dcSSimon Schubert }
1718cf7f2e2dSJohn Marino 
17195796c8dcSSimon Schubert void
mi_cmd_enable_timings(char * command,char ** argv,int argc)17205796c8dcSSimon Schubert mi_cmd_enable_timings (char *command, char **argv, int argc)
17215796c8dcSSimon Schubert {
1722c50c785cSJohn Marino   if (argc == 0)
1723a45ae5f8SJohn Marino     do_timings = 1;
1724a45ae5f8SJohn Marino   else if (argc == 1)
17255796c8dcSSimon Schubert     {
17265796c8dcSSimon Schubert       if (strcmp (argv[0], "yes") == 0)
17275796c8dcSSimon Schubert 	do_timings = 1;
17285796c8dcSSimon Schubert       else if (strcmp (argv[0], "no") == 0)
17295796c8dcSSimon Schubert 	do_timings = 0;
17305796c8dcSSimon Schubert       else
17315796c8dcSSimon Schubert 	goto usage_error;
17325796c8dcSSimon Schubert     }
17335796c8dcSSimon Schubert   else
1734c50c785cSJohn Marino     goto usage_error;
17355796c8dcSSimon Schubert 
17365796c8dcSSimon Schubert   return;
17375796c8dcSSimon Schubert 
17385796c8dcSSimon Schubert  usage_error:
17395796c8dcSSimon Schubert   error (_("-enable-timings: Usage: %s {yes|no}"), command);
17405796c8dcSSimon Schubert }
17415796c8dcSSimon Schubert 
17425796c8dcSSimon Schubert void
mi_cmd_list_features(char * command,char ** argv,int argc)1743a45ae5f8SJohn Marino mi_cmd_list_features (char *command, char **argv, int argc)
17445796c8dcSSimon Schubert {
1745cf7f2e2dSJohn Marino   if (argc == 0)
17465796c8dcSSimon Schubert     {
17475796c8dcSSimon Schubert       struct cleanup *cleanup = NULL;
1748cf7f2e2dSJohn Marino       struct ui_out *uiout = current_uiout;
1749cf7f2e2dSJohn Marino 
17505796c8dcSSimon Schubert       cleanup = make_cleanup_ui_out_list_begin_end (uiout, "features");
17515796c8dcSSimon Schubert       ui_out_field_string (uiout, NULL, "frozen-varobjs");
17525796c8dcSSimon Schubert       ui_out_field_string (uiout, NULL, "pending-breakpoints");
17535796c8dcSSimon Schubert       ui_out_field_string (uiout, NULL, "thread-info");
17545796c8dcSSimon Schubert       ui_out_field_string (uiout, NULL, "data-read-memory-bytes");
1755c50c785cSJohn Marino       ui_out_field_string (uiout, NULL, "breakpoint-notifications");
17565796c8dcSSimon Schubert       ui_out_field_string (uiout, NULL, "ada-task-info");
17575796c8dcSSimon Schubert 
1758cf7f2e2dSJohn Marino #if HAVE_PYTHON
1759cf7f2e2dSJohn Marino       ui_out_field_string (uiout, NULL, "python");
1760cf7f2e2dSJohn Marino #endif
1761cf7f2e2dSJohn Marino 
1762cf7f2e2dSJohn Marino       do_cleanups (cleanup);
1763cf7f2e2dSJohn Marino       return;
1764cf7f2e2dSJohn Marino     }
1765cf7f2e2dSJohn Marino 
1766cf7f2e2dSJohn Marino   error (_("-list-features should be passed no arguments"));
1767cf7f2e2dSJohn Marino }
1768a45ae5f8SJohn Marino 
1769cf7f2e2dSJohn Marino void
mi_cmd_list_target_features(char * command,char ** argv,int argc)1770cf7f2e2dSJohn Marino mi_cmd_list_target_features (char *command, char **argv, int argc)
1771c50c785cSJohn Marino {
1772c50c785cSJohn Marino   if (argc == 0)
1773c50c785cSJohn Marino     {
1774c50c785cSJohn Marino       struct cleanup *cleanup = NULL;
1775c50c785cSJohn Marino       struct ui_out *uiout = current_uiout;
1776c50c785cSJohn Marino 
1777c50c785cSJohn Marino       cleanup = make_cleanup_ui_out_list_begin_end (uiout, "features");
1778c50c785cSJohn Marino       if (target_can_async_p ())
1779c50c785cSJohn Marino 	ui_out_field_string (uiout, NULL, "async");
1780c50c785cSJohn Marino       if (target_can_execute_reverse)
1781c50c785cSJohn Marino 	ui_out_field_string (uiout, NULL, "reverse");
1782c50c785cSJohn Marino 
1783cf7f2e2dSJohn Marino       do_cleanups (cleanup);
1784cf7f2e2dSJohn Marino       return;
1785cf7f2e2dSJohn Marino     }
1786cf7f2e2dSJohn Marino 
1787cf7f2e2dSJohn Marino   error (_("-list-target-features should be passed no arguments"));
1788cf7f2e2dSJohn Marino }
1789cf7f2e2dSJohn Marino 
1790c50c785cSJohn Marino void
mi_cmd_add_inferior(char * command,char ** argv,int argc)1791cf7f2e2dSJohn Marino mi_cmd_add_inferior (char *command, char **argv, int argc)
1792cf7f2e2dSJohn Marino {
1793c50c785cSJohn Marino   struct inferior *inf;
1794cf7f2e2dSJohn Marino 
1795cf7f2e2dSJohn Marino   if (argc != 0)
1796cf7f2e2dSJohn Marino     error (_("-add-inferior should be passed no arguments"));
1797c50c785cSJohn Marino 
1798c50c785cSJohn Marino   inf = add_inferior_with_spaces ();
1799*74a8b0f5SJohn Marino 
1800c50c785cSJohn Marino   ui_out_field_fmt (current_uiout, "inferior", "i%d", inf->num);
1801c50c785cSJohn Marino }
1802c50c785cSJohn Marino 
1803c50c785cSJohn Marino /* Callback used to find the first inferior other than the current
1804c50c785cSJohn Marino    one.  */
1805c50c785cSJohn Marino 
1806c50c785cSJohn Marino static int
get_other_inferior(struct inferior * inf,void * arg)1807c50c785cSJohn Marino get_other_inferior (struct inferior *inf, void *arg)
1808c50c785cSJohn Marino {
1809c50c785cSJohn Marino   if (inf == current_inferior ())
1810c50c785cSJohn Marino     return 0;
1811c50c785cSJohn Marino 
1812*74a8b0f5SJohn Marino   return 1;
1813c50c785cSJohn Marino }
1814c50c785cSJohn Marino 
1815c50c785cSJohn Marino void
mi_cmd_remove_inferior(char * command,char ** argv,int argc)1816c50c785cSJohn Marino mi_cmd_remove_inferior (char *command, char **argv, int argc)
1817cf7f2e2dSJohn Marino {
1818cf7f2e2dSJohn Marino   int id;
1819cf7f2e2dSJohn Marino   struct inferior *inf;
1820cf7f2e2dSJohn Marino 
1821cf7f2e2dSJohn Marino   if (argc != 1)
1822cf7f2e2dSJohn Marino     error (_("-remove-inferior should be passed a single argument"));
18235796c8dcSSimon Schubert 
18245796c8dcSSimon Schubert   if (sscanf (argv[0], "i%d", &id) != 1)
18255796c8dcSSimon Schubert     error (_("the thread group id is syntactically invalid"));
18265796c8dcSSimon Schubert 
18275796c8dcSSimon Schubert   inf = find_inferior_id (id);
18285796c8dcSSimon Schubert   if (!inf)
18295796c8dcSSimon Schubert     error (_("the specified thread group does not exist"));
18305796c8dcSSimon Schubert 
1831a45ae5f8SJohn Marino   if (inf->pid != 0)
18325796c8dcSSimon Schubert     error (_("cannot remove an active inferior"));
18335796c8dcSSimon Schubert 
18345796c8dcSSimon Schubert   if (inf == current_inferior ())
18355796c8dcSSimon Schubert     {
18365796c8dcSSimon Schubert       struct thread_info *tp = 0;
18375796c8dcSSimon Schubert       struct inferior *new_inferior
18385796c8dcSSimon Schubert 	= iterate_over_inferiors (get_other_inferior, NULL);
18395796c8dcSSimon Schubert 
18405796c8dcSSimon Schubert       if (new_inferior == NULL)
18415796c8dcSSimon Schubert 	error (_("Cannot remove last inferior"));
18425796c8dcSSimon Schubert 
18435796c8dcSSimon Schubert       set_current_inferior (new_inferior);
18445796c8dcSSimon Schubert       if (new_inferior->pid != 0)
18455796c8dcSSimon Schubert 	tp = any_thread_of_process (new_inferior->pid);
18465796c8dcSSimon Schubert       switch_to_thread (tp ? tp->ptid : null_ptid);
18475796c8dcSSimon Schubert       set_current_program_space (new_inferior->pspace);
18485796c8dcSSimon Schubert     }
18495796c8dcSSimon Schubert 
18505796c8dcSSimon Schubert   delete_inferior_1 (inf, 1 /* silent */);
18515796c8dcSSimon Schubert }
18525796c8dcSSimon Schubert 
18535796c8dcSSimon Schubert 
18545796c8dcSSimon Schubert 
18555796c8dcSSimon Schubert /* Execute a command within a safe environment.
18565796c8dcSSimon Schubert    Return <0 for error; >=0 for ok.
18575796c8dcSSimon Schubert 
18585796c8dcSSimon Schubert    args->action will tell mi_execute_command what action
18595796c8dcSSimon Schubert    to perfrom after the given command has executed (display/suppress
18605796c8dcSSimon Schubert    prompt, display error).  */
18615796c8dcSSimon Schubert 
18625796c8dcSSimon Schubert static void
captured_mi_execute_command(struct ui_out * uiout,struct mi_parse * context)18635796c8dcSSimon Schubert captured_mi_execute_command (struct ui_out *uiout, struct mi_parse *context)
18645796c8dcSSimon Schubert {
18655796c8dcSSimon Schubert   struct cleanup *cleanup;
18665796c8dcSSimon Schubert 
18675796c8dcSSimon Schubert   if (do_timings)
18685796c8dcSSimon Schubert     current_command_ts = context->cmd_start;
18695796c8dcSSimon Schubert 
18705796c8dcSSimon Schubert   current_token = xstrdup (context->token);
18715796c8dcSSimon Schubert   cleanup = make_cleanup (free_current_contents, &current_token);
18725796c8dcSSimon Schubert 
18735796c8dcSSimon Schubert   running_result_record_printed = 0;
18745796c8dcSSimon Schubert   mi_proceeded = 0;
18755796c8dcSSimon Schubert   switch (context->op)
18765796c8dcSSimon Schubert     {
18775796c8dcSSimon Schubert     case MI_COMMAND:
18785796c8dcSSimon Schubert       /* A MI command was read from the input stream.  */
18795796c8dcSSimon Schubert       if (mi_debug_p)
18805796c8dcSSimon Schubert 	/* FIXME: gdb_???? */
18815796c8dcSSimon Schubert 	fprintf_unfiltered (raw_stdout, " token=`%s' command=`%s' args=`%s'\n",
18825796c8dcSSimon Schubert 			    context->token, context->command, context->args);
1883cf7f2e2dSJohn Marino 
18845796c8dcSSimon Schubert       mi_cmd_execute (context);
18855796c8dcSSimon Schubert 
18865796c8dcSSimon Schubert       /* Print the result if there were no errors.
18875796c8dcSSimon Schubert 
18885796c8dcSSimon Schubert 	 Remember that on the way out of executing a command, you have
18895796c8dcSSimon Schubert 	 to directly use the mi_interp's uiout, since the command
18905796c8dcSSimon Schubert 	 could have reset the interpreter, in which case the current
18915796c8dcSSimon Schubert 	 uiout will most likely crash in the mi_out_* routines.  */
18925796c8dcSSimon Schubert       if (!running_result_record_printed)
18935796c8dcSSimon Schubert 	{
18945796c8dcSSimon Schubert 	  fputs_unfiltered (context->token, raw_stdout);
18955796c8dcSSimon Schubert 	  /* There's no particularly good reason why target-connect results
18965796c8dcSSimon Schubert 	     in not ^done.  Should kill ^connected for MI3.  */
18975796c8dcSSimon Schubert 	  fputs_unfiltered (strcmp (context->command, "target-select") == 0
18985796c8dcSSimon Schubert 			    ? "^connected" : "^done", raw_stdout);
18995796c8dcSSimon Schubert 	  mi_out_put (uiout, raw_stdout);
19005796c8dcSSimon Schubert 	  mi_out_rewind (uiout);
19015796c8dcSSimon Schubert 	  mi_print_timing_maybe ();
19025796c8dcSSimon Schubert 	  fputs_unfiltered ("\n", raw_stdout);
19035796c8dcSSimon Schubert 	}
19045796c8dcSSimon Schubert       else
19055796c8dcSSimon Schubert 	/* The command does not want anything to be printed.  In that
19065796c8dcSSimon Schubert 	   case, the command probably should not have written anything
19075796c8dcSSimon Schubert 	   to uiout, but in case it has written something, discard it.  */
19085796c8dcSSimon Schubert 	mi_out_rewind (uiout);
19095796c8dcSSimon Schubert       break;
19105796c8dcSSimon Schubert 
19115796c8dcSSimon Schubert     case CLI_COMMAND:
19125796c8dcSSimon Schubert       {
19135796c8dcSSimon Schubert 	char *argv[2];
19145796c8dcSSimon Schubert 
19155796c8dcSSimon Schubert 	/* A CLI command was read from the input stream.  */
19165796c8dcSSimon Schubert 	/* This "feature" will be removed as soon as we have a
19175796c8dcSSimon Schubert 	   complete set of mi commands.  */
19185796c8dcSSimon Schubert 	/* Echo the command on the console.  */
19195796c8dcSSimon Schubert 	fprintf_unfiltered (gdb_stdlog, "%s\n", context->command);
19205796c8dcSSimon Schubert 	/* Call the "console" interpreter.  */
19215796c8dcSSimon Schubert 	argv[0] = "console";
1922c50c785cSJohn Marino 	argv[1] = context->command;
1923c50c785cSJohn Marino 	mi_cmd_interpreter_exec ("-interpreter-exec", argv, 2);
1924c50c785cSJohn Marino 
1925c50c785cSJohn Marino 	/* If we changed interpreters, DON'T print out anything.  */
1926c50c785cSJohn Marino 	if (current_interp_named_p (INTERP_MI)
1927c50c785cSJohn Marino 	    || current_interp_named_p (INTERP_MI1)
1928c50c785cSJohn Marino 	    || current_interp_named_p (INTERP_MI2)
1929c50c785cSJohn Marino 	    || current_interp_named_p (INTERP_MI3))
1930c50c785cSJohn Marino 	  {
1931c50c785cSJohn Marino 	    if (!running_result_record_printed)
1932c50c785cSJohn Marino 	      {
1933c50c785cSJohn Marino 		fputs_unfiltered (context->token, raw_stdout);
1934c50c785cSJohn Marino 		fputs_unfiltered ("^done", raw_stdout);
19355796c8dcSSimon Schubert 		mi_out_put (uiout, raw_stdout);
19365796c8dcSSimon Schubert 		mi_out_rewind (uiout);
19375796c8dcSSimon Schubert 		mi_print_timing_maybe ();
19385796c8dcSSimon Schubert 		fputs_unfiltered ("\n", raw_stdout);
1939c50c785cSJohn Marino 	      }
1940c50c785cSJohn Marino 	    else
1941c50c785cSJohn Marino 	      mi_out_rewind (uiout);
19425796c8dcSSimon Schubert 	  }
19435796c8dcSSimon Schubert 	break;
19445796c8dcSSimon Schubert       }
19455796c8dcSSimon Schubert     }
19465796c8dcSSimon Schubert 
19475796c8dcSSimon Schubert   do_cleanups (cleanup);
1948cf7f2e2dSJohn Marino }
1949cf7f2e2dSJohn Marino 
1950c50c785cSJohn Marino /* Print a gdb exception to the MI output stream.  */
1951c50c785cSJohn Marino 
1952c50c785cSJohn Marino static void
mi_print_exception(const char * token,struct gdb_exception exception)1953c50c785cSJohn Marino mi_print_exception (const char *token, struct gdb_exception exception)
1954c50c785cSJohn Marino {
1955c50c785cSJohn Marino   fputs_unfiltered (token, raw_stdout);
1956c50c785cSJohn Marino   fputs_unfiltered ("^error,msg=\"", raw_stdout);
1957c50c785cSJohn Marino   if (exception.message == NULL)
1958c50c785cSJohn Marino     fputs_unfiltered ("unknown error", raw_stdout);
1959c50c785cSJohn Marino   else
19605796c8dcSSimon Schubert     fputstr_unfiltered (exception.message, '"', raw_stdout);
1961a45ae5f8SJohn Marino   fputs_unfiltered ("\"\n", raw_stdout);
19625796c8dcSSimon Schubert }
19635796c8dcSSimon Schubert 
1964c50c785cSJohn Marino void
mi_execute_command(const char * cmd,int from_tty)1965c50c785cSJohn Marino mi_execute_command (const char *cmd, int from_tty)
19665796c8dcSSimon Schubert {
19675796c8dcSSimon Schubert   char *token;
19685796c8dcSSimon Schubert   struct mi_parse *command = NULL;
19695796c8dcSSimon Schubert   volatile struct gdb_exception exception;
19705796c8dcSSimon Schubert 
19715796c8dcSSimon Schubert   /* This is to handle EOF (^D). We just quit gdb.  */
19725796c8dcSSimon Schubert   /* FIXME: we should call some API function here.  */
1973a45ae5f8SJohn Marino   if (cmd == 0)
1974a45ae5f8SJohn Marino     quit_force (NULL, from_tty);
1975a45ae5f8SJohn Marino 
1976a45ae5f8SJohn Marino   target_log_command (cmd);
19775796c8dcSSimon Schubert 
19785796c8dcSSimon Schubert   TRY_CATCH (exception, RETURN_MASK_ALL)
19795796c8dcSSimon Schubert     {
19805796c8dcSSimon Schubert       command = mi_parse (cmd, &token);
1981c50c785cSJohn Marino     }
1982a45ae5f8SJohn Marino   if (exception.reason < 0)
19835796c8dcSSimon Schubert     {
19845796c8dcSSimon Schubert       mi_print_exception (token, exception);
1985cf7f2e2dSJohn Marino       xfree (token);
1986cf7f2e2dSJohn Marino     }
19875796c8dcSSimon Schubert   else
19885796c8dcSSimon Schubert     {
19895796c8dcSSimon Schubert       volatile struct gdb_exception result;
19905796c8dcSSimon Schubert       ptid_t previous_ptid = inferior_ptid;
19915796c8dcSSimon Schubert 
19925796c8dcSSimon Schubert       command->token = token;
19935796c8dcSSimon Schubert 
19945796c8dcSSimon Schubert       if (do_timings)
19955796c8dcSSimon Schubert 	{
19965796c8dcSSimon Schubert 	  command->cmd_start = (struct mi_timestamp *)
19975796c8dcSSimon Schubert 	    xmalloc (sizeof (struct mi_timestamp));
19985796c8dcSSimon Schubert 	  timestamp (command->cmd_start);
19995796c8dcSSimon Schubert 	}
20005796c8dcSSimon Schubert 
20015796c8dcSSimon Schubert       TRY_CATCH (result, RETURN_MASK_ALL)
20025796c8dcSSimon Schubert 	{
20035796c8dcSSimon Schubert 	  captured_mi_execute_command (current_uiout, command);
20045796c8dcSSimon Schubert 	}
20055796c8dcSSimon Schubert       if (result.reason < 0)
20065796c8dcSSimon Schubert 	{
20075796c8dcSSimon Schubert 	  /* The command execution failed and error() was called
20085796c8dcSSimon Schubert 	     somewhere.  */
20095796c8dcSSimon Schubert 	  mi_print_exception (command->token, result);
2010cf7f2e2dSJohn Marino 	  mi_out_rewind (current_uiout);
20115796c8dcSSimon Schubert 	}
20125796c8dcSSimon Schubert 
20135796c8dcSSimon Schubert       bpstat_do_actions ();
20145796c8dcSSimon Schubert 
20155796c8dcSSimon Schubert       if (/* The notifications are only output when the top-level
20165796c8dcSSimon Schubert 	     interpreter (specified on the command line) is MI.  */
2017cf7f2e2dSJohn Marino 	  ui_out_is_mi_like_p (interp_ui_out (top_level_interpreter ()))
20185796c8dcSSimon Schubert 	  /* Don't try report anything if there are no threads --
20195796c8dcSSimon Schubert 	     the program is dead.  */
20205796c8dcSSimon Schubert 	  && thread_count () != 0
20215796c8dcSSimon Schubert 	  /* -thread-select explicitly changes thread. If frontend uses that
20225796c8dcSSimon Schubert 	     internally, we don't want to emit =thread-selected, since
20235796c8dcSSimon Schubert 	     =thread-selected is supposed to indicate user's intentions.  */
20245796c8dcSSimon Schubert 	  && strcmp (command->command, "thread-select") != 0)
20255796c8dcSSimon Schubert 	{
20265796c8dcSSimon Schubert 	  struct mi_interp *mi = top_level_interpreter_data ();
20275796c8dcSSimon Schubert 	  int report_change = 0;
20285796c8dcSSimon Schubert 
20295796c8dcSSimon Schubert 	  if (command->thread == -1)
20305796c8dcSSimon Schubert 	    {
20315796c8dcSSimon Schubert 	      report_change = (!ptid_equal (previous_ptid, null_ptid)
20325796c8dcSSimon Schubert 			       && !ptid_equal (inferior_ptid, previous_ptid)
20335796c8dcSSimon Schubert 			       && !ptid_equal (inferior_ptid, null_ptid));
20345796c8dcSSimon Schubert 	    }
20355796c8dcSSimon Schubert 	  else if (!ptid_equal (inferior_ptid, null_ptid))
20365796c8dcSSimon Schubert 	    {
20375796c8dcSSimon Schubert 	      struct thread_info *ti = inferior_thread ();
20385796c8dcSSimon Schubert 
20395796c8dcSSimon Schubert 	      report_change = (ti->num != command->thread);
2040a45ae5f8SJohn Marino 	    }
20415796c8dcSSimon Schubert 
2042cf7f2e2dSJohn Marino 	  if (report_change)
2043cf7f2e2dSJohn Marino 	    {
2044cf7f2e2dSJohn Marino 	      struct thread_info *ti = inferior_thread ();
2045cf7f2e2dSJohn Marino 
2046cf7f2e2dSJohn Marino 	      target_terminal_ours ();
2047cf7f2e2dSJohn Marino 	      fprintf_unfiltered (mi->event_channel,
2048cf7f2e2dSJohn Marino 				  "thread-selected,id=\"%d\"",
2049cf7f2e2dSJohn Marino 				  ti->num);
2050cf7f2e2dSJohn Marino 	      gdb_flush (mi->event_channel);
20515796c8dcSSimon Schubert 	    }
20525796c8dcSSimon Schubert 	}
20535796c8dcSSimon Schubert 
2054cf7f2e2dSJohn Marino       mi_parse_free (command);
2055cf7f2e2dSJohn Marino     }
2056cf7f2e2dSJohn Marino }
2057cf7f2e2dSJohn Marino 
2058cf7f2e2dSJohn Marino static void
mi_cmd_execute(struct mi_parse * parse)2059cf7f2e2dSJohn Marino mi_cmd_execute (struct mi_parse *parse)
2060cf7f2e2dSJohn Marino {
2061cf7f2e2dSJohn Marino   struct cleanup *cleanup;
2062cf7f2e2dSJohn Marino 
2063cf7f2e2dSJohn Marino   cleanup = prepare_execute_command ();
2064cf7f2e2dSJohn Marino 
2065cf7f2e2dSJohn Marino   if (parse->all && parse->thread_group != -1)
2066cf7f2e2dSJohn Marino     error (_("Cannot specify --thread-group together with --all"));
2067*74a8b0f5SJohn Marino 
2068a45ae5f8SJohn Marino   if (parse->all && parse->thread != -1)
2069cf7f2e2dSJohn Marino     error (_("Cannot specify --thread together with --all"));
2070cf7f2e2dSJohn Marino 
2071cf7f2e2dSJohn Marino   if (parse->thread_group != -1 && parse->thread != -1)
2072cf7f2e2dSJohn Marino     error (_("Cannot specify --thread together with --thread-group"));
20735796c8dcSSimon Schubert 
20745796c8dcSSimon Schubert   if (parse->frame != -1 && parse->thread == -1)
20755796c8dcSSimon Schubert     error (_("Cannot specify --frame without --thread"));
2076cf7f2e2dSJohn Marino 
20775796c8dcSSimon Schubert   if (parse->thread_group != -1)
20785796c8dcSSimon Schubert     {
20795796c8dcSSimon Schubert       struct inferior *inf = find_inferior_id (parse->thread_group);
20805796c8dcSSimon Schubert       struct thread_info *tp = 0;
20815796c8dcSSimon Schubert 
20825796c8dcSSimon Schubert       if (!inf)
20835796c8dcSSimon Schubert 	error (_("Invalid thread group for the --thread-group option"));
20845796c8dcSSimon Schubert 
20855796c8dcSSimon Schubert       set_current_inferior (inf);
20865796c8dcSSimon Schubert       /* This behaviour means that if --thread-group option identifies
20875796c8dcSSimon Schubert 	 an inferior with multiple threads, then a random one will be
20885796c8dcSSimon Schubert 	 picked.  This is not a problem -- frontend should always
20895796c8dcSSimon Schubert 	 provide --thread if it wishes to operate on a specific
2090cf7f2e2dSJohn Marino 	 thread.  */
20915796c8dcSSimon Schubert       if (inf->pid != 0)
20925796c8dcSSimon Schubert 	tp = any_live_thread_of_process (inf->pid);
20935796c8dcSSimon Schubert       switch_to_thread (tp ? tp->ptid : null_ptid);
20945796c8dcSSimon Schubert       set_current_program_space (inf->pspace);
20955796c8dcSSimon Schubert     }
20965796c8dcSSimon Schubert 
20975796c8dcSSimon Schubert   if (parse->thread != -1)
20985796c8dcSSimon Schubert     {
2099cf7f2e2dSJohn Marino       struct thread_info *tp = find_thread_id (parse->thread);
2100cf7f2e2dSJohn Marino 
2101a45ae5f8SJohn Marino       if (!tp)
2102a45ae5f8SJohn Marino 	error (_("Invalid thread id: %d"), parse->thread);
2103a45ae5f8SJohn Marino 
2104a45ae5f8SJohn Marino       if (is_exited (tp->ptid))
2105a45ae5f8SJohn Marino 	error (_("Thread id: %d has terminated"), parse->thread);
2106a45ae5f8SJohn Marino 
21075796c8dcSSimon Schubert       switch_to_thread (tp->ptid);
2108a45ae5f8SJohn Marino     }
21095796c8dcSSimon Schubert 
2110a45ae5f8SJohn Marino   if (parse->frame != -1)
21115796c8dcSSimon Schubert     {
21125796c8dcSSimon Schubert       struct frame_info *fid;
21135796c8dcSSimon Schubert       int frame = parse->frame;
21145796c8dcSSimon Schubert 
21155796c8dcSSimon Schubert       fid = find_relative_frame (get_current_frame (), &frame);
21165796c8dcSSimon Schubert       if (frame == 0)
21175796c8dcSSimon Schubert 	/* find_relative_frame was successful */
21185796c8dcSSimon Schubert 	select_frame (fid);
21195796c8dcSSimon Schubert       else
21205796c8dcSSimon Schubert 	error (_("Invalid frame id: %d"), frame);
21215796c8dcSSimon Schubert     }
21225796c8dcSSimon Schubert 
21235796c8dcSSimon Schubert   current_context = parse;
21245796c8dcSSimon Schubert 
21255796c8dcSSimon Schubert   if (parse->cmd->suppress_notification != NULL)
21265796c8dcSSimon Schubert     {
21275796c8dcSSimon Schubert       make_cleanup_restore_integer (parse->cmd->suppress_notification);
21285796c8dcSSimon Schubert       *parse->cmd->suppress_notification = 1;
21295796c8dcSSimon Schubert     }
21305796c8dcSSimon Schubert 
21315796c8dcSSimon Schubert   if (parse->cmd->argv_func != NULL)
21325796c8dcSSimon Schubert     {
21335796c8dcSSimon Schubert       parse->cmd->argv_func (parse->command, parse->argv, parse->argc);
21345796c8dcSSimon Schubert     }
21355796c8dcSSimon Schubert   else if (parse->cmd->cli.cmd != 0)
21365796c8dcSSimon Schubert     {
21375796c8dcSSimon Schubert       /* FIXME: DELETE THIS. */
21385796c8dcSSimon Schubert       /* The operation is still implemented by a cli command.  */
21395796c8dcSSimon Schubert       /* Must be a synchronous one.  */
21405796c8dcSSimon Schubert       mi_execute_cli_command (parse->cmd->cli.cmd, parse->cmd->cli.args_p,
21415796c8dcSSimon Schubert 			      parse->args);
21425796c8dcSSimon Schubert     }
21435796c8dcSSimon Schubert   else
21445796c8dcSSimon Schubert     {
21455796c8dcSSimon Schubert       /* FIXME: DELETE THIS.  */
21465796c8dcSSimon Schubert       struct ui_file *stb;
2147cf7f2e2dSJohn Marino 
21485796c8dcSSimon Schubert       stb = mem_fileopen ();
21495796c8dcSSimon Schubert 
21505796c8dcSSimon Schubert       fputs_unfiltered ("Undefined mi command: ", stb);
21515796c8dcSSimon Schubert       fputstr_unfiltered (parse->command, '"', stb);
21525796c8dcSSimon Schubert       fputs_unfiltered (" (missing implementation)", stb);
21535796c8dcSSimon Schubert 
21545796c8dcSSimon Schubert       make_cleanup_ui_file_delete (stb);
21555796c8dcSSimon Schubert       error_stream (stb);
21565796c8dcSSimon Schubert     }
21575796c8dcSSimon Schubert   do_cleanups (cleanup);
21585796c8dcSSimon Schubert }
21595796c8dcSSimon Schubert 
21605796c8dcSSimon Schubert /* FIXME: This is just a hack so we can get some extra commands going.
21615796c8dcSSimon Schubert    We don't want to channel things through the CLI, but call libgdb directly.
21625796c8dcSSimon Schubert    Use only for synchronous commands.  */
21635796c8dcSSimon Schubert 
21645796c8dcSSimon Schubert void
mi_execute_cli_command(const char * cmd,int args_p,const char * args)21655796c8dcSSimon Schubert mi_execute_cli_command (const char *cmd, int args_p, const char *args)
21665796c8dcSSimon Schubert {
21675796c8dcSSimon Schubert   if (cmd != 0)
21685796c8dcSSimon Schubert     {
21695796c8dcSSimon Schubert       struct cleanup *old_cleanups;
21705796c8dcSSimon Schubert       char *run;
21715796c8dcSSimon Schubert 
21725796c8dcSSimon Schubert       if (args_p)
21735796c8dcSSimon Schubert 	run = xstrprintf ("%s %s", cmd, args);
21745796c8dcSSimon Schubert       else
21755796c8dcSSimon Schubert 	run = xstrdup (cmd);
21765796c8dcSSimon Schubert       if (mi_debug_p)
21775796c8dcSSimon Schubert 	/* FIXME: gdb_???? */
21785796c8dcSSimon Schubert 	fprintf_unfiltered (gdb_stdout, "cli=%s run=%s\n",
21795796c8dcSSimon Schubert 			    cmd, run);
21805796c8dcSSimon Schubert       old_cleanups = make_cleanup (xfree, run);
21815796c8dcSSimon Schubert       execute_command (run, 0 /* from_tty */ );
21825796c8dcSSimon Schubert       do_cleanups (old_cleanups);
21835796c8dcSSimon Schubert       return;
21845796c8dcSSimon Schubert     }
21855796c8dcSSimon Schubert }
21865796c8dcSSimon Schubert 
21875796c8dcSSimon Schubert void
mi_execute_async_cli_command(char * cli_command,char ** argv,int argc)21885796c8dcSSimon Schubert mi_execute_async_cli_command (char *cli_command, char **argv, int argc)
21895796c8dcSSimon Schubert {
21905796c8dcSSimon Schubert   struct cleanup *old_cleanups;
21915796c8dcSSimon Schubert   char *run;
21925796c8dcSSimon Schubert 
21935796c8dcSSimon Schubert   if (target_can_async_p ())
2194a45ae5f8SJohn Marino     run = xstrprintf ("%s %s&", cli_command, argc ? *argv : "");
21955796c8dcSSimon Schubert   else
21965796c8dcSSimon Schubert     run = xstrprintf ("%s %s", cli_command, argc ? *argv : "");
21975796c8dcSSimon Schubert   old_cleanups = make_cleanup (xfree, run);
21985796c8dcSSimon Schubert 
2199a45ae5f8SJohn Marino   execute_command (run, 0 /* from_tty */ );
22005796c8dcSSimon Schubert 
22015796c8dcSSimon Schubert   /* Do this before doing any printing.  It would appear that some
22025796c8dcSSimon Schubert      print code leaves garbage around in the buffer.  */
2203a45ae5f8SJohn Marino   do_cleanups (old_cleanups);
22045796c8dcSSimon Schubert }
2205a45ae5f8SJohn Marino 
22065796c8dcSSimon Schubert void
mi_load_progress(const char * section_name,unsigned long sent_so_far,unsigned long total_section,unsigned long total_sent,unsigned long grand_total)2207a45ae5f8SJohn Marino mi_load_progress (const char *section_name,
22085796c8dcSSimon Schubert 		  unsigned long sent_so_far,
22095796c8dcSSimon Schubert 		  unsigned long total_section,
22105796c8dcSSimon Schubert 		  unsigned long total_sent,
2211a45ae5f8SJohn Marino 		  unsigned long grand_total)
2212a45ae5f8SJohn Marino {
22135796c8dcSSimon Schubert   struct timeval time_now, delta, update_threshold;
22145796c8dcSSimon Schubert   static struct timeval last_update;
22155796c8dcSSimon Schubert   static char *previous_sect_name = NULL;
22165796c8dcSSimon Schubert   int new_section;
22175796c8dcSSimon Schubert   struct ui_out *saved_uiout;
22185796c8dcSSimon Schubert   struct ui_out *uiout;
22195796c8dcSSimon Schubert 
22205796c8dcSSimon Schubert   /* This function is called through deprecated_show_load_progress
22215796c8dcSSimon Schubert      which means uiout may not be correct.  Fix it for the duration
22225796c8dcSSimon Schubert      of this function.  */
22235796c8dcSSimon Schubert   saved_uiout = current_uiout;
22245796c8dcSSimon Schubert 
22255796c8dcSSimon Schubert   if (current_interp_named_p (INTERP_MI)
22265796c8dcSSimon Schubert       || current_interp_named_p (INTERP_MI2))
22275796c8dcSSimon Schubert     current_uiout = mi_out_new (2);
22285796c8dcSSimon Schubert   else if (current_interp_named_p (INTERP_MI1))
22295796c8dcSSimon Schubert     current_uiout = mi_out_new (1);
22305796c8dcSSimon Schubert   else if (current_interp_named_p (INTERP_MI3))
2231cf7f2e2dSJohn Marino     current_uiout = mi_out_new (3);
22325796c8dcSSimon Schubert   else
22335796c8dcSSimon Schubert     return;
22345796c8dcSSimon Schubert 
22355796c8dcSSimon Schubert   uiout = current_uiout;
22365796c8dcSSimon Schubert 
22375796c8dcSSimon Schubert   update_threshold.tv_sec = 0;
22385796c8dcSSimon Schubert   update_threshold.tv_usec = 500000;
22395796c8dcSSimon Schubert   gettimeofday (&time_now, NULL);
22405796c8dcSSimon Schubert 
22415796c8dcSSimon Schubert   delta.tv_usec = time_now.tv_usec - last_update.tv_usec;
22425796c8dcSSimon Schubert   delta.tv_sec = time_now.tv_sec - last_update.tv_sec;
22435796c8dcSSimon Schubert 
22445796c8dcSSimon Schubert   if (delta.tv_usec < 0)
22455796c8dcSSimon Schubert     {
22465796c8dcSSimon Schubert       delta.tv_sec -= 1;
22475796c8dcSSimon Schubert       delta.tv_usec += 1000000L;
22485796c8dcSSimon Schubert     }
22495796c8dcSSimon Schubert 
22505796c8dcSSimon Schubert   new_section = (previous_sect_name ?
22515796c8dcSSimon Schubert 		 strcmp (previous_sect_name, section_name) : 1);
2252cf7f2e2dSJohn Marino   if (new_section)
22535796c8dcSSimon Schubert     {
22545796c8dcSSimon Schubert       struct cleanup *cleanup_tuple;
22555796c8dcSSimon Schubert 
22565796c8dcSSimon Schubert       xfree (previous_sect_name);
22575796c8dcSSimon Schubert       previous_sect_name = xstrdup (section_name);
22585796c8dcSSimon Schubert 
22595796c8dcSSimon Schubert       if (current_token)
22605796c8dcSSimon Schubert 	fputs_unfiltered (current_token, raw_stdout);
22615796c8dcSSimon Schubert       fputs_unfiltered ("+download", raw_stdout);
22625796c8dcSSimon Schubert       cleanup_tuple = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
22635796c8dcSSimon Schubert       ui_out_field_string (uiout, "section", section_name);
22645796c8dcSSimon Schubert       ui_out_field_int (uiout, "section-size", total_section);
22655796c8dcSSimon Schubert       ui_out_field_int (uiout, "total-size", grand_total);
22665796c8dcSSimon Schubert       do_cleanups (cleanup_tuple);
22675796c8dcSSimon Schubert       mi_out_put (uiout, raw_stdout);
22685796c8dcSSimon Schubert       fputs_unfiltered ("\n", raw_stdout);
22695796c8dcSSimon Schubert       gdb_flush (raw_stdout);
22705796c8dcSSimon Schubert     }
2271a45ae5f8SJohn Marino 
22725796c8dcSSimon Schubert   if (delta.tv_sec >= update_threshold.tv_sec &&
22735796c8dcSSimon Schubert       delta.tv_usec >= update_threshold.tv_usec)
22745796c8dcSSimon Schubert     {
22755796c8dcSSimon Schubert       struct cleanup *cleanup_tuple;
22765796c8dcSSimon Schubert 
22775796c8dcSSimon Schubert       last_update.tv_sec = time_now.tv_sec;
22785796c8dcSSimon Schubert       last_update.tv_usec = time_now.tv_usec;
22795796c8dcSSimon Schubert       if (current_token)
22805796c8dcSSimon Schubert 	fputs_unfiltered (current_token, raw_stdout);
22815796c8dcSSimon Schubert       fputs_unfiltered ("+download", raw_stdout);
22825796c8dcSSimon Schubert       cleanup_tuple = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
22835796c8dcSSimon Schubert       ui_out_field_string (uiout, "section", section_name);
22845796c8dcSSimon Schubert       ui_out_field_int (uiout, "section-sent", sent_so_far);
2285cf7f2e2dSJohn Marino       ui_out_field_int (uiout, "section-size", total_section);
2286cf7f2e2dSJohn Marino       ui_out_field_int (uiout, "total-sent", total_sent);
2287cf7f2e2dSJohn Marino       ui_out_field_int (uiout, "total-size", grand_total);
22885796c8dcSSimon Schubert       do_cleanups (cleanup_tuple);
22895796c8dcSSimon Schubert       mi_out_put (uiout, raw_stdout);
22905796c8dcSSimon Schubert       fputs_unfiltered ("\n", raw_stdout);
22915796c8dcSSimon Schubert       gdb_flush (raw_stdout);
2292cf7f2e2dSJohn Marino     }
22935796c8dcSSimon Schubert 
22945796c8dcSSimon Schubert   xfree (uiout);
22955796c8dcSSimon Schubert   current_uiout = saved_uiout;
22965796c8dcSSimon Schubert }
22975796c8dcSSimon Schubert 
22985796c8dcSSimon Schubert static void
timestamp(struct mi_timestamp * tv)22995796c8dcSSimon Schubert timestamp (struct mi_timestamp *tv)
2300cf7f2e2dSJohn Marino {
23015796c8dcSSimon Schubert   gettimeofday (&tv->wallclock, NULL);
23025796c8dcSSimon Schubert #ifdef HAVE_GETRUSAGE
23035796c8dcSSimon Schubert   getrusage (RUSAGE_SELF, &rusage);
23045796c8dcSSimon Schubert   tv->utime.tv_sec = rusage.ru_utime.tv_sec;
23055796c8dcSSimon Schubert   tv->utime.tv_usec = rusage.ru_utime.tv_usec;
23065796c8dcSSimon Schubert   tv->stime.tv_sec = rusage.ru_stime.tv_sec;
23075796c8dcSSimon Schubert   tv->stime.tv_usec = rusage.ru_stime.tv_usec;
23085796c8dcSSimon Schubert #else
23095796c8dcSSimon Schubert   {
23105796c8dcSSimon Schubert     long usec = get_run_time ();
23115796c8dcSSimon Schubert 
23125796c8dcSSimon Schubert     tv->utime.tv_sec = usec/1000000L;
23135796c8dcSSimon Schubert     tv->utime.tv_usec = usec - 1000000L*tv->utime.tv_sec;
23145796c8dcSSimon Schubert     tv->stime.tv_sec = 0;
23155796c8dcSSimon Schubert     tv->stime.tv_usec = 0;
23165796c8dcSSimon Schubert   }
23175796c8dcSSimon Schubert #endif
23185796c8dcSSimon Schubert }
23195796c8dcSSimon Schubert 
23205796c8dcSSimon Schubert static void
print_diff_now(struct mi_timestamp * start)23215796c8dcSSimon Schubert print_diff_now (struct mi_timestamp *start)
23225796c8dcSSimon Schubert {
23235796c8dcSSimon Schubert   struct mi_timestamp now;
23245796c8dcSSimon Schubert 
23255796c8dcSSimon Schubert   timestamp (&now);
23265796c8dcSSimon Schubert   print_diff (start, &now);
23275796c8dcSSimon Schubert }
23285796c8dcSSimon Schubert 
23295796c8dcSSimon Schubert void
mi_print_timing_maybe(void)23305796c8dcSSimon Schubert mi_print_timing_maybe (void)
2331cf7f2e2dSJohn Marino {
2332cf7f2e2dSJohn Marino   /* If the command is -enable-timing then do_timings may be true
2333cf7f2e2dSJohn Marino      whilst current_command_ts is not initialized.  */
2334cf7f2e2dSJohn Marino   if (do_timings && current_command_ts)
2335cf7f2e2dSJohn Marino     print_diff_now (current_command_ts);
2336cf7f2e2dSJohn Marino }
2337cf7f2e2dSJohn Marino 
2338cf7f2e2dSJohn Marino static long
timeval_diff(struct timeval start,struct timeval end)2339cf7f2e2dSJohn Marino timeval_diff (struct timeval start, struct timeval end)
2340cf7f2e2dSJohn Marino {
2341cf7f2e2dSJohn Marino   return ((end.tv_sec - start.tv_sec) * 1000000L)
2342cf7f2e2dSJohn Marino     + (end.tv_usec - start.tv_usec);
2343cf7f2e2dSJohn Marino }
2344cf7f2e2dSJohn Marino 
2345cf7f2e2dSJohn Marino static void
print_diff(struct mi_timestamp * start,struct mi_timestamp * end)2346cf7f2e2dSJohn Marino print_diff (struct mi_timestamp *start, struct mi_timestamp *end)
2347cf7f2e2dSJohn Marino {
2348cf7f2e2dSJohn Marino   fprintf_unfiltered
2349cf7f2e2dSJohn Marino     (raw_stdout,
2350cf7f2e2dSJohn Marino      ",time={wallclock=\"%0.5f\",user=\"%0.5f\",system=\"%0.5f\"}",
2351cf7f2e2dSJohn Marino      timeval_diff (start->wallclock, end->wallclock) / 1000000.0,
2352cf7f2e2dSJohn Marino      timeval_diff (start->utime, end->utime) / 1000000.0,
2353cf7f2e2dSJohn Marino      timeval_diff (start->stime, end->stime) / 1000000.0);
2354cf7f2e2dSJohn Marino }
2355cf7f2e2dSJohn Marino 
2356cf7f2e2dSJohn Marino void
mi_cmd_trace_define_variable(char * command,char ** argv,int argc)2357cf7f2e2dSJohn Marino mi_cmd_trace_define_variable (char *command, char **argv, int argc)
2358cf7f2e2dSJohn Marino {
2359cf7f2e2dSJohn Marino   struct expression *expr;
2360cf7f2e2dSJohn Marino   LONGEST initval = 0;
2361cf7f2e2dSJohn Marino   struct trace_state_variable *tsv;
2362cf7f2e2dSJohn Marino   char *name = 0;
2363cf7f2e2dSJohn Marino 
2364cf7f2e2dSJohn Marino   if (argc != 1 && argc != 2)
2365cf7f2e2dSJohn Marino     error (_("Usage: -trace-define-variable VARIABLE [VALUE]"));
2366cf7f2e2dSJohn Marino 
2367cf7f2e2dSJohn Marino   name = argv[0];
2368cf7f2e2dSJohn Marino   if (*name++ != '$')
2369cf7f2e2dSJohn Marino     error (_("Name of trace variable should start with '$'"));
2370cf7f2e2dSJohn Marino 
2371cf7f2e2dSJohn Marino   validate_trace_state_variable_name (name);
2372cf7f2e2dSJohn Marino 
2373cf7f2e2dSJohn Marino   tsv = find_trace_state_variable (name);
2374cf7f2e2dSJohn Marino   if (!tsv)
2375cf7f2e2dSJohn Marino     tsv = create_trace_state_variable (name);
2376cf7f2e2dSJohn Marino 
2377cf7f2e2dSJohn Marino   if (argc == 2)
2378cf7f2e2dSJohn Marino     initval = value_as_long (parse_and_eval (argv[1]));
2379cf7f2e2dSJohn Marino 
2380cf7f2e2dSJohn Marino   tsv->initial_value = initval;
2381cf7f2e2dSJohn Marino }
2382cf7f2e2dSJohn Marino 
2383cf7f2e2dSJohn Marino void
mi_cmd_trace_list_variables(char * command,char ** argv,int argc)2384cf7f2e2dSJohn Marino mi_cmd_trace_list_variables (char *command, char **argv, int argc)
2385cf7f2e2dSJohn Marino {
2386cf7f2e2dSJohn Marino   if (argc != 0)
2387cf7f2e2dSJohn Marino     error (_("-trace-list-variables: no arguments allowed"));
2388cf7f2e2dSJohn Marino 
2389cf7f2e2dSJohn Marino   tvariables_info_1 ();
2390cf7f2e2dSJohn Marino }
2391cf7f2e2dSJohn Marino 
2392cf7f2e2dSJohn Marino void
mi_cmd_trace_find(char * command,char ** argv,int argc)2393cf7f2e2dSJohn Marino mi_cmd_trace_find (char *command, char **argv, int argc)
2394cf7f2e2dSJohn Marino {
2395cf7f2e2dSJohn Marino   char *mode;
2396cf7f2e2dSJohn Marino 
2397cf7f2e2dSJohn Marino   if (argc == 0)
2398cf7f2e2dSJohn Marino     error (_("trace selection mode is required"));
2399cf7f2e2dSJohn Marino 
2400cf7f2e2dSJohn Marino   mode = argv[0];
2401cf7f2e2dSJohn Marino 
2402cf7f2e2dSJohn Marino   if (strcmp (mode, "none") == 0)
2403cf7f2e2dSJohn Marino     {
2404cf7f2e2dSJohn Marino       tfind_1 (tfind_number, -1, 0, 0, 0);
2405cf7f2e2dSJohn Marino       return;
2406cf7f2e2dSJohn Marino     }
2407cf7f2e2dSJohn Marino 
2408cf7f2e2dSJohn Marino   if (current_trace_status ()->running)
2409cf7f2e2dSJohn Marino     error (_("May not look at trace frames while trace is running."));
2410cf7f2e2dSJohn Marino 
2411cf7f2e2dSJohn Marino   if (strcmp (mode, "frame-number") == 0)
2412cf7f2e2dSJohn Marino     {
2413cf7f2e2dSJohn Marino       if (argc != 2)
2414cf7f2e2dSJohn Marino 	error (_("frame number is required"));
2415cf7f2e2dSJohn Marino       tfind_1 (tfind_number, atoi (argv[1]), 0, 0, 0);
2416cf7f2e2dSJohn Marino     }
2417cf7f2e2dSJohn Marino   else if (strcmp (mode, "tracepoint-number") == 0)
2418cf7f2e2dSJohn Marino     {
2419cf7f2e2dSJohn Marino       if (argc != 2)
2420cf7f2e2dSJohn Marino 	error (_("tracepoint number is required"));
2421cf7f2e2dSJohn Marino       tfind_1 (tfind_tp, atoi (argv[1]), 0, 0, 0);
2422cf7f2e2dSJohn Marino     }
2423cf7f2e2dSJohn Marino   else if (strcmp (mode, "pc") == 0)
2424cf7f2e2dSJohn Marino     {
2425cf7f2e2dSJohn Marino       if (argc != 2)
2426cf7f2e2dSJohn Marino 	error (_("PC is required"));
2427cf7f2e2dSJohn Marino       tfind_1 (tfind_pc, 0, parse_and_eval_address (argv[1]), 0, 0);
2428cf7f2e2dSJohn Marino     }
2429cf7f2e2dSJohn Marino   else if (strcmp (mode, "pc-inside-range") == 0)
2430cf7f2e2dSJohn Marino     {
2431cf7f2e2dSJohn Marino       if (argc != 3)
2432cf7f2e2dSJohn Marino 	error (_("Start and end PC are required"));
2433cf7f2e2dSJohn Marino       tfind_1 (tfind_range, 0, parse_and_eval_address (argv[1]),
2434cf7f2e2dSJohn Marino 	       parse_and_eval_address (argv[2]), 0);
2435cf7f2e2dSJohn Marino     }
2436cf7f2e2dSJohn Marino   else if (strcmp (mode, "pc-outside-range") == 0)
2437cf7f2e2dSJohn Marino     {
2438cf7f2e2dSJohn Marino       if (argc != 3)
2439cf7f2e2dSJohn Marino 	error (_("Start and end PC are required"));
2440a45ae5f8SJohn Marino       tfind_1 (tfind_outside, 0, parse_and_eval_address (argv[1]),
2441cf7f2e2dSJohn Marino 	       parse_and_eval_address (argv[2]), 0);
2442cf7f2e2dSJohn Marino     }
2443cf7f2e2dSJohn Marino   else if (strcmp (mode, "line") == 0)
2444cf7f2e2dSJohn Marino     {
2445cf7f2e2dSJohn Marino       struct symtabs_and_lines sals;
2446cf7f2e2dSJohn Marino       struct symtab_and_line sal;
2447cf7f2e2dSJohn Marino       static CORE_ADDR start_pc, end_pc;
2448cf7f2e2dSJohn Marino       struct cleanup *back_to;
2449cf7f2e2dSJohn Marino 
2450cf7f2e2dSJohn Marino       if (argc != 2)
2451cf7f2e2dSJohn Marino 	error (_("Line is required"));
2452cf7f2e2dSJohn Marino 
2453cf7f2e2dSJohn Marino       sals = decode_line_with_current_source (argv[1],
2454cf7f2e2dSJohn Marino 					      DECODE_LINE_FUNFIRSTLINE);
2455cf7f2e2dSJohn Marino       back_to = make_cleanup (xfree, sals.sals);
2456cf7f2e2dSJohn Marino 
2457cf7f2e2dSJohn Marino       sal = sals.sals[0];
2458cf7f2e2dSJohn Marino 
2459cf7f2e2dSJohn Marino       if (sal.symtab == 0)
2460cf7f2e2dSJohn Marino 	error (_("Could not find the specified line"));
2461cf7f2e2dSJohn Marino 
2462cf7f2e2dSJohn Marino       if (sal.line > 0 && find_line_pc_range (sal, &start_pc, &end_pc))
2463cf7f2e2dSJohn Marino 	tfind_1 (tfind_range, 0, start_pc, end_pc - 1, 0);
2464cf7f2e2dSJohn Marino       else
2465cf7f2e2dSJohn Marino 	error (_("Could not find the specified line"));
2466cf7f2e2dSJohn Marino 
2467cf7f2e2dSJohn Marino       do_cleanups (back_to);
2468cf7f2e2dSJohn Marino     }
2469cf7f2e2dSJohn Marino   else
2470cf7f2e2dSJohn Marino     error (_("Invalid mode '%s'"), mode);
2471cf7f2e2dSJohn Marino 
2472cf7f2e2dSJohn Marino   if (has_stack_frames () || get_traceframe_number () >= 0)
2473cf7f2e2dSJohn Marino     print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC);
2474cf7f2e2dSJohn Marino }
2475cf7f2e2dSJohn Marino 
2476cf7f2e2dSJohn Marino void
mi_cmd_trace_save(char * command,char ** argv,int argc)2477cf7f2e2dSJohn Marino mi_cmd_trace_save (char *command, char **argv, int argc)
2478cf7f2e2dSJohn Marino {
2479cf7f2e2dSJohn Marino   int target_saves = 0;
2480cf7f2e2dSJohn Marino   char *filename;
2481cf7f2e2dSJohn Marino 
2482cf7f2e2dSJohn Marino   if (argc != 1 && argc != 2)
2483cf7f2e2dSJohn Marino     error (_("Usage: -trace-save [-r] filename"));
2484cf7f2e2dSJohn Marino 
2485cf7f2e2dSJohn Marino   if (argc == 2)
2486cf7f2e2dSJohn Marino     {
2487cf7f2e2dSJohn Marino       filename = argv[1];
2488cf7f2e2dSJohn Marino       if (strcmp (argv[0], "-r") == 0)
2489cf7f2e2dSJohn Marino 	target_saves = 1;
2490cf7f2e2dSJohn Marino       else
2491cf7f2e2dSJohn Marino 	error (_("Invalid option: %s"), argv[0]);
2492cf7f2e2dSJohn Marino     }
2493a45ae5f8SJohn Marino   else
2494cf7f2e2dSJohn Marino     {
2495cf7f2e2dSJohn Marino       filename = argv[0];
2496cf7f2e2dSJohn Marino     }
2497cf7f2e2dSJohn Marino 
2498cf7f2e2dSJohn Marino   trace_save (filename, target_saves);
2499cf7f2e2dSJohn Marino }
2500cf7f2e2dSJohn Marino 
2501cf7f2e2dSJohn Marino void
mi_cmd_trace_start(char * command,char ** argv,int argc)2502cf7f2e2dSJohn Marino mi_cmd_trace_start (char *command, char **argv, int argc)
2503cf7f2e2dSJohn Marino {
2504cf7f2e2dSJohn Marino   start_tracing (NULL);
2505a45ae5f8SJohn Marino }
2506cf7f2e2dSJohn Marino 
2507cf7f2e2dSJohn Marino void
mi_cmd_trace_status(char * command,char ** argv,int argc)2508a45ae5f8SJohn Marino mi_cmd_trace_status (char *command, char **argv, int argc)
2509a45ae5f8SJohn Marino {
2510a45ae5f8SJohn Marino   trace_status_mi (0);
2511a45ae5f8SJohn Marino }
2512a45ae5f8SJohn Marino 
2513a45ae5f8SJohn Marino void
mi_cmd_trace_stop(char * command,char ** argv,int argc)2514a45ae5f8SJohn Marino mi_cmd_trace_stop (char *command, char **argv, int argc)
2515a45ae5f8SJohn Marino {
2516a45ae5f8SJohn Marino   stop_tracing (NULL);
2517a45ae5f8SJohn Marino   trace_status_mi (1);
2518a45ae5f8SJohn Marino }
2519 
2520 /* Implement the "-ada-task-info" command.  */
2521 
2522 void
mi_cmd_ada_task_info(char * command,char ** argv,int argc)2523 mi_cmd_ada_task_info (char *command, char **argv, int argc)
2524 {
2525   if (argc != 0 && argc != 1)
2526     error (_("Invalid MI command"));
2527 
2528   print_ada_task_info (current_uiout, argv[0], current_inferior ());
2529 }
2530