Fix copyright comments and file comments.
[deliverable/binutils-gdb.git] / gdb / infcmd.c
index ac093ed09e56ec15b8c6d785d6a217403726f5df..06439d0248d1f7bdeab36f0cb5e3f00e64f2bc56 100644 (file)
@@ -34,6 +34,9 @@
 #include "language.h"
 #include "symfile.h"
 #include "objfiles.h"
+#ifdef UI_OUT
+#include "ui-out.h"
+#endif
 #include "event-top.h"
 #include "parser-defs.h"
 
@@ -88,6 +91,8 @@ static void signal_command PARAMS ((char *, int));
 static void jump_command PARAMS ((char *, int));
 
 static void step_1 PARAMS ((int, int, char *));
+static void step_once (int skip_subroutines, int single_inst, int count);
+static void step_1_continuation (struct continuation_arg *arg);
 
 void nexti_command PARAMS ((char *, int));
 
@@ -315,6 +320,16 @@ Start it from the beginning? "))
 
   if (from_tty)
     {
+#ifdef UI_OUT
+      ui_out_field_string (uiout, NULL, "Starting program");
+      ui_out_text (uiout, ": ");
+      if (exec_file)
+       ui_out_field_string (uiout, "execfile", exec_file);
+      ui_out_spaces (uiout, 1);
+      ui_out_field_string (uiout, "infargs", inferior_args);
+      ui_out_text (uiout, "\n");
+      ui_out_flush (uiout);
+#else
       puts_filtered ("Starting program: ");
       if (exec_file)
        puts_filtered (exec_file);
@@ -322,6 +337,7 @@ Start it from the beginning? "))
       puts_filtered (inferior_args);
       puts_filtered ("\n");
       gdb_flush (gdb_stdout);
+#endif
     }
 
   target_create_inferior (exec_file, inferior_args,
@@ -472,11 +488,133 @@ step_1 (skip_subroutines, single_inst, count_string)
   if (!single_inst || skip_subroutines)                /* leave si command alone */
     {
       enable_longjmp_breakpoint ();
-      cleanups = make_cleanup ((make_cleanup_func) disable_longjmp_breakpoint,
-                              0);
+      if (!event_loop_p || !target_can_async_p ())
+       cleanups = make_cleanup ((make_cleanup_func) disable_longjmp_breakpoint,
+                                0);
+      else
+        make_exec_cleanup ((make_cleanup_func) disable_longjmp_breakpoint, 0);
+    }
+
+  /* In synchronous case, all is well, just use the regular for loop. */
+  if (!event_loop_p || !target_can_async_p ())
+    {
+      for (; count > 0; count--)
+       {
+         clear_proceed_status ();
+
+         frame = get_current_frame ();
+         if (!frame)           /* Avoid coredump here.  Why tho? */
+           error ("No current frame");
+         step_frame_address = FRAME_FP (frame);
+         step_sp = read_sp ();
+
+         if (!single_inst)
+           {
+             find_pc_line_pc_range (stop_pc, &step_range_start, &step_range_end);
+             if (step_range_end == 0)
+               {
+                 char *name;
+                 if (find_pc_partial_function (stop_pc, &name, &step_range_start,
+                                               &step_range_end) == 0)
+                   error ("Cannot find bounds of current function");
+
+                 target_terminal_ours ();
+                 printf_filtered ("\
+Single stepping until exit from function %s, \n\
+which has no line number information.\n", name);
+               }
+           }
+         else
+           {
+             /* Say we are stepping, but stop after one insn whatever it does.  */
+             step_range_start = step_range_end = 1;
+             if (!skip_subroutines)
+               /* It is stepi.
+                  Don't step over function calls, not even to functions lacking
+                  line numbers.  */
+               step_over_calls = 0;
+           }
+
+         if (skip_subroutines)
+           step_over_calls = 1;
+
+         step_multi = (count > 1);
+         proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 1);
+
+         if (!stop_step)
+           break;
+
+         /* FIXME: On nexti, this may have already been done (when we hit the
+            step resume break, I think).  Probably this should be moved to
+            wait_for_inferior (near the top).  */
+#if defined (SHIFT_INST_REGS)
+         SHIFT_INST_REGS ();
+#endif
+       }
+
+      if (!single_inst || skip_subroutines)
+       do_cleanups (cleanups);
+      return;
+    }
+  /* In case of asynchronous target things get complicated, do only
+     one step for now, before returning control to the event loop. Let
+     the continuation figure out how many other steps we need to do,
+     and handle them one at the time, through step_once(). */
+  else
+    {
+      if (event_loop_p && target_can_async_p ())
+       step_once (skip_subroutines, single_inst, count);
+    }
+}
+
+/* Called after we are done with one step operation, to check whether
+   we need to step again, before we print the prompt and return control
+   to the user. If count is > 1, we will need to do one more call to
+   proceed(), via step_once(). Basically it is like step_once and
+   step_1_continuation are co-recursive. */
+static void
+step_1_continuation (arg)
+     struct continuation_arg *arg;
+{
+  int count;
+  int skip_subroutines;
+  int single_inst;
+
+  skip_subroutines = arg->data.integer;
+  single_inst      = arg->next->data.integer;
+  count            = arg->next->next->data.integer;
+
+  if (stop_step)
+    {
+      /* FIXME: On nexti, this may have already been done (when we hit the
+        step resume break, I think).  Probably this should be moved to
+        wait_for_inferior (near the top).  */
+#if defined (SHIFT_INST_REGS)
+      SHIFT_INST_REGS ();
+#endif
+      step_once (skip_subroutines, single_inst, count - 1);
     }
+  else
+    if (!single_inst || skip_subroutines)
+      do_exec_cleanups (ALL_CLEANUPS);
+}
+
+/* Do just one step operation. If count >1 we will have to set up a
+   continuation to be done after the target stops (after this one
+   step). This is useful to implement the 'step n' kind of commands, in
+   case of asynchronous targets. We had to split step_1 into two parts,
+   one to be done before proceed() and one afterwards. This function is
+   called in case of step n with n>1, after the first step operation has
+   been completed.*/
+static void 
+step_once (int skip_subroutines, int single_inst, int count)
+{ 
+  struct continuation_arg *arg1; 
+  struct continuation_arg *arg2;
+  struct continuation_arg *arg3; 
+  struct frame_info *frame;
 
-  for (; count > 0; count--)
+  if (count > 0)
     {
       clear_proceed_status ();
 
@@ -517,21 +655,23 @@ which has no line number information.\n", name);
        step_over_calls = 1;
 
       step_multi = (count > 1);
+      arg1 =
+       (struct continuation_arg *) xmalloc (sizeof (struct continuation_arg));
+      arg2 =
+       (struct continuation_arg *) xmalloc (sizeof (struct continuation_arg));
+      arg3 =
+       (struct continuation_arg *) xmalloc (sizeof (struct continuation_arg));
+      arg1->next = arg2;
+      arg1->data.integer = skip_subroutines;
+      arg2->next = arg3;
+      arg2->data.integer = single_inst;
+      arg3->next = NULL;
+      arg3->data.integer = count;
+      add_intermediate_continuation (step_1_continuation, arg1);
       proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 1);
-      if (!stop_step)
-       break;
-
-      /* FIXME: On nexti, this may have already been done (when we hit the
-         step resume break, I think).  Probably this should be moved to
-         wait_for_inferior (near the top).  */
-#if defined (SHIFT_INST_REGS)
-      SHIFT_INST_REGS ();
-#endif
     }
-
-  if (!single_inst || skip_subroutines)
-    do_cleanups (cleanups);
 }
+
 \f
 /* Continue program at specified address.  */
 
@@ -712,8 +852,13 @@ breakpoint_auto_delete_contents (arg)
    The dummy's frame is automatically popped whenever that break is hit.
    If that is the first time the program stops, run_stack_dummy
    returns to its caller with that frame already gone and returns 0.
-   Otherwise, run_stack-dummy returns 1 (the frame will eventually be popped
-   when we do hit that breakpoint).  */
+   
+   Otherwise, run_stack-dummy returns a non-zero value.
+   If the called function receives a random signal, we do not allow the user
+   to continue executing it as this may not work.  The dummy frame is poped
+   and we return 1.
+   If we hit a breakpoint, we leave the frame in place and return 2 (the frame
+   will eventually be popped when we do hit the dummy end breakpoint).  */
 
 int
 run_stack_dummy (addr, buffer)
@@ -721,6 +866,7 @@ run_stack_dummy (addr, buffer)
      char *buffer;
 {
   struct cleanup *old_cleanups = make_cleanup (null_cleanup, 0);
+  int saved_async = 0;
 
   /* Now proceed, having reached the desired place.  */
   clear_proceed_status ();
@@ -767,15 +913,29 @@ run_stack_dummy (addr, buffer)
 
   disable_watchpoints_before_interactive_call_start ();
   proceed_to_finish = 1;       /* We want stop_registers, please... */
+
+  if (target_can_async_p ())
+    saved_async = target_async_mask (0);
+
   proceed (addr, TARGET_SIGNAL_0, 0);
+
+  if (saved_async)
+    target_async_mask (saved_async);
+
   enable_watchpoints_after_interactive_call_stop ();
 
   discard_cleanups (old_cleanups);
 
-  if (!stop_stack_dummy)
+  /* We can stop during an inferior call because a signal is received. */
+  if (stopped_by_random_signal)
     return 1;
+    
+  /* We may also stop prematurely because we hit a breakpoint in the
+     called routine. */
+  if (!stop_stack_dummy)
+    return 2;
 
-  /* On return, the stack dummy has been popped already.  */
+  /* On normal return, the stack dummy has been popped already.  */
 
   memcpy (buffer, stop_registers, REGISTER_BYTES);
   return 0;
@@ -876,13 +1036,26 @@ static void
 print_return_value (int structure_return, struct type *value_type)
 {
   register value_ptr value;
+#ifdef UI_OUT
+  static struct ui_stream *stb = NULL;
+#endif /* UI_OUT */
 
   if (!structure_return)
     {
       value = value_being_returned (value_type, stop_registers, structure_return);
+#ifdef UI_OUT
+      stb = ui_out_stream_new (uiout);
+      ui_out_text (uiout, "Value returned is ");
+      ui_out_field_fmt (uiout, "gdb-result-var", "$%d", record_latest_value (value));
+      ui_out_text (uiout, "= ");
+      value_print (value, stb->stream, 0, Val_no_prettyprint);
+      ui_out_field_stream (uiout, "return-value", stb);
+      ui_out_text (uiout, "\n");
+#else /* UI_OUT */
       printf_filtered ("Value returned is $%d = ", record_latest_value (value));
       value_print (value, gdb_stdout, 0, Val_no_prettyprint);
       printf_filtered ("\n");
+#endif /* UI_OUT */
     }
   else
     {
@@ -891,13 +1064,30 @@ print_return_value (int structure_return, struct type *value_type)
         initiate the call, as opposed to the call_function_by_hand case */
 #ifdef VALUE_RETURNED_FROM_STACK
       value = 0;
+#ifdef UI_OUT
+      ui_out_text (uiout, "Value returned has type: ");
+      ui_out_field_string (uiout, "return-type", TYPE_NAME (value_type));
+      ui_out_text (uiout, ".");
+      ui_out_text (uiout, " Cannot determine contents\n");
+#else /* UI_OUT */
       printf_filtered ("Value returned has type: %s.", TYPE_NAME (value_type));
       printf_filtered (" Cannot determine contents\n");
+#endif /* UI_OUT */
 #else
       value = value_being_returned (value_type, stop_registers, structure_return);
+#ifdef UI_OUT
+      stb = ui_out_stream_new (uiout);
+      ui_out_text (uiout, "Value returned is ");
+      ui_out_field_fmt (uiout, "gdb-result-var", "$%d", record_latest_value (value));
+      ui_out_text (uiout, "= ");
+      value_print (value, stb->stream, 0, Val_no_prettyprint);
+      ui_out_field_stream (uiout, "return-value", stb);
+      ui_out_text (uiout, "\n");
+#else
       printf_filtered ("Value returned is $%d = ", record_latest_value (value));
       value_print (value, gdb_stdout, 0, Val_no_prettyprint);
       printf_filtered ("\n");
+#endif
 #endif
     }
 }
@@ -916,9 +1106,11 @@ finish_command_continuation (arg)
 {
   register struct symbol *function;
   struct breakpoint *breakpoint;
+  struct cleanup *cleanups;
 
-  breakpoint = (struct breakpoint *) arg->data;
-  function = (struct symbol *) (arg->next)->data;
+  breakpoint = (struct breakpoint *) arg->data.pointer;
+  function   = (struct symbol *)     arg->next->data.pointer;
+  cleanups   = (struct cleanup *)    arg->next->next->data.pointer;
 
   if (bpstat_find_breakpoint (stop_bpstat, breakpoint) != NULL
       && function != 0)
@@ -933,7 +1125,7 @@ finish_command_continuation (arg)
 
       if (TYPE_CODE (value_type) == TYPE_CODE_VOID)
        {
-         do_exec_cleanups (ALL_CLEANUPS);
+         do_exec_cleanups (cleanups);
          return;
        }
 
@@ -946,7 +1138,7 @@ finish_command_continuation (arg)
 
       print_return_value (struct_return, value_type); 
     }
-  do_exec_cleanups (ALL_CLEANUPS);
+  do_exec_cleanups (cleanups);
 }
 
 /* "finish": Set a temporary breakpoint at the place
@@ -962,7 +1154,7 @@ finish_command (arg, from_tty)
   register struct symbol *function;
   struct breakpoint *breakpoint;
   struct cleanup *old_chain;
-  struct continuation_arg *arg1, *arg2;
+  struct continuation_arg *arg1, *arg2, *arg3;
 
   int async_exec = 0;
 
@@ -1004,7 +1196,7 @@ finish_command (arg, from_tty)
   if (!event_loop_p || !target_can_async_p ())
     old_chain = make_cleanup ((make_cleanup_func) delete_breakpoint, breakpoint);
   else
-    make_exec_cleanup ((make_cleanup_func) delete_breakpoint, breakpoint);
+    old_chain = make_exec_cleanup ((make_cleanup_func) delete_breakpoint, breakpoint);
 
   /* Find the function we will return from.  */
 
@@ -1028,10 +1220,14 @@ finish_command (arg, from_tty)
        (struct continuation_arg *) xmalloc (sizeof (struct continuation_arg));
       arg2 =
        (struct continuation_arg *) xmalloc (sizeof (struct continuation_arg));
+      arg3 =
+       (struct continuation_arg *) xmalloc (sizeof (struct continuation_arg));
       arg1->next = arg2;
-      arg2->next = NULL;
-      arg1->data = (PTR) breakpoint;
-      arg2->data = (PTR) function;
+      arg2->next = arg3;
+      arg3->next = NULL;
+      arg1->data.pointer = breakpoint;
+      arg2->data.pointer = function;
+      arg3->data.pointer = old_chain;
       add_continuation (finish_command_continuation, arg1);
     }
 
@@ -1600,6 +1796,15 @@ detach_command (args, from_tty)
 
 /* Stop the execution of the target while running in async mode, in
    the backgound. */
+#ifdef UI_OUT
+void
+interrupt_target_command_wrapper (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  interrupt_target_command (args, from_tty);
+}
+#endif
 static void
 interrupt_target_command (args, from_tty)
      char *args;
This page took 0.027218 seconds and 4 git commands to generate.