History

Additional debugger command (term) Add command line arguments for enabling debugger from exec

Remove tabs from all logging

arr committed 10 years ago

Commit 660681b1 parent e2f8e255 files · +190 −23Browse files

Showing the changes to src/exec/main.cpp (1 of 5 files). Show all

Unified · Split

src/exec/main.cpp+140−15
@@ -30,10 +30,14 @@ namespace · 29 unmodified lines
3030
3131 std::shared_ptr<const vm_module_t> command_module;
3232
33− std::unique_ptr<vm_module_t> create_entry_module(vm_t &vm, int argc, char* argv[])
33+ std::unique_ptr<vm_module_t> create_entry_module(vm_t &vm, const std::vector<char *> &vm_args)
3434 {
35+ if (vm_args.size() == 0)
36+ throw vm_user_exception{ "Entry module not supplied" };
37+
3538 // First argument is the module to load
36− auto command_module_path = new vm_string_t{ std::strlen(argv[0]), reinterpret_cast<uint8_t *>(argv[0]) };
39+ auto entry_module_path = vm_args[0];
40+ auto command_module_path = new vm_string_t{ std::strlen(entry_module_path), reinterpret_cast<uint8_t *>(entry_module_path) };
3741
3842 // Pre-load the command module in the VM.
3943 command_module = vm.load_module(command_module_path->str());
@@ -41,9 +45,9 @@ namespace · 1 unmodified line
4145 // Convert arguments to a list
4246 vm_list_t *args = nullptr;
4347 vm_list_t *last = nullptr;
44− for (auto i = 1; i < argc; ++i)
48+ for (auto i = std::size_t{ 1 }; i < vm_args.size(); ++i)
4549 {
46− auto tmp = argv[i];
50+ auto tmp = vm_args[i];
4751 auto arg = new vm_string_t{ std::strlen(tmp), reinterpret_cast<uint8_t *>(tmp) };
4852 if (args == nullptr)
4953 {
@@ -165,39 +169,160 @@ namespace · 115 unmodified lines
165169 }
166170 }
167171
172+struct arg_exception_t : std::runtime_error
173+{
174+ arg_exception_t(const char *m, const char *arg)
175+ : std::runtime_error{ m }
176+ , arg{ arg }
177+ { }
178+
179+ const char * const arg;
180+};
181+
182+struct exec_options
183+{
184+ std::vector<char *> vm_args;
185+
186+ bool print_help;
187+ bool quiet_start;
188+ bool enabled_debugger;
189+ debugger_options debugger;
190+};
191+
192+void print_banner(const exec_options &options)
193+{
194+ std::cout
195+ << "DisVM\n"
196+ << "----------------\n"
197+ << "Debugger enabled: " << std::boolalpha << options.enabled_debugger << "\n";
198+
199+ if (options.enabled_debugger)
200+ std::cout << options.debugger << "\n";
201+
202+ std::cout << std::endl;
203+}
204+
205+void print_help()
206+{
207+ std::cout
208+ << "Usage: disvm-exec [-d[e|m|x]*] [-q] [-?] <entry module> <args>*\n"
209+ << " d - Enable debugger\n"
210+ << " e - Break on entry\n"
211+ << " m - Break on module load\n"
212+ << " x - Break on exception (first chance)\n"
213+ << " q - Suppress banner and configuration\n"
214+ << " ? - Print help\n";
215+}
216+
217+void process_arg(char* arg, std::function<char *()> next, exec_options &options)
218+{
219+ assert(arg != nullptr && next != nullptr);
220+ if (arg[0] != '-')
221+ {
222+ for (; arg != nullptr; arg = next())
223+ options.vm_args.push_back(arg);
224+
225+ return;
226+ }
227+
228+ auto arg_len = std::strlen(arg);
229+ if (arg_len < 2)
230+ throw arg_exception_t{ "Invalid flag format", arg };
231+
232+ switch (arg[1])
233+ {
234+ case 'd':
235+ options.enabled_debugger = true;
236+ for (auto i = std::size_t{ 2 }; i < arg_len; ++i)
237+ {
238+ switch (arg[i])
239+ {
240+ case 'e': options.debugger.break_on_enter = true;
241+ break;
242+ case 'm': options.debugger.break_on_module_load = true;
243+ break;
244+ case 'x': options.debugger.break_on_exception = true;
245+ break;
246+ }
247+ }
248+
249+ break;
250+
251+ case 'q':
252+ options.quiet_start = true;
253+ break;
254+
255+ case '?':
256+ options.print_help = true;
257+ break;
258+
259+ default:
260+ throw arg_exception_t{ "Unknown flag", arg };
261+ }
262+}
263+
168264 int main(int argc, char* argv[])
169265 {
170− // [TODO] Handle command line arguments
171− assert(argc > 1);
266+ exec_options options = {};
267+
268+ try
269+ {
270+ // Ignore the process name
271+ auto arg_idx = int{ 1 };
272+ auto next_arg = [&]()
273+ {
274+ return arg_idx < argc ? argv[arg_idx++] : nullptr;
275+ };
276+
277+ for (auto curr_arg = next_arg(); curr_arg != nullptr; curr_arg = next_arg())
278+ process_arg(curr_arg, next_arg, options);
279+ }
280+ catch (const arg_exception_t &ae)
281+ {
282+ std::cerr << ae.what();
283+ if (ae.arg != nullptr)
284+ std::cerr << ": " << ae.arg << std::endl;
285+
286+ return EXIT_FAILURE;
287+ }
288+
289+ if (!options.quiet_start)
290+ print_banner(options);
291+
292+ if (options.print_help)
293+ {
294+ print_help();
295+ return EXIT_SUCCESS;
296+ }
172297
173298 vm_t vm;
174299
175− //vm.load_tool(std::make_shared<debugger>());
300+ if (options.enabled_debugger)
301+ vm.load_tool(std::make_shared<debugger>(options.debugger));
176302
177303 try
178304 {
179− // Ignore the process name
180− auto entry = create_entry_module(vm, argc - 1, argv + 1);
305+ auto entry = create_entry_module(vm, options.vm_args);
181306
182307 vm.exec(std::move(entry));
183308
184309 vm.spin_sleep_till_idle(std::chrono::milliseconds(100));
185310 }
186− catch (vm_user_exception &ue)
311+ catch (const vm_user_exception &ue)
187312 {
188− std::cout << ue.what() << std::endl;
313+ std::cerr << ue.what() << std::endl;
189314
190315 return EXIT_FAILURE;
191316 }
192− catch (vm_system_exception &se)
317+ catch (const vm_system_exception &se)
193318 {
194− std::cout
195− << "Internal exception:\n\t"
319+ std::cerr
320+ << "Internal exception:\n "
196321 << se.what()
197322 << std::endl;
198323
199324 return EXIT_FAILURE;
200325 }
201326
202− return 0;
327+ return EXIT_SUCCESS;
203328 }