00001 #include "wvstreamsdebugger.h"
00002 #include "wvlinklist.h"
00003
00004
00005 static const int command_map_size = 16;
00006
00007 DeclareWvList(WvStreamsDebugger);
00008 static WvStreamsDebuggerList *debuggers;
00009
00010
00011 WvStreamsDebugger::CommandMap *WvStreamsDebugger::commands;
00012
00013
00014 class WvStreamsDebuggerStaticInitCleanup
00015 {
00016 public:
00017 WvStreamsDebuggerStaticInitCleanup()
00018 {
00019 WvStreamsDebugger::add_command("help",
00020 0, &WvStreamsDebugger::help_run_cb, 0);
00021 }
00022 ~WvStreamsDebuggerStaticInitCleanup()
00023 {
00024 assert(!debuggers || debuggers->isempty());
00025
00026 if (WvStreamsDebugger::commands)
00027 {
00028 WvStreamsDebugger::CommandMap::Iter i(*WvStreamsDebugger::commands);
00029 for (i.rewind(); i.next(); )
00030 delete i->data;
00031 WvStreamsDebugger::commands->zap();
00032 delete WvStreamsDebugger::commands;
00033 WvStreamsDebugger::commands = NULL;
00034 }
00035
00036 if (debuggers)
00037 {
00038 delete debuggers;
00039 debuggers = NULL;
00040 }
00041 }
00042 };
00043 static WvStreamsDebuggerStaticInitCleanup ___;
00044
00045
00046 void *WvStreamsDebugger::get_command_data(WvStringParm cmd, Command *command)
00047 {
00048 if (command == NULL)
00049 {
00050 Command **pcommand = commands->find(cmd);
00051 if (!pcommand)
00052 return NULL;
00053 command = *pcommand;
00054 }
00055
00056 void **pcd = (void **)command_data.find(cmd);
00057 void *cd;
00058 if (pcd == NULL)
00059 {
00060
00061
00062
00063 if (!!command->init_cb)
00064 cd = command->init_cb(cmd);
00065 else
00066 cd = NULL;
00067
00068 command_data.add(cmd, (char *)cd);
00069 }
00070 else
00071 cd = *pcd;
00072
00073 return cd;
00074 }
00075
00076
00077 WvStreamsDebugger::WvStreamsDebugger() :
00078 command_data(command_map_size)
00079 {
00080 if (!debuggers)
00081 debuggers = new WvStreamsDebuggerList;
00082 debuggers->append(this, false);
00083
00084
00085 CommandMap::Iter i(*commands);
00086 for (i.rewind(); i.next(); )
00087 (void)get_command_data(i->key, i->data);
00088 }
00089
00090
00091 WvStreamsDebugger::~WvStreamsDebugger()
00092 {
00093
00094 CommandDataMap::Iter i(command_data);
00095 for (i.rewind(); i.next(); )
00096 {
00097 WvString cmd = i->key;
00098 void *cd = i->data;
00099
00100 Command *command = (*commands)[cmd];
00101 if (!!command->cleanup_cb)
00102 command->cleanup_cb(cmd, cd);
00103 }
00104 command_data.zap();
00105
00106 debuggers->unlink(this);
00107 }
00108
00109
00110 WvString WvStreamsDebugger::run(WvStringParm cmd, WvStringList &args,
00111 ResultCallback result_cb)
00112 {
00113 Command **pcommand = commands->find(cmd);
00114 if (!pcommand)
00115 return "No such command";
00116 Command *command = *pcommand;
00117
00118 return command->run_cb(cmd, args, result_cb, get_command_data(cmd, command));
00119 }
00120
00121
00122 bool WvStreamsDebugger::add_command(WvStringParm cmd,
00123 InitCallback init_cb,
00124 RunCallback run_cb,
00125 CleanupCallback cleanup_cb)
00126 {
00127 if (!commands)
00128 commands = new CommandMap(command_map_size);
00129
00130 if (commands->exists(cmd))
00131 return false;
00132 Command *command = new Command(init_cb, run_cb, cleanup_cb);
00133 commands->add(cmd, command);
00134 return true;
00135 }
00136
00137
00138 bool WvStreamsDebugger::foreach(WvStringParm cmd, ForeachCallback foreach_cb)
00139 {
00140 Command **pcommand = commands->find(cmd);
00141 if (!pcommand)
00142 return false;
00143 Command *command = *pcommand;
00144
00145 if (debuggers)
00146 {
00147 WvStreamsDebuggerList::Iter i(*debuggers);
00148 for (i.rewind(); i.next(); )
00149 {
00150 void *cd = i->get_command_data(cmd, command);
00151 foreach_cb(cmd, cd);
00152 }
00153 }
00154
00155 return true;
00156 }
00157
00158
00159 WvString WvStreamsDebugger::help_run_cb(WvStringParm cmd,
00160 WvStringList &args,
00161 ResultCallback result_cb, void *)
00162 {
00163 WvStringList cmd_list;
00164 cmd_list.append("Commands availible:");
00165 CommandMap::Iter i(*commands);
00166 for (i.rewind(); i.next(); )
00167 cmd_list.append(i->key);
00168 result_cb(cmd, cmd_list);
00169 return WvString::null;
00170 }