/***************************************************************************
**
**    $Header$
**
**    $Log$
** 
****************************************************************************/

/////////////////////////////////////////////////////////////////////////////
//
//  File name: SYNTAX.CPP
//
//  Description: The implementation file for the class: CSyntaxCheck.
//
//  Author: Chen Jun
//
//  Date: 04/03/95
//
//  Modification:
//      1. 04/03/95, Initial version of the class: CSyntaxCheck.
//      2. 10/10/95, Remove Stepoption command.
//
/////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////
//
//	How to add a new Shell command "XXX":
//
//	1.In the \ep251\maketab directory, modify "alias.dat"
//	2.Make "ep251\maketab\maketab.exe", and run it.
//	3.Copy "command.dat" to \ep251
//	4.In the "shlsynco.cpp", modify the global variable "nMaxCmdNo"
//	5.In the "syncore.h", add a command ID "CMDID_XXX" in the enum 
//	6.In the "syncore2.cpp", add "SyntaxCheckXXX" routing.
//	7.In the "syncore1.cpp", modify "CSyntaxCore::SyntaxDispatch" routing
//	8.In the "syntax.cpp", modify "CSyntaxCheck::DispatchCommand" routing
//	9.In the "hints.dat", add a command hints
//	10.In the "shlsynco.cpp", add "SyntaxCheckXXXSub" routing
//	11.In the "shlcolor.cpp", add "SetSyntaxColorXXX" routing                
//  12.In the "cmdlist.dat", add a command help
//
/////////////////////////////////////////////////////////////////////////////


/////////////////////////////////////////////////////////////////////////////
// Include files.
#include "stdafx.h"
#include "resource.h"

#include "shlcom.h"
#include "tstinc.h"
#include "syntax.h"
#include "shlmacro.h"
#include <ctype.h>
#include <string.h>
#include "goapi.h"
#include "aliaspub.h"
#include "hosterrs.h"
#include "symblsvr.h"
#include "goapi.h"
// Added by Chen, 04/29/97
#include "srcdef.h"

#include "ldrexp.h"
#include "ep196.h"    

#include "srcdef.h"  

/////////////////////////////////////////////////////////////////////////////
// Debug flags.
#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif


/////////////////////////////////////////////////////////////////////////////
// Type definitions.


/////////////////////////////////////////////////////////////////////////////
// Macro definitions.


/////////////////////////////////////////////////////////////////////////////
// Global variables.


/////////////////////////////////////////////////////////////////////////////
// Static variables.


/////////////////////////////////////////////////////////////////////////////
// External variables.
extern BOOL isRunInclude;   // Defined in TSTINC.CPP
extern BOOL isDefineMacro;  //Defined in shlmacro.cpp
extern BOOL isRunMacro;		//Defined in shlmacro.cpp
//Defined in tstinc.cpp
extern int nIncludeIndex;   
extern BOOL isRunInc[CIncludeFile::maxFileNo];
extern CIncludeFile* pInclude[CIncludeFile::maxFileNo];
//Defined in shlmacro.cpp
extern BOOL isRunMac[CMacroFile::maxFileNo];
extern int nMacroIndex ;
extern CMacroFile* pMacro[CMacroFile::maxFileNo];


/////////////////////////////////////////////////////////////////////////////
// Global function prototypes.
void ShowLine(char* pszBuffer);
void CommandProcess(char* pchBuf, int nLen);
BOOL SeparateCommand(char* pchBuf, int nLen, int nPromptLen, CStringList* strTempBuf);
void ExpandKeyword(char* pszTemp);
void ShellCommandProcess(char* pszCommandBuf, int nLen);
void IncludeProcess(int nIncIndex);
void MacroProcess(int nMacIndex);
BOOL IsKeywordRunMacro(char* pszTemp);
BOOL IsKeywordRunInc(char* pszTemp);
void DisplayOutOfMemory(void);

/////////////////////////////////////////////////////////////////////////////
// Local function prototypes.

/////////////////////////////////////////////////////////////////////////////
// External function prototypes.

// Defined in TSTLOG.CPP
void TstLogInfo(char* pchBuf, int nLen=0);

// Defined in TSTINC.CPP
void TstReadOneInc(char* pszBuf);
void TstFreeInclude(void);
BOOL TstIsInnerCommand(char* pszIncLine);

// Defined in TSTTEMP.CPP
void TstCreateStock(void);
void TstDestroyStock(void);
void TstOpenStock(void);
void TstCloseStock(void);
void TstAppendStock(char* pszPrompt, char* pszResult);

// Defined in UICOM.CPP
void ShlShowLine(char * pch, int nLen);
int TestKey(WORD wKey);

// Shell commands.
void RunMacroCmd(int nArgc, char* pszArgv[]);              
//void CalcCmd(int nArgc, char* pszArgv[]);
void AliasCmd(int m_nArgc, char* m_pszArgv[]);

void AssembleCmd(int nArgc, char* pszArgv[]);
void BitCmd(int nArgc, char* pszArgv[]);
//void BreakpointCmd(int nArgc, char* pszArgv[]);
void ByteCmd(int nArgc, char* pszArgv[]);
void ChecksumCmd(int nArgc, char* pszArgv[]);
//void ClearCmd(int nArgc, char* pszArgv[]);
void CompareCmd(int nArgc, char* pszArgv[]);
void ControlCmd(int nArgc, char* pszArgv[]);
void CopyCmd(int nArgc, char* pszArgv[]);
void CycleCmd(int nArgc, char* pszArgv[]);
void DisassembleCmd(int nArgc, char* pszArgv[]); 
void DiagnosticCmd(int nArgc, char* pszArgv[]);
void Ev1Cmd(int nArgc, char* pszArgv[]);
void Ev2Cmd(int nArgc, char* pszArgv[]);
void Ev3Cmd(int nArgc, char* pszArgv[]);
void EventCmd(int nArgc, char* pszArgv[]);
void FillCmd(int nArgc, char* pszArgv[]);
void HelpCmd(int nArgc, char* pszArgv[]);
void IdentifyCmd(int nArgc, char* pszArgv[]);
void IncludeCmd(int nArgc, char* pszArgv[]);
void InportCmd(int nArgc, char* pszArgv[]);
void LevelCmd(int nArgc, char* pszArgv[]);
void ListCmd(int nArgc, char* pszArgv[]);
void LogCmd(int nArgc, char* pszArgv[]);
void LongCmd(int nArgc, char* pszArgv[]); 
void Lv1Cmd(int nArgc, char* pszArgv[]);
void Lv2Cmd(int nArgc, char* pszArgv[]);
void MapCmd(int nArgc, char* pszArgv[]);
void MacroCmd(int nArgc, char* pszArgv[]);
void DelMacroCmd(int nArgc, char* pszArgv[]); 
void ShowMacroCmd(int nArgc, char* pszArgv[]);
void ListMacroCmd(int nArgc, char* pszArgv[]);
void MendCmd(int nArgc, char* pszArgv[]);
void RunMacroCmd(int nArgc, char* pszArgv[]);
void MemoryCmd(int nArgc, char* pszArgv[]);
void OutportCmd(int nArgc, char* pszArgv[]);
void PortCmd(int nArgc, char* pszArgv[]); 
void QualifyCmd(int nArgc, char* pszArgv[]);
void RegisterCmd(int nArgc, char* pszArgv[]);
void ResetCmd(int nArgc, char* pszArgv[]);
void SearchCmd(int nArgc, char* pszArgv[]);
//void StepCmd(int nArgc, char* pszArgv[]);
void TestCmd(int nArgc, char* pszArgv[]);   
void TraceCmd(int nArgc, char* pszArgv[]);
void TriggerCmd(int nArgc, char* pszArgv[]);
//void UploadCmd(int nArgc, char* pszArgv[]);
void VerifyCmd(int nArgc, char* pszArgv[]);
void WordCmd(int nArgc, char* pszArgv[]);
//void CreateCmd(int nArgc, char* pszArgv[]);
//void DeleteCmd(int nArgc, char* pszArgv[]);
//void LoadCmd(int nArgc, char* pszArgv[]);

//void QueryCmd(int nArgc, char* pszArgv[]);

//void SsaveCmd(int nArgc, char* pszArgv[]);
//void SrecallCmd(int nArgc, char* pszArgv[]);
//void SymbolCmd(int nArgc, char* pszArgv[]);
//void WatchCmd(int nArgc, char* pszArgv[]);

// Defined in UICOM.CPP
#include "uicom2.h"
void MarkPC(void);
//void RepaintSource(void);
//void RepaintCPU(void);
//void RepaintMemory(void);
//void RepaintTrace(void);
//void RepaintStack(void);
//void RepaintVariable(void);

//void OnEmulation(void);  

extern void RefreshTraceWnd();         


//Defined in shlmacro.cpp
void DefineMacro(char* pszBuf, int nLen);
void RunMacroCmd(int nArgc, char* pszArgv[]);
BOOL IsMacroInnerCommand(char* pszMacroLine);
void ReadOneMacro(char* pszBuf);

//Defined in emugo.cpp

int ExpandCommand(const char* pszCommand, char* pszExpand, char* pszHints);
BOOL ExpandParameter(const char* pszCommand, const char* pszParameter, char* pszExpand);

void MinAllMemWnd();
/////////////////////////////////////////////////////////////////////////////
// Executable codes.

/////////////////////////////////////////////////////////////////////////////
// Public functions.

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   CommandProcess().
//
//  Description: The shell of the syntax checking kernel.
//
//  Input:  pchBuf - The line editor buffer.
//          nLen - The number of the characters in the line editor buffer.
//
//  Output: None.
//
//  Return: None.
//
/////////////////////////////////////////////////////////////////////////////
void CommandProcess(char* pchBuf, int nLen)
{                   
    ASSERT( pchBuf );
    ASSERT( nLen >= 0 && nLen <= 255 );

	char* pszCopy = new char[nLen+10];
	strncpy(pszCopy, pchBuf, nLen+1);
	pszCopy[nLen+1] = '\0';            

	// Single command                  
    int nPromptLen;

	if ( 1 == nAsmFlag) {
		nPromptLen = 10;  //4/16/97  
		pchBuf[nPromptLen+nLen] = 0;
		TstLogInfo(pchBuf, nLen+nPromptLen);
        DadAssemble(pchBuf+nPromptLen); 
		delete []pszCopy;
		pszCopy = 0;
        return;
    }
	else if( TRUE == isDefineMacro) {
		nPromptLen = 6;
    	char* pTemp = new char[260];
	    	                                    
		TstLogInfo(pchBuf, nLen+nPromptLen);
    	strncpy(pTemp, pchBuf+nPromptLen,nLen);
    	pTemp[nLen] = '\0';
    	CString strTemp(pTemp);
    	strTemp.TrimLeft();    
    	strTemp.MakeLower();
    	if (strTemp.GetLength() >= 6) {
	    	if (strTemp.Find("mend") == 0 && strTemp[4] == ' ' ) {                       
	    		//Send SyntaxCheck   
	    		ShellCommandProcess(pchBuf+nPromptLen,nLen);		
			}   
            else if ( strTemp.Find("macro") == 0 && strTemp[5] == ' ' ) {                       
                //Send SyntaxCheck   
                ShellCommandProcess(pchBuf+nPromptLen,nLen);        
            }   
			else {
				DefineMacro(pchBuf+nPromptLen,nLen);								
			}                     			
		}   
        else if (strTemp.GetLength() == 5) {
            if (strTemp.Find("mend") == 0 && strTemp[4] == ' ' ) {                       
                //Send SyntaxCheck   
                ShellCommandProcess(pchBuf+nPromptLen,nLen);        
            }   
            else if ( strTemp.Find("macro") == 0 ) {                       
                //Send SyntaxCheck   
                ShellCommandProcess(pchBuf+nPromptLen,nLen);        
            }   
            else {
                DefineMacro(pchBuf+nPromptLen,nLen);                                
            }                               
        }   
		else if (strTemp.GetLength() == 4) { 
			if (strTemp.Find("mend") == 0 ) {                       
	    		//Send SyntaxCheck   
	    		ShellCommandProcess(pchBuf+nPromptLen,nLen);		
			}   
			else {
				DefineMacro(pchBuf+nPromptLen,nLen);								
			}                     			
		}
		else {                                  
			DefineMacro(pchBuf+nPromptLen,nLen);				
		}
		delete []pTemp;
		pTemp = 0;     
		delete []pszCopy;
		pszCopy = 0;
		return;
    }
	else {
		nPromptLen = 1;                         
		TstLogInfo(pchBuf, nLen+nPromptLen);
		ShellCommandProcess(pchBuf+nPromptLen,nLen);		
	}
		
	if ( isRunInclude ) {
		IncludeProcess(nIncludeIndex);
	}
	else if (isRunMacro) {
	    MacroProcess(nMacroIndex);
	}                             
	delete []pszCopy;
	pszCopy = 0;
	return;       	   
	
}   // End of CommandProcess().


/////////////////////////////////////////////////////////////////////////////
//
//  Name:   ShellCommandProcess(char* pszCommandBuf, int nLen)
//
//  Description:   Entry the Syntax checking routine.
//
//  Input:  pszCommandBuf - The command editor buffer.
//			nLen          - The length of buffer
//
//  Output: None.
//
//  Return: None.
//
/////////////////////////////////////////////////////////////////////////////
void ShellCommandProcess(char* pszCommandBuf, int nLen)
{
    CSyntaxCheck* pSyntaxCheck = new CSyntaxCheck;
    if ( !pSyntaxCheck ) {
        DisplayOutOfMemory();                
        ASSERT( FALSE );
        return;
    }
    else {
        TstOpenStock();                    
        pSyntaxCheck->CheckCommandSyntax(pszCommandBuf, nLen);
        delete pSyntaxCheck;
        pSyntaxCheck = 0;
        TstCloseStock();
    }

}	//End of ShellCommandProcess().

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   IncludeProcess(int nIncIndex)
//
//  Description:   Run include file
//
//  Input:  None.
//
//  Output: None.
//
//  Return: None.
//
/////////////////////////////////////////////////////////////////////////////
void IncludeProcess(int nIncIndex)
{
    // Allocate two buffers.
    char* pszIncBuf = new char[260+7];
    if ( !pszIncBuf ) {
        DisplayOutOfMemory();
        ASSERT( FALSE );
        return;
    }
    char* pszTemp = new char[260];
    if ( !pszTemp ) {
        DisplayOutOfMemory();
        ASSERT( FALSE );
        delete []pszIncBuf;
        pszIncBuf = 0;
        return;
    }                          

    // Include loop.
    do {
        // Set the Include input buffer.
        // Create the Include stock.
        TstCreateStock();
        // Detect the Ctrl-Break key instead of ESC key.
        if ( 1 == TestKey(VK_ESCAPE) ) {
            ShowLine("Include file is aborted by user.");
			/*
			char pchText[256];
			ErrGetErrorText(ER_ABORT_INC, pchText);
			ShowLine(pchText);            
			*/
            nAsmFlag = 0;
            //isRunInclude = FALSE;
            goto Exit;
        }
        // Initial the allocated buffer.
        memset(pszIncBuf, 0, 267);
        memset(pszTemp, 0, 260);
        // Read one line from the Include file.
        TstReadOneInc(pszTemp); 
        int nLen = strlen(pszTemp);
        if ( nLen > 0 ) {
            if ( '\n' == *(pszTemp+nLen-1) ) {
                nLen -= 1;
                *(pszTemp+nLen) = 0;
            }
        }
        //Add by Annie, 3/29/96
        //Auto-expand the keywords in the include file
		if (1 != nAsmFlag ) {
			strcat(pszTemp," ");
            char *pszExpand;
		    int nPos;
		    BOOL isOk;
		    
		    pszExpand = new char[260];
		    strcpy(pszExpand, pszTemp);
		    CSyntaxCheck* pSyntaxCheck = new CSyntaxCheck;     
            ExpandKeyword(pszExpand);      		    
			isOk = pSyntaxCheck->CheckCommandSyntax(pszExpand, strlen(pszExpand), nPos);    
			delete pSyntaxCheck;                       
			if ( isOk) {                       
				strcpy(pszTemp, pszExpand);							
			}
			else {
				CString strExpand(pszExpand);
				strExpand.MakeUpper();          				
				if ( strExpand.Find("ALIAS") != -1 && nPos == 3) {
					strcpy(pszTemp, pszExpand);	
				}			
			}                              			
            delete []pszExpand;
            nLen = strlen(pszTemp);
		}
				            
        // Link Command & Prompt.
        if ( 1 == nAsmFlag ) {
            nShellPrompt = PMT_RND;
            ASSERT( 7 == strlen(PromptStr[nShellPrompt]) );
        }
        else if (TRUE == isDefineMacro) {
        	nShellPrompt = PMT_MACRO;
            ASSERT( 6 == strlen(PromptStr[nShellPrompt]) );
        }
        else
		{
            nShellPrompt = PMT_NORMAL;
            ASSERT( 1 == strlen(PromptStr[nShellPrompt]) );
        }
        strcpy(pszIncBuf, PromptStr[nShellPrompt]);
        strcat(pszIncBuf, pszTemp);

        // Log the user's commands.
        int nPromptLen;
        if ( 1 == nAsmFlag) {
			nPromptLen = 10;     //4/16/97
		}
		else if( TRUE == isDefineMacro) {
			nPromptLen = 6;
		}
		else {
			nPromptLen = 1;
		}

        //Define Macro
        if ( isDefineMacro ) {
			nPromptLen = 6;
	    	char* pTemp = new char[260];
	    	strcpy(pTemp, pszIncBuf+nPromptLen);
	    	pTemp[nLen] = '\0';    

	    	char* strMacroCommand = new char[strlen(pTemp)+8];
			strcpy( strMacroCommand, "MACRO>");
			strcat( strMacroCommand, pTemp);
			ShowLine(strMacroCommand);               	

	    	CString strTemp(pTemp);
	    	strTemp.TrimLeft();    
	    	strTemp.MakeLower();
	    	if (strTemp.GetLength() >= 5) {
		    	if (strTemp.Find("mend") == 0 && strTemp[4] == ' ') {                       
		    		//Send SyntaxCheck   
		    		ShellCommandProcess(pszIncBuf+nPromptLen,nLen);		
				}       
				else {
					DefineMacro(pszIncBuf+nPromptLen,nLen);								
				}                 			
			}
			else if (strTemp.GetLength() == 4) { 
				if (strTemp.Find("mend") == 0 ) {                       
		    		//Send SyntaxCheck   
		    		ShellCommandProcess(pszIncBuf+nPromptLen,nLen);		
				}   
				else {
					DefineMacro(pszIncBuf+nPromptLen,nLen);								
				}                     			
			}
			else {                                  
				DefineMacro(pszIncBuf+nPromptLen,nLen);				
			}
			delete []pTemp;
			pTemp = 0;
			continue;			
        }

        //If Run Macro  @AA
		if ( IsKeywordRunMacro(pszTemp) ) {		        
			ShowLine(pszIncBuf);    	
    		CSyntaxCheck* pSyntaxCheck = new CSyntaxCheck;
			pSyntaxCheck->CheckCommandSyntax(pszTemp, strlen(pszTemp)); 
	        delete pSyntaxCheck;
	        pSyntaxCheck = 0;
	        if (isRunMacro && isRunMac[nMacroIndex]) {	
	        	MacroProcess(nMacroIndex); 
	        }	
	        continue;
		}
		    
		//If Run Include     
		if ( IsKeywordRunInc(pszTemp) ) {		        
			ShowLine(pszIncBuf);    	    		
    		CSyntaxCheck* pSyntaxCheck = new CSyntaxCheck;
			pSyntaxCheck->CheckCommandSyntax(pszTemp, strlen(pszTemp));
	        delete pSyntaxCheck;
	        pSyntaxCheck = 0;
			if ( isRunInclude && isRunInc[nIncludeIndex] ) {
	        	IncludeProcess(nIncludeIndex); 
	        }	
	        continue;
		}		
            
        // Show the Include commands.
        if ( isRunInc[nIncIndex] ) {
	        ShlShowLine(pszIncBuf, nLen+nPromptLen);
    	}
        TstLogInfo(pszIncBuf, nLen+nPromptLen);

        if ( 0 == nLen ) {
            if ( isRunInc[nIncIndex] ) {
                continue;
            }
            else {
                goto Exit;
            }
        }

		if ( isRunInc[nIncIndex] ) {
        	if ( TstIsInnerCommand(pszIncBuf+nPromptLen) ) 
	        continue;                                      
	    }    
        
        // Assemble command input.
        if ( 1 == nAsmFlag ) {
            // ESC('\\') to abort Assemble command.
            if ( isRunInc[nIncIndex] ) {
	            char* p = pszIncBuf + nPromptLen;
	            while ( *p ) {
	                if ( isspace(*p) ) {
	                    p++;
	                }
	                else {
	                    break;
	                }
	            }
	            if ( '\\' == *p ) {
	                char* ptr = p+1;
	                while ( *ptr ) {
	                    if ( isspace(*ptr) ) {
	                        ptr++;
	                    }
	                    else {
	                        break;
	                    }
	                }
	                nAsmFlag = 0;
	                continue;
	            }
            }
            TstOpenStock();
            pszIncBuf[nPromptLen+nLen] = 0;
            DadAssemble(pszIncBuf+nPromptLen);
            TstCloseStock();
            continue;
        }
		ShellCommandProcess(pszIncBuf+nPromptLen,nLen);
    } while ( isRunInc[nIncIndex] && isRunInclude);
    // Destroy the Include stock.
    TstDestroyStock();

    // Free the allocated bufffer.
    if ( pszIncBuf ) {
        delete []pszIncBuf;
        pszIncBuf = 0;
    }
    if ( pszTemp ) {
        delete []pszTemp;
        pszTemp  = 0;
    }
	return;
    
Exit:
    // Free all of the Include objects.
    if (pInclude[nIncludeIndex]) {
    	delete []pInclude[nIncludeIndex]; 
    	pInclude[nIncludeIndex] = 0;
    }	                            
                                      
	isRunInc[nIncludeIndex] = FALSE;    
    nIncludeIndex--;                     
    if ( -1 == nIncludeIndex ) {
    	isRunInclude = FALSE;
	}
	
    // Destroy the Include stock.
    TstDestroyStock();

    // Free the allocated bufffer.
    if ( pszIncBuf ) {
        delete []pszIncBuf;
        pszIncBuf = 0;
    }
    if ( pszTemp ) {
        delete []pszTemp;
        pszTemp = 0;
    }
    
}	//End of IncludeProcess(). 
                         
BOOL IsKeywordRunMacro(char* pszTemp)
{
	int index = 0;
	while ( pszTemp[index] ) {
		if ( !isspace(pszTemp[index]) ) break;
		index++; 	
	}          
	if ('@' == pszTemp[index] )
		return (TRUE);
	else
		return (FALSE);

}	//End of IsKeywordRunMacro().
                         
/////////////////////////////////////////////////////////////////////////////
//
//  Name:   MacroProcess(int nMacIndex)
//
//  Description:   Run Macro file
//
//  Input:  None.
//
//  Output: None.
//
//  Return: None.
//
/////////////////////////////////////////////////////////////////////////////
void MacroProcess(int nMacIndex)
{
    // Allocate two buffers.
    char* pszMacroBuf = new char[260+7];
    if ( !pszMacroBuf ) {
        DisplayOutOfMemory();
        ASSERT( FALSE );
        return;
    }
    char* pszTemp = new char[260];
    if ( !pszTemp ) {
        DisplayOutOfMemory();
        ASSERT( FALSE );
        delete []pszMacroBuf;
        pszMacroBuf = 0;
        return;
    }                          

    // Macro loop.
    do {
        // Set the Macro input buffer.
        // Create the Macro stock.
        TstCreateStock();
        // Detect the Ctrl-Break key instead of ESC key.
        if ( 1 == TestKey(VK_ESCAPE) ) {
            ShowLine("Macro file is aborted by user.");
			/*
			char pchText[256];
			ErrGetErrorText(ER_ABORT_MACRO, pchText);
			ShowLine(pchText);
            */
            nAsmFlag = 0;    
            //isRunMacro = FALSE;
            goto Exit;
        }
        // Initial the allocated buffer.
        memset(pszMacroBuf, 0, 267);
        memset(pszTemp, 0, 260);
        // Read one line from the Macro file.
        ReadOneMacro(pszTemp); 
        int nLen = strlen(pszTemp);
        if ( nLen > 0 ) {
            if ( '\n' == *(pszTemp+nLen-1) ) {
                nLen -= 1;
                *(pszTemp+nLen) = 0;
            }
        }
        //Add by Annie, 3/29/96
        //Auto-expand the keywords in the Macro file
		if (1 != nAsmFlag ) {
			strcat(pszTemp," ");
            char *pszExpand;
		    int nPos;
		    BOOL isOk;
		    
		    pszExpand = new char[strlen(pszTemp)+4];
		    strcpy(pszExpand, pszTemp);
		    CSyntaxCheck* pSyntaxCheck = new CSyntaxCheck;     
            ExpandKeyword(pszExpand);      		    
			isOk = pSyntaxCheck->CheckCommandSyntax(pszExpand, strlen(pszExpand), nPos);    
			delete pSyntaxCheck;                       
			if ( isOk) {                       
				strcpy(pszTemp, pszExpand);							
			}
			else {
				CString strExpand(pszExpand);
				strExpand.MakeUpper();          				
				if ( strExpand.Find("ALIAS") != -1 && nPos == 3) {
					strcpy(pszTemp, pszExpand);	
				}			
			}                              			
            delete []pszExpand;
            nLen = strlen(pszTemp);
		}    		            
        // Link Command & Prompt.
        if ( 1 == nAsmFlag ) {
            nShellPrompt = PMT_RND;
            ASSERT( 7 == strlen(PromptStr[nShellPrompt]) );
        }
        else if (TRUE == isDefineMacro) {
        	nShellPrompt = PMT_MACRO;
            ASSERT( 6 == strlen(PromptStr[nShellPrompt]) );
        }
        else {
            nShellPrompt = PMT_NORMAL;
            ASSERT( 1 == strlen(PromptStr[nShellPrompt]) );
        }
        strcpy(pszMacroBuf, PromptStr[nShellPrompt]);
        strcat(pszMacroBuf, pszTemp);

        // Log the user's commands.
        int nPromptLen;
        if ( 1 == nAsmFlag) {
			nPromptLen = 10;  //4/16/97
		}
		else if( TRUE == isDefineMacro) {
			nPromptLen = 6;
		}
		else {
			nPromptLen = 1;
		}

        //Define Macro
        if ( isDefineMacro ) {
        	nPromptLen = 6;
	    	char* pTemp = new char[260];
	    	strcpy(pTemp, pszMacroBuf+nPromptLen);
	    	pTemp[nLen] = '\0';
	
	    	char* strMacroCommand = new char[strlen(pTemp)+8];
			strcpy( strMacroCommand, "MACRO>");
			strcat( strMacroCommand, pTemp);
			ShowLine(strMacroCommand);               	
            
            delete []strMacroCommand;  
            
	    	CString strTemp(pTemp);
	    	strTemp.TrimLeft();    
	    	strTemp.MakeLower();
	    	if (strTemp.GetLength() >= 5) {
		    	if (strTemp.Find("mend") == 0 && strTemp[4] == ' ') {                       
		    		//Send SyntaxCheck   
		    		ShellCommandProcess(pszMacroBuf+nPromptLen,nLen);		
				}
				else {
					DefineMacro(pszMacroBuf+nPromptLen,nLen);								
				}                        			
			}
			else if (strTemp.GetLength() == 4) { 
				if (strTemp.Find("mend") == 0 ) {                       
		    		//Send SyntaxCheck   
		    		ShellCommandProcess(pszMacroBuf+nPromptLen,nLen);		
				}   
				else {
					DefineMacro(pszMacroBuf+nPromptLen,nLen);								
				}                     			
			}
			else {                                  
				DefineMacro(pszMacroBuf+nPromptLen,nLen);				
			}
			delete []pTemp;
			pTemp = 0;
			continue;			
		}

        //If Run Include 
    	if ( IsKeywordRunInc(pszTemp) ) {		        
    		ShowLine(pszMacroBuf);
    		CSyntaxCheck* pSyntaxCheck = new CSyntaxCheck;
			pSyntaxCheck->CheckCommandSyntax(pszTemp, strlen(pszTemp));
            delete pSyntaxCheck;
	        pSyntaxCheck = 0;
	        if ( isRunInclude && isRunInc[nIncludeIndex] ) {
	        	IncludeProcess(nIncludeIndex); 
	        }	
	        continue;
		}                         

        //If Run Macro  @AA
		if ( IsKeywordRunMacro(pszTemp) ) {		        
			ShowLine(pszMacroBuf);    	
    		CSyntaxCheck* pSyntaxCheck = new CSyntaxCheck;
			pSyntaxCheck->CheckCommandSyntax(pszTemp, strlen(pszTemp));
	        delete pSyntaxCheck;
	        pSyntaxCheck = 0;
	        if (isRunMacro && isRunMac[nMacroIndex]) {				
	        	MacroProcess(nMacroIndex); 
	        }	
	        continue;
		}
            
		        
        // Show the Macro commands.
        if ( isRunMac[nMacIndex] ) {
	        ShowLine(pszMacroBuf);
    	}
        TstLogInfo(pszMacroBuf, nLen+nPromptLen);
        if ( isRunMac[nMacIndex] ) {
	        if ( IsMacroInnerCommand(pszMacroBuf+nPromptLen) ) 
		        continue;
	    }     

        // Assemble command input.
        if ( 1 == nAsmFlag ) {
            // ESC('\\') to abort Assemble command.
            if ( isRunMac[nMacIndex] ) {
	            char* p = pszMacroBuf + nPromptLen;
	            while ( *p ) {
	                if ( isspace(*p) ) {
	                    p++;
	                }
	                else {
	                    break;
	                }
	            }
	            if ( '\\' == *p ) {
	                char* ptr = p+1;
	                while ( *ptr ) {
	                    if ( isspace(*ptr) ) {
	                        ptr++;
	                    }
	                    else {
	                        break;
	                    }
	                }
	                nAsmFlag = 0;
	                continue;
	            }
			}
            TstOpenStock();
            pszMacroBuf[nPromptLen+nLen] = 0;
            DadAssemble(pszMacroBuf+nPromptLen);
            TstCloseStock();
            continue;
        }
		ShellCommandProcess(pszMacroBuf+nPromptLen,nLen);
		
    } while ( isRunMac[nMacIndex] && isRunMacro );
    // Destroy the Macro stock.
    TstDestroyStock();
    
    // Free the allocated bufffer.
    if ( pszMacroBuf ) {
        delete []pszMacroBuf;
        pszMacroBuf = 0;
    }
    if ( pszTemp ) {
        delete []pszTemp;
        pszTemp = 0;
    }                        
	
	return;
    
Exit:
    // Destroy the Macro stock.
    TstDestroyStock();
    if (pMacro[nMacroIndex]) {
    	delete []pMacro[nMacroIndex];
    	pMacro[nMacroIndex] = 0;
    }	

	isRunMac[nMacroIndex] = FALSE;    
    nMacroIndex--;                     
    if ( -1 == nMacroIndex ) {
    	isRunMacro = FALSE;
	}
	
    // Free the allocated bufffer.
    if ( pszMacroBuf ) {
        delete []pszMacroBuf;
        pszMacroBuf = 0;
    }
    if ( pszTemp ) {
        delete []pszTemp;
        pszTemp = 0;
    }                        

}	//End of MacroProcess(). 

BOOL IsKeywordRunInc(char* pszTemp)
{
	int index = 0;
	while ( pszTemp[index] ) {
		if ( !isspace(pszTemp[index]) ) break;
		index++; 	
	}          
	char* p = pszTemp+index;
	
	if ( 1 == (strstr(strlwr(p),"include")-p+1) )
		return (TRUE);
	else
		return (FALSE);

}	//End of IsKeywordRunMacro().


/////////////////////////////////////////////////////////////////////////////
//
//  Name:   ShowLine().
//
//  Description: Show the results in the Shell window line.
//
//  Input:  pszBuffer - The line editor buffer.
//
//  Output: None.
//
//  Return: None.
//
/////////////////////////////////////////////////////////////////////////////
void ShowLine(char* pszBuffer)
{
    // Assertion of the input parameters.
    ASSERT( pszBuffer );

    // Log the commands' result.
    TstLogInfo(pszBuffer);
    
    // Register command result.
    TstAppendStock(PromptStr[nShellPrompt], pszBuffer);
    
    // Display the message in the Shell window.
    ShlShowLine(pszBuffer, strlen(pszBuffer));

}   // End of ShowLine().

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   BOOL SeparateCommand(char* pchBuf, int nLen, int nPromptLen, CStringList* strTempBuf).
//
//  Description: Separate each command from macro command
//
//  Input:  pszBuffer - The line editor buffer.
//          nLen      - The length of buffer.
//
//  Output: strTempBuf
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
BOOL SeparateCommand(char* pchBuf, int nLen, int nPromptLen, CStringList* strTempBuf)
{
    CString strSingle;
    int nLen1 = 0;
    int nTotalLen = 0;
    int nCurrentLen = 0;
    BOOL isFirstToken = FALSE;

	char* pszTemp = new char[nLen+nPromptLen+2];                               
	strncpy(pszTemp,pchBuf, nLen+nPromptLen);
	
	strTempBuf->RemoveAll();                                
    pszTemp[nLen+nPromptLen]=';';
    pszTemp[nLen+nPromptLen+1]='\0';
    CString str(pszTemp);

    nTotalLen = str.GetLength();
    nCurrentLen = nTotalLen;
    
    if (nLen > 128) {
    	//ShowLine("The length of input is large than 128 bytes");
		char pchText[256];
//		ErrGetErrorText(ER_LARGE_LEN, pchText);
		ShowLine(pchText);
    	
	    if (pszTemp) {
	    	delete []pszTemp;
	    	pszTemp = 0;
	    }	 
    	return (FALSE);                                         
    }
    else if (nLen == 0) {
	    if (pszTemp) {
	    	delete []pszTemp;
	    	pszTemp = 0;
	    }	     
		return (FALSE);                                  
	}	           		
    for (;;) {
        nLen1 = str.Find(';');
        if (nLen1 != -1 && nLen1 != 0) {
            strSingle = str.Left(nLen1);
            nCurrentLen = nCurrentLen - nLen1 - 1;
            if (isFirstToken == FALSE) {
                isFirstToken = TRUE;
            }
            else {
                strSingle = ">" + strSingle;
            }

            //skip space
            CString strTemp;
            for (int i=0;i<strSingle.GetLength();i++) {
                if (strSingle.GetAt(i) != ' ')
                    strTemp += strSingle.GetAt(i);
            }
            if ( strTemp.GetLength()==1 ) {
                strSingle = strTemp;
            }

            str = str.Right(nCurrentLen);
            if (strSingle.GetLength()!=1) {
            	CString strTemp = strSingle;
            	strTemp.TrimLeft();
            	
	            char* pszCommandCopy = new char[300];
	            strcpy(pszCommandCopy, strTemp.GetBuffer(strTemp.GetLength())+1);
	            strcat(pszCommandCopy, " ");
				ExpandKeyword(pszCommandCopy);     
				strTemp = pszCommandCopy;       		
	            strTemp += " ";
	            strSingle = ">";
	            strSingle += pszCommandCopy;
	            delete []pszCommandCopy;               	
            	strTemp.MakeLower();           
            	 
            	int nFind1 = strTemp.Find(' ');
            	int nFind2 = strTemp.Find("assemble");
                int nFind3 = strTemp.Find("disassemble");
                if ( nFind3 == 0 ) {
                    strTempBuf->AddTail(strSingle);     
                }    
                else if ( -1 == nFind2 || nFind2 > nFind1) {
	                strTempBuf->AddTail(strSingle);     
	            }    
            }    
        }
        else if (nLen1 == 0) {
            nCurrentLen--;
            str = str.Right(nCurrentLen);
        }
        else {  
		    if (pszTemp) {
		    	delete []pszTemp;
		    	pszTemp = 0;
		    }	 
        	return (TRUE);
        }	
    }
    if (pszTemp) {
    	delete []pszTemp;
    	pszTemp = 0;
    }	 
}   // End of SeparateCommand()

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   void ExpandKeyword(char* pszTemp).
//
//  Description: Expand the keyword in the include file
//
//  Input:  pszTemp - The include file line buffer.
//
//  Output: 
//
//  Return: none
//
/////////////////////////////////////////////////////////////////////////////
void ExpandKeyword(char* pszTemp)
{               
	int nLen = strlen(pszTemp);   
	int nLeft, nRight;
	BOOL isToken = FALSE;
	BOOL isFirstToken = FALSE;
	int nTokenLen = 0;
	
	char* p = new char[260];
	char* pszToken = new char[260];   
	char* pszCommandName = new char[260];
	char* pszEvent = new char[10];
	ASSERT ( pszEvent );
	ASSERT (p);           
	ASSERT (pszToken);
	ASSERT (pszCommandName);
	
	memset(pszEvent, 0, 10);	

	nLeft = 0;            
	memset(p, 0, 260);
	
	if ('\"' == pszTemp[0]) {
	    if (p) {
	    	delete []p;
	    	p = 0;
	    }	
	    if (pszToken) {
	    	delete []pszToken;
	    	pszToken = 0;
	    }	
	    if (pszCommandName) {
	    	delete []pszCommandName;
	    	pszCommandName = 0;
	    }	
	    if (pszEvent) {
	    	delete []pszEvent;
	        pszEvent = 0;
	    }    
		return;
	}
	// Skip heading space
	while (nLeft < nLen) {
		if(isspace(pszTemp[nLeft]))	{
			p[nLeft] = ' ';
			++nLeft;       			
		}	
	 	else	break;
	}                             
	nRight = nLeft;
	for( int i = nLeft; i < nLen; i++) {
		// Only for "xxx"
		if( '\"' == pszTemp[i] && ' ' == pszTemp[i-1]) {
			int nPLen = strlen(p);
			for ( int j = i; j < nLen; j++) {
				p[nPLen] = pszTemp[j];
				nPLen++;
			}             
			p[nPLen]='\0';		
			strcpy(pszTemp,p);	
		    if (p) {
		    	delete []p;
		    	p = 0;
		    }	
		    if (pszToken) {
		    	delete []pszToken;
		    	pszToken = 0;
		    }
		    if (pszCommandName) {
		    	delete []pszCommandName;
		    	pszCommandName = 0;
		    }	
		    if (pszEvent) {
		    	delete []pszEvent;
		        pszEvent = 0;
		    }    
			return;		
		}
		//Normal case
		if ( ' ' == pszTemp[i]) {
			if ( TRUE == isToken ) {
				pszToken[nTokenLen] = 0;	
				if (isFirstToken == FALSE) {
					isFirstToken = TRUE;
					//Expand Command
					char* pszExpand = new char[21];
					char* pszHints = new char[300];
		
					int nRet=::ExpandCommand(pszToken, pszExpand, pszHints);  
					if (nRet == CCommandSet::COMMAND ) {
						if (strcmp(pszExpand,"@") == 0 || strcmp(pszExpand,"$") == 0){
							strcat(p, pszToken);
							strcat(p," ");
							strcpy(pszCommandName, pszToken);							
						}
						else {	
							strcat(p, pszExpand);
							strcat(p," ");
							strcpy(pszCommandName, pszExpand);
						}	
					}
					else if (nRet == CCommandSet::ALIAS) {
						strcpy(pszCommandName, pszExpand);				
						strcat(p,pszToken);
						strcat(p," ");					      				
					}	
					else {	                              
						strcpy(pszCommandName, pszToken);
						strcat(p,pszToken);
						strcat(p," ");					      			
					}	                                
					delete []pszExpand;
					pszExpand = 0;
					delete []pszHints;
					pszHints = 0;
				}                       
				else {
					//Expand Parameter      
					char* pszExpand = new char[21];
					char* pszParameter = new char[nTokenLen+10];

					strcpy(pszParameter,pszToken);    
					if (stricmp(pszCommandName,"event") == 0 && 
						( stricmp(pszParameter,"1") == 0 ||
						 stricmp(pszParameter,"2") == 0 ||
						 stricmp(pszParameter,"3") == 0)) {
						
						strcpy(pszEvent, pszCommandName);
						strcat(pszEvent, " ");
						strcat(pszEvent, pszParameter);	 
					}	 				
						 
					if (strnicmp(pszEvent, "event", 5) == 0 ) {						 
						if (::ExpandEventPara(pszEvent, pszParameter, 
							pszExpand)) {
							strcat(p, pszExpand);
							strcat(p," ");					
						}
						else {
						    strcat(p,pszToken);
							strcat(p," ");
						}						
					}					
					else {
						if (::ExpandParameter(pszCommandName, pszParameter, pszExpand)) {				
							if ( stricmp(pszCommandName, "alias") != 0) {
								strcat(p, pszExpand);
								strcat(p," ");					
							}	 
                            else {
	                            strcat(p,pszToken);
	                            strcat(p," ");                            
                            }							
						}
						else {
						    strcat(p,pszToken);
							strcat(p," ");
						}	            
					}	
					delete []pszExpand;
					pszExpand = 0; 
					delete []pszParameter;
					pszParameter = 0;					
				}                   					
				isToken = FALSE;
				nTokenLen = 0;      			
			}	
		}	         
		else {
			if (FALSE == isToken) {
				isToken = TRUE;
			}
			pszToken[nTokenLen++] = pszTemp[i];	
		}
   	}
	
	strcpy(pszTemp,p);	   
    if (p) {
    	delete []p;
    	p = 0;
    }	
    if (pszToken) {
    	delete []pszToken;
    	pszToken = 0;
    }	
    if (pszCommandName) {
    	delete []pszCommandName;
    	pszCommandName = 0;
    }	
    if (pszEvent) {
    	delete []pszEvent;
        pszEvent = 0;
    }    
}   // End of ExpandCommand()
                 
                 
/////////////////////////////////////////////////////////////////////////////
//
//  Name:   void DisplayOutOfMemory(void).
//
//  Description: When out of memory display error message
//
//  Input:  none
//
//  Output: none
//
//  Return: none
//
/////////////////////////////////////////////////////////////////////////////
void DisplayOutOfMemory(void)
{
	CString strErr;
//    ErrGetErrorText(ER_OUT_OF_MEMORY, strErr);
    AfxMessageBox(strErr);

}	//End of DisplayOutOfMemory

/////////////////////////////////////////////////////////////////////////////
// Implementation codes of class: CSyntaxCheck.

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   CSyntaxCheck::CSyntaxCheck().
//
//  Description: The construction of the class: CSyntaxCheck.
//
//  Input:  None.
//
//  Output: None.
//
//  Return: None.
//
/////////////////////////////////////////////////////////////////////////////
CSyntaxCheck::CSyntaxCheck()
{
    // Receive from the Shell command line initialization.
    m_nLen = 0;
    for ( int i = 0; i < MAX_CMDLINE+1; i++ ) {
        m_pchLineBuf[i] = '\0';
    }    

    // Command ID initialization.
    m_nCommandID = 0;
	m_nToken = 0;
}   // End of CSyntaxCheck::CSyntaxCheck().


/////////////////////////////////////////////////////////////////////////////
//
//  Name:   CSyntaxCheck::~CSyntaxCheck().
//
//  Description: The destruction of the class: CSyntaxCheck.
//
//  Input:  None.
//
//  Output: None.
//
//  Return: None.
//
/////////////////////////////////////////////////////////////////////////////
CSyntaxCheck::~CSyntaxCheck()
{

}   // End of CSyntaxCheck::~CSyntaxCheck().


/////////////////////////////////////////////////////////////////////////////
//
//  Name:   CSyntaxCheck::CheckCommandSyntax().
//
//  Description: Main control routine of the class: CSyntaxCheck.
//
//  Input:  pchEditBuf - The line editor buffer.
//          nLen - The number of the characters in the line editor buffer.
//
//  Output: None.
//
//  Return: FALSE - syntax error; TRUE - syntax OK.
//
/////////////////////////////////////////////////////////////////////////////
BOOL CSyntaxCheck::CheckCommandSyntax(const char* pchEditBuf, const int nLen)
{
    // Assertion of the input parameters.
    ASSERT( nLen >= 0 && nLen <= MAX_CMDLINE );
    for ( int i = 0; i < nLen; i++ ) {
        ASSERT( pchEditBuf[i] >= MIN_KEY && pchEditBuf[i] <= MAX_KEY );
    }
    
    // Make a copy from the editor buffer.
    CopyCommandLine(pchEditBuf, nLen);
    
    // Parse the command's parameters.
    if ( !CommandParse() ) {
        AfxMessageBox("Command Parsing error !");
        ASSERT( FALSE );
        return (FALSE);
    }
    
    // Check command keyword.
    if ( !CheckCommandKeyword() ) {
        if (m_nErrorID == NO_COMMAND) {
			return (FALSE);
		}
		else {	        
	        DisplaySyntaxError();
	        return (FALSE);
	    }    
    }

    // Call the syntax core.
    SyntaxDispatch(m_nCommandID);
    
    // Return back.
    if ( 0 == m_nErrorID ) {
        DispatchCommand();
        return (TRUE);
    }                                  
    //Because the error message has been show by Address server
    else if (NOT_SHOW_ERROR == m_nErrorID) {
		return (FALSE);    	
    }
    else {
        DisplaySyntaxError();
        return (FALSE);
    }

}   // End of CSyntaxCheck::CheckCommandSyntax().

BOOL CSyntaxCheck::CheckCommandSyntax(const char* pchEditBuf, const int nLen, int& nPos)
{                           
    BOOL isTrue = FALSE;
    
    // Make a copy from the editor buffer.
    CopyCommandLine(pchEditBuf, nLen);

    // Parse the command's parameters.
    if ( !CommandParseSub() ) {
        ASSERT( FALSE );
        return (FALSE);
    }              
 
    // Check command keyword.
    if ( !CheckCommandKeyword(TRUE) ) {
    	return FALSE;
    }
     
    // Call the syntax core.
    isTrue = SyntaxDispatch(m_nCommandID, TRUE);

    nPos = m_nPos;
	
	return isTrue;
}    


/////////////////////////////////////////////////////////////////////////////
//
//  Name:   CSyntaxCheck::CopyCommandLine().
//
//  Description: Make a copy from the editor buffer.
//
//  Input:  pchEditBuf - The line editor buffer.
//          nLen - The number of the characters in the line editor buffer.
//
//  Output: m_pchLineBuf - A copy of the line editor buffer.
//          m_pchLineBuf[255] = 0x20 (The last SPACE).
//          m_nLen - (nLen + 1).
//
//  Return: None.
//
/////////////////////////////////////////////////////////////////////////////
void CSyntaxCheck::CopyCommandLine(const char* pchEditBuf, const int nLen)
{
    // Assertion of the input parameters.
    ASSERT( nLen >= 0 && nLen <= MAX_CMDLINE );
    for ( int i = 0; i < nLen; i++ ) {
        ASSERT( pchEditBuf[i] >= MIN_KEY && pchEditBuf[i] <= MAX_KEY );
        m_pchLineBuf[i] = pchEditBuf[i];
    }
    m_pchLineBuf[i] = TOKEN_KEY;
    m_nLen = nLen + 1;

}   // End of CSyntaxCheck::CopyCommandLine().
    

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   CSyntaxCheck::CommandParse().
//
//  Description: Parse the input commands.
//
//  Input:  m_pchLineBuf - To save the user's keyin and the last SPACE.
//          m_nLen - The number of the characters in the line buffer.
//
//  Output: m_nArgc - The number of the command parameters.
//          m_pszArgv[nArgc] - The contents of the command parameters.
//          m_pszArgv[0] is to save the command.
//
//  Return: FALSE - error; TRUE - normal.
//
/////////////////////////////////////////////////////////////////////////////
BOOL CSyntaxCheck::CommandParse(void)
{
    // Assertion of the input parameters.
    ASSERT( m_nLen > 0 && m_nLen <= MAX_CMDLINE+1 );
    for ( int i = 0; i < m_nLen; i++ ) {
        ASSERT( m_pchLineBuf[i] >= MIN_KEY && m_pchLineBuf[i] <= MAX_KEY );
    }
    
    //Add by Annie, 4/12/96
    //For macro variable
    char* p = m_pchLineBuf;
    while (*p) {
    	if ( isspace(*p) )
    		p++;
    	else
    		break;	
    }           
    if ( '$' == *p ) {
		m_nArgc = 1;
		NewMem(m_pszArgv[0], m_nLen);
		strcpy(m_pszArgv[0], p);		    
		return(TRUE);
    }                        
    
    // Get the token of the commands.
    char pszToken[MAX_CMDLINE+1];
    int nTokenLen = 0;
    BOOL isToken = FALSE;
    BOOL isToken1 = FALSE;  //is token '<'
    
    for ( i = 0; i < m_nLen; i++ ) {
        // Only for: "xxxx".
        if ( KEY_DQ == m_pchLineBuf[i] && TOKEN_KEY == m_pchLineBuf[i-1] ) {
			NewMem(m_pszArgv[m_nArgc], m_nLen-i+1);            
            if ( !m_pszArgv[m_nArgc] ) {
                DisplayOutOfMemory();
                ASSERT( FALSE );
                return (FALSE);
            }
            else {
                memcpy(m_pszArgv[m_nArgc], m_pchLineBuf+i, m_nLen-i);
                m_pszArgv[m_nArgc++][m_nLen-i] = 0;
                return (TRUE);
            }    
        }
        
        // for: <xx xx>
        if ( '<' == m_pchLineBuf[i] && !isToken1 ) {   
        	isToken1 = TRUE;
        	nTokenLen = 0;	 	
        	pszToken[nTokenLen++] = m_pchLineBuf[i]; 
        	continue;        
        }         
        if ( isToken1 ) {
        	pszToken[nTokenLen++] = m_pchLineBuf[i];
        	if ( ('>' == m_pchLineBuf[i] && ' ' == m_pchLineBuf[i+1])
        		|| i == m_nLen - 1) {
        		isToken1 = FALSE;
				pszToken[nTokenLen] = 0;        		                 
				NewMem(m_pszArgv[m_nArgc], nTokenLen*sizeof(char)+1);
				strcpy(m_pszArgv[m_nArgc++], pszToken);
                nTokenLen = 0;
        	}   
        	continue;
        }          
        
        // Normal case.
        if ( TOKEN_KEY == m_pchLineBuf[i] ) {
            if ( TRUE == isToken ) {
                pszToken[nTokenLen] = 0;
                NewMem(m_pszArgv[m_nArgc], nTokenLen*sizeof(char)+1);
                if ( !m_pszArgv[m_nArgc] ) {
					DisplayOutOfMemory();
                    ASSERT( FALSE );
                    return (FALSE);
                }
                else {
                    isToken = FALSE;
                    strcpy(m_pszArgv[m_nArgc++], pszToken);
                    nTokenLen = 0;
                }    
            }
        }
        else {
            if ( FALSE == isToken ) {
                isToken = TRUE;
            }
            pszToken[nTokenLen++] = m_pchLineBuf[i];
        }
    }
                                     
    // Return back.
    return (TRUE);

}   // End of CSyntaxCheck::CommandParse().              

BOOL CSyntaxCheck::CommandParseSub(void)
{
    // Assertion of the input parameters.
    ASSERT( m_nLen > 0 && m_nLen <= MAX_CMDLINE+1 );
    for ( int i = 0; i < m_nLen; i++ ) {
        ASSERT( m_pchLineBuf[i] >= MIN_KEY && m_pchLineBuf[i] <= MAX_KEY );
    }

    //For macro variable
    char* p = m_pchLineBuf;
    while (*p) {
    	if ( isspace(*p) )
    		p++;
    	else
    		break;	
    }           
    if ( '$' == *p ) {
		m_nArgc = 1;
		NewMem(m_pszArgv[0], m_nLen);

		strcpy(m_pszArgv[0], p);		    
		return(TRUE);
    }                        
    
    // Get the token of the commands.
    char pszToken[MAX_CMDLINE+1];
    int nTokenLen = 0;
    BOOL isToken = FALSE;
    BOOL isToken1 = FALSE;  //is token '<'
        
    for ( i = 0; i < m_nLen; i++ ) {
        // Only for: "xxxx".
        if ( KEY_DQ == m_pchLineBuf[i] && TOKEN_KEY == m_pchLineBuf[i-1] ) {
			NewMem(m_pszArgv[m_nArgc], m_nLen-i+1);            
            if ( !m_pszArgv[m_nArgc] ) {
                ASSERT( FALSE );
                return (FALSE);
            }
            else {
                memcpy(m_pszArgv[m_nArgc], m_pchLineBuf+i, m_nLen-i);
                //m_pszArgv[m_nArgc++][m_nLen-i] = 0;
                int nPos = m_nLen-i-1;
                while (m_pszArgv[m_nArgc][nPos] == ' ') {
					nPos--;                	
                }          
				m_pszArgv[m_nArgc++][nPos+1] = 0;                
				m_nToken = m_nArgc;
                return (TRUE);
            }    
        }

        // for: <xx xx>
        if ( '<' == m_pchLineBuf[i] && !isToken1 ) {   
        	isToken1 = TRUE;
        	nTokenLen = 0;	 	
        	pszToken[nTokenLen++] = m_pchLineBuf[i]; 
        	continue;        
        }         
        if ( isToken1 ) {
        	pszToken[nTokenLen++] = m_pchLineBuf[i];
        	if ( ('>' == m_pchLineBuf[i] && ' ' == m_pchLineBuf[i+1])
        		|| i == m_nLen - 1) {
        		isToken1 = FALSE;
				pszToken[nTokenLen] = 0;        		                 
				NewMem(m_pszArgv[m_nArgc], nTokenLen*sizeof(char)+1);
				strcpy(m_pszArgv[m_nArgc++], pszToken);
                nTokenLen = 0;
        	}                           
        	if ( i == m_nLen -1 ) {
        		m_nToken = m_nArgc;
        		return TRUE;
        	}
        	continue;
        }          

        // Normal case.
        if ( TOKEN_KEY == m_pchLineBuf[i] ) {
            if ( TRUE == isToken ) {
                pszToken[nTokenLen] = 0;
                NewMem(m_pszArgv[m_nArgc], nTokenLen*sizeof(char)+1);
                if ( !m_pszArgv[m_nArgc] ) {
                    ASSERT( FALSE );
                    return (FALSE);
                }
                else {
                    isToken = FALSE;
                    strcpy(m_pszArgv[m_nArgc++], pszToken);
                    nTokenLen = 0;
                }    
            }
        }
        else {
            if ( FALSE == isToken ) {
                isToken = TRUE;
            }
            pszToken[nTokenLen++] = m_pchLineBuf[i];
        }
    }
                         
	if ( m_pchLineBuf[m_nLen-2] != ' ') {
		m_nToken = (m_nArgc == 1) ? 1 : (m_nArgc - 1);		
	}                       
	else {
		m_nToken = m_nArgc;
	}	

    // Return back.
    return (TRUE);

}   // End of CSyntaxCheck::CommandParseSub(). 



/////////////////////////////////////////////////////////////////////////////
//
//  Name:   CSyntaxCheck::CheckCommandKeyword().
//
//  Description: Check the command keyword and fill command ID.
//
//  Input:  m_pszArgv[0] is to save the command keyword.
//
//  Output: m_nCommandID - The command ID.
//
//  Return: FALSE - no such command; TRUE - pass.
//
/////////////////////////////////////////////////////////////////////////////
BOOL CSyntaxCheck::CheckCommandKeyword(BOOL isSub)
{
    // Assertion of the input parameters.
    ASSERT( 0 == m_nCommandID );
    if ( 0 == m_nArgc ) {
	    m_nErrorID = NO_COMMAND;
        return (FALSE);
    }
    ASSERT( m_nArgc > 0 );
    ASSERT( m_pszArgv[0] );
    
    if ('@' == m_pszArgv[0][0]) {
		m_nCommandID = CMDID_RUNMACRO;
        return (TRUE);			
	}
	
    if ('$' == m_pszArgv[0][0]) {
		m_nCommandID = CMDID_VARDEFINE;
        return (TRUE);			
	}

	char* pszExpand = new char[21];
	char* pszHints = new char[400];
                                             
    int nRet = ::ExpandCommand(m_pszArgv[0], pszExpand, pszHints);

	if ( isSub ) {
		if ( nRet != CCommandSet::NO_COMMAND) {
			NewMem(m_pszArgv[0], strlen(pszExpand));
			strcpy(m_pszArgv[0] , pszExpand); 
		}                                    
	}	
	else {
		if ( nRet == CCommandSet::ALIAS) {
			NewMem(m_pszArgv[0], strlen(pszExpand));
			strcpy(m_pszArgv[0] , pszExpand); 
		}                                    
	}	
	delete []pszExpand;
	pszExpand = 0;
	delete []pszHints;
	pszHints = 0;
	
    // Detect the command ID.
    nRet = GetTotalCommandId(m_pszArgv[0]);
	           
	extern BOOL g_isTraceBoard;	                                
	//5/12/97
	if ( !g_isTraceBoard ) {
		if ( nRet == CMDID_EV1 || 
			 nRet == CMDID_EV2 ||
			 nRet == CMDID_EVENT ||
			 nRet == CMDID_LEVEL ||
			 nRet == CMDID_LIST ||
			 nRet == CMDID_LV1 ||
			 nRet == CMDID_LV2 ||
			 nRet == CMDID_QUALIFY ||
			 nRet == CMDID_TRACE ||
			 nRet == CMDID_TRIGGER ) {
			m_nErrorID = NO_TRACE_BOARD;
			m_nCommandID = nRet;
			return FALSE;
		}
	}           	
	                                
	if (nRet == CCommandSet::NO_COMMAND) {
		m_nErrorID = NO_SUCH_COMMAND;    
		return FALSE;
	}	
	else {
		m_nCommandID = nRet;
		return TRUE;
	}	   
    // No such command.
    return (FALSE);

}   // End of CSyntaxCheck::CheckCommandKeyword().


/////////////////////////////////////////////////////////////////////////////
//
//  Name:   CSyntaxCheck::DisplaySyntaxError().
//
//  Description: Display the syntax error message on the command line.
//
//  Input:  m_nErrorID - The ID of the syntax error.
//
//  Output: None.
//
//  Return: None.
//
/////////////////////////////////////////////////////////////////////////////
void CSyntaxCheck::DisplaySyntaxError(void) const
{
    // Assertion of the input parameters.
    ASSERT( m_nErrorID > NO_ERROR && m_nErrorID < MAX_ERROR );
    
    // Define the error message.

    char* pszErrorMsg[] = {
        "",
        "",
        "",                 
        "No such command.",
        "Syntax error.",            
        "The address is out of range.", 
        "The length is out of range.",
        "The length is invalid.",  
        "The address include invalid char.",
        "The address type is error.", 
        "Map address boundary error.",
        "The map attribute is error.",
        "The register name is invalid.",
        "The data is out of range.",
        "The data is invalid.",
        "The file name is invalid.",
        "The module name is invalid.",        
        "The variable name is invalid.",
        "The symbol name is invalid.",        
        "The count is invalid.",
        "The count is out of range.",
		"The port is invalid.",        
		"The address format is error.",
		"The symbol doesn't exist.",
		"The second address is less than first.",
		"The address text string is overflow.",
		"The address text string is empty.", 
		"The status is error.",        
		"No trace board.",
    };

    ShowLine(pszErrorMsg[m_nErrorID]);
    
    // Display the special error message.     
/*	
	char* pszErr = new char[260];
    ErrGetErrorText(ER_SYN_BASE + m_nErrorID, pszErr);
    ShowLine(pszErr);
	delete []pszErr;
	pszErr = 0;
*/
		
}   // End of CSyntaxCheck::DisplaySyntaxError().


/////////////////////////////////////////////////////////////////////////////
//
//  Name:   CSyntaxCheck::DispatchCommand().
//
//  Description: Dispatch the commands.
//
//  Input:  m_nCommandID - The ID of the commands.
//
//  Output: None.
//
//  Return: None.
//
/////////////////////////////////////////////////////////////////////////////
void CSyntaxCheck::DispatchCommand(void)
{
    // Assertion of the input parameters.
    ASSERT( m_nCommandID >= MIN_CMDID && m_nCommandID <= MAX_CMDID );
    ASSERT( m_nArgc > 0 );
    ASSERT( 0 == m_nErrorID );
    for ( int i = 0; i < m_nArgc; i++ ) {
        ASSERT( m_pszArgv[i] );
    }

//	return;
		
    // Dispatch the command routine.
    switch ( m_nCommandID ) {
    	case CMDID_RUNMACRO:
    		RunMacroCmd(m_nArgc, m_pszArgv);
    		break;
    	case CMDID_VARDEFINE:
    		CalcCmd(m_nArgc, m_pszArgv);
    		break;	
    	case CMDID_ALIAS:
    		AliasCmd(m_nArgc, m_pszArgv);
    		break;	
        case CMDID_ASSEMBLE: 			
            if ( GetCpuStatus2() == STATUS_HALT ) {
            	nAsmFlag = 1;
            	AssembleCmd(m_nArgc, m_pszArgv);		        	
            }
            else {
            	ShowLine("EP running.");
            }	
		    break;
        case CMDID_BREAKPOINT:
            BreakpointCmd(m_nArgc, m_pszArgv);
            break;
        case CMDID_BYTE:
            ByteCmd(m_nArgc, m_pszArgv);
            ::RepaintMemory();
            ::RepaintStack();
            ::RepaintVariable();
            break;
        case CMDID_CHECKSUM:
            ChecksumCmd(m_nArgc, m_pszArgv);
            break;
        case CMDID_CLEAR:
            ClearCmd(m_nArgc, m_pszArgv);
            break;
        case CMDID_COMPARE:
            CompareCmd(m_nArgc, m_pszArgv);
            break;
        case CMDID_CONTROL:
            ControlCmd(m_nArgc, m_pszArgv);
            break;
        case CMDID_COPY:
            CopyCmd(m_nArgc, m_pszArgv);
            ::RepaintMemory();            
            ::RepaintStack();
            ::RepaintVariable();
            break;
/*
        case CMDID_DIAGNOSIS:
            DiagnosticCmd(m_nArgc, m_pszArgv);
        	break;
*/
        case CMDID_DISASSEMBLE:
            DisassembleCmd(m_nArgc, m_pszArgv);
            break;                           
		case CMDID_EV1:
			Ev1Cmd(m_nArgc, m_pszArgv);
			break;
		case CMDID_EV2:
			Ev2Cmd(m_nArgc, m_pszArgv);
			break;
		case CMDID_EV3:
			Ev3Cmd(m_nArgc, m_pszArgv);
			break;
		case CMDID_EVENT:
			EventCmd(m_nArgc, m_pszArgv);
			break;			
        case CMDID_FILL:
            FillCmd(m_nArgc, m_pszArgv);
            ::RepaintMemory(); 
            ::RepaintStack();
            ::RepaintVariable();
            break;
        case CMDID_GO:
            ::MinAllMemWnd();
            GoCmd(m_nArgc, m_pszArgv);
            break;
        case CMDID_HALT:
            HaltCmd(m_nArgc, m_pszArgv);
            ::OnEmulation();
            ::RefreshTraceWnd();

            break;
        case CMDID_HELP:
            HelpCmd(m_nArgc, m_pszArgv);
            break;
        case CMDID_IDENTIFY:
            IdentifyCmd(m_nArgc, m_pszArgv);
            break;		
        case CMDID_INCLUDE:
            IncludeCmd(m_nArgc, m_pszArgv);
            break;
        case CMDID_INPORT:
            InportCmd(m_nArgc, m_pszArgv);
            break;                                  
        case CMDID_JUMP:
            JumpCmd(m_nArgc, m_pszArgv);            
            OnEmulation();
            break;                                  
		case CMDID_LEVEL:
			LevelCmd(m_nArgc, m_pszArgv);
			break;                      		
		case CMDID_LIST:
			ListCmd(m_nArgc, m_pszArgv);
			break;                      		
        case CMDID_LOG:
            LogCmd(m_nArgc, m_pszArgv);
            break;
        case CMDID_LONG:
            LongCmd(m_nArgc, m_pszArgv);
            ::RepaintMemory();
            ::RepaintStack();
            ::RepaintVariable();
            break;                      
		case CMDID_LV1:
			Lv1Cmd(m_nArgc, m_pszArgv);
			break;
		case CMDID_LV2:
			Lv2Cmd(m_nArgc, m_pszArgv);
			break;	                    
        case CMDID_MAP:
        
            MapCmd(m_nArgc, m_pszArgv);
            ::RepaintMemory();            
            ::RepaintStack();
            ::RepaintVariable();
            break;
        case CMDID_MACRO:
        	MacroCmd(m_nArgc, m_pszArgv);
        	break;
        case CMDID_MDEL:                 
        	DelMacroCmd(m_nArgc, m_pszArgv);
        	break;
        case CMDID_MEMORY:      
            MemoryCmd(m_nArgc, m_pszArgv);
            break;
        case CMDID_MEND:                    
        	MendCmd(m_nArgc, m_pszArgv);
        	break;
        case CMDID_MLIST:
        	ListMacroCmd(m_nArgc, m_pszArgv);
        	break;                      
        case CMDID_OUTPORT:
            OutportCmd(m_nArgc, m_pszArgv); 
            ::RepaintCPU();
            break;
		case CMDID_QUALIFY:
			QualifyCmd(m_nArgc, m_pszArgv);
			break;                         
        case CMDID_REGISTER:			
            RegisterCmd(m_nArgc, m_pszArgv);            
            OnEmulation();
            break;
        case CMDID_RESET:
            ResetCmd(m_nArgc, m_pszArgv);
//            ::OnEmulation();
			::SrcUpdateSourceWindow(::srcReset);
		    ::RepaintCPU();
		    ::RepaintMemory();
		    ::RepaintVariable();
		    ::RepaintStack();
		    ::RepaintPeri();
            break;                          
        case CMDID_RESTART:
        	RestartCmd(m_nArgc, m_pszArgv);
        	::OnEmulation();
        	break;                          
        case CMDID_SEARCH:
            SearchCmd(m_nArgc, m_pszArgv);
            break;                          
        case CMDID_STEP:
            StepCmd(m_nArgc, m_pszArgv);
            break;                          
        case CMDID_TEST:
            TestCmd(m_nArgc, m_pszArgv);
            //::OnEmulation();
            ::RepaintMemory();
            ::RepaintStack();
            ::RepaintVariable();
            break;                          
        case CMDID_TRACE:
        	TraceCmd(m_nArgc, m_pszArgv);
        	break;
        case CMDID_TRIGGER:
        	TriggerCmd(m_nArgc, m_pszArgv);
        	break;	                        
        case CMDID_UPLOAD:
            UploadCmd(m_nArgc, m_pszArgv);
            break;
        case CMDID_VERIFY:
            VerifyCmd(m_nArgc, m_pszArgv);
            break;
        case CMDID_WORD:
            WordCmd(m_nArgc, m_pszArgv);
            ::RepaintMemory();
            ::RepaintStack();
            ::RepaintVariable();
            break;
        case CMDID_CREATE:
            CreateCmd(m_nArgc, m_pszArgv);
            break;
        case CMDID_DELETE:
            DeleteCmd(m_nArgc, m_pszArgv);
            break;
        case CMDID_LOAD:
            LoadCmd(m_nArgc, m_pszArgv);            
            break;
        case CMDID_QUERY:
            QueryCmd(m_nArgc, m_pszArgv);
            break;
        case CMDID_SSAVE:
            SsaveCmd(m_nArgc, m_pszArgv);
            break;
        case CMDID_SRECALL:
            SrecallCmd(m_nArgc, m_pszArgv);
            break;
        case CMDID_SYMBOL:
            SymbolCmd(m_nArgc, m_pszArgv);
            break;
        case CMDID_WATCH:
            WatchCmd(m_nArgc, m_pszArgv);
            break;
        default:
            ASSERT( FALSE );
            break;
    }

}   // End of CSyntaxCheck::DispatchCommand().
	
//////////////////////////////// End of File ////////////////////////////////
