| 181 | const int MAX_DBGP_ARGS = 16; // More than currently necessary. |
| 182 | |
| 183 | int Debugger::ProcessCommands() |
| 184 | { |
| 185 | // Disable notification of READ readiness and reset socket to synchronous mode. |
| 186 | u_long zero = 0; |
| 187 | WSAAsyncSelect(mSocket, g_hWnd, 0, 0); |
| 188 | ioctlsocket(mSocket, FIONBIO, &zero); |
| 189 | |
| 190 | int err; |
| 191 | |
| 192 | for (;;) |
| 193 | { |
| 194 | int command_length; |
| 195 | |
| 196 | if (err = ReceiveCommand(&command_length)) |
| 197 | break; // Already called FatalError(). |
| 198 | |
| 199 | char *command = mCommandBuf.mData; |
| 200 | char *args = strchr(command, ' '); |
| 201 | char *argv[MAX_DBGP_ARGS]; |
| 202 | int arg_count = 0; |
| 203 | |
| 204 | // transaction_id is considered optional for the following reasons: |
| 205 | // - The spec doesn't explicitly say it is mandatory (just "standard"). |
| 206 | // - We don't actually need it for anything. |
| 207 | // - Rejecting the command doesn't seem useful. |
| 208 | // - It makes manually typing DBGp commands easier. |
| 209 | char *transaction_id = ""; |
| 210 | |
| 211 | if (args) |
| 212 | { |
| 213 | // Split command name and args. |
| 214 | *args++ = '\0'; |
| 215 | // Split args into arg vector. |
| 216 | err = ParseArgs(args, argv, arg_count, transaction_id); |
| 217 | } |
| 218 | |
| 219 | if (!err) |
| 220 | { |
| 221 | for (int i = 0; ; ++i) |
| 222 | { |
| 223 | if (i == _countof(sCommands)) |
| 224 | { |
| 225 | err = DEBUGGER_E_UNIMPL_COMMAND; |
| 226 | break; |
| 227 | } |
| 228 | if (!strcmp(sCommands[i].mName, command)) |
| 229 | { |
| 230 | // EXECUTE THE DBGP COMMAND. |
| 231 | err = (this->*sCommands[i].mFunc)(argv, arg_count, transaction_id); |
| 232 | break; |
| 233 | } |
| 234 | } |
| 235 | } |
| 236 | |
| 237 | if (!err) |
| 238 | { |
| 239 | if (mResponseBuf.mDataUsed) |
| 240 | err = SendResponse(); |
no test coverage detected