Пример #1
0
/******************************************************************************
*                                                                             *
*   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 );
}
Пример #2
0
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;
}