]> git.tdb.fi Git - gldbg.git/commitdiff
Add framework necessary to support more modular tools
authorMikko Rasa <tdb@tdb.fi>
Wed, 16 Jun 2010 15:58:05 +0000 (15:58 +0000)
committerMikko Rasa <tdb@tdb.fi>
Wed, 16 Jun 2010 15:58:05 +0000 (15:58 +0000)
Makefile
source/commandinterpreter.cpp
source/commandinterpreter.h
source/gldbg.cpp
source/gldbg.h
source/tool.cpp [new file with mode: 0644]
source/tool.h [new file with mode: 0644]

index 119aef3033bb3ca64a3699f1027cacbad5de44f1..1adeb6440c91f6bf718b545dd8d3025d0d3893ee 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -30,7 +30,8 @@ SOURCES_gldbg := source/gldbg.cpp \
        source/texturestate.cpp \
        source/bufferstate.cpp \
        source/profiler.cpp \
        source/texturestate.cpp \
        source/bufferstate.cpp \
        source/profiler.cpp \
-       source/arraystate.cpp
+       source/arraystate.cpp \
+       source/tool.cpp
 TEMPLATES := source/functions.enum.t \
        source/gldecoder.funcs.t \
        source/gldecoder.struct.t \
 TEMPLATES := source/functions.enum.t \
        source/gldecoder.funcs.t \
        source/gldecoder.struct.t \
index e73494c1e013790e0b7d209c24d36d90e6f31f28..367ac17f9651684e98113d472140cc1b23e4a4d2 100644 (file)
@@ -23,66 +23,66 @@ using namespace Msp;
 CommandInterpreter::CommandInterpreter(GlDbg &d):
        gldbg(d)
 {
 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["quit"] = Command(&commands["exit"]);
-
-       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\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");
-
-       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");
+       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("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");
+
+       register_command("trace", this, &CommandInterpreter::cmd_trace)
+               .set_help("Traces GL function calls",
+                       "trace\n"
+                       "  Send trace output to stdout.\n\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");
+
+       register_command("profile", this, &CommandInterpreter::cmd_profile)
+               .set_help("Profiles GL usage and performance",
+                       "profile {on|off}\n"
+                       "  Enables or disables profiling\n");
+
+       register_command("state", this, &CommandInterpreter::cmd_state)
+               .set_help("Inspects general GL state",
+                       "state vertex\n"
+                       "  Print current vertex attributes\n\n"
+                       "state bind\n"
+                       "  Show current bindings\n");
+
+       register_command("texture", this, &CommandInterpreter::cmd_texture)
+               .set_help("Inspect texture state",
+                       "texture\n"
+                       "  Lists texture objects\n\n"
+                       "texture ID\n"
+                       "  Print information about a texture object\n");
+
+       register_command("buffer", this, &CommandInterpreter::cmd_buffer)
+               .set_help("Inspect buffer object state",
+                       "buffer\n"
+                       "  Lists buffer objects\n\n"
+                       "buffer ID\n"
+                       "  Print information about a buffer object\n");
 }
 
 void CommandInterpreter::execute(const string &cmd)
 }
 
 void CommandInterpreter::execute(const string &cmd)
@@ -103,30 +103,30 @@ void CommandInterpreter::execute(const string &cmd)
        if(space!=string::npos)
                args = cmd.substr(space+1);
 
        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())
        {
 }
 
 void CommandInterpreter::cmd_help(const string &args)
 {
        if(args.empty())
        {
-               for(map<string, Command>::const_iterator i=commands.begin(); i!=commands.end(); ++i)
-                       if(!i->second.alias_for)
-                               IO::print("%-10s : %s\n", i->first, i->second.description);
+               for(CommandMap::const_iterator i=commands.begin(); i!=commands.end(); ++i)
+                       if(!dynamic_cast<const CommandAlias *>(i->second))
+                               IO::print("%-10s : %s\n", i->first, i->second->get_description());
        }
        else
        {
        }
        else
        {
-               map<string, Command>::const_iterator i = commands.find(args);
+               CommandMap::const_iterator i = commands.find(args);
                if(i==commands.end())
                        throw KeyError("Unknown command", args);
 
                if(i==commands.end())
                        throw KeyError("Unknown command", args);
 
-               const Command *cmd = &i->second;
-               while(cmd->alias_for)
-                       cmd = cmd->alias_for;
+               const Command *cmd = i->second;
+               while(const CommandAlias *alias = dynamic_cast<const CommandAlias *>(cmd))
+                       cmd = alias->get_target();
 
 
-               IO::print("%s : %s\n", i->first, cmd->description);
-               if(!i->second.help.empty())
-                       IO::print("\n%s", cmd->help);
+               IO::print("%s : %s\n", i->first, cmd->get_description());
+               if(!cmd->get_help().empty())
+                       IO::print("\n%s", cmd->get_help());
        }
 }
 
        }
 }
 
@@ -397,25 +397,23 @@ void CommandInterpreter::cmd_buffer(const string &args)
 }
 
 
 }
 
 
-CommandInterpreter::Command::Command():
-       func(0),
-       alias_for(0)
-}
+void CommandInterpreter::Command::set_help(const string &d)
+{
+       description = d;
+}
 
 
-CommandInterpreter::Command::Command(Command *cmd):
-       func(cmd->func),
-       alias_for(cmd)
-{ }
+void CommandInterpreter::Command::set_help(const string &d, const string &h)
+{
+       description = d;
+       help = h;
+}
 
 
-CommandInterpreter::Command::Command(Func f, const string &d):
-       func(f),
-       description(d),
-       alias_for(0)
-{ }
 
 
-CommandInterpreter::Command::Command(Func f, const string &d, const string &h):
-       func(f),
-       description(d),
-       help(h),
-       alias_for(0)
+CommandInterpreter::CommandAlias::CommandAlias(Command *t):
+       target(t)
 { }
 { }
+
+void CommandInterpreter::CommandAlias::execute(const string &a)
+{
+       target->execute(a);
+}
index 537245fb53c1a0f38bea5b0a652f490e97fa64cf..487abb232fcdfcd6e4cb79cc56214db0720b19cb 100644 (file)
@@ -15,29 +15,66 @@ class GlDbg;
 
 class CommandInterpreter
 {
 
 class CommandInterpreter
 {
-private:
+public:
        struct Command
        {
        struct Command
        {
-               typedef void (CommandInterpreter::*Func)(const std::string &);
-
-               Func func;
+       private:
                std::string description;
                std::string help;
                std::string description;
                std::string help;
-               Command *alias_for;
 
 
-               Command();
-               Command(Command *);
-               Command(Func, const std::string &);
-               Command(Func, const std::string &, const std::string &);
+       protected:
+               Command() { }
+
+       public:
+               void set_help(const std::string &);
+               void set_help(const std::string &, const std::string &);
+               const std::string &get_description() const { return description; }
+               const std::string &get_help() const { return help; }
+
+               virtual void execute(const std::string &) = 0;
        };
 
        };
 
-       typedef std::map<std::string, Command> CommandMap;
+private:
+       template<typename T>
+       class CommandFunction: public Command
+       {
+       private:
+               typedef void (T::*Func)(const std::string &);
+
+               T *obj;
+               Func func;
+       public:
+               CommandFunction(T *o, Func f): obj(o), func(f) { }
+
+               virtual void execute(const std::string &a)
+               { (obj->*func)(a); }
+       };
+
+       class CommandAlias: public Command
+       {
+       private:
+               Command *target;
+
+       public:
+               CommandAlias(Command *);
+
+               const Command *get_target() const { return target; }
+
+               virtual void execute(const std::string &);
+       };
+
+       typedef std::map<std::string, Command *> CommandMap;
 
        GlDbg &gldbg;
        CommandMap commands;
 
 public:
        CommandInterpreter(GlDbg &);
 
        GlDbg &gldbg;
        CommandMap commands;
 
 public:
        CommandInterpreter(GlDbg &);
+
+       template<typename T>
+       Command &register_command(const std::string &n, T *o, void (T::*f)(const std::string &))
+       { return *(commands[n] = new CommandFunction<T>(o, f)); }
+
        void execute(const std::string &);
 
 private:
        void execute(const std::string &);
 
 private:
index d18ff51bba753b9c2ccbb97cb510d48169fa957a..bc621ce490e2679c91e30e6ca11348616559011d 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of gldbg
 /* $Id$
 
 This file is part of gldbg
-Copyright © 2009  Mikko Rasa, Mikkosoft Productions
+Copyright © 2009-2010  Mikko Rasa, Mikkosoft Productions
 Distributed under the GPL
 */
 
 Distributed under the GPL
 */
 
@@ -17,6 +17,7 @@ Distributed under the GPL
 #include <msp/strings/lexicalcast.h>
 #include "gldbg.h"
 #include "glprint.h"
 #include <msp/strings/lexicalcast.h>
 #include "gldbg.h"
 #include "glprint.h"
+#include "tool.h"
 
 using namespace std;
 using namespace Msp;
 
 using namespace std;
 using namespace Msp;
@@ -32,6 +33,10 @@ GlDbg::GlDbg(int argc, char **argv):
 {
        FS::Path libdir = FS::get_sys_lib_dir(argv[0], "gldbg");
        process.setenv("LD_PRELOAD", (libdir/"glwrap.so").str().c_str());
 {
        FS::Path libdir = FS::get_sys_lib_dir(argv[0], "gldbg");
        process.setenv("LD_PRELOAD", (libdir/"glwrap.so").str().c_str());
+
+       const list<Tool::Factory *> &factories = Tool::get_factories();
+       for(list<Tool::Factory *>::const_iterator i=factories.begin(); i!=factories.end(); ++i)
+               tools.push_back((*i)->create(*this));
 }
 
 int GlDbg::main()
 }
 
 int GlDbg::main()
@@ -133,6 +138,8 @@ void GlDbg::read_stream()
                                int size = gldecoder_decode(0, data, len);
                                if(size<0)
                                        break;
                                int size = gldecoder_decode(0, data, len);
                                if(size<0)
                                        break;
+                               for(list<Tool *>::iterator i=tools.begin(); i!=tools.end(); ++i)
+                                       (*i)->decode(data, size);
                                tracer.decode(data, len);
                                glstate.decode(data, len);
                                profiler.decode(data, len);
                                tracer.decode(data, len);
                                glstate.decode(data, len);
                                profiler.decode(data, len);
@@ -141,7 +148,7 @@ void GlDbg::read_stream()
                        if(buf_offset>8192)
                        {
                                buffer.erase(0, buf_offset);
                        if(buf_offset>8192)
                        {
                                buffer.erase(0, buf_offset);
-                               buf_offset=0;
+                               buf_offset = 0;
                        }
                }
        }
                        }
                }
        }
index e42e4aa1d1425cb5c105bca4528d6835ad81ad77..543df05a580265b5d88e395f995ffb2b2a0f0438 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of gldbg
 /* $Id$
 
 This file is part of gldbg
-Copyright © 2009  Mikko Rasa, Mikkosoft Productions
+Copyright © 2009-2010  Mikko Rasa, Mikkosoft Productions
 Distributed under the GPL
 */
 
 Distributed under the GPL
 */
 
@@ -18,6 +18,8 @@ Distributed under the GPL
 #include "profiler.h"
 #include "tracer.h"
 
 #include "profiler.h"
 #include "tracer.h"
 
+class Tool;
+
 class GlDbg: public Msp::Application
 {
 private:
 class GlDbg: public Msp::Application
 {
 private:
@@ -27,6 +29,7 @@ private:
        std::string buffer;
        unsigned buf_offset;
        bool flushing;
        std::string buffer;
        unsigned buf_offset;
        bool flushing;
+       std::list<Tool *> tools;
        Tracer tracer;
        GlState glstate;
        Profiler profiler;
        Tracer tracer;
        GlState glstate;
        Profiler profiler;
@@ -37,6 +40,7 @@ private:
 public:
        GlDbg(int, char **);
        int main();
 public:
        GlDbg(int, char **);
        int main();
+       CommandInterpreter &get_command_interpreter() { return cmd_interp; }
        Tracer &get_tracer() { return tracer; }
        GlState &get_glstate() { return glstate; }
        Profiler &get_profiler() { return profiler; }
        Tracer &get_tracer() { return tracer; }
        GlState &get_glstate() { return glstate; }
        Profiler &get_profiler() { return profiler; }
diff --git a/source/tool.cpp b/source/tool.cpp
new file mode 100644 (file)
index 0000000..0e2cae1
--- /dev/null
@@ -0,0 +1,22 @@
+/* $Id$
+
+This file is part of gldbg
+Copyright © 2010  Mikko Rasa, Mikkosoft Productions
+Distributed under the GPL
+*/
+
+#include "tool.h"
+
+using namespace std;
+
+list<Tool::Factory *> &Tool::get_factories()
+{
+       static list<Tool::Factory *> factories;
+       return factories;
+}
+
+
+Tool::Factory::Factory()
+{
+       get_factories().push_back(this);
+}
diff --git a/source/tool.h b/source/tool.h
new file mode 100644 (file)
index 0000000..b299e2a
--- /dev/null
@@ -0,0 +1,57 @@
+/* $Id$
+
+This file is part of gldbg
+Copyright © 2010  Mikko Rasa, Mikkosoft Productions
+Distributed under the GPL
+*/
+
+#ifndef TOOL_H_
+#define TOOL_H_
+
+#include <list>
+
+class GlDbg;
+
+class Tool
+{
+public:
+       class Factory
+       {
+       protected:
+               Factory();
+
+       public:
+               virtual Tool *create(GlDbg &) const = 0;
+       };
+
+protected:
+       Tool() { }
+public:
+       virtual ~Tool() { }
+
+       virtual void decode(const char *, unsigned) = 0;
+
+       static std::list<Factory *> &get_factories();
+};
+
+
+template<typename T>
+class RegisteredTool: public Tool
+{
+protected:
+       class Factory: public Tool::Factory
+       {
+               virtual Tool *create(GlDbg &g) const { return new T(g); }
+       };
+
+       static Factory factory;
+
+protected:
+       // The no-op expression is necessary to instantiate the static member
+       RegisteredTool() { (void)factory; }
+};
+
+template<typename T>
+typename RegisteredTool<T>::Factory RegisteredTool<T>::factory;
+
+#endif