Scripting: Add "console" logger bridge

This commit is contained in:
Vicki Pfau 2022-05-09 00:42:13 -07:00
parent e3758597f8
commit 17d2373975
5 changed files with 155 additions and 1 deletions

View File

@ -56,6 +56,9 @@ int mLogFilterLevels(const struct mLogFilter*, int category);
ATTRIBUTE_FORMAT(printf, 3, 4)
void mLog(int category, enum mLogLevel level, const char* format, ...);
ATTRIBUTE_FORMAT(printf, 4, 5)
void mLogExplicit(struct mLogger*, int category, enum mLogLevel level, const char* format, ...);
#define mLOG(CATEGORY, LEVEL, ...) mLog(_mLOG_CAT_ ## CATEGORY, mLOG_ ## LEVEL, __VA_ARGS__)
#define mLOG_DECLARE_CATEGORY(CATEGORY) extern int _mLOG_CAT_ ## CATEGORY;

View File

@ -10,13 +10,18 @@
CXX_GUARD_START
#include <mgba/core/log.h>
#ifdef USE_DEBUGGERS
#include <mgba/debugger/debugger.h>
#endif
#include <mgba/script/types.h>
mLOG_DECLARE_CATEGORY(SCRIPT);
struct mCore;
struct mLogger;
mSCRIPT_DECLARE_STRUCT(mCore);
mSCRIPT_DECLARE_STRUCT(mLogger);
struct mScriptBridge;
struct VFile;
@ -52,10 +57,12 @@ bool mScriptBridgeLoadScript(struct mScriptBridge*, const char* name);
bool mScriptBridgeLookupSymbol(struct mScriptBridge*, const char* name, int32_t* out);
struct mScriptContext;
struct mCore;
void mScriptContextAttachCore(struct mScriptContext*, struct mCore*);
void mScriptContextDetachCore(struct mScriptContext*);
void mScriptContextAttachLogger(struct mScriptContext*, struct mLogger*);
void mScriptContextDetachLogger(struct mScriptContext*);
CXX_GUARD_END
#endif

View File

@ -80,6 +80,14 @@ void mLog(int category, enum mLogLevel level, const char* format, ...) {
va_end(args);
}
void mLogExplicit(struct mLogger* context, int category, enum mLogLevel level, const char* format, ...) {
va_list args;
va_start(args, format);
if (!context->filter || mLogFilterTest(context->filter, category, level)) {
context->log(context, category, level, format, args);
}
}
void mLogFilterInit(struct mLogFilter* filter) {
HashTableInit(&filter->categories, 8, NULL);
TableInit(&filter->levels, 8, NULL);

View File

@ -10,6 +10,8 @@
#include <mgba-util/table.h>
#include <mgba-util/vfs.h>
mLOG_DEFINE_CATEGORY(SCRIPT, "Scripting", "script");
struct mScriptBridge {
struct Table engines;
struct mDebugger* debugger;
@ -196,3 +198,36 @@ void mScriptContextAttachCore(struct mScriptContext* context, struct mCore* core
void mScriptContextDetachCore(struct mScriptContext* context) {
mScriptContextRemoveGlobal(context, "emu");
}
void mScriptLog(struct mLogger* logger, struct mScriptString* msg) {
mLogExplicit(logger, _mLOG_CAT_SCRIPT, mLOG_INFO, "%s", msg->buffer);
}
void mScriptWarn(struct mLogger* logger, struct mScriptString* msg) {
mLogExplicit(logger, _mLOG_CAT_SCRIPT, mLOG_WARN, "%s", msg->buffer);
}
void mScriptError(struct mLogger* logger, struct mScriptString* msg) {
mLogExplicit(logger, _mLOG_CAT_SCRIPT, mLOG_ERROR, "%s", msg->buffer);
}
mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mLogger, log, mScriptLog, 1, STR, msg);
mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mLogger, warn, mScriptWarn, 1, STR, msg);
mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mLogger, error, mScriptError, 1, STR, msg);
mSCRIPT_DEFINE_STRUCT(mLogger)
mSCRIPT_DEFINE_STRUCT_METHOD(mLogger, log)
mSCRIPT_DEFINE_STRUCT_METHOD(mLogger, warn)
mSCRIPT_DEFINE_STRUCT_METHOD(mLogger, error)
mSCRIPT_DEFINE_END;
void mScriptContextAttachLogger(struct mScriptContext* context, struct mLogger* logger) {
struct mScriptValue* value = mScriptValueAlloc(mSCRIPT_TYPE_MS_S(mLogger));
value->value.opaque = logger;
mScriptContextSetGlobal(context, "console", value);
mScriptValueDeref(value);
}
void mScriptContextDetachLogger(struct mScriptContext* context) {
mScriptContextRemoveGlobal(context, "console");
}

View File

@ -6,6 +6,7 @@
#include "util/test/suite.h"
#include <mgba/core/core.h>
#include <mgba/core/log.h>
#include <mgba/core/scripting.h>
#include <mgba/internal/script/lua.h>
#include <mgba/script/context.h>
@ -23,6 +24,13 @@
#error "Need a valid platform for testing"
#endif
struct mScriptTestLogger {
struct mLogger d;
char* log;
char* warn;
char* error;
};
static const uint8_t _fakeGBROM[0x4000] = {
[0x100] = 0x18, // Loop forever
[0x101] = 0xFE, // jr, $-2
@ -76,6 +84,59 @@ static const uint8_t _fakeGBROM[0x4000] = {
mScriptValueDeref(global); \
} while(0)
static void _mScriptTestLog(struct mLogger* log, int category, enum mLogLevel level, const char* format, va_list args) {
UNUSED(category);
struct mScriptTestLogger* logger = (struct mScriptTestLogger*) log;
char* message;
#ifdef HAVE_VASPRINTF
vasprintf(&message, format, args);
#else
char messageBuf[64];
vsnprintf(messageBuf, format, args);
message = strdup(messageBuf);
#endif
switch (level) {
case mLOG_INFO:
if (logger->log) {
free(logger->log);
}
logger->log = message;
break;
case mLOG_WARN:
if (logger->warn) {
free(logger->warn);
}
logger->warn = message;
break;
case mLOG_ERROR:
if (logger->error) {
free(logger->error);
}
logger->error = message;
break;
default:
free(message);
}
}
static void mScriptTestLoggerInit(struct mScriptTestLogger* logger) {
memset(logger, 0, sizeof(*logger));
logger->d.log = _mScriptTestLog;
}
static void mScriptTestLoggerDeinit(struct mScriptTestLogger* logger) {
if (logger->log) {
free(logger->log);
}
if (logger->warn) {
free(logger->warn);
}
if (logger->error) {
free(logger->error);
}
}
M_TEST_SUITE_SETUP(mScriptCore) {
if (mSCRIPT_ENGINE_LUA->init) {
mSCRIPT_ENGINE_LUA->init(mSCRIPT_ENGINE_LUA);
@ -230,6 +291,45 @@ M_TEST_DEFINE(memoryWrite) {
mScriptContextDeinit(&context);
}
M_TEST_DEFINE(logging) {
SETUP_LUA;
struct mScriptTestLogger logger;
mScriptTestLoggerInit(&logger);
mScriptContextAttachLogger(&context, &logger.d);
LOAD_PROGRAM(
"assert(console)\n"
"console:log(\"log\")\n"
"console:warn(\"warn\")\n"
"console:error(\"error\")\n"
"a = console\n"
);
assert_true(lua->run(lua));
assert_non_null(logger.log);
assert_non_null(logger.warn);
assert_non_null(logger.error);
assert_string_equal(logger.log, "log");
assert_string_equal(logger.warn, "warn");
assert_string_equal(logger.error, "error");
mScriptContextDetachLogger(&context);
LOAD_PROGRAM(
"assert(not console)\n"
);
assert_true(lua->run(lua));
LOAD_PROGRAM(
"a:log(\"l2\")\n"
);
assert_false(lua->run(lua));
mScriptTestLoggerDeinit(&logger);
mScriptContextDeinit(&context);
}
M_TEST_SUITE_DEFINE_SETUP_TEARDOWN(mScriptCore,
cmocka_unit_test(globals),
cmocka_unit_test(infoFuncs),
@ -237,4 +337,5 @@ M_TEST_SUITE_DEFINE_SETUP_TEARDOWN(mScriptCore,
cmocka_unit_test(runFrame),
cmocka_unit_test(memoryRead),
cmocka_unit_test(memoryWrite),
cmocka_unit_test(logging),
)