src/debugger/cli-debugger-scripting.c (view raw)
1/* Copyright (c) 2013-2020 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#include <mgba-util/string.h>
8#include <mgba-util/vfs.h>
9
10#include <mgba/debugger/debugger.h>
11#include <mgba/internal/debugger/cli-debugger.h>
12
13static const char* CLIScriptEngineName(struct mScriptEngine*);
14static bool CLIScriptEngineInit(struct mScriptEngine*, struct mScriptBridge*);
15static void CLIScriptEngineDeinit(struct mScriptEngine*);
16static bool CLIScriptEngineIsScript(struct mScriptEngine*, const char* name, struct VFile* vf);
17static bool CLIScriptEngineLoadScript(struct mScriptEngine*, const char* name, struct VFile* vf);
18static void CLIScriptEngineRun(struct mScriptEngine*);
19static bool CLIScriptEngineLookupSymbol(struct mScriptEngine*, const char* name, int32_t* out);
20static void CLIScriptDebuggerEntered(struct mScriptEngine*, enum mDebuggerEntryReason, struct mDebuggerEntryInfo*);
21
22struct CLIScriptStatement {
23 char* command;
24 size_t commandLen;
25};
26
27DECLARE_VECTOR(CLIScript, struct CLIScriptStatement);
28DEFINE_VECTOR(CLIScript, struct CLIScriptStatement);
29
30struct CLIScriptEngine {
31 struct mScriptEngine d;
32 struct mScriptBridge* sb;
33 struct CLIScript script;
34};
35
36static void CLIScriptEngineClear(struct CLIScriptEngine* engine) {
37 size_t i = CLIScriptSize(&engine->script);
38 while (i-- > 0) {
39 struct CLIScriptStatement* statement = CLIScriptGetPointer(&engine->script, i);
40 free(statement->command);
41 }
42 CLIScriptClear(&engine->script);
43}
44
45struct CLIScriptEngine* CLICreateScriptEngine(void) {
46 struct CLIScriptEngine* engine = malloc(sizeof(*engine));
47 engine->d.name = CLIScriptEngineName;
48 engine->d.init = CLIScriptEngineInit;
49 engine->d.deinit = CLIScriptEngineDeinit;
50 engine->d.isScript = CLIScriptEngineIsScript;
51 engine->d.loadScript = CLIScriptEngineLoadScript;
52 engine->d.run = CLIScriptEngineRun;
53 engine->d.lookupSymbol = CLIScriptEngineLookupSymbol;
54 engine->d.debuggerEntered = CLIScriptDebuggerEntered;
55 engine->sb = NULL;
56 return engine;
57}
58
59void CLIDebuggerScriptEngineInstall(struct mScriptBridge* sb) {
60 struct CLIScriptEngine* se = CLICreateScriptEngine();
61 mScriptBridgeInstallEngine(sb, &se->d);
62}
63
64const char* CLIScriptEngineName(struct mScriptEngine* se) {
65 UNUSED(se);
66 return "cli-debugger";
67}
68
69bool CLIScriptEngineInit(struct mScriptEngine* se, struct mScriptBridge* sb) {
70 struct CLIScriptEngine* engine = (struct CLIScriptEngine*) se;
71 engine->sb = sb;
72 CLIScriptInit(&engine->script, 0);
73 return true;
74}
75
76void CLIScriptEngineDeinit(struct mScriptEngine* se) {
77 struct CLIScriptEngine* engine = (struct CLIScriptEngine*) se;
78 CLIScriptEngineClear(engine);
79 CLIScriptDeinit(&engine->script);
80 free(se);
81}
82
83bool CLIScriptEngineIsScript(struct mScriptEngine* se, const char* name, struct VFile* vf) {
84 UNUSED(se);
85 UNUSED(vf);
86 return endswith(name, ".mrc");
87}
88
89bool CLIScriptEngineLoadScript(struct mScriptEngine* se, const char* name, struct VFile* vf) {
90 UNUSED(name);
91 struct CLIScriptEngine* engine = (struct CLIScriptEngine*) se;
92 char buffer[256];
93 ssize_t size;
94 CLIScriptEngineClear(engine);
95 struct CLIScriptStatement* statement;
96 while ((size = vf->readline(vf, buffer, sizeof(buffer))) > 0) {
97 if (buffer[size - 1] == '\n') {
98 --size;
99 }
100 statement = CLIScriptAppend(&engine->script);
101 statement->command = strndup(buffer, size);
102 statement->commandLen = size;
103 }
104 return true;
105}
106
107void CLIScriptEngineRun(struct mScriptEngine* se) {
108 struct CLIScriptEngine* engine = (struct CLIScriptEngine*) se;
109 struct CLIDebugger* debugger = (struct CLIDebugger*) mScriptBridgeGetDebugger(engine->sb);
110 struct CLIScriptStatement* statement;
111 size_t statementCount = CLIScriptSize(&engine->script);
112 size_t i;
113 for (i = 0; i < statementCount; i++) {
114 statement = CLIScriptGetPointer(&engine->script, i);
115 CLIDebuggerRunCommand(debugger, statement->command, statement->commandLen);
116 }
117}
118
119bool CLIScriptEngineLookupSymbol(struct mScriptEngine* se, const char* name, int32_t* out) {
120 UNUSED(se);
121 UNUSED(name);
122 UNUSED(out);
123 return false;
124}
125
126void CLIScriptDebuggerEntered(struct mScriptEngine* se, enum mDebuggerEntryReason reason, struct mDebuggerEntryInfo* info) {
127 UNUSED(reason);
128 UNUSED(info);
129 struct CLIScriptEngine* engine = (struct CLIScriptEngine*) se;
130
131 struct mDebugger* debugger = mScriptBridgeGetDebugger(engine->sb);
132 if (!debugger) {
133 return;
134 }
135
136 // TODO: CLIDebuggerEntered(reason, info);
137}