aboutsummaryrefslogtreecommitdiffstats
path: root/bruiser
diff options
context:
space:
mode:
Diffstat (limited to 'bruiser')
-rw-r--r--bruiser/README.md18
-rw-r--r--bruiser/bruiser-extra.h51
-rw-r--r--bruiser/bruiser.cpp340
-rw-r--r--bruiser/lua-scripts/list.lua14
-rw-r--r--bruiser/lua-scripts/test.lua1
-rw-r--r--bruiser/lua-scripts/test1.lua1
-rw-r--r--bruiser/lua-scripts/test2.lua1
-rw-r--r--bruiser/lua-scripts/test3.lua1
-rw-r--r--bruiser/lua-scripts/test4.lua4
-rw-r--r--bruiser/luadummy.h605
10 files changed, 982 insertions, 54 deletions
diff --git a/bruiser/README.md b/bruiser/README.md
index 3fef1f4..062ea3a 100644
--- a/bruiser/README.md
+++ b/bruiser/README.md
@@ -2,10 +2,24 @@
### What is it?
Bruiser is implemented as an interactive commandline interface. It features an embedded lua interpreter plus the history and auto-completion and suggestion features we have all come to expect from shell-like tools.<br/>
-Regarding the actual functionality, it will feature non-blind selective mutations. You can ask it to list information regrading the source codes it is run on. The eventuality of this idea is to help with maintaining code or in giving the viewer an overview of the code. The final feature is the name-sale. It looks at the code and decides how to break it. For more explanation please read on.<br/>
+Regarding the actual functionality, it will feature non-blind selective mutations. You can ask it to list information regrading the source codes it is run on. The eventuality of this idea is to help with maintaining code or in giving the viewer an overview of the code. The final feature is the name-sake. It looks at the code and decides how to break it. For more explanation please read on.<br/>
+
+### How it Works?
+To put it simply, bruiser is an interactive lua interpreter that uses linenoise for shell-like features(history, tab-completion, auto-suggestion). You get the full power of lua plus the bruiser functions whcih are implemented as lua scripts that call back to the cpp code to get things done.<br/>
+To put this into perspecttive, think you run `list vars` in bruiser. It gets you the list of vars but that's it. You can't save them to a file or do anything else with them. With the old way of doing things I had to add a command that did that and then you could do it but what if you wanted to do something else? what then? well you get the idea. That would also mean that bruiser's language would be made up gradually which would result in something ugly and warrant a lot of rewrites.<br/>
+With the new way of doing things, the user is only limited by their imagination and lua, not me, and there is no learning curve for learning a garbage language that I would have to come up with.<br/>
+Also, there is no reason to implement any extra features to be able to automate your use of bruiser. just run a lua script and tell bruiser to run that.<br/>
### DSL?
-bruiser has an embedded lua interpreter so nobody would have to deal with a new DSL.<br/>
+bruiser has an embedded lua interpreter so nobody would have to deal with a new DSL. It's good old lua.<br/>
+
+### Lua vs Luajit
+In the current implementation, bruiser will only support lua and not luajit. luajit is way faster than lua which will play an important role in bruiser's overall performance but luajit is generally less stable than lua and usually behind in terms of what new features of lua the language it supports.<br/>
+The plan is to add both and for the user to be able to pick which one to use when running bruiser.<br/>
+
+### Warning
+The current implementation loads all lua libraries which also includes it's `os` library. To give you an idea, `os.execute()` is very similar to `system()` in C. This decision has been made to speed up testing and the dev process.<br/>
+Also like `mutatord` and `mutatorclient`, bruiser does not need any sudo access.<br/>
### Non-blind Selective mutation?
bruiser looks at your code, learns your code and then decides how to mutate your code. That's non-blind selective mutation.<br/>
diff --git a/bruiser/bruiser-extra.h b/bruiser/bruiser-extra.h
index 2f5de84..554b170 100644
--- a/bruiser/bruiser-extra.h
+++ b/bruiser/bruiser-extra.h
@@ -91,23 +91,21 @@ std::vector<std::string> BRUISR_COMMANDS =
std::vector<std::string> LUA_FUNCS =
{
- "help",
+ "help()",
"quit",
"exit",
- "list",
- "list vars",
- "list funcs",
- "list structs",
- "list classes",
- "list unions",
- "list records",
- "history",
- "shell",
- "version",
- "clear",
- "hijack",
- "hijack main",
- "m0",
+ "history()",
+ "version()",
+ "clear()",
+ "m0()",
+ "runlua",
+ "Funcs()",
+ "Vars()",
+ "Arrays()",
+ "Structs()",
+ "Unions()",
+ "Classes()",
+ "hijackmain()",
"_G",
"_VERSION",
"assert",
@@ -267,7 +265,28 @@ std::vector<std::string> LUA_FUNCS =
"LUA_INIT",
"LUA_INIT_5_3",
"LUA_PATH",
- "LUA_PATH_5_3"
+ "LUA_PATH_5_3",
+ "and",
+ "break",
+ "do",
+ "else",
+ "elseif",
+ "end",
+ "false",
+ "for",
+ "function",
+ "if",
+ "in",
+ "local",
+ "nil",
+ "not",
+ "or",
+ "repeat",
+ "return",
+ "then",
+ "true",
+ "until",
+ "while"
};
/**********************************************************************************************************************/
#endif
diff --git a/bruiser/bruiser.cpp b/bruiser/bruiser.cpp
index 4bd4f87..12cbea0 100644
--- a/bruiser/bruiser.cpp
+++ b/bruiser/bruiser.cpp
@@ -49,6 +49,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.*
#include "lua-5.3.4/src/lua.hpp"
#include "lua-5.3.4/src/lualib.h"
#include "lua-5.3.4/src/lauxlib.h"
+
+#include "luadummy.h"
/**********************************************************************************************************************/
/*used namespaces*/
using namespace llvm;
@@ -64,6 +66,7 @@ using namespace clang::tooling;
/**********************************************************************************************************************/
/*global vars*/
static llvm::cl::OptionCategory BruiserCategory("Empty");
+std::vector<std::string> PushToLua;
bruiser::M0_ERR m0_err;
bruiser::BruiserReport BruiseRep;
@@ -79,23 +82,41 @@ class LuaEngine
LS = luaL_newstate();
}
- void LoadBaseLib(void)
- {
- luaopen_base(LS);
- }
+ /*@DEVI-this will just create member functions that open a single lua libarary.
+ * For example to load the string library just call LuaEngine::LoadstringLib().*/
+#define OPEN_LUA_LIBS(__x1) \
+ void Load##__x1##Lib(void){\
+ luaL_requiref(LS, #__x1, luaopen_##__x1, 1);}
+
+ OPEN_LUA_LIBS(base)
+ OPEN_LUA_LIBS(table)
+ OPEN_LUA_LIBS(io)
+ OPEN_LUA_LIBS(string)
+ OPEN_LUA_LIBS(math)
+ OPEN_LUA_LIBS(os)
+
+#undef OPEN_LUA_LIBS
void LoadAuxLibs(void)
{
- luaopen_table(LS);
- luaopen_io(LS);
- luaopen_string(LS);
+ luaL_requiref(LS, "table", luaopen_table, 1);
+ luaL_requiref(LS, "io", luaopen_io, 1);
+ luaL_requiref(LS, "string", luaopen_string, 1);
}
void LoadEverylib(void)
{
- this->LoadBaseLib();
- this->LoadAuxLibs();
- luaopen_math(LS);
+ luaL_openlibs(LS);
+ }
+
+ void RunString(char* __lua_string)
+ {
+
+ }
+
+ void RunChunk(char* __lua_chunk)
+ {
+ dostring(LS, __lua_chunk, "test");
}
int RunScript(char* __lua_script)
@@ -103,6 +124,33 @@ class LuaEngine
return luaL_dofile(LS, __lua_script);
}
+ void Test(void)
+ {
+ luaL_dofile(LS, "./lua-scripts/test.lua");
+ luaL_dofile(LS, "./lua-scripts/test1.lua");
+ luaL_dofile(LS, "./lua-scripts/test2.lua");
+ }
+
+ void Test2(void)
+ {
+ luaL_dofile(LS, "./lua-scripts/test1.lua");
+ }
+
+ void Test3(void)
+ {
+ luaL_dofile(LS, "./lua-scripts/test2.lua");
+ }
+
+ void Test4(void)
+ {
+ luaL_dofile(LS, "./lua-scripts/test3.lua");
+ }
+
+ lua_State* GetLuaState(void)
+ {
+ return this->LS;
+ }
+
void Cleanup(void)
{
lua_close(LS);
@@ -123,7 +171,6 @@ bruiser::BruiserReport::~BruiserReport()
BruiserLog.close();
}
-template <typename T>
/**
* @brief Will print the argument in the log file. Expects to receive valid types usable for a stream.
*
@@ -131,6 +178,7 @@ template <typename T>
*
* @return Returns true if the write was successful, false otherwise.
*/
+template <typename T>
bool bruiser::BruiserReport::PrintToLog(T __arg)
{
BruiserLog << __arg << "\n";
@@ -366,6 +414,7 @@ class LiveListFuncs : public MatchFinder::MatchCallback
//printf(CYAN"%s", R.getRewrittenText(clang::SourceRange(SLShebang, SLBody.getLocWithOffset(-1))).c_str());
//printf(NORMAL "\n");
PRINT_WITH_COLOR_LB(CYAN, R.getRewrittenText(clang::SourceRange(SLShebang, SLBody.getLocWithOffset(-1))).c_str());
+ PushToLua.push_back(R.getRewrittenText(clang::SourceRange(SLShebang, SLBody.getLocWithOffset(-1))));
//PRINT_WITH_COLOR_LB(GREEN, "end");
}
else
@@ -373,6 +422,7 @@ class LiveListFuncs : public MatchFinder::MatchCallback
SourceLocation SL = FD->getLocStart();
SourceLocation SLE = FD->getLocEnd();
PRINT_WITH_COLOR_LB(CYAN, R.getRewrittenText(clang::SourceRange(SL, SLE)).c_str());
+ PushToLua.push_back(R.getRewrittenText(clang::SourceRange(SL, SLE)));
}
}
}
@@ -393,6 +443,7 @@ class LiveListVars : public MatchFinder::MatchCallback
const clang::VarDecl* VD = MR.Nodes.getNodeAs<clang::VarDecl>("livelistvars");
PRINT_WITH_COLOR_LB(CYAN, R.getRewrittenText(SourceRange(VD->getLocStart(), VD->getLocEnd())).c_str());
+ PushToLua.push_back(R.getRewrittenText(SourceRange(VD->getLocStart(), VD->getLocEnd())));
}
}
@@ -412,6 +463,7 @@ class LiveListRecords : public MatchFinder::MatchCallback
const clang::RecordDecl* RD = MR.Nodes.getNodeAs<clang::RecordDecl>("livelistvars");
PRINT_WITH_COLOR_LB(CYAN, R.getRewrittenText(SourceRange(RD->getLocStart(), RD->getLocEnd())).c_str());
+ PushToLua.push_back(R.getRewrittenText(SourceRange(RD->getLocStart(), RD->getLocEnd())));
}
}
@@ -609,7 +661,10 @@ class BruiserFrontendAction : public ASTFrontendAction
{
public:
BruiserFrontendAction() {}
- virtual ~BruiserFrontendAction() {}
+ virtual ~BruiserFrontendAction()
+ {
+ delete BDCProto;
+ }
void EndSourceFileAction() override
{
@@ -619,21 +674,21 @@ public:
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, StringRef file) override
{
DiagnosticsEngine &DE = CI.getPreprocessor().getDiagnostics();
- BlankDiagConsumer* BDCProto = new BlankDiagConsumer;
- DE.setClient(BDCProto);
+ DE.setClient(BDCProto, false);
TheRewriter.setSourceMgr(CI.getSourceManager(), CI.getLangOpts());
return llvm::make_unique<BruiserASTConsumer>(TheRewriter);
}
private:
Rewriter TheRewriter;
+ BlankDiagConsumer* BDCProto = new BlankDiagConsumer;
};
/**********************************************************************************************************************/
class LiveActionListVars : public ASTFrontendAction
{
public:
- LiveActionListVars() {}
- virtual ~LiveActionListVars()
+ LiveActionListVars() = default;
+ virtual ~LiveActionListVars()
{
delete BDCProto;
}
@@ -643,7 +698,7 @@ class LiveActionListVars : public ASTFrontendAction
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, StringRef file) override
{
DiagnosticsEngine &DE = CI.getPreprocessor().getDiagnostics();
- DE.setClient(BDCProto);
+ DE.setClient(BDCProto, false);
TheRewriter.setSourceMgr(CI.getSourceManager(), CI.getLangOpts());
return llvm::make_unique<LiveListVarsConsumer>(TheRewriter);
}
@@ -657,108 +712,270 @@ class LiveActionListFuncs : public ASTFrontendAction
{
public:
LiveActionListFuncs() {}
- ~LiveActionListFuncs() {}
+ ~LiveActionListFuncs()
+ {
+ delete BDCProto;
+ }
void EndSourceFileAction() override {}
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, StringRef file) override
{
DiagnosticsEngine &DE = CI.getPreprocessor().getDiagnostics();
- BlankDiagConsumer* BDCProto = new BlankDiagConsumer;
- DE.setClient(BDCProto);
+ DE.setClient(BDCProto, false);
TheRewriter.setSourceMgr(CI.getSourceManager(), CI.getLangOpts());
return llvm::make_unique<LiveListFuncsConsumer>(TheRewriter);
}
private:
Rewriter TheRewriter;
+ BlankDiagConsumer* BDCProto = new BlankDiagConsumer;
};
/**********************************************************************************************************************/
class LiveActionListStructs : public ASTFrontendAction
{
public:
LiveActionListStructs() {}
- ~LiveActionListStructs() {}
+ ~LiveActionListStructs()
+ {
+ delete BDCProto;
+ }
void EndSourceFileAction() override {}
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, StringRef file) override
{
DiagnosticsEngine &DE = CI.getPreprocessor().getDiagnostics();
- BlankDiagConsumer* BDCProto = new BlankDiagConsumer;
- DE.setClient(BDCProto);
+ DE.setClient(BDCProto, false);
TheRewriter.setSourceMgr(CI.getSourceManager(), CI.getLangOpts());
return llvm::make_unique<LiveListStructConsumer>(TheRewriter);
}
private:
Rewriter TheRewriter;
+ BlankDiagConsumer* BDCProto = new BlankDiagConsumer;
};
/**********************************************************************************************************************/
class LiveActionListClasses : public ASTFrontendAction
{
public:
LiveActionListClasses() {}
- ~LiveActionListClasses() {}
+ ~LiveActionListClasses()
+ {
+ delete BDCProto;
+ }
void EndSourceFileAction() override {}
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, StringRef file) override
{
DiagnosticsEngine &DE = CI.getPreprocessor().getDiagnostics();
- BlankDiagConsumer* BDCProto = new BlankDiagConsumer;
- DE.setClient(BDCProto);
+ DE.setClient(BDCProto, false);
TheRewriter.setSourceMgr(CI.getSourceManager(), CI.getLangOpts());
return llvm::make_unique<LiveListClassConsumer>(TheRewriter);
}
private:
Rewriter TheRewriter;
+ BlankDiagConsumer* BDCProto = new BlankDiagConsumer;
};
/**********************************************************************************************************************/
class LiveActionListUnions : public ASTFrontendAction
{
public:
LiveActionListUnions() {}
- ~LiveActionListUnions() {}
+ ~LiveActionListUnions()
+ {
+ delete BDCProto;
+ }
void EndSourceFileAction() override {}
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, StringRef file) override
{
DiagnosticsEngine &DE = CI.getPreprocessor().getDiagnostics();
- BlankDiagConsumer* BDCProto = new BlankDiagConsumer;
- DE.setClient(BDCProto);
+ DE.setClient(BDCProto, false);
TheRewriter.setSourceMgr(CI.getSourceManager(), CI.getLangOpts());
return llvm::make_unique<LiveListUnionConsumer>(TheRewriter);
}
private:
Rewriter TheRewriter;
+ BlankDiagConsumer* BDCProto = new BlankDiagConsumer;
};
/**********************************************************************************************************************/
class LiveActionListArrays : public ASTFrontendAction
{
public:
LiveActionListArrays() {}
- ~LiveActionListArrays() {}
+ ~LiveActionListArrays()
+ {
+ delete BDCProto;
+ }
void EndSourceFileAction() override {}
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, StringRef file) override
{
DiagnosticsEngine &DE = CI.getPreprocessor().getDiagnostics();
- BlankDiagConsumer* BDCProto = new BlankDiagConsumer;
- DE.setClient(BDCProto);
+ DE.setClient(BDCProto, false);
TheRewriter.setSourceMgr(CI.getSourceManager(), CI.getLangOpts());
return llvm::make_unique<LiveListArrayConsumer>(TheRewriter);
}
private:
Rewriter TheRewriter;
+ BlankDiagConsumer* BDCProto = new BlankDiagConsumer;
+};
+/**********************************************************************************************************************/
+/**********************************************************************************************************************/
+/*lua wrappers*/
+class LuaWrapper
+{
+ public:
+ LuaWrapper(ClangTool &__CT) : CT(__CT) {}
+
+ int BruiserLuaHistory(lua_State* __ls)
+ {
+ std::ifstream historyfile;
+ historyfile.open(SHELL_HISTORY_FILE);
+
+ std::string tempstring;
+ unsigned int tempint = 0;
+ while(std::getline(historyfile, tempstring))
+ {
+ printf(GREEN"%d - %s", tempint, tempstring.c_str());
+ printf(NORMAL"\n");
+
+ tempint++;
+ }
+
+ return tempint;
+ }
+
+ int BruiserLuaHelp(lua_State* __ls)
+ {
+ unsigned int argcount = 0U;
+
+ for (auto &iter : bruiser::CMDHelp)
+ {
+ printf(GREEN"%s:%s:%s",iter.name.c_str(),iter.proto.c_str(),iter.descr.c_str());
+ printf(NORMAL"\n");
+ argcount++;
+ }
+
+ std::cout << NORMAL;
+ return argcount;
+ }
+
+ int BruiserLuaHijackMain(lua_State* __ls)
+ {
+ int RunResult = this->GetClangTool().run(newFrontendActionFactory<BruiserFrontendAction>().get());
+ //std::cout << CYAN <<"hijacking main returned " << RunResult << "\n" << NORMAL;
+ printf(CYAN"hijacking main returned %d", RunResult);
+ printf(NORMAL"\n");
+
+ return 1;
+ }
+
+ int BruiserLuaVersion(lua_State* __ls)
+ {
+ PRINT_WITH_COLOR_LB(GREEN, "bruiser experimental version something.");
+ PRINT_WITH_COLOR_LB(GREEN, "project mutator");
+ PRINT_WITH_COLOR_LB(GREEN, "GPL v2.0");
+ PRINT_WITH_COLOR_LB(GREEN, "bloodstalker 2017");
+
+ return 1;
+ }
+
+ int BruiserLuaClear(lua_State* _ls)
+ {
+ linenoiseClearScreen();
+ return 0;
+ }
+
+ int BruiserLuaM0(lua_State* __ls)
+ {
+ BruiseRep.PrintToLog("bruiser exited with:");
+
+ bruiser::ReadM0 M0Rep;
+ tinyxml2::XMLError XMLErr;
+
+ XMLErr = M0Rep.LoadXMLDoc();
+ if (XMLErr != XML_SUCCESS)
+ {
+ std::cout << RED << "could not load m0 xml report.\n" << NORMAL;
+ std::cout << RED << "tinyxml2 returned " << XMLErr << NORMAL;
+ return XMLErr;
+ }
+
+ XMLErr = M0Rep.ReadFirstElement();
+ if (XMLErr != XML_SUCCESS)
+ {
+ std::cerr << RED << "could not read first element of m0 xml report.\n" << NORMAL;
+ return XMLErr;
+ }
+
+ bruiser::SearchM0(M0Rep.getRootPointer());
+
+ return 1;
+ }
+
+#define LIST_GENERATOR(__x1) \
+ int List##__x1(lua_State* __ls)\
+ {\
+ unsigned int InArgCnt = 0U;\
+ InArgCnt = lua_gettop(__ls);\
+ unsigned int returncount=0U;\
+ this->GetClangTool().run(newFrontendActionFactory<LiveActionList##__x1>().get());\
+ for(auto &iter : PushToLua)\
+ {lua_pushstring(__ls, iter.c_str());returncount++;}\
+ PushToLua.clear();\
+ return returncount;\
+ }
+
+#define LIST_LIST_GENERATORS \
+ X(Funcs, "lists all functions") \
+ X(Vars, "lists all variables") \
+ X(Arrays, "lists all arrays") \
+ X(Classes, "lists all classes") \
+ X(Structs, "lists all structs") \
+ X(Unions, "lists all unions") \
+
+#define X(__x1, __x2) LIST_GENERATOR(__x1)
+
+ LIST_LIST_GENERATORS
+
+#undef X
+#undef LIST_GENERATOR
+
+ ClangTool GetClangTool(void)
+ {
+ return this->CT;
+ }
+
+ private:
+ ClangTool CT;
};
/**********************************************************************************************************************/
/**********************************************************************************************************************/
+typedef int (LuaWrapper::*mem_func)(lua_State* L);
+
+/**
+ * @brief A template function to wrap LuaWrapper members into somehting that lua accepts.
+ *
+ * @param __ls
+ *
+ * @return
+ */
+template<mem_func func>
+int LuaDispatch(lua_State* __ls)
+{
+ LuaWrapper* LWPtr = *static_cast<LuaWrapper**>(lua_getextraspace(__ls));
+ return ((*LWPtr).*func)(__ls);
+}
+/**********************************************************************************************************************/
+/**********************************************************************************************************************/
/*Main*/
int main(int argc, const char **argv)
{
@@ -776,8 +993,11 @@ int main(int argc, const char **argv)
std::regex dumplist("^list\\sdump\\s");
std::smatch smresult;
+ /*gets the compilation database and options for the clang instances that we would later run*/
CommonOptionsParser op(argc, argv, BruiserCategory);
ClangTool Tool(op.getCompilations(), op.getSourcePathList());
+ /*initialize the LuaWrapper class so we can register and run them from lua.*/
+ LuaWrapper LW(Tool);
/*linenoise init*/
linenoiseSetCompletionCallback(bruiser::ShellCompletion);
@@ -787,15 +1007,42 @@ int main(int argc, const char **argv)
linenoiseHistoryLoad(SHELL_HISTORY_FILE);
linenoiseSetMultiLine(1);
- /*start runnnin the cli*/
+ /*start running the cli*/
{
char* command;
+
+ LuaEngine LE;
+ LE.LoadEverylib();
+ *static_cast<LuaWrapper**>(lua_getextraspace(LE.GetLuaState())) = &LW;
+
+ /*@DEVI-this part is just registering our LuaWrapper member functions with lua so we can call them from lua.*/
+ lua_register(LE.GetLuaState(), "history", &LuaDispatch<&LuaWrapper::BruiserLuaHistory>);
+ lua_register(LE.GetLuaState(), "help", &LuaDispatch<&LuaWrapper::BruiserLuaHelp>);
+ lua_register(LE.GetLuaState(), "hijackmain", &LuaDispatch<&LuaWrapper::BruiserLuaHijackMain>);
+ lua_register(LE.GetLuaState(), "version", &LuaDispatch<&LuaWrapper::BruiserLuaVersion>);
+ lua_register(LE.GetLuaState(), "clear", &LuaDispatch<&LuaWrapper::BruiserLuaClear>);
+ /*its just regisering the List function from LuaWrapper with X-macros.*/
+#define X(__x1, __x2) lua_register(LE.GetLuaState(), #__x1, &LuaDispatch<&LuaWrapper::List##__x1>);
+
+ LIST_LIST_GENERATORS
+
+#undef X
+#undef LIST_LIST_GENERATORS
+
+ while((command = linenoise("bruiser>>")) != NULL)
+ {
+ linenoiseHistoryAdd(command);
+ linenoiseHistorySave(SHELL_HISTORY_FILE);
+ LE.RunChunk(command);
+ }
+
+ /*end of bruiser main*/
+
while((command = linenoise("bruiser>>")) != NULL)
{
linenoiseHistoryAdd(command);
linenoiseHistorySave(SHELL_HISTORY_FILE);
- //std::cin.getline(command, sizeof(command));
std::string dummy_string(command);
shHistory.History.push_back(command);
@@ -950,9 +1197,30 @@ int main(int argc, const char **argv)
{
LuaEngine LE;
LE.LoadEverylib();
- LE.RunScript((char*)"/home/bloodstalker/devi/abbatoir/hole6/proto.lua");
- LE.Cleanup();
+ LE.Test();
+ //LE.Cleanup();
+ continue;
+ }
+
+#if 1
+ if (std::strcmp(command, "runluachain1") == 0)
+ {
+ LuaEngine LE;
+ LE.LoadEverylib();
+ LE.Test2();
+ //LE.Cleanup();
+ continue;
+ }
+
+ if (std::strcmp(command, "runluachain2") == 0)
+ {
+ LuaEngine LE;
+ LE.LoadEverylib();
+ LE.Test3();
+ //LE.Cleanup();
+ continue;
}
+#endif
if (command[0] == '!')
{
diff --git a/bruiser/lua-scripts/list.lua b/bruiser/lua-scripts/list.lua
new file mode 100644
index 0000000..d23ef04
--- /dev/null
+++ b/bruiser/lua-scripts/list.lua
@@ -0,0 +1,14 @@
+in_command = io.read()
+if in_command == "list funcs" then
+ clangreturn = Funcs()
+elseif in_command == "list vars" then
+ clangreturn = Vars()
+elseif in_command == "list structs" then
+ clangreturn = Structs()
+elseif in_command == "list arrays" then
+ clangreturn = Arrayss()
+elseif in_command == "list classes" then
+ clangreturn = Classes()
+elseif in_command == "list unions" then
+ clangreturn = Unions()
+end
diff --git a/bruiser/lua-scripts/test.lua b/bruiser/lua-scripts/test.lua
new file mode 100644
index 0000000..9c06d44
--- /dev/null
+++ b/bruiser/lua-scripts/test.lua
@@ -0,0 +1 @@
+print("hi, i'm bruiser.")
diff --git a/bruiser/lua-scripts/test1.lua b/bruiser/lua-scripts/test1.lua
new file mode 100644
index 0000000..fc6490e
--- /dev/null
+++ b/bruiser/lua-scripts/test1.lua
@@ -0,0 +1 @@
+teststring = "im not supposed to be empty"
diff --git a/bruiser/lua-scripts/test2.lua b/bruiser/lua-scripts/test2.lua
new file mode 100644
index 0000000..e939cdb
--- /dev/null
+++ b/bruiser/lua-scripts/test2.lua
@@ -0,0 +1 @@
+print (teststring)
diff --git a/bruiser/lua-scripts/test3.lua b/bruiser/lua-scripts/test3.lua
new file mode 100644
index 0000000..c6a65de
--- /dev/null
+++ b/bruiser/lua-scripts/test3.lua
@@ -0,0 +1 @@
+os.exit()s
diff --git a/bruiser/lua-scripts/test4.lua b/bruiser/lua-scripts/test4.lua
new file mode 100644
index 0000000..6d0db5b
--- /dev/null
+++ b/bruiser/lua-scripts/test4.lua
@@ -0,0 +1,4 @@
+--print("yolo")
+--bubu()
+--Funcs()
+Vars()
diff --git a/bruiser/luadummy.h b/bruiser/luadummy.h
new file mode 100644
index 0000000..ed6a939
--- /dev/null
+++ b/bruiser/luadummy.h
@@ -0,0 +1,605 @@
+
+/*DISCLAIMER*/
+/*This header is an exact copy of the lua.c file minus the main function
+ * provided by the lua organization.*/
+/*All rights belong to the respective owners. The license is the same as the
+ * license for the lua implementation provided by the lua organization.*/
+
+
+extern "C"
+{
+/*
+** $Id: lua.c,v 1.230 2017/01/12 17:14:26 roberto Exp $
+** Lua stand-alone interpreter
+** See Copyright Notice in lua.h
+*/
+
+#define lua_c
+
+#include "lua-5.3.4/src/lprefix.h"
+
+
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "lua-5.3.4/src/lua.h"
+
+#include "lua-5.3.4/src/lauxlib.h"
+#include "lua-5.3.4/src/lualib.h"
+
+
+
+#if !defined(LUA_PROMPT)
+#define LUA_PROMPT "> "
+#define LUA_PROMPT2 ">> "
+#endif
+
+#if !defined(LUA_PROGNAME)
+#define LUA_PROGNAME "lua"
+#endif
+
+#if !defined(LUA_MAXINPUT)
+#define LUA_MAXINPUT 512
+#endif
+
+#if !defined(LUA_INIT_VAR)
+#define LUA_INIT_VAR "LUA_INIT"
+#endif
+
+#define LUA_INITVARVERSION LUA_INIT_VAR LUA_VERSUFFIX
+
+
+/*
+** lua_stdin_is_tty detects whether the standard input is a 'tty' (that
+** is, whether we're running lua interactively).
+*/
+#if !defined(lua_stdin_is_tty) /* { */
+
+#if defined(LUA_USE_POSIX) /* { */
+
+#include <unistd.h>
+#define lua_stdin_is_tty() isatty(0)
+
+#elif defined(LUA_USE_WINDOWS) /* }{ */
+
+#include <io.h>
+#include <windows.h>
+
+#define lua_stdin_is_tty() _isatty(_fileno(stdin))
+
+#else /* }{ */
+
+/* ISO C definition */
+#define lua_stdin_is_tty() 1 /* assume stdin is a tty */
+
+#endif /* } */
+
+#endif /* } */
+
+
+/*
+** lua_readline defines how to show a prompt and then read a line from
+** the standard input.
+** lua_saveline defines how to "save" a read line in a "history".
+** lua_freeline defines how to free a line read by lua_readline.
+*/
+#if !defined(lua_readline) /* { */
+
+#if defined(LUA_USE_READLINE) /* { */
+
+#include <readline/readline.h>
+#include <readline/history.h>
+#define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL)
+#define lua_saveline(L,line) ((void)L, add_history(line))
+#define lua_freeline(L,b) ((void)L, free(b))
+
+#else /* }{ */
+
+#define lua_readline(L,b,p) \
+ ((void)L, fputs(p, stdout), fflush(stdout), /* show prompt */ \
+ fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */
+#define lua_saveline(L,line) { (void)L; (void)line; }
+#define lua_freeline(L,b) { (void)L; (void)b; }
+
+#endif /* } */
+
+#endif /* } */
+
+
+
+
+static lua_State *globalL = NULL;
+
+static const char *progname = LUA_PROGNAME;
+
+
+/*
+** Hook set by signal function to stop the interpreter.
+*/
+static void lstop (lua_State *L, lua_Debug *ar) {
+ (void)ar; /* unused arg. */
+ lua_sethook(L, NULL, 0, 0); /* reset hook */
+ luaL_error(L, "interrupted!");
+}
+
+
+/*
+** Function to be called at a C signal. Because a C signal cannot
+** just change a Lua state (as there is no proper synchronization),
+** this function only sets a hook that, when called, will stop the
+** interpreter.
+*/
+static void laction (int i) {
+ signal(i, SIG_DFL); /* if another SIGINT happens, terminate process */
+ lua_sethook(globalL, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1);
+}
+
+
+static void print_usage (const char *badoption) {
+ lua_writestringerror("%s: ", progname);
+ if (badoption[1] == 'e' || badoption[1] == 'l')
+ lua_writestringerror("'%s' needs argument\n", badoption);
+ else
+ lua_writestringerror("unrecognized option '%s'\n", badoption);
+ lua_writestringerror(
+ "usage: %s [options] [script [args]]\n"
+ "Available options are:\n"
+ " -e stat execute string 'stat'\n"
+ " -i enter interactive mode after executing 'script'\n"
+ " -l name require library 'name'\n"
+ " -v show version information\n"
+ " -E ignore environment variables\n"
+ " -- stop handling options\n"
+ " - stop handling options and execute stdin\n"
+ ,
+ progname);
+}
+
+
+/*
+** Prints an error message, adding the program name in front of it
+** (if present)
+*/
+static void l_message (const char *pname, const char *msg) {
+ if (pname) lua_writestringerror("%s: ", pname);
+ lua_writestringerror("%s\n", msg);
+}
+
+
+/*
+** Check whether 'status' is not OK and, if so, prints the error
+** message on the top of the stack. It assumes that the error object
+** is a string, as it was either generated by Lua or by 'msghandler'.
+*/
+static int report (lua_State *L, int status) {
+ if (status != LUA_OK) {
+ const char *msg = lua_tostring(L, -1);
+ l_message(progname, msg);
+ lua_pop(L, 1); /* remove message */
+ }
+ return status;
+}
+
+
+/*
+** Message handler used to run all chunks
+*/
+static int msghandler (lua_State *L) {
+ const char *msg = lua_tostring(L, 1);
+ if (msg == NULL) { /* is error object not a string? */
+ if (luaL_callmeta(L, 1, "__tostring") && /* does it have a metamethod */
+ lua_type(L, -1) == LUA_TSTRING) /* that produces a string? */
+ return 1; /* that is the message */
+ else
+ msg = lua_pushfstring(L, "(error object is a %s value)",
+ luaL_typename(L, 1));
+ }
+ luaL_traceback(L, L, msg, 1); /* append a standard traceback */
+ return 1; /* return the traceback */
+}
+
+
+/*
+** Interface to 'lua_pcall', which sets appropriate message function
+** and C-signal handler. Used to run all chunks.
+*/
+static int docall (lua_State *L, int narg, int nres) {
+ int status;
+ int base = lua_gettop(L) - narg; /* function index */
+ lua_pushcfunction(L, msghandler); /* push message handler */
+ lua_insert(L, base); /* put it under function and args */
+ globalL = L; /* to be available to 'laction' */
+ signal(SIGINT, laction); /* set C-signal handler */
+ status = lua_pcall(L, narg, nres, base);
+ signal(SIGINT, SIG_DFL); /* reset C-signal handler */
+ lua_remove(L, base); /* remove message handler from the stack */
+ return status;
+}
+
+
+static void print_version (void) {
+ lua_writestring(LUA_COPYRIGHT, strlen(LUA_COPYRIGHT));
+ lua_writeline();
+}
+
+
+/*
+** Create the 'arg' table, which stores all arguments from the
+** command line ('argv'). It should be aligned so that, at index 0,
+** it has 'argv[script]', which is the script name. The arguments
+** to the script (everything after 'script') go to positive indices;
+** other arguments (before the script name) go to negative indices.
+** If there is no script name, assume interpreter's name as base.
+*/
+static void createargtable (lua_State *L, char **argv, int argc, int script) {
+ int i, narg;
+ if (script == argc) script = 0; /* no script name? */
+ narg = argc - (script + 1); /* number of positive indices */
+ lua_createtable(L, narg, script + 1);
+ for (i = 0; i < argc; i++) {
+ lua_pushstring(L, argv[i]);
+ lua_rawseti(L, -2, i - script);
+ }
+ lua_setglobal(L, "arg");
+}
+
+
+static int dochunk (lua_State *L, int status) {
+ if (status == LUA_OK) status = docall(L, 0, 0);
+ return report(L, status);
+}
+
+
+static int dofile (lua_State *L, const char *name) {
+ return dochunk(L, luaL_loadfile(L, name));
+}
+
+
+static int dostring (lua_State *L, const char *s, const char *name) {
+ return dochunk(L, luaL_loadbuffer(L, s, strlen(s), name));
+}
+
+
+/*
+** Calls 'require(name)' and stores the result in a global variable
+** with the given name.
+*/
+static int dolibrary (lua_State *L, const char *name) {
+ int status;
+ lua_getglobal(L, "require");
+ lua_pushstring(L, name);
+ status = docall(L, 1, 1); /* call 'require(name)' */
+ if (status == LUA_OK)
+ lua_setglobal(L, name); /* global[name] = require return */
+ return report(L, status);
+}
+
+
+/*
+** Returns the string to be used as a prompt by the interpreter.
+*/
+static const char *get_prompt (lua_State *L, int firstline) {
+ const char *p;
+ lua_getglobal(L, firstline ? "_PROMPT" : "_PROMPT2");
+ p = lua_tostring(L, -1);
+ if (p == NULL) p = (firstline ? LUA_PROMPT : LUA_PROMPT2);
+ return p;
+}
+
+/* mark in error messages for incomplete statements */
+#define EOFMARK "<eof>"
+#define marklen (sizeof(EOFMARK)/sizeof(char) - 1)
+
+
+/*
+** Check whether 'status' signals a syntax error and the error
+** message at the top of the stack ends with the above mark for
+** incomplete statements.
+*/
+static int incomplete (lua_State *L, int status) {
+ if (status == LUA_ERRSYNTAX) {
+ size_t lmsg;
+ const char *msg = lua_tolstring(L, -1, &lmsg);
+ if (lmsg >= marklen && strcmp(msg + lmsg - marklen, EOFMARK) == 0) {
+ lua_pop(L, 1);
+ return 1;
+ }
+ }
+ return 0; /* else... */
+}
+
+
+/*
+** Prompt the user, read a line, and push it into the Lua stack.
+*/
+static int pushline (lua_State *L, int firstline) {
+ char buffer[LUA_MAXINPUT];
+ char *b = buffer;
+ size_t l;
+ const char *prmt = get_prompt(L, firstline);
+ int readstatus = lua_readline(L, b, prmt);
+ if (readstatus == 0)
+ return 0; /* no input (prompt will be popped by caller) */
+ lua_pop(L, 1); /* remove prompt */
+ l = strlen(b);
+ if (l > 0 && b[l-1] == '\n') /* line ends with newline? */
+ b[--l] = '\0'; /* remove it */
+ if (firstline && b[0] == '=') /* for compatibility with 5.2, ... */
+ lua_pushfstring(L, "return %s", b + 1); /* change '=' to 'return' */
+ else
+ lua_pushlstring(L, b, l);
+ lua_freeline(L, b);
+ return 1;
+}
+
+
+/*
+** Try to compile line on the stack as 'return <line>;'; on return, stack
+** has either compiled chunk or original line (if compilation failed).
+*/
+static int addreturn (lua_State *L) {
+ const char *line = lua_tostring(L, -1); /* original line */
+ const char *retline = lua_pushfstring(L, "return %s;", line);
+ int status = luaL_loadbuffer(L, retline, strlen(retline), "=stdin");
+ if (status == LUA_OK) {
+ lua_remove(L, -2); /* remove modified line */
+ if (line[0] != '\0') /* non empty? */
+ lua_saveline(L, line); /* keep history */
+ }
+ else
+ lua_pop(L, 2); /* pop result from 'luaL_loadbuffer' and modified line */
+ return status;
+}
+
+
+/*
+** Read multiple lines until a complete Lua statement
+*/
+static int multiline (lua_State *L) {
+ for (;;) { /* repeat until gets a complete statement */
+ size_t len;
+ const char *line = lua_tolstring(L, 1, &len); /* get what it has */
+ int status = luaL_loadbuffer(L, line, len, "=stdin"); /* try it */
+ if (!incomplete(L, status) || !pushline(L, 0)) {
+ lua_saveline(L, line); /* keep history */
+ return status; /* cannot or should not try to add continuation line */
+ }
+ lua_pushliteral(L, "\n"); /* add newline... */
+ lua_insert(L, -2); /* ...between the two lines */
+ lua_concat(L, 3); /* join them */
+ }
+}
+
+
+/*
+** Read a line and try to load (compile) it first as an expression (by
+** adding "return " in front of it) and second as a statement. Return
+** the final status of load/call with the resulting function (if any)
+** in the top of the stack.
+*/
+static int loadline (lua_State *L) {
+ int status;
+ lua_settop(L, 0);
+ if (!pushline(L, 1))
+ return -1; /* no input */
+ if ((status = addreturn(L)) != LUA_OK) /* 'return ...' did not work? */
+ status = multiline(L); /* try as command, maybe with continuation lines */
+ lua_remove(L, 1); /* remove line from the stack */
+ lua_assert(lua_gettop(L) == 1);
+ return status;
+}
+
+
+/*
+** Prints (calling the Lua 'print' function) any values on the stack
+*/
+static void l_print (lua_State *L) {
+ int n = lua_gettop(L);
+ if (n > 0) { /* any result to be printed? */
+ luaL_checkstack(L, LUA_MINSTACK, "too many results to print");
+ lua_getglobal(L, "print");
+ lua_insert(L, 1);
+ if (lua_pcall(L, n, 0, 0) != LUA_OK)
+ l_message(progname, lua_pushfstring(L, "error calling 'print' (%s)",
+ lua_tostring(L, -1)));
+ }
+}
+
+
+/*
+** Do the REPL: repeatedly read (load) a line, evaluate (call) it, and
+** print any results.
+*/
+static void doREPL (lua_State *L) {
+ int status;
+ const char *oldprogname = progname;
+ progname = NULL; /* no 'progname' on errors in interactive mode */
+ while ((status = loadline(L)) != -1) {
+ if (status == LUA_OK)
+ status = docall(L, 0, LUA_MULTRET);
+ if (status == LUA_OK) l_print(L);
+ else report(L, status);
+ }
+ lua_settop(L, 0); /* clear stack */
+ lua_writeline();
+ progname = oldprogname;
+}
+
+
+/*
+** Push on the stack the contents of table 'arg' from 1 to #arg
+*/
+static int pushargs (lua_State *L) {
+ int i, n;
+ if (lua_getglobal(L, "arg") != LUA_TTABLE)
+ luaL_error(L, "'arg' is not a table");
+ n = (int)luaL_len(L, -1);
+ luaL_checkstack(L, n + 3, "too many arguments to script");
+ for (i = 1; i <= n; i++)
+ lua_rawgeti(L, -i, i);
+ lua_remove(L, -i); /* remove table from the stack */
+ return n;
+}
+
+
+static int handle_script (lua_State *L, char **argv) {
+ int status;
+ const char *fname = argv[0];
+ if (strcmp(fname, "-") == 0 && strcmp(argv[-1], "--") != 0)
+ fname = NULL; /* stdin */
+ status = luaL_loadfile(L, fname);
+ if (status == LUA_OK) {
+ int n = pushargs(L); /* push arguments to script */
+ status = docall(L, n, LUA_MULTRET);
+ }
+ return report(L, status);
+}
+
+
+
+/* bits of various argument indicators in 'args' */
+#define has_error 1 /* bad option */
+#define has_i 2 /* -i */
+#define has_v 4 /* -v */
+#define has_e 8 /* -e */
+#define has_E 16 /* -E */
+
+/*
+** Traverses all arguments from 'argv', returning a mask with those
+** needed before running any Lua code (or an error code if it finds
+** any invalid argument). 'first' returns the first not-handled argument
+** (either the script name or a bad argument in case of error).
+*/
+static int collectargs (char **argv, int *first) {
+ int args = 0;
+ int i;
+ for (i = 1; argv[i] != NULL; i++) {
+ *first = i;
+ if (argv[i][0] != '-') /* not an option? */
+ return args; /* stop handling options */
+ switch (argv[i][1]) { /* else check option */
+ case '-': /* '--' */
+ if (argv[i][2] != '\0') /* extra characters after '--'? */
+ return has_error; /* invalid option */
+ *first = i + 1;
+ return args;
+ case '\0': /* '-' */
+ return args; /* script "name" is '-' */
+ case 'E':
+ if (argv[i][2] != '\0') /* extra characters after 1st? */
+ return has_error; /* invalid option */
+ args |= has_E;
+ break;
+ case 'i':
+ args |= has_i; /* (-i implies -v) *//* FALLTHROUGH */
+ case 'v':
+ if (argv[i][2] != '\0') /* extra characters after 1st? */
+ return has_error; /* invalid option */
+ args |= has_v;
+ break;
+ case 'e':
+ args |= has_e; /* FALLTHROUGH */
+ case 'l': /* both options need an argument */
+ if (argv[i][2] == '\0') { /* no concatenated argument? */
+ i++; /* try next 'argv' */
+ if (argv[i] == NULL || argv[i][0] == '-')
+ return has_error; /* no next argument or it is another option */
+ }
+ break;
+ default: /* invalid option */
+ return has_error;
+ }
+ }
+ *first = i; /* no script name */
+ return args;
+}
+
+
+/*
+** Processes options 'e' and 'l', which involve running Lua code.
+** Returns 0 if some code raises an error.
+*/
+static int runargs (lua_State *L, char **argv, int n) {
+ int i;
+ for (i = 1; i < n; i++) {
+ int option = argv[i][1];
+ lua_assert(argv[i][0] == '-'); /* already checked */
+ if (option == 'e' || option == 'l') {
+ int status;
+ const char *extra = argv[i] + 2; /* both options need an argument */
+ if (*extra == '\0') extra = argv[++i];
+ lua_assert(extra != NULL);
+ status = (option == 'e')
+ ? dostring(L, extra, "=(command line)")
+ : dolibrary(L, extra);
+ if (status != LUA_OK) return 0;
+ }
+ }
+ return 1;
+}
+
+
+
+static int handle_luainit (lua_State *L) {
+ const char *name = "=" LUA_INITVARVERSION;
+ const char *init = getenv(name + 1);
+ if (init == NULL) {
+ name = "=" LUA_INIT_VAR;
+ init = getenv(name + 1); /* try alternative name */
+ }
+ if (init == NULL) return LUA_OK;
+ else if (init[0] == '@')
+ return dofile(L, init+1);
+ else
+ return dostring(L, init, name);
+}
+
+
+/*
+** Main body of stand-alone interpreter (to be called in protected mode).
+** Reads the options and handles them all.
+*/
+static int pmain (lua_State *L) {
+ int argc = (int)lua_tointeger(L, 1);
+ char **argv = (char **)lua_touserdata(L, 2);
+ int script;
+ int args = collectargs(argv, &script);
+ luaL_checkversion(L); /* check that interpreter has correct version */
+ if (argv[0] && argv[0][0]) progname = argv[0];
+ if (args == has_error) { /* bad arg? */
+ print_usage(argv[script]); /* 'script' has index of bad arg. */
+ return 0;
+ }
+ if (args & has_v) /* option '-v'? */
+ print_version();
+ if (args & has_E) { /* option '-E'? */
+ lua_pushboolean(L, 1); /* signal for libraries to ignore env. vars. */
+ lua_setfield(L, LUA_REGISTRYINDEX, "LUA_NOENV");
+ }
+ luaL_openlibs(L); /* open standard libraries */
+ createargtable(L, argv, argc, script); /* create table 'arg' */
+ if (!(args & has_E)) { /* no option '-E'? */
+ if (handle_luainit(L) != LUA_OK) /* run LUA_INIT */
+ return 0; /* error running LUA_INIT */
+ }
+ if (!runargs(L, argv, script)) /* execute arguments -e and -l */
+ return 0; /* something failed */
+ if (script < argc && /* execute main script (if there is one) */
+ handle_script(L, argv + script) != LUA_OK)
+ return 0;
+ if (args & has_i) /* -i option? */
+ doREPL(L); /* do read-eval-print loop */
+ else if (script == argc && !(args & (has_e | has_v))) { /* no arguments? */
+ if (lua_stdin_is_tty()) { /* running in interactive mode? */
+ print_version();
+ doREPL(L); /* do read-eval-print loop */
+ }
+ else dofile(L, NULL); /* executes stdin as a file */
+ }
+ lua_pushboolean(L, 1); /* signal no errors */
+ return 1;
+}
+
+}