-
Notifications
You must be signed in to change notification settings - Fork 0
/
Interpreter.h
170 lines (147 loc) · 4.97 KB
/
Interpreter.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
//===-- jcut/Interpreter.h --------------------------------------*- C++ -*-===//
//
// This file is part of JCUT, A Just-n-time C Unit Testing framework.
//
// Copyright (c) 2014 Adrián Ortega García <adrianog(dot)sw(at)gmail(dot)com>
// All rights reserved.
//
// JCUT is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// JCUT is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with JCUT (See LICENSE.TXT for details).
// If not, see <http://www.gnu.org/licenses/>.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief
///
//===----------------------------------------------------------------------===//
#ifndef INTERPRETER_H_
#define INTERPRETER_H_
#include <iostream>
#include <string>
#include <map>
#include "linenoise.h"
namespace clang{
namespace tooling {
class CommonOptionsParser;
}
}
using clang::tooling::CommonOptionsParser;
using namespace std;
namespace jcut {
// @todo Keep a copy of the original command line!, argc and argv
class Interpreter {
private:
int mArgc;
const char ** mArgv;
vector<const char*> toBeFreed;
vector<string> unloadedFiles;
vector<string> mLoadedFiles;
bool mOptionsParsed;
void convertToAbsolutePaths(int argc, const char **argv);
bool executeCommand(const std::string& cmd,
Interpreter& i, std::string& final_cmd);
static void completionCallBack(const char * line, linenoiseCompletions *lc);
public:
Interpreter(const int argc, const char **argv);
~Interpreter();
// Runs the SyntaxOnlyAction followed by the Action defined by T.
template<class T>
int runAction() {
int argc = 0;
const char ** argv = cloneArgv(argc);
int failed = runAction<T>(argc, argv);
freeArgv(argc, argv);
return failed;
}
// Runs the SyntaxOnlyAction followed by the Action defined by T.
template<class T>
int runAction(int argc, const char **argv);
int mainLoop();
// For every call to the cloneArgv() methods there has to be 1 call to freeArgv
const char** cloneArgv(int& new_argc) const;
const char** cloneArgv(int argc, const char** argv, int& new_argc) const;
void freeArgv(int argc, const char** argv);
bool addFileToArgv(const string& str);
bool removeFileFromArgv(const string& str);
// 2 means the binary name and the mythical --
bool hasLoadedFiles() { return mLoadedFiles.size() > 0; }
};
class Command {
friend class Help;
protected:
Interpreter& mInt;
std::vector<std::string> mArgs;
public:
std::string name;
std::string desc;
Command(const Command&) = delete;
Command(const std::string& n, const std::string& d,
Interpreter& i) : mInt(i), name(n), desc(d) {}
virtual ~Command(){}
void setArguments(const std::vector<std::string>& args) { mArgs = args; }
virtual bool execute() {return true;}
std::string str() const { return name;}
};
class Help : public Command{
public:
Help(Interpreter& i) : Command("/help",
"Lists all the available options for the jcut interpreter.", i) {}
bool execute();
};
class Exit : public Command{
public:
Exit(Interpreter& i) : Command("/exit", "Exits the jcut interpreter.", i) {}
};
class Pwd : public Command{
public:
Pwd(Interpreter& i) : Command("/pwd", "Prints the working directory where jcut is being run.", i) {}
bool execute();
};
class Load : public Command{
public:
Load(Interpreter& i) : Command("/load", "Loads all the specified source files separated by a space.",i) {}
bool execute();
};
class Unload : public Command{
public:
Unload(Interpreter& i) : Command("/unload", "Removes the specified C source files from jcut memory.", i) {}
bool execute();
};
class Ls : public Command{
public:
Ls(Interpreter& i) : Command("/ls", "Lists all the functions for all the loaded C source files.", i) {}
bool execute();
};
class CommandFactory {
friend class Help;
private:
CommandFactory(Interpreter& i) : mInterpreter(i) {
// Every time a new command is added make sure you add an entry here.
registered_cmds["/help"] = unique_ptr<Command>(new Help(i));
registered_cmds["/exit"] = unique_ptr<Command>(new Exit(i));
registered_cmds["/pwd"] = unique_ptr<Command>(new Pwd(i));
registered_cmds["/ls"] = unique_ptr<Command>(new Ls(i));
registered_cmds["/load"] = unique_ptr<Command>(new Load(i));
registered_cmds["/unload"] = unique_ptr<Command>(new Unload(i));
}
std::vector<std::string> parseArguments(const std::string&);
std::map<std::string,unique_ptr<Command>> registered_cmds;
static unique_ptr<CommandFactory> factory;
Interpreter& mInterpreter;
public:
static CommandFactory& instance(Interpreter& i);
Command* create(const string& cmd);
};
} /* namespace jcut */
#endif /* INTERPRETER_H_ */