/****************************************************************************** * * * BOOL CommandExecute( char *pOrigCmd ) * * * ******************************************************************************* * * Executes commands stored in a string. If the command contains a macro, * this function is called recursively. * * We also exit if there was an error evaluating a command. * * Where: * pOrigCmd is the string with commands. Multiple commands may be separated * with ';' * * Returns: * FALSE if the command reuqested debugger to continue running * the debugee program (such are commands 'g' or 't') * TRUE if suggested staying in the debugger * ******************************************************************************/ BOOL CommandExecute( char *pOrigCmd ) { static int nDeep = 0; // Recursion depth count char Command[MAX_STRING]; // Command buffer on the stack char *pCmd = Command; // Pointer to a local buffer char *pCmdNext, cDelimiter; char *pMacro; // Pointer to a macro string (expanded) BOOL fInString, fRet = TRUE; int i; nDeep++; // Inside the function, recursion count // Copy given command(s) into a local buffer so we can recurse strcpy(pCmd, pOrigCmd); do { // Find the first non-space, non-delimiter character of the current command while( (*pCmd==' ' || *pCmd==';') && (*pCmd!=0) ) pCmd++; // Look for the ";" delimiter, ignore it within a string pCmdNext = pCmd; fInString = FALSE; while( *pCmdNext!=0 && (*pCmdNext!=';' || fInString) ) { if( *pCmdNext=='"' ) fInString = !fInString; pCmdNext++; } // If the command is empty, return if( *pCmd==0 ) break; // Got the first character.. Search all known command keywords from // back to front to find a match for( i=iLast; i>=0; i--) { if( !strnicmp(pCmd, Cmd[i].sCmd, Cmd[i].nLen) && !isalnum(pCmd[Cmd[i].nLen])) break; } // Separate current string from the next one cDelimiter = *pCmdNext; *pCmdNext = 0; if( i>= 0 ) { // Find the first non-space character to assign it as a pointer to the first argument pCmd += Cmd[i].nLen; while( *pCmd==' ' ) pCmd++; // Call the command function handler fRet = (Cmd[i].pfnCommand)( pCmd, Cmd[i].subClass ); } else { // Command was not found. Search all defined macros. pMacro = MacroExpand(pCmd); if( pMacro != NULL ) { // Recursively submit expanded macro for execution // Keep the recursion count so we can terminate if too deep if( nDeep <= MAX_MACRO_RECURSE ) fRet = CommandExecute(pMacro); else fRet = TRUE; } else { // The last thing we search the extended commands (DOT-commands) // Only if the first character is a DOT, though if( *pCmd=='.' ) { return( DispatchExtCommand(pCmd+1) ); } else { PostError(ERR_COMMAND, 0); return( TRUE ); } } } // Restore the delimiter character *pCmdNext = cDelimiter; pCmd = pCmdNext; } while( (*pCmd != 0) && fRet ); nDeep--; // Leaving the function, recursion count return( fRet ); }
bool CDebuggerWin::ExecCommand(char *linetext) { char emptystring[]=" "; char tmptext[MAX_LINE_SIZE+1]; char *arglist[MAX_COMMAND_ARGS+1]; int argcount=0,loop=0; bool cmd_ok=TRUE; enum { COMMAND_QUIT, COMMAND_RUN, COMMAND_STOP, COMMAND_STEP, COMMAND_BPOINT, COMMAND_BPOINTC, COMMAND_RESET, COMMAND_REGISTERS, COMMAND_MEM_SET, COMMAND_MEM_DUMP, COMMAND_MEM_LOAD, COMMAND_MEM_SAVE, COMMAND_CART_SET, COMMAND_CART_DUMP, COMMAND_CART_LOAD, COMMAND_CART_SAVE, COMMAND_HELP, COMMAND_SCRIPT, COMMAND_SEARCH, COMMAND_REM, COMMAND_EXECUTE, COMMAND_LOG, COMMAND_UNKNOWN }; const struct command_list commands[]= { { COMMAND_QUIT, "QUIT" ,"QUIT - Immediate exit from the emulator back to windows" ,"" }, { COMMAND_RUN, "RUN" ,"RUN [xxxx] - Run from xxxx (optional)" ,"Usage: RUN [addr]" }, { COMMAND_STOP, "STOP" ,"STOP - Halt CPU" ,"" }, { COMMAND_STEP, "STEP" ,"STEP [xxxx] - Single Step the CPU from addr xxxx (optional)" ,"" }, { COMMAND_SCRIPT, "SCRIPT","SCRIPT <file> - Run a script file" ,"Usage: SCRIPT <file>" }, { COMMAND_BPOINT, "BP" ,"BP [n] [xxxx]/CLR - Set/List/Clear breakpoint n to xxxx" ,"Usage: BP [n] [xxxx]/CLR" }, { COMMAND_RESET, "RESET" ,"RESET - Reset CPU, also halts" ,"" }, { COMMAND_REGISTERS, "REG" ,"REG [PC/SP/PS/X/Y/A] [Value] - Display/Set registers" ,"Usage: REG [PC/SP/PS/X/Y/A] [Value]" }, { COMMAND_MEM_SET, "MS" ,"MS <xxxx> <aa> [bb]..[ff] - Set RAM xxxx to aa.bb,cc,etc" ,"Usage: MS <xxxx> <aa> [bb]..[ff]" }, { COMMAND_MEM_DUMP, "MD" ,"MD [xxxx] [yyyy] - Dump RAM from xxxx to yyyy" ,"Usage: MD <xxxx> [yyyy]" }, { COMMAND_MEM_LOAD, "MLOAD" ,"MLOAD <xxxx> <file> - Load RAM from file starting at xxxx" ,"Usage: MLOAD <xxxx> <file>" }, { COMMAND_MEM_SAVE, "MSAVE" ,"MSAVE <xxxx> <yyyy> <file> - Save RAM to file from xxxx-yyyy" ,"Usage: MSAVE <xxxx> <yyyy> <file>" }, { COMMAND_SEARCH, "MSRCH" ,"MSRCH <xxxx> <yyyy> \"param\" - Search RAM for string" ,"Usage: MSRCH <xxxx> <yyyy> \"param\"\\<aa bb cc ...>" }, { COMMAND_SEARCH, "MSRCH" ,"MSRCH <xxxx> <yyyy> <aa bb ..> - Search RAM for bytes" ,"Usage: MSRCH <xxxx> <yyyy> \"param\"\\<aa bb cc ...>" }, { COMMAND_CART_SET, "CS" ,"CS <xxxx> <aa> [bb]..[ff] - Set cartridge memory xxxx to aa.bb,cc,etc" ,"Usage: CS <xxxx> <aa> [bb]..[ff]" }, { COMMAND_CART_DUMP, "CD" ,"CD [xxxxxx] [yyyyyy] - Dump cartridge memory from xxxxxx to yyyyyy" ,"Usage: CD <xxxxxx> [yyyyyy]" }, { COMMAND_CART_LOAD, "CLOAD" ,"CLOAD <xxxxxx> <file> - Load cartridge from file starting at xxxxxx" ,"Usage: CLOAD <xxxxxx> <file>" }, { COMMAND_CART_SAVE, "CSAVE" ,"CSAVE <xxxxxx> <yyyyyy> <file> - Save cartridge to file from xxxxxx-yyyyyy" ,"Usage: CSAVE <xxxxxx> <yyyyyy> <file>" }, { COMMAND_SEARCH, "CSRCH" ,"CSRCH <xxxx> <yyyy> \"param\" - Search cartridge for string" ,"Usage: CSRCH <xxxx> <yyyy> \"param\"\\<aa bb cc ...>" }, { COMMAND_SEARCH, "CSRCH" ,"CSRCH <xxxx> <yyyy> <aa bb ..> - Search cartridge for bytes" ,"Usage: CSRCH <xxxx> <yyyy> \"param\"\\<aa bb cc ...>" }, { COMMAND_REM, "REM" ,"REM - Some comments - Script Remark/Comments, will be ignored " ,"" }, { COMMAND_EXECUTE, "EXEC" ,"EXEC .... - Execute/Spawn external command" ,"Usage: EXEC (args....)" }, { COMMAND_LOG, "LOG" ,"LOG [filename] .... - Log all output to a file" ,"Usage: LOG [filename]" }, { COMMAND_HELP, "HELP" ,"HELP - Prints this text" ,"" }, { COMMAND_UNKNOWN, "" ,"" ,"" } }; // Dump back to the edit window strcpy(tmptext,">"); strncat(tmptext,linetext,MAX_LINE_SIZE-1); tmptext[MAX_LINE_SIZE]=0; LineOutput(tmptext); // Splat remaining arg array to null for(loop=0;loop<MAX_COMMAND_ARGS;loop++) arglist[loop]=&emptystring[0]; arglist[MAX_COMMAND_ARGS]=NULL; loop=0; // Put all to upper case while(linetext[loop]!=0x00) { linetext[loop]=toupper(linetext[loop]); loop++; } if((arglist[0]=Tokenize(linetext))!=NULL) { argcount++; while(argcount<MAX_COMMAND_ARGS) { if((arglist[argcount]=Tokenize(NULL))==NULL) { // Fix up the null string on the end arglist[argcount]=emptystring; break; } argcount++; } } // Process into argc/argv if(argcount) { loop=0; for(;;) { // Check for the end of the list if(strcmp(commands[loop].command,"")==0) break; // Check our command if(strcmp(commands[loop].command,arglist[0])==0) break; loop++; } switch(commands[loop].command_id) { case COMMAND_REM: cmd_ok=TRUE; break; case COMMAND_QUIT: cmd_ok=CommandQuit(argcount,arglist); break; case COMMAND_RUN: cmd_ok=CommandRun(argcount,arglist); break; case COMMAND_STOP: cmd_ok=CommandStop(argcount,arglist); break; case COMMAND_STEP: cmd_ok=CommandStep(argcount,arglist); break; case COMMAND_BPOINT: cmd_ok=CommandBpoint(argcount,arglist); break; case COMMAND_SCRIPT: cmd_ok=CommandScript(argcount,arglist); break; case COMMAND_SEARCH: cmd_ok=CommandSearch(argcount,arglist); break; case COMMAND_RESET: cmd_ok=CommandReset(argcount,arglist); break; case COMMAND_REGISTERS: cmd_ok=CommandRegisters(argcount,arglist); break; case COMMAND_MEM_SET: cmd_ok=CommandMemSet(argcount,arglist); break; case COMMAND_MEM_DUMP: cmd_ok=CommandMemDump(argcount,arglist); break; case COMMAND_MEM_LOAD: cmd_ok=CommandMemLoad(argcount,arglist); break; case COMMAND_MEM_SAVE: cmd_ok=CommandMemSave(argcount,arglist); break; case COMMAND_CART_SET: cmd_ok=CommandCartSet(argcount,arglist); break; case COMMAND_CART_DUMP: cmd_ok=CommandCartDump(argcount,arglist); break; case COMMAND_CART_LOAD: cmd_ok=CommandCartLoad(argcount,arglist); break; case COMMAND_CART_SAVE: cmd_ok=CommandCartSave(argcount,arglist); break; case COMMAND_EXECUTE: cmd_ok=CommandExecute(argcount,arglist); break; case COMMAND_LOG: cmd_ok=CommandLog(argcount,arglist); break; case COMMAND_HELP: { int loop=0; LineOutput("Supported Command Line Functions are:"); do { if(strcmp(commands[loop].help,"")!=0) LineOutput(commands[loop].help); loop++; } while(commands[loop].command_id!=COMMAND_UNKNOWN); LineOutput(" ( <xx> - Mandatory agrument, [xx] - Optional argument )"); LineOutput(""); cmd_ok=TRUE; } break; default: case COMMAND_UNKNOWN: cmd_ok=CommandNotFound(argcount,arglist); break; } // Redraw all debug windows incase global data change AfxGetMainWnd()->PostMessage(WM_COMMAND,IDM_DRAW_DEBUG_WINDOWS); if(cmd_ok) { // Clear the command line mpEditLine->SetWindowText(""); } else { // Provide usage text if available if(strcmp(commands[loop].help,"")!=0) LineOutput(commands[loop].usage); } } return cmd_ok; }