src/core/scripting.c (view raw)
1/* Copyright (c) 2013-2017 Jeffrey Pfau
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6#include <mgba/core/scripting.h>
7
8#include <mgba-util/table.h>
9#include <mgba-util/vfs.h>
10
11struct mScriptBridge {
12 struct Table engines;
13 struct mDebugger* debugger;
14};
15
16struct mScriptInfo {
17 const char* name;
18 struct VFile* vf;
19 bool success;
20};
21
22static void _seDeinit(void* value) {
23 struct mScriptEngine* se = value;
24 se->deinit(se);
25}
26
27static void _seTryLoad(const char* key, void* value, void* user) {
28 UNUSED(key);
29 struct mScriptEngine* se = value;
30 struct mScriptInfo* si = user;
31 if (!si->success && se->isScript(se, si->name, si->vf)) {
32 si->success = se->loadScript(se, si->name, si->vf);
33 }
34}
35
36static void _seRun(const char* key, void* value, void* user) {
37 UNUSED(key);
38 UNUSED(user);
39 struct mScriptEngine* se = value;
40 se->run(se);
41}
42
43#ifdef USE_DEBUGGERS
44struct mScriptDebuggerEntry {
45 enum mDebuggerEntryReason reason;
46 struct mDebuggerEntryInfo* info;
47};
48
49static void _seDebuggerEnter(const char* key, void* value, void* user) {
50 UNUSED(key);
51 struct mScriptEngine* se = value;
52 struct mScriptDebuggerEntry* entry = user;
53 se->debuggerEntered(se, entry->reason, entry->info);
54}
55#endif
56
57struct mScriptBridge* mScriptBridgeCreate(void) {
58 struct mScriptBridge* sb = malloc(sizeof(*sb));
59 HashTableInit(&sb->engines, 0, _seDeinit);
60 sb->debugger = NULL;
61 return sb;
62}
63
64void mScriptBridgeDestroy(struct mScriptBridge* sb) {
65 HashTableDeinit(&sb->engines);
66 free(sb);
67}
68
69void mScriptBridgeInstallEngine(struct mScriptBridge* sb, struct mScriptEngine* se) {
70 if (!se->init(se, sb)) {
71 return;
72 }
73 const char* name = se->name(se);
74 HashTableInsert(&sb->engines, name, se);
75}
76
77#ifdef USE_DEBUGGERS
78void mScriptBridgeSetDebugger(struct mScriptBridge* sb, struct mDebugger* debugger) {
79 sb->debugger = debugger;
80 debugger->bridge = sb;
81}
82
83struct mDebugger* mScriptBridgeGetDebugger(struct mScriptBridge* sb) {
84 return sb->debugger;
85}
86
87void mScriptBridgeDebuggerEntered(struct mScriptBridge* sb, enum mDebuggerEntryReason reason, struct mDebuggerEntryInfo* info) {
88 struct mScriptDebuggerEntry entry = {
89 .reason = reason,
90 .info = info
91 };
92 HashTableEnumerate(&sb->engines, _seDebuggerEnter, &entry);
93}
94#endif
95
96void mScriptBridgeRun(struct mScriptBridge* sb) {
97 HashTableEnumerate(&sb->engines, _seRun, NULL);
98}
99
100bool mScriptBridgeLoadScript(struct mScriptBridge* sb, const char* name) {
101 struct VFile* vf = VFileOpen(name, O_RDONLY);
102 if (!vf) {
103 return false;
104 }
105 struct mScriptInfo info = {
106 .name = name,
107 .vf = vf,
108 .success = false
109 };
110 HashTableEnumerate(&sb->engines, _seTryLoad, &info);
111 vf->close(vf);
112 return info.success;
113}