+ struct call_thread_fsm *sm;
+
+ sm = XCNEW (struct call_thread_fsm);
+ thread_fsm_ctor (&sm->thread_fsm, &call_thread_fsm_ops);
+
+ sm->return_meta_info.gdbarch = gdbarch;
+ sm->return_meta_info.function = function;
+ sm->return_meta_info.value_type = value_type;
+ sm->return_meta_info.struct_return_p = struct_return_p;
+ sm->return_meta_info.struct_addr = struct_addr;
+
+ return sm;
+}
+
+/* Implementation of should_stop method for infcalls. */
+
+static int
+call_thread_fsm_should_stop (struct thread_fsm *self)
+{
+ struct call_thread_fsm *f = (struct call_thread_fsm *) self;
+
+ if (stop_stack_dummy == STOP_STACK_DUMMY)
+ {
+ /* Done. */
+ thread_fsm_set_finished (self);
+
+ /* Stash the return value before the dummy frame is popped and
+ registers are restored to what they were before the
+ call.. */
+ f->return_value = get_call_return_value (&f->return_meta_info);
+
+ /* Break out of wait_sync_command_done. */
+ async_enable_stdin ();
+ }
+
+ return 1;
+}
+
+/* Implementation of should_notify_stop method for infcalls. */
+
+static int
+call_thread_fsm_should_notify_stop (struct thread_fsm *self)
+{
+ if (thread_fsm_finished_p (self))
+ {
+ /* Infcall succeeded. Be silent and proceed with evaluating the
+ expression. */
+ return 0;
+ }
+
+ /* Something wrong happened. E.g., an unexpected breakpoint
+ triggered, or a signal was intercepted. Notify the stop. */
+ return 1;
+}
+
+/* Subroutine of call_function_by_hand to simplify it.
+ Start up the inferior and wait for it to stop.
+ Return the exception if there's an error, or an exception with
+ reason >= 0 if there's no error.
+
+ This is done inside a TRY_CATCH so the caller needn't worry about
+ thrown errors. The caller should rethrow if there's an error. */
+
+static struct gdb_exception
+run_inferior_call (struct call_thread_fsm *sm,
+ struct thread_info *call_thread, CORE_ADDR real_pc)
+{
+ struct gdb_exception caught_error = exception_none;
+ int saved_in_infcall = call_thread->control.in_infcall;
+ ptid_t call_thread_ptid = call_thread->ptid;
+ int saved_sync_execution = sync_execution;
+ int was_running = call_thread->state == THREAD_RUNNING;
+ int saved_interpreter_async = interpreter_async;
+
+ /* Infcalls run synchronously, in the foreground. */
+ sync_execution = 1;
+ /* So that we don't print the prompt prematurely in
+ fetch_inferior_event. */
+ interpreter_async = 0;
+
+ call_thread->control.in_infcall = 1;
+
+ clear_proceed_status (0);
+
+ /* Associate the FSM with the thread after clear_proceed_status
+ (otherwise it'd clear this FSM), and before anything throws, so
+ we don't leak it (and any resources it manages). */
+ call_thread->thread_fsm = &sm->thread_fsm;
+
+ disable_watchpoints_before_interactive_call_start ();
+
+ /* We want to print return value, please... */
+ call_thread->control.proceed_to_finish = 1;
+
+ TRY
+ {
+ proceed (real_pc, GDB_SIGNAL_0);
+
+ /* Inferior function calls are always synchronous, even if the
+ target supports asynchronous execution. */
+ wait_sync_command_done ();
+ }
+ CATCH (e, RETURN_MASK_ALL)
+ {
+ caught_error = e;
+ }
+ END_CATCH
+
+ /* If GDB was previously in sync execution mode, then ensure that it
+ remains so. normal_stop calls async_enable_stdin, so reset it
+ again here. In other cases, stdin will be re-enabled by
+ inferior_event_handler, when an exception is thrown. */
+ sync_execution = saved_sync_execution;
+ interpreter_async = saved_interpreter_async;
+
+ /* At this point the current thread may have changed. Refresh
+ CALL_THREAD as it could be invalid if its thread has exited. */
+ call_thread = find_thread_ptid (call_thread_ptid);
+
+ /* If the infcall does NOT succeed, normal_stop will have already
+ finished the thread states. However, on success, normal_stop
+ defers here, so that we can set back the thread states to what
+ they were before the call. Note that we must also finish the
+ state of new threads that might have spawned while the call was
+ running. The main cases to handle are:
+
+ - "(gdb) print foo ()", or any other command that evaluates an
+ expression at the prompt. (The thread was marked stopped before.)
+
+ - "(gdb) break foo if return_false()" or similar cases where we
+ do an infcall while handling an event (while the thread is still
+ marked running). In this example, whether the condition
+ evaluates true and thus we'll present a user-visible stop is
+ decided elsewhere. */
+ if (!was_running
+ && ptid_equal (call_thread_ptid, inferior_ptid)
+ && stop_stack_dummy == STOP_STACK_DUMMY)
+ finish_thread_state (user_visible_resume_ptid (0));
+
+ enable_watchpoints_after_interactive_call_stop ();
+
+ /* Call breakpoint_auto_delete on the current contents of the bpstat
+ of inferior call thread.
+ If all error()s out of proceed ended up calling normal_stop
+ (and perhaps they should; it already does in the special case
+ of error out of resume()), then we wouldn't need this. */
+ if (caught_error.reason < 0)
+ {
+ if (call_thread != NULL)
+ breakpoint_auto_delete (call_thread->control.stop_bpstat);
+ }
+
+ if (call_thread != NULL)
+ call_thread->control.in_infcall = saved_in_infcall;
+
+ return caught_error;
+}
+
+/* A cleanup function that calls delete_std_terminate_breakpoint. */
+static void
+cleanup_delete_std_terminate_breakpoint (void *ignore)
+{
+ delete_std_terminate_breakpoint ();
+}
+
+/* See infcall.h. */
+
+struct value *
+call_function_by_hand (struct value *function, int nargs, struct value **args)
+{
+ return call_function_by_hand_dummy (function, nargs, args, NULL, NULL);