3 This file is part of gldbg
4 Copyright © 2009 Mikko Rasa, Mikkosoft Productions
5 Distributed under the GPL
9 #include <msp/core/except.h>
10 #include <msp/io/file.h>
11 #include <msp/io/print.h>
12 #include <msp/strings/lexicalcast.h>
13 #include <msp/strings/utils.h>
14 #include "commandinterpreter.h"
21 CommandInterpreter::CommandInterpreter(GlDbg &d):
24 commands["help"] = Command(&CommandInterpreter::cmd_help,
25 "Provides help on commands",
27 " Displays a list of commands\n\n"
29 " Gives detailed information on a command\n");
30 commands["exit"] = Command(&CommandInterpreter::cmd_exit,
31 "Ends the debugging session");
33 commands["run"] = Command(&CommandInterpreter::cmd_run,
34 "Starts the program");
35 commands["continue"] = Command(&CommandInterpreter::cmd_continue,
36 "Resumes program execution");
37 commands["kill"] = Command(&CommandInterpreter::cmd_kill,
38 "Terminates the program immediately");
39 commands["signal"] = Command(&CommandInterpreter::cmd_signal,
40 "Resumes execution with a signal",
43 " Sends the signal identified by NUM or NAME to the program and resumes\n"
44 " execution. Currently recognized signal names are HUP, INT, TERM, SEGV\n"
47 commands["trace"] = Command(&CommandInterpreter::cmd_trace,
48 "Traces GL function calls",
50 " Send trace output to FILE. As a special case, - means stdout.\n\n"
52 " Temporarily suspend or resume trace without closing the file.\n\n"
54 " Terminate trace, closing the file.\n");
57 void CommandInterpreter::execute(const string &cmd)
59 unsigned space = cmd.find(' ');
60 string name = cmd.substr(0, space);
61 CommandMap::const_iterator i = commands.lower_bound(name);
62 if(i==commands.end() || i->first.compare(0, name.size(), name))
63 throw KeyError("Unknown command", name);
66 CommandMap::const_iterator j = i;
67 if((++j)!=commands.end() && !j->first.compare(0, name.size(), name))
68 throw KeyError("Ambiguous command", name);
72 if(space!=string::npos)
73 args = cmd.substr(space+1);
75 (this->*(i->second.func))(args);
78 void CommandInterpreter::cmd_help(const string &args)
82 for(map<string, Command>::const_iterator i=commands.begin(); i!=commands.end(); ++i)
83 IO::print("%-10s : %s\n", i->first, i->second.description);
87 map<string, Command>::const_iterator i = commands.find(args);
89 throw KeyError("Unknown command", args);
90 IO::print("%s : %s\n", i->first, i->second.description);
91 if(!i->second.help.empty())
92 IO::print("\n%s", i->second.help);
96 void CommandInterpreter::cmd_run(const string &)
101 void CommandInterpreter::cmd_continue(const string &)
103 gldbg.get_process().resume();
106 void CommandInterpreter::cmd_signal(const string &args)
109 if(args=="HUP" || args=="SIGHUP")
111 else if(args=="INT" || args=="SIGINT")
113 else if(args=="ILL" || args=="SIGILL")
115 else if(args=="SEGV" || args=="SIGSEGV")
117 else if(args=="TERM" || args=="SIGTERM")
119 else if(isnumrc(args))
120 sig = lexical_cast<unsigned>(args);
122 throw InvalidParameterValue("Invalid signal specification");
123 gldbg.get_process().resume(sig);
126 void CommandInterpreter::cmd_kill(const string &)
128 gldbg.get_process().kill();
131 void CommandInterpreter::cmd_exit(const string &)
136 void CommandInterpreter::cmd_trace(const string &args)
138 Tracer &tracer = gldbg.get_tracer();
141 string fn = args.substr(1);
144 tracer.set_output(IO::cout);
145 IO::print("Tracing to stdout\n");
149 tracer.set_output(new IO::File(fn, IO::M_WRITE));
150 IO::print("Tracing to %s\n", fn);
158 IO::print("Tracing enabled\n");
163 IO::print("Tracing disabled\n");
167 tracer.set_output(0);
168 IO::print("Tracing terminated\n");
174 CommandInterpreter::Command::Command():
178 CommandInterpreter::Command::Command(Func f, const string &d):
183 CommandInterpreter::Command::Command(Func f, const string &d, const string &h):