X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fcommandinterpreter.cpp;h=b8a10a99d03cb0f30a4048c4754f370d42f09f8b;hb=a34325fadec5b2be003bf9af1f081bfc4c83e8b6;hp=c684979bae2061b49f9fddd06a8cead8c381e9d6;hpb=ca49785159e6a7cfd2d999a99041fa1567575a24;p=gldbg.git diff --git a/source/commandinterpreter.cpp b/source/commandinterpreter.cpp index c684979..b8a10a9 100644 --- a/source/commandinterpreter.cpp +++ b/source/commandinterpreter.cpp @@ -1,87 +1,62 @@ -/* $Id$ - -This file is part of gldbg -Copyright © 2009 Mikko Rasa, Mikkosoft Productions -Distributed under the GPL -*/ - +#include +#include #include #include -#include -#include -#include -#include -#include +#include "breakpoint.h" #include "commandinterpreter.h" #include "enums.h" +#include "functions.h" #include "gldbg.h" #include "tracer.h" using namespace std; -using namespace Msp; CommandInterpreter::CommandInterpreter(GlDbg &d): gldbg(d) { - commands["help"] = Command(&CommandInterpreter::cmd_help, - "Provides help on commands", - "help\n" - " Displays a list of commands\n\n" - "help COMMAND\n" - " Gives detailed information on a command\n"); - commands["exit"] = Command(&CommandInterpreter::cmd_exit, - "Ends the debugging session"); - - commands["run"] = Command(&CommandInterpreter::cmd_run, - "Starts the program"); - commands["continue"] = Command(&CommandInterpreter::cmd_continue, - "Resumes program execution"); - commands["kill"] = Command(&CommandInterpreter::cmd_kill, - "Terminates the program immediately"); - commands["signal"] = Command(&CommandInterpreter::cmd_signal, - "Resumes execution with a signal", - "signal NUM\n" - "signal NAME\n" - " Sends the signal identified by NUM or NAME to the program and resumes\n" - " execution. Currently recognized signal names are HUP, INT, TERM, SEGV\n" - " and TERM.\n"); - - commands["trace"] = Command(&CommandInterpreter::cmd_trace, - "Traces GL function calls", - "trace\n" - " Send trace output to stdout.\n" - "trace FILE\n" - " Send trace output to FILE (- for stdout).\n\n" - "trace {off|on}\n" - " Temporarily suspend or resume trace without closing the file.\n\n" - "trace end\n" - " Terminate trace, closing the file.\n"); - - commands["profile"] = Command(&CommandInterpreter::cmd_profile, - "Profiles GL usage and performance", - "profile {on|off}\n" - " Enables or disables profiling\n"); + register_command("help", this, &CommandInterpreter::cmd_help) + .set_help("Provides help on commands", + "help\n" + " Displays a list of commands\n\n" + "help COMMAND\n" + " Gives detailed information on a command\n"); + register_command("exit", this, &CommandInterpreter::cmd_exit) + .set_help("Ends the debugging session"); + commands["quit"] = new CommandAlias(commands["exit"]); + + register_command("run", this, &CommandInterpreter::cmd_run) + .set_help("Starts the program"); + register_command("break", this, &CommandInterpreter::cmd_break) + .set_help("Sets a breakpoint", + "break FUNC\n" + " Makes program execution stop at FUNC\n"); + register_command("unbreak", this, &CommandInterpreter::cmd_unbreak) + .set_help("Removes a breakpoint", + "unbreak FUNC\n" + " Makes program execution no longer stop at FUNC\n"); + register_command("next", this, &CommandInterpreter::cmd_next) + .set_help("Resumes program execution until the next function call"); + commands["step"] = new CommandAlias(commands["next"]); + register_command("finish", this, &CommandInterpreter::cmd_finish) + .set_help("Resumes program execution until the next function return"); + register_command("continue", this, &CommandInterpreter::cmd_continue) + .set_help("Resumes program execution"); + register_command("kill", this, &CommandInterpreter::cmd_kill) + .set_help("Terminates the program immediately"); + register_command("signal", this, &CommandInterpreter::cmd_signal) + .set_help("Resumes execution with a signal", + "signal NUM\n" + "signal NAME\n" + " Sends the signal identified by NUM or NAME to the program and resumes\n" + " execution. Currently recognized signal names are HUP, INT, TERM, SEGV\n" + " and TERM.\n"); - commands["state"] = Command(&CommandInterpreter::cmd_state, - "Inspects general GL state", - "state vertex\n" - " Print current vertex attributes\n\n" - "state bind\n" - " Show current bindings\n"); - - commands["texture"] = Command(&CommandInterpreter::cmd_texture, - "Inspect texture state", - "texture\n" - " Lists texture objects\n\n" - "texture ID\n" - " Print information about a texture object\n"); +} - commands["buffer"] = Command(&CommandInterpreter::cmd_buffer, - "Inspect buffer object state", - "buffer\n" - " Lists buffer objects\n\n" - "buffer ID\n" - " Print information about a buffer object\n"); +CommandInterpreter::~CommandInterpreter() +{ + for(CommandMap::iterator i=commands.begin(); i!=commands.end(); ++i) + delete i->second; } void CommandInterpreter::execute(const string &cmd) @@ -90,36 +65,42 @@ void CommandInterpreter::execute(const string &cmd) string name = cmd.substr(0, space); CommandMap::const_iterator i = commands.lower_bound(name); if(i==commands.end() || i->first.compare(0, name.size(), name)) - throw KeyError("Unknown command", name); + throw runtime_error("Unknown command "+name); if(i->first!=name) { CommandMap::const_iterator j = i; if((++j)!=commands.end() && !j->first.compare(0, name.size(), name)) - throw KeyError("Ambiguous command", name); + throw runtime_error("Ambiguous command "+name); } string args; if(space!=string::npos) args = cmd.substr(space+1); - (this->*(i->second.func))(args); + i->second->execute(args); } void CommandInterpreter::cmd_help(const string &args) { if(args.empty()) { - for(map::const_iterator i=commands.begin(); i!=commands.end(); ++i) - IO::print("%-10s : %s\n", i->first, i->second.description); + for(CommandMap::const_iterator i=commands.begin(); i!=commands.end(); ++i) + if(!dynamic_cast(i->second)) + printf("%-10s : %s\n", i->first.c_str(), i->second->get_description().c_str()); } else { - map::const_iterator i = commands.find(args); + CommandMap::const_iterator i = commands.find(args); if(i==commands.end()) - throw KeyError("Unknown command", args); - IO::print("%s : %s\n", i->first, i->second.description); - if(!i->second.help.empty()) - IO::print("\n%s", i->second.help); + throw runtime_error("Unknown command "+args); + + const Command *cmd = i->second; + while(const CommandAlias *alias = dynamic_cast(cmd)) + cmd = alias->get_target(); + + printf("%s : %s\n", i->first.c_str(), cmd->get_description().c_str()); + if(!cmd->get_help().empty()) + printf("\n%s", cmd->get_help().c_str()); } } @@ -128,9 +109,39 @@ void CommandInterpreter::cmd_run(const string &) gldbg.launch(); } +void CommandInterpreter::cmd_break(const string &args) +{ + unsigned short func = get_function(args.c_str()); + if(!func) + throw runtime_error("Unknown function"); + + gldbg.set_breakpoint(func, BREAK_CALL, 0); +} + +void CommandInterpreter::cmd_unbreak(const string &args) +{ + unsigned short func = get_function(args.c_str()); + if(!func) + throw runtime_error("Unknown function"); + + gldbg.clear_breakpoint(func, BREAK_CALL, 0); +} + +void CommandInterpreter::cmd_next(const string &) +{ + gldbg.set_breakpoint(0, BREAK_CALL, 0); + gldbg.get_process().resume(); +} + +void CommandInterpreter::cmd_finish(const string &) +{ + gldbg.set_breakpoint(0, BREAK_RETURN, 0); + gldbg.get_process().resume(); +} + void CommandInterpreter::cmd_continue(const string &) { - IO::print("Continuing.\n"); + printf("Continuing.\n"); gldbg.get_process().resume(); } @@ -147,10 +158,13 @@ void CommandInterpreter::cmd_signal(const string &args) sig = SIGSEGV; else if(args=="TERM" || args=="SIGTERM") sig = SIGTERM; - else if(isnumrc(args)) - sig = lexical_cast(args); else - throw InvalidParameterValue("Invalid signal specification"); + { + char *end; + sig = strtoul(args.c_str(), &end, 0); + if(end && *end) + throw runtime_error("Invalid signal specification"); + } gldbg.get_process().resume(sig); } @@ -163,7 +177,7 @@ void CommandInterpreter::cmd_exit(const string &) { if(gldbg.get_process().get_state()!=Process::INACTIVE) { - IO::print("Program is still running. Kill it?\n"); + printf("Program is still running. Kill it?\n"); char *answer = readline("[y/n] "); if(answer[0]=='y') { @@ -171,154 +185,30 @@ void CommandInterpreter::cmd_exit(const string &) gldbg.quit(true); } else - IO::print("Not confirmed.\n"); + printf("Not confirmed.\n"); } else gldbg.quit(false); } -void CommandInterpreter::cmd_trace(const string &args) -{ - Tracer &tracer = gldbg.get_tracer(); - if(args.empty() || args=="-") - { - tracer.set_output(IO::cout); - IO::print("Tracing to stdout\n"); - } - else if(args=="on") - { - tracer.enable(); - IO::print("Tracing enabled\n"); - } - else if(args=="off") - { - tracer.disable(); - IO::print("Tracing disabled\n"); - } - else if(args=="end") - { - tracer.set_output(0); - IO::print("Tracing terminated\n"); - } - else - { - tracer.set_output(new IO::File(args, IO::M_WRITE)); - IO::print("Tracing to %s\n", args); - } -} - -void CommandInterpreter::cmd_profile(const string &args) -{ - Profiler &profiler = gldbg.get_profiler(); - if(args.empty() || args=="on") - profiler.enable(); - else if(args=="off") - profiler.disable(); - else - throw InvalidParameterValue("Invalid argument"); -} -void CommandInterpreter::cmd_state(const string &args) +void CommandInterpreter::Command::set_help(const string &d) { - const GlState &glstate = gldbg.get_glstate(); - if(args=="vertex") - { - IO::print("Current vertex attributes:\n"); - const Vector4 &color = glstate.get_color(); - IO::print(" Color: [%05.3f, %05.3f, %05.3f, %05.3f]\n", color.r, color.g, color.b, color.a); - for(unsigned i=0; i<8; ++i) - { - const Vector4 &texcoord = glstate.get_texcoord(i); - IO::print(" TexCoord%d: [%05.3f, %05.3f, %05.3f, %05.3f]\n", i, texcoord.s, texcoord.t, texcoord.p, texcoord.q); - } - const Vector3 &normal = glstate.get_normal(); - IO::print(" Normal: [%05.3f, %05.3f, %05.3f]\n", normal.x, normal.y, normal.z); - } - else if(args=="bind") - { - IO::print("Current bindings:\n"); - for(unsigned i=0; i<8; ++i) - { - IO::print(" Texture unit %d:\n", i); - const TexUnitState &unit = glstate.get_texture_unit(i); - IO::print(" GL_TEXTURE_2D: %s\n", unit.describe_binding(GL_TEXTURE_2D)); - IO::print(" GL_TEXTURE_3D: %s\n", unit.describe_binding(GL_TEXTURE_3D)); - } - IO::print(" Buffers:\n"); - const BufferState *buf = glstate.get_current_buffer(GL_ARRAY_BUFFER); - IO::print(" GL_ARRAY_BUFFER: %d\n", (buf ? buf->id : 0)); - buf = glstate.get_current_buffer(GL_ELEMENT_ARRAY_BUFFER); - IO::print(" GL_ELEMENT_ARRAY_BUFFER: %d\n", (buf ? buf->id : 0)); - } - else - throw InvalidParameterValue("Invalid or missing argument"); + description = d; } -void CommandInterpreter::cmd_texture(const string &args) +void CommandInterpreter::Command::set_help(const string &d, const string &h) { - if(args.empty()) - { - const map &textures = gldbg.get_glstate().get_textures(); - IO::print("%d texture objects:\n", textures.size()); - for(map::const_iterator i = textures.begin(); i!=textures.end(); ++i) - { - const TextureState &tex = i->second; - IO::print(" %d: %s, %d images\n", i->first, tex.describe(), tex.images.size()); - } - } - else - { - unsigned id = lexical_cast(args); - const TextureState &tex = gldbg.get_glstate().get_texture(id); - IO::print("Texture object %d\n", id); - IO::print(" Target: %s\n", describe_enum(tex.target, "TextureTarget")); - IO::print(" Images:\n"); - for(unsigned i=0; ifirst, i->second.describe()); - } - else - { - unsigned id = lexical_cast(args); - const BufferState &buf = gldbg.get_glstate().get_buffer(id); - IO::print("Buffer %d:\n", id); - IO::print(" Size: %d bytes\n", buf.size); - IO::print(" Usage: %s\n", describe_enum(buf.usage, "")); - } -} - -CommandInterpreter::Command::Command(): - func(0) +CommandInterpreter::CommandAlias::CommandAlias(Command *t): + target(t) { } -CommandInterpreter::Command::Command(Func f, const string &d): - func(f), - description(d) -{ } - -CommandInterpreter::Command::Command(Func f, const string &d, const string &h): - func(f), - description(d), - help(h) -{ } +void CommandInterpreter::CommandAlias::execute(const string &a) +{ + target->execute(a); +}