Core: Add symbol lookups from scripts

This commit is contained in:
Vicki Pfau 2017-07-15 19:51:33 -07:00
parent 6a3002d398
commit 220b786c9c
6 changed files with 78 additions and 11 deletions

View File

@ -24,6 +24,7 @@ struct mScriptEngine {
bool (*isScript)(struct mScriptEngine*, const char* name, struct VFile* vf);
bool (*loadScript)(struct mScriptEngine*, const char* name, struct VFile* vf);
void (*run)(struct mScriptEngine*);
bool (*lookupSymbol)(struct mScriptEngine*, const char* name, int32_t* out);
#ifdef USE_DEBUGGERS
void (*debuggerEntered)(struct mScriptEngine*, enum mDebuggerEntryReason, struct mDebuggerEntryInfo*);
@ -44,6 +45,8 @@ void mScriptBridgeDebuggerEntered(struct mScriptBridge*, enum mDebuggerEntryReas
void mScriptBridgeRun(struct mScriptBridge*);
bool mScriptBridgeLoadScript(struct mScriptBridge*, const char* name);
bool mScriptBridgeLookupSymbol(struct mScriptBridge*, const char* name, int32_t* out);
CXX_GUARD_END
#endif

View File

@ -19,6 +19,12 @@ struct mScriptInfo {
bool success;
};
struct mScriptSymbol {
const char* name;
int32_t* out;
bool success;
};
static void _seDeinit(void* value) {
struct mScriptEngine* se = value;
se->deinit(se);
@ -33,6 +39,15 @@ static void _seTryLoad(const char* key, void* value, void* user) {
}
}
static void _seLookupSymbol(const char* key, void* value, void* user) {
UNUSED(key);
struct mScriptEngine* se = value;
struct mScriptSymbol* si = user;
if (!si->success) {
si->success = se->lookupSymbol(se, si->name, si->out);
}
}
static void _seRun(const char* key, void* value, void* user) {
UNUSED(key);
UNUSED(user);
@ -111,3 +126,13 @@ bool mScriptBridgeLoadScript(struct mScriptBridge* sb, const char* name) {
vf->close(vf);
return info.success;
}
bool mScriptBridgeLookupSymbol(struct mScriptBridge* sb, const char* name, int32_t* out) {
struct mScriptSymbol info = {
.name = name,
.out = out,
.success = false
};
HashTableEnumerate(&sb->engines, _seLookupSymbol, &info);
return info.success;
}

View File

@ -551,6 +551,11 @@ static void _lookupIdentifier(struct mDebugger* debugger, const char* name, stru
struct CLIDebugger* cliDebugger = (struct CLIDebugger*) debugger;
if (cliDebugger->system) {
uint32_t value;
#ifdef ENABLE_SCRIPTING
if (debugger->bridge && mScriptBridgeLookupSymbol(debugger->bridge, name, &dv->intValue)) {
return;
}
#endif
if (debugger->core->symbolTable && mDebuggerSymbolLookup(debugger->core->symbolTable, name, &dv->intValue, &dv->segmentValue)) {
return;
}

View File

@ -72,22 +72,26 @@ ffi.embedding_api('\n'.join(lines))
ffi.embedding_init_code("""
from mgba._pylib import ffi, lib
debugger = None
symbols = {}
globalSyms = {
'symbols': symbols
}
pendingCode = []
@ffi.def_extern()
def mPythonSetDebugger(_debugger):
def mPythonSetDebugger(debugger):
from mgba.debugger import NativeDebugger, CLIDebugger
global debugger
if debugger and debugger._native == _debugger:
oldDebugger = globalSyms.get('debugger')
if oldDebugger and oldDebugger._native == debugger:
return
if not _debugger:
debugger = None
if oldDebugger and not debugger:
del globalSyms['debugger']
return
if _debugger.type == lib.DEBUGGER_CLI:
debugger = CLIDebugger(_debugger)
if debugger.type == lib.DEBUGGER_CLI:
debugger = CLIDebugger(debugger)
else:
debugger = NativeDebugger(_debugger)
debugger = NativeDebugger(debugger)
globalSyms['debugger'] = debugger
@ffi.def_extern()
def mPythonLoadScript(name, vf):
@ -106,18 +110,40 @@ ffi.embedding_init_code("""
def mPythonRunPending():
global pendingCode
for code in pendingCode:
exec(code)
exec(code, globalSyms, {})
pendingCode = []
@ffi.def_extern()
def mPythonDebuggerEntered(reason, info):
global debugger
debugger = globalSyms['debugger']
if not debugger:
return
if info == ffi.NULL:
info = None
for cb in debugger._cbs:
cb(reason, info)
@ffi.def_extern()
def mPythonLookupSymbol(name, outptr):
name = ffi.string(name).decode('utf-8')
if name not in symbols:
return False
sym = symbols[name]
val = None
try:
val = int(sym)
except:
try:
val = sym()
except:
pass
if val is None:
return False
try:
outptr[0] = ffi.cast('int32_t', val)
return True
except:
return False
""")
if __name__ == "__main__":

View File

@ -21,6 +21,7 @@ static void mPythonScriptEngineDeinit(struct mScriptEngine*);
static bool mPythonScriptEngineIsScript(struct mScriptEngine*, const char* name, struct VFile* vf);
static bool mPythonScriptEngineLoadScript(struct mScriptEngine*, const char* name, struct VFile* vf);
static void mPythonScriptEngineRun(struct mScriptEngine*);
static bool mPythonScriptEngineLookupSymbol(struct mScriptEngine*, const char* name, int32_t* out);
#ifdef USE_DEBUGGERS
static void mPythonScriptDebuggerEntered(struct mScriptEngine*, enum mDebuggerEntryReason, struct mDebuggerEntryInfo*);
@ -39,6 +40,7 @@ struct mPythonScriptEngine* mPythonCreateScriptEngine(void) {
engine->d.isScript = mPythonScriptEngineIsScript;
engine->d.loadScript = mPythonScriptEngineLoadScript;
engine->d.run = mPythonScriptEngineRun;
engine->d.lookupSymbol = mPythonScriptEngineLookupSymbol;
#ifdef USE_DEBUGGERS
engine->d.debuggerEntered = mPythonScriptDebuggerEntered;
#endif
@ -89,6 +91,11 @@ void mPythonScriptEngineRun(struct mScriptEngine* se) {
mPythonRunPending();
}
bool mPythonScriptEngineLookupSymbol(struct mScriptEngine* se, const char* name, int32_t* out) {
struct mPythonScriptEngine* engine = (struct mPythonScriptEngine*) se;
return mPythonLookupSymbol(name, out);
}
#ifdef USE_DEBUGGERS
void mPythonScriptDebuggerEntered(struct mScriptEngine* se, enum mDebuggerEntryReason reason, struct mDebuggerEntryInfo* info) {
struct mPythonScriptEngine* engine = (struct mPythonScriptEngine*) se;

View File

@ -4,6 +4,7 @@ struct VFile;
extern bool mPythonLoadScript(const char*, struct VFile*);
extern void mPythonRunPending();
extern bool mPythonLookupSymbol(const char* name, int32_t* out);
#ifdef USE_DEBUGGERS
extern void mPythonSetDebugger(struct mDebugger*);