CBuild
C++ build system with scripts written in c++
Loading...
Searching...
No Matches
cli_parser.cpp
Go to the documentation of this file.
1
22// C++ libraries
23#include "string"
24#include "vector"
25// Project includes
28#include "../../headers/map.hpp"
31/* data */
32namespace CBuild {
33bool real_exit = true;
34void exit(int code) {
36 std::exit(code);
37 }
38}
39ARG_TYPE force_handler(lib::map<std::string, std::string>* args, char** argv, int argc, int ptr,
40 CBuild::RType* type) {
41 try {
42 args->push_back_check("force", "force");
43 } catch (std::exception& e) {
44 CBuild::print_full("Force recompilation mode is already set!)", CBuild::RED);
45 }
46 return CBuild::ARG_TYPE::SIMPLE_ARG;
47}
48ARG_TYPE out_handler(lib::map<std::string, std::string>* args, char** argv, int argc, int ptr,
49 CBuild::RType* type) {
50 std::string str = "";
51 // Select proper output type based on token
52 if (std::string(argv[ptr]) == std::string("-v")) {
53 str = "verbose";
55 } else if (std::string(argv[ptr]) == std::string("--no-cli-out")) {
56 str = "none";
58 } else {
59 CBuild::print(std::string("Illegal output mode! - \"") + std::string(argv[ptr]) +
60 std::string("\""),
62 CBuild::exit(0xFF);
63 }
64 // Return it to the rest of CBuild
65 try {
66 args->push_back_check("out", str);
67 } catch (std::exception& e) {
68 CBuild::print_full(std::string("Output mode is already set! New output mode - \"") +
69 std::string(argv[ptr + 1]) +
70 std::string("\", old output mode is - \"") +
71 std::string(args->get_ptr("out")->data) + std::string("\"!"),
73 }
74 return CBuild::ARG_TYPE::SIMPLE_ARG;
75}
77 CBuild::RType* type) {
78 // User do not provide needed argument (ptr is current argument, so (ptr +
79 // 1) is next argument
80 if (!(argc >= (ptr + 1))) {
81 CBuild::print("Illegal command format!", CBuild::RED);
82 CBuild::print("Usage: -g <generator id>", CBuild::GREEN);
83 CBuild::exit(0xFF);
84 }
85 // Get genrators and check if one of them match our needed
86 std::vector<std::string> gens = CBuild::Registry::GetGeneratorsList();
87 bool err = true;
88 for (std::string gen : gens) {
89 if (gen == std::string(argv[ptr + 1])) {
90 err = false;
91 }
92 }
93 // If no match, yes, we are safe to crash here and remaind proper format of
94 // the argument to user
95 if (err == true) {
96 CBuild::print(std::string("Illegal or unregistered generator name! - \"") +
97 std::string(argv[ptr + 1]) + std::string("\""),
99 CBuild::print("Usage: -g <generator id>", CBuild::GREEN);
100 CBuild::exit(0xFF);
101 }
102 // If all good - save selected generator for later
103 try {
104 args->push_back_check("gen", argv[ptr + 1]);
105 } catch (std::exception& e) {
106 CBuild::print_full(std::string("Generator is already set! New generator - \"") +
107 std::string(argv[ptr + 1]) +
108 std::string("\", old generator is - \"") +
109 std::string(args->get_ptr("gen")->data) + std::string("\"!"),
111 }
112 return CBuild::ARG_TYPE::GENERATOR_ARG;
113}
114ARG_TYPE build_handler(lib::map<std::string, std::string>* args, char** argv, int argc, int ptr,
115 CBuild::RType* type) {
116 // User do not provide needed argument (ptr is current argument, so (ptr +
117 // 1) is next argument
118 if (argc <= (ptr + 1)) {
119 CBuild::print("Illegal command format!", CBuild::RED);
120 CBuild::print(std::string("Usage: ") + std::string(argv[ptr]) +
121 std::string(" <toolchain id>"),
123 CBuild::exit(0xFF);
124 }
125 // Now we need to figure why user run this app
126 // Lets save current token to std::string to ease of use
127 std::string token = argv[ptr];
128 // There go boring comparisions
129 if (token == std::string("-b")) {
130 *type = CBuild::BUILD;
131 } else if (token == std::string("-br")) {
132 *type = CBuild::BUILD_RUN;
133 } else if (token == std::string("-r")) {
134 *type = CBuild::RUN;
135 } else if (token == std::string("-d")) {
136 *type = CBuild::DEBUG;
137 } else if (token == std::string("-c")) {
138 *type = CBuild::CLEAR;
139 } else if (token == std::string("-ld")) {
140 *type = CBuild::LOAD_DEPS;
141 }
142 // Get toolchains and check if one of them match our needed
143 std::vector<std::string> tools = CBuild::Registry::GetToolchainsList();
144 bool err = true;
145 for (std::string tool : tools) {
146 if (tool == std::string(argv[ptr + 1])) {
147 err = false;
148 }
149 }
150 // We have exception for -b all
151 if (*type == CBuild::BUILD && std::string(argv[ptr + 1]) == std::string("all")) {
152 err = false;
153 }
154 // If no match, yes, we are safe to crash here and remaind proper format of
155 // the argument to user
156 if (err == true) {
157 CBuild::print(std::string("Illegal or unregistered toolchain name! - \"") +
158 std::string(argv[ptr + 1]) + std::string("\""),
160 CBuild::print(std::string("Usage: ") + std::string(argv[ptr]) +
161 std::string(" <toolchain id>"),
163 CBuild::exit(0xFF);
164 }
165 // If all good - save selected toolchain for later
166 try {
167 args->push_back_check("toolchain_id", argv[ptr + 1]);
168 } catch (std::exception& e) {
170 std::string("Toolchain is already set! New toolchain - \"") +
171 std::string(argv[ptr + 1]) + std::string("\", old toolchain is - \"") +
172 std::string(args->get_ptr("toolchain_id")->data) + std::string("\"!"),
174 CBuild::exit(0xFF);
175 }
176 return CBuild::ARG_TYPE::TOOLCHAIN_ARG;
177}
178ARG_TYPE task_handler(lib::map<std::string, std::string>* args, char** argv, int argc, int ptr,
179 CBuild::RType* type) {
180 // User do not provide needed argument (ptr is current argument, so (ptr +
181 // 1) is next argument
182 if (!(argc > (ptr + 1))) {
183 CBuild::print("Illegal command format!", CBuild::RED);
184 CBuild::print(std::string("Usage: -t <task id>"), CBuild::GREEN);
185 CBuild::exit(0xFF);
186 }
187 // Get task from user
188 std::string task = argv[ptr + 1];
189 // Get registered tasks
190 auto tasks = CBuild::Registry::GetTasksList();
191 // Check if task is registered
192 bool err = true;
193 for (std::string t : tasks) {
194 if (task == t) {
195 err = false;
196 }
197 }
198 // If no match, yes, we are safe to crash here and remaind proper format of
199 // the argument to user
200 if (err == true) {
201 CBuild::print(std::string("Illegal or unregistered task name! - \"") +
202 std::string(argv[ptr + 1]) + std::string("\""),
204 CBuild::print(std::string("Usage: -t <task id>"), CBuild::GREEN);
205 CBuild::exit(0xFF);
206 }
207 // Return correct data
208 try {
209 args->push_back_check("task_id", argv[ptr + 1]);
210 } catch (std::exception& e) {
211 CBuild::print_full(std::string("Task is already set! New task - \"") +
212 std::string(argv[ptr + 1]) + std::string("\", old task is - \"") +
213 std::string(args->get_ptr("task_id")->data) + std::string("\"!"),
215 CBuild::exit(0xFF);
216 }
217 *type = CBuild::TASK;
218 return CBuild::ARG_TYPE::TASK_ARG;
219}
220// Some vars for arg and parg
221int arg = 0;
222int parg = 0;
223ARG_TYPE arg_handler(lib::map<std::string, std::string>* args, char** argv, int argc, int ptr,
224 CBuild::RType* type) {
225 // User do not provide needed argument (ptr is current argument, so (ptr +
226 // 1) is next argument
227 if (!(argc > (ptr + 1))) {
228 CBuild::print("Illegal command format!", CBuild::RED);
229 CBuild::print(std::string("Usage: ") + std::string(argv[ptr]) + std::string(" <argument>"),
231 CBuild::exit(0xFF);
232 }
233 // Check `pa`
234 if (std::string(argv[ptr]) == std::string("-pa")) {
235 try {
236 args->push_back_check(std::string("pa") + std::to_string(CBuild::parg), argv[ptr + 1]);
237 } catch (std::exception& e) {
238 }
239 CBuild::parg++;
240 // Check `a`
241 } else if (std::string(argv[ptr]) == std::string("-a")) {
242 try {
243 args->push_back_check(std::string("a") + std::to_string(CBuild::arg), argv[ptr + 1]);
244 } catch (std::exception& e) {
245 }
246 CBuild::arg++;
247 // Else - error
248 } else {
249 CBuild::print(std::string("Uknown argument! - ") + std::string(argv[ptr]), CBuild::RED);
250 }
251 // Repack data to other format ;)
252 return CBuild::ARG_TYPE::GENERICK_ARG;
253}
254ARG_TYPE rebuild_handler(lib::map<std::string, std::string>* args, char** argv, int argc, int ptr,
255 CBuild::RType* type) {
256 *type = CBuild::REBUILD;
257 try {
258 args->push_back_check("toolchain_id", "cbuild_rebuild_build_script");
259 } catch (std::exception& e) {
260 }
261 return CBuild::ARG_TYPE::SIMPLE_ARG;
262}
267 {"-f", &force_handler}, {"-v", &out_handler}, {"--no-cli-out", &out_handler},
268 {"-g", &generator_handler}, {"-b", &build_handler}, {"-r", &build_handler},
269 {"-br", &build_handler}, {"-d", &build_handler}, {"-ld", &build_handler},
270 {"-c", &build_handler}, {"-t", &task_handler}, {"-a", &arg_handler},
271 {"-pa", &arg_handler}, {"--rebuild", &rebuild_handler}};
272} // namespace CBuild
273/* cli_parser.hpp */
275 // Init CBuild registry
277 // Some internal variables
279 int ptr = 1;
280 auto keywords = CBuild::Registry::GetKeywordsList();
281 // For every token
282 while (ptr < argc) {
283 // Get handler
284 auto h = CBuild::parsers_list.get_ptr(argv[ptr]);
286 // If it is available
287 if (h != NULL) {
288 // Call it
289 inc = h->data(args, argv, argc, ptr, &ret);
290 } else {
291 // Else check for custom keywords
292 const std::string* task = keywords.get(argv[ptr]);
293 if (task != NULL) {
294 ret = CBuild::TASK;
295 try {
296 args->push_back_check("task_id", *task);
297 } catch (std::exception& e) {
298 }
299 inc = CBuild::ARG_TYPE::SIMPLE_ARG;
300 } else {
301 // Else - error
302 CBuild::print(std::string("Illegal argument! - \"") + std::string(argv[ptr]) +
303 std::string("\""),
305 exit(0xFF);
306 }
307 }
308 // Handler must return number of consumed tokens, so, increment pointer
309 // by this number
310 ptr += inc;
311 }
312 return ret;
313}
314/* cli_parse_handler.hpp */
316 try {
317 CBuild::parsers_list.push_back_check(cmd, parser);
318 } catch (std::exception& e) {
319 return false;
320 }
321 return true;
322}
Main headers of CBuild core.
Simple map implementation with some stack operation added.
Definition map.hpp:79
void push_back_check(lib::mapData< _K, _D > element)
Add data, but check if key exists, if exist - trow exception.
Definition map.hpp:129
lib::mapData< _K, _D > * get_ptr(_K key)
Get reference to key and value of map.
Definition map.hpp:175
Defines and registering for handlers for cli parser.
Custom implementation of map datatype.
std::vector< std::string > GetToolchainsList()
Get list of registered toolchains.
Definition register.cpp:338
lib::map< std::string, std::string > GetKeywordsList()
Get list of all user registered keywords.
Definition register.cpp:276
void init()
Internal init.
Definition register.cpp:165
std::vector< std::string > GetGeneratorsList()
Get list of registered generators.
Definition register.cpp:331
std::vector< std::string > GetTasksList()
Get list of registered tasks.
Definition register.cpp:345
Filebuffer for CBuild ecosystem.
Definition Build.hpp:34
ARG_TYPE force_handler(lib::map< std::string, std::string > *args, char **argv, int argc, int ptr, CBuild::RType *type)
ARG_TYPE out_handler(lib::map< std::string, std::string > *args, char **argv, int argc, int ptr, CBuild::RType *type)
lib::map< std::string, handler > parsers_list
All handlers.
void void void print_verbose()
Enable verbose flag.
Definition print.cpp:98
ARG_TYPE task_handler(lib::map< std::string, std::string > *args, char **argv, int argc, int ptr, CBuild::RType *type)
bool real_exit
void print(std::string msg, color fg=CBuild::WHITE)
Print colored text to STDOUT.
Definition print.cpp:70
ARG_TYPE arg_handler(lib::map< std::string, std::string > *args, char **argv, int argc, int ptr, CBuild::RType *type)
@ RED
Definition print.hpp:34
@ GREEN
Definition print.hpp:35
ARG_TYPE(*)(lib::map< std::string, std::string > *, char **, int, int, CBuild::RType *) handler
Handler for specific argument.
RType parse(lib::map< std::string, std::string > *args, int argc, char **argv)
Parse arguments.
void exit(int code)
RType
Run mode.
Definition CBuild.hpp:34
@ REBUILD
Rebuild user executable.
Definition CBuild.hpp:62
@ ERROR
Some error occurred.
Definition CBuild.hpp:70
@ DEBUG
Build and run target in debug mode.
Definition CBuild.hpp:54
@ RUN
Run target.
Definition CBuild.hpp:46
@ CLEAR
Clear build output and cache.
Definition CBuild.hpp:58
@ TASK
Run task.
Definition CBuild.hpp:38
@ BUILD_RUN
Build and run target.
Definition CBuild.hpp:50
@ LOAD_DEPS
Load other project deps.
Definition CBuild.hpp:66
@ BUILD
Build target.
Definition CBuild.hpp:42
ARG_TYPE
Type of argument, indicate how many tokens this argument consumes, including self.
@ BLANK_ARG
No argument.
void print_none()
Fully disable all print though CBuild::print.
Definition print.cpp:101
ARG_TYPE rebuild_handler(lib::map< std::string, std::string > *args, char **argv, int argc, int ptr, CBuild::RType *type)
void print_full(std::string msg, color fg=CBuild::WHITE)
Print colored text to STDOUT if verbose flag is set.
Definition print.cpp:75
ARG_TYPE generator_handler(lib::map< std::string, std::string > *args, char **argv, int argc, int ptr, CBuild::RType *type)
ARG_TYPE build_handler(lib::map< std::string, std::string > *args, char **argv, int argc, int ptr, CBuild::RType *type)
bool register_parse_handler(std::string cmd, CBuild::handler parser)
Register new handler for parsing cli args, see handler typedef comment to guide how to write handlers...
Custom print that support color codes.
Register any things.
Command for compile_commands.json.