Skip to content

Commit 0641fdc

Browse files
committed
Added persistence
1 parent dd27c8c commit 0641fdc

2 files changed

Lines changed: 205 additions & 23 deletions

File tree

CMakeLists.txt

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,31 +10,39 @@ if(NOT X64DBGFOLDER)
1010
endif()
1111
endif()
1212

13-
IF(CMAKE_BUILD_TYPE MATCHES DEBUG)
13+
IF(CMAKE_BUILD_TYPE MATCHES Debug)
1414
set(SUFFIX "d")
1515
else()
1616
set(SUFFIX "")
17-
ENDIF(CMAKE_BUILD_TYPE MATCHES DEBUG)
17+
ENDIF()
1818

1919
if(${CMAKE_SIZEOF_VOID_P} EQUAL 4)
2020
set(ARCH "32")
21+
set(ARCH_NAME "86")
2122
else()
2223
set(ARCH "64")
24+
set(ARCH_NAME "64")
2325
endif()
24-
26+
message("Building with suffix ${SUFFIX}(${CMAKE_BUILD_TYPE}), for x${ARCH}")
2527
# Figure out if the folder given is a release or not
2628
if(EXISTS ${X64DBGFOLDER}/bin)
2729
set (CMAKE_LIBRARY_OUTPUT_DIRECTORY ${X64DBGFOLDER}/bin/x${ARCH}${SUFFIX}/plugins)
2830
set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${X64DBGFOLDER}/bin/x${ARCH}${SUFFIX}/plugins)
2931
include_directories( ${X64DBGFOLDER}/release )
30-
LINK_DIRECTORIES( ${X64DBGFOLDER}/bin/x${ARCH}${SUFFIX} )
32+
33+
set(PLUGINSDK_DIR ${X64DBGFOLDER}/release/pluginsdk )
34+
LINK_DIRECTORIES( ${X64DBGFOLDER}/bin/x${ARCH}${SUFFIX})
3135
else()
3236
set (CMAKE_LIBRARY_OUTPUT_DIRECTORY ${X64DBGFOLDER}/release/x${ARCH}${SUFFIX}/plugins)
3337
set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${X64DBGFOLDER}/release/x${ARCH}${SUFFIX}/plugins)
3438
include_directories( ${X64DBGFOLDER} )
39+
40+
set(PLUGINSDK_DIR ${X64DBGFOLDER}/pluginsdk )
3541
LINK_DIRECTORIES( ${X64DBGFOLDER}/pluginsdk )
3642
endif()
3743

44+
LINK_DIRECTORIES(${PLUGINSDK_DIR}/jansson)
45+
3846
include_directories( . ChaiScript/include)
3947
set(CMAKE_INCLUDE_CURRENT_DIR ON)
4048
set(CMAKE_AUTOMOC ON)
@@ -55,5 +63,10 @@ add_library(chaiScriptPlugin SHARED
5563
set_source_files_properties(Std.cc PROPERTIES COMPILE_FLAGS "/YcStd.h")
5664
set_source_files_properties(pluginmain.cc PROPERTIES COMPILE_FLAGS "/YuStd.h")
5765

58-
target_link_libraries(chaiScriptPlugin x${ARCH}dbg x${ARCH}bridge Qt5::Core Qt5::Widgets )
66+
target_link_libraries(chaiScriptPlugin
67+
x${ARCH}dbg
68+
x${ARCH}bridge
69+
Qt5::Core Qt5::Widgets
70+
jansson_x${ARCH_NAME}
71+
)
5972
set_target_properties(chaiScriptPlugin PROPERTIES SUFFIX ".dp${ARCH}")

pluginmain.cc

Lines changed: 187 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
#include "Std.h"
22
#include <QLibraryInfo>
3+
#include <QFileSystemWatcher>
4+
35
#include <pluginsdk/bridgemain.h>
46

57
chaiscript::ChaiScript chai(chaiscript::Std_Lib::library());
68

9+
710
#define plugin_name "CHAISCRIPTPLUGIN"
811
#define plugin_version 1
912

@@ -14,6 +17,8 @@ int hMenuDisasm;
1417
int hMenuDump;
1518
int hMenuStack;
1619

20+
QFileSystemWatcher* fileWatcher = 0;
21+
1722
std::string to_hex(int d, size_t digits = 2) {
1823
std::stringstream ss;
1924
ss << std::hex <<
@@ -23,24 +28,54 @@ std::string to_hex(int d, size_t digits = 2) {
2328
return ss.str();
2429
}
2530

26-
bool chaiEval(int argc, char* argv[]) {
27-
if(argc < 2) {
28-
_plugin_logprintf("Please specify a chai command\n");
29-
return true;
30-
}
31+
static std::set<std::string> commands;
32+
static std::set<std::string> workspace_set;
33+
static std::vector<std::string> workspace;
3134

35+
duint chaiEvalDirect(const char* cmd) {
3236
try {
33-
auto bv = chai.eval(argv[1]);
34-
if(bv.get_type_info().is_arithmetic()) {
35-
return chai.boxed_cast<int>(bv);
37+
auto bv = chai.eval(cmd);
38+
if(bv.get_type_info().is_arithmetic()) {
39+
return chai.boxed_cast<duint>(bv);
40+
}
41+
if(bv.get_type_info().name() == "bool") {
42+
return chai.boxed_cast<bool>(bv);
3643
}
37-
return true;
44+
_plugin_logprintf(" >>> bv type is: %s \n" , bv.get_type_info().name().c_str() );
45+
return 0;
3846
}
3947
catch ( const std::exception &e ) {
4048
_plugin_logprintf(" >>> Exception thrown: %s \n" , e.what( ) );
4149
}
4250

43-
return true;
51+
return 0;
52+
}
53+
54+
bool chaiEvalCommand(int argc, char* argv[]) {
55+
if(argc == 0)
56+
return false;
57+
std::string cmdName = argv[0];
58+
auto pos = cmdName.find_first_of(" \t");
59+
if(pos != std::string::npos)
60+
cmdName = cmdName.substr(0, pos);
61+
62+
std::stringstream cmd;
63+
cmd << cmdName << "(";
64+
for(int i = 1;i < argc;i++) {
65+
if(i > 1)
66+
cmd << ", ";
67+
cmd << argv[i];
68+
}
69+
cmd << ")";
70+
return chaiEvalDirect(cmd.str().c_str());
71+
}
72+
73+
74+
bool chaiEval(int argc, char* argv[]) {
75+
if(argc < 2)
76+
return false;
77+
78+
return chaiEvalDirect(argv[1]);
4479
}
4580

4681
bool chaiShowEnv(int argc, char* argv[]) {
@@ -62,15 +97,41 @@ bool chaiShowEnv(int argc, char* argv[]) {
6297
_plugin_logprintf("%s, ", func.first.c_str() );
6398
}
6499
}
100+
101+
_plugin_logprintf("\nWorkspace: \n");
102+
for(const auto &script : workspace) {
103+
if(std::regex_search(script, reg)) {
104+
_plugin_logprintf("\t%s\n", script.c_str() );
105+
}
106+
}
107+
108+
_plugin_logprintf("\nCommands: \n");
109+
for(const auto &command : commands) {
110+
if(std::regex_search(command, reg)) {
111+
_plugin_logprintf("\t%s\n", command.c_str() );
112+
}
113+
}
65114
_plugin_logprintf("\n\n");
66115

67116
return true;
68117
}
69118

70-
static void _chaiLoad(const std::string& fileName) {
119+
static void _chaiLoad(const std::string& fileName, bool reload = false) {
71120
try {
72121
chai.eval_file(fileName);
73-
_plugin_logprintf(" >>> [" plugin_name "] Loaded %s \n" , fileName.c_str() );
122+
if(workspace_set.find(fileName) == workspace_set.end()) {
123+
workspace.push_back(fileName);
124+
workspace_set.insert(fileName);
125+
if(fileWatcher) {
126+
QString qtFileName(fileName.c_str());
127+
fileWatcher->addPath(qtFileName);
128+
}
129+
}
130+
if(reload) {
131+
_plugin_logprintf(" >>> [" plugin_name "] Reloaded %s on modifcation\n" , fileName.c_str() );
132+
} else {
133+
_plugin_logprintf(" >>> [" plugin_name "] Loaded %s \n" , fileName.c_str() );
134+
}
74135
}
75136
catch ( const std::exception &e ) {
76137
_plugin_logprintf(" >>> Exception thrown: %s \n" , e.what( ) );
@@ -86,6 +147,52 @@ static void _chaiLoad() {
86147
_chaiLoad(fileName);
87148
}
88149
}
150+
bool chaiClearWorkspace(int argc, char* argv[]) {
151+
for(auto script : workspace) {
152+
QString path(script.c_str());
153+
if(fileWatcher)
154+
fileWatcher->removePath(path);
155+
}
156+
commands.clear();
157+
workspace.clear();
158+
workspace_set.clear();
159+
return true;
160+
}
161+
162+
duint chaiExpr(int argc, const duint* argv, void * usrdata) {
163+
std::string& cmdName = *(std::string*)usrdata;
164+
std::stringstream cmd;
165+
cmd << cmdName << "(";
166+
for(int i = 0;i < argc;i++) {
167+
if(i != 0)
168+
cmd << ", ";
169+
cmd << argv[i];
170+
}
171+
cmd << ")";
172+
return chaiEvalDirect(cmd.str().c_str());
173+
}
174+
175+
bool chaiRegisterCommand(const char* cmd) {
176+
commands.insert(cmd);
177+
178+
const auto funcs = chai.get_state().engine_state.m_boxed_functions;
179+
try {
180+
const chaiscript::Boxed_Value& c = chai.eval(std::string(cmd) + ".get_arity()");
181+
int arity = chaiscript::boxed_cast<int>(c);
182+
_plugin_registerexprfunctionuserdata(pluginHandle, cmd, arity, chaiExpr, new std::string(cmd));
183+
}
184+
catch ( const std::exception &e ) {
185+
_plugin_logprintf(" >>> Exception thrown: %s \n" , e.what( ) );
186+
}
187+
return _plugin_registercommand(pluginHandle, cmd, chaiEvalCommand, false);
188+
}
189+
190+
bool chaiRegisterCommand(int argc, char* argv[]) {
191+
if(argc < 2) {
192+
return false;
193+
}
194+
return chaiRegisterCommand(argv[1]);
195+
}
89196

90197
bool chaiLoad(int argc, char* argv[]) {
91198
std::string fileName = "";
@@ -129,29 +236,85 @@ static void registerChaiFunctions() {
129236
#define DBG_FUNCTION(x) chai.add(chaiscript::fun(FunctionWrapper(&x, 0)), Sanitize(#x));
130237
#include "dbgops.h"
131238

239+
chai.add(chaiscript::type_conversion<int, duint>());
240+
chai.add(chaiscript::type_conversion<unsigned int, duint>());
132241
}
133242

134-
extern "C" DLL_EXPORT bool plugstop() {
135-
return true;
243+
static void saveCache(CBTYPE cbType, void* callbackInfo) {
244+
PLUG_CB_LOADSAVEDB* loadSaveInfo = (PLUG_CB_LOADSAVEDB*)callbackInfo;
245+
246+
json_t* chaiScriptRoot = json_object();
247+
248+
if(!workspace.empty()) {
249+
json_t* loadedScripts = json_array();
250+
for(auto script : workspace) {
251+
json_array_append_new(loadedScripts, json_string(script.c_str()));
252+
}
253+
json_object_set(chaiScriptRoot, "workspace", loadedScripts);
254+
}
255+
256+
if(!commands.empty()) {
257+
json_t* definedCommands = json_array();
258+
for(auto command : commands) {
259+
json_array_append_new(definedCommands, json_string(command.c_str()));
260+
}
261+
json_object_set(chaiScriptRoot, "commands", definedCommands);
262+
}
263+
264+
json_object_set(loadSaveInfo->root, "chaiScript", chaiScriptRoot);
136265
}
137266

267+
static void loadCache(CBTYPE cbType, void* callbackInfo) {
268+
PLUG_CB_LOADSAVEDB* loadSaveInfo = (PLUG_CB_LOADSAVEDB*)callbackInfo;
269+
270+
json_t* chaiScriptRoot = json_object_get(loadSaveInfo->root, "chaiScript");
271+
if(chaiScriptRoot == 0)
272+
return;
273+
274+
json_t* loadedScripts = json_object_get(chaiScriptRoot, "workspace");
275+
276+
for(size_t i = 0;i < json_array_size(loadedScripts);i++) {
277+
_chaiLoad( json_string_value( json_array_get(loadedScripts, i) ) );
278+
}
279+
280+
json_t* definedCommands = json_object_get(chaiScriptRoot, "commands");
281+
282+
for(size_t i = 0;i < json_array_size(definedCommands);i++) {
283+
chaiRegisterCommand(json_string_value(json_array_get(definedCommands, i)));
284+
}
285+
}
286+
287+
138288
extern "C" DLL_EXPORT bool pluginit(PLUG_INITSTRUCT* initStruct) {
139289
initStruct->pluginVersion = plugin_version;
140290
initStruct->sdkVersion = PLUG_SDKVERSION;
141-
strcpy(initStruct->pluginName, plugin_name);
291+
strncpy_s(initStruct->pluginName, sizeof(initStruct->pluginName), plugin_name, sizeof(initStruct->pluginName));
142292
pluginHandle = initStruct->pluginHandle;
143293

144294
_plugin_logprintf("[ChaiScript] Qt version %s\n", QLibraryInfo::build());
145295

146296
if(!_plugin_registercommand(pluginHandle, "chaiEval", chaiEval, false))
147-
_plugin_logputs("error registering the \"exec\" command!");
297+
_plugin_logputs("error registering the \"chaiEval\" command!");
148298

149299
if(!_plugin_registercommand(pluginHandle, "chaiLoad", chaiLoad, false))
150-
_plugin_logputs("error registering the \"exec\" command!");
300+
_plugin_logputs("error registering the \"chaiLoad\" command!");
151301

152302
if(!_plugin_registercommand(pluginHandle, "chaiShowEnv", chaiShowEnv, false))
153-
_plugin_logputs("error registering the \"exec\" command!");
303+
_plugin_logputs("error registering the \"chaiShowEnv\" command!");
304+
305+
if(!_plugin_registercommand(pluginHandle, "chaiClearWorkspace", chaiClearWorkspace, false))
306+
_plugin_logputs("error registering the \"chaiClearWorkspace\" command!");
307+
308+
if(!_plugin_registercommand(pluginHandle, "chaiRegisterCommand", chaiRegisterCommand, false))
309+
_plugin_logputs("error registering the \"chaiRegisterCommand\" command!");
310+
311+
fileWatcher = new QFileSystemWatcher();
312+
QObject::connect(fileWatcher, &QFileSystemWatcher::fileChanged, [] (const QString& path) {
313+
_chaiLoad(path.toStdString(), true);
314+
});
154315

316+
_plugin_registercallback(pluginHandle, CBTYPE::CB_SAVEDB, saveCache);
317+
_plugin_registercallback(pluginHandle, CBTYPE::CB_LOADDB, loadCache);
155318
return true;
156319
}
157320

@@ -165,6 +328,12 @@ extern "C" DLL_EXPORT void plugsetup(PLUG_SETUPSTRUCT* setupStruct) {
165328
registerChaiFunctions();
166329
}
167330

331+
extern "C" DLL_EXPORT bool plugstop() {
332+
delete fileWatcher;
333+
fileWatcher = 0;
334+
return true;
335+
}
336+
168337
extern "C" DLL_EXPORT BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
169338
return TRUE;
170339
}

0 commit comments

Comments
 (0)