[gamecode] Delay .ctor calls if debugging

This allows a debugger to do any symbol lookups and other preparations
between loading progs and the first code execution. .ctors are called as
per normal if debug_handler is not set.
This commit is contained in:
Bill Currie 2020-04-02 17:28:37 +09:00
parent f90613bc3a
commit c09f57c39e
3 changed files with 37 additions and 12 deletions

View file

@ -236,14 +236,24 @@ void PR_AddLoadFinishFunc (progs_t *pr, pr_load_func_t *func);
\return true for success, false for failure \return true for success, false for failure
Calls the first set of internal load functions followed by the supplied Calls the first set of internal load functions followed by the supplied
symbol resolution function, if any (progs_t::resolve), the second set of symbol resolution function, if any (progs_t::resolve), then the second set
internal load functions. After that, any primary load functions are called of internal load functions. After that, any primary load functions are
in order of registration followed by any \c .ctor functions in the progs, called in order of registration, and if there is no debug handler,
then any secondary load functions the primary load functions registered PR_RunPostLoadFuncs() is called.
in \e reverse order of registration.
*/ */
int PR_RunLoadFuncs (progs_t *pr); int PR_RunLoadFuncs (progs_t *pr);
/** Run any progs-dependent load functions.
\param pr pointer to ::progs_t VM struct
\return true for success, false for failure
This means any \c .ctor functions in the progs, followed by any secondary
load functions registered by either the primary load functions or the
\.c ctor functions in \e reverse order of registration. This is called
automatically by PR_RunLoadFuncs() if there is no debug handler, otherwise
it is up to the host to call this function.
*/
int PR_RunPostLoadFuncs (progs_t *pr);
/** Validate the opcodes and statement addresses in the progs. This is an /** Validate the opcodes and statement addresses in the progs. This is an
internal load function. internal load function.
\param pr pointer to ::progs_t VM struct \param pr pointer to ::progs_t VM struct

View file

@ -422,6 +422,12 @@ PR_RunLoadFuncs (progs_t *pr)
if (!pr->load_funcs[i] (pr)) if (!pr->load_funcs[i] (pr))
return 0; return 0;
return 1;
}
VISIBLE int
PR_RunPostLoadFuncs (progs_t *pr)
{
if (!pr_run_ctors (pr)) if (!pr_run_ctors (pr))
return 0; return 0;
@ -449,8 +455,12 @@ PR_LoadProgs (progs_t *pr, const char *progsname)
if (!pr->progs) if (!pr->progs)
return; return;
if (!PR_RunLoadFuncs (pr)) if (!PR_RunLoadFuncs (pr)) {
PR_Error (pr, "unable to load %s", progsname); PR_Error (pr, "unable to load %s", progsname);
}
if (!pr->debug_handler && !PR_RunPostLoadFuncs (pr)) {
PR_Error (pr, "unable to load %s", progsname);
}
} }
VISIBLE void VISIBLE void

View file

@ -206,6 +206,17 @@ spawn_progs (qwaq_thread_t *thread)
Sys_Error ("couldn't load %s", name); Sys_Error ("couldn't load %s", name);
} }
if ((dfunc = PR_FindFunction (pr, ".main"))
|| (dfunc = PR_FindFunction (pr, "main"))) {
thread->main_func = dfunc - pr->pr_functions;
} else {
PR_Undefined (pr, "function", "main");
}
if (!PR_RunPostLoadFuncs (pr)) {
PR_Error (pr, "unable to load %s", pr->progs_name);
}
PR_PushFrame (pr); PR_PushFrame (pr);
if (thread->args.size > 2) { if (thread->args.size > 2) {
pr_argc = thread->args.size - 1; pr_argc = thread->args.size - 1;
@ -216,12 +227,6 @@ spawn_progs (qwaq_thread_t *thread)
pr_argv[i] = PR_SetTempString (pr, thread->args.a[1 + i]); pr_argv[i] = PR_SetTempString (pr, thread->args.a[1 + i]);
pr_argv[i] = 0; pr_argv[i] = 0;
if ((dfunc = PR_FindFunction (pr, ".main"))
|| (dfunc = PR_FindFunction (pr, "main"))) {
thread->main_func = dfunc - pr->pr_functions;
} else {
PR_Undefined (pr, "function", "main");
}
PR_RESET_PARAMS (pr); PR_RESET_PARAMS (pr);
P_INT (pr, 0) = pr_argc; P_INT (pr, 0) = pr_argc;
P_POINTER (pr, 1) = PR_SetPointer (pr, pr_argv); P_POINTER (pr, 1) = PR_SetPointer (pr, pr_argv);