 
/***************************************************************************
**
**    $Header:   D:/EPSLDV1/SRC/LOG/SRCMDL.CPP   1.6   10 Jun 1996 10:22:34   ZJRD  $
**
**    $Log:   D:/EPSLDV1/SRC/LOG/SRCMDL.CPP  $
** 
**    Rev 1.6   10 Jun 1996 10:22:34   ZJRD
** EasyPack/SLD Version 1.20
** 
**    Rev 1.4   29 May 1996 09:33:22   ZJRD
** No change.
** 
**    Rev 1.3   16 May 1996 09:05:28   ZJRD
** EasyPack/SLD Version 1.94
** 
**    Rev 1.1   02 May 1996 10:28:36   ZJRD
** EasyPack/SLD Version 1.92
** 
**    Rev 1.31   18 Apr 1996 12:59:34   Shirley
** No change.
** 
**    Rev 1.30   12 Apr 1996 10:39:40   Shirley
** EasyPack/SLD Version 1.90
** 
**    Rev 1.28   15 Feb 1996 08:53:18   Shirley
** No change.
** 
**    Rev 1.27   12 Feb 1996 14:10:04   Shirley
** No change.
** 
**    Rev 1.26   06 Feb 1996 15:36:28   Shirley
** No change.
** 
**    Rev 1.25   06 Feb 1996 13:50:44   Shirley
** No change.
** 
**    Rev 1.24   01 Feb 1996 10:12:00   Shirley
** EasyPack/SLD Version 0.35b
** 
**    Rev 1.23   26 Jan 1996 09:15:04   Shirley
** No change.
** 
**    Rev 1.22   25 Jan 1996 13:14:58   Shirley
** No change.
** 
**    Rev 1.21   24 Jan 1996 10:38:34   Shirley
** No change.
** 
**    Rev 1.20   23 Jan 1996 11:23:44   Shirley
** EasypPack/SLD Version 0.34c
** 
**    Rev 1.19   18 Jan 1996 10:08:28   Shirley
** EasyPack/SLD Version 0.34b
** 
**    Rev 1.18   15 Jan 1996 16:13:22   Shirley
** EasyPack/SLD Version 0.34a
** 
**    Rev 1.17   04 Jan 1996 11:07:44   Shirley
** EasyPack/SLD Version 0.34
** 
**    Rev 1.16   30 Nov 1995 09:10:18   Shirley
** No change.
** 
**    Rev 1.15   28 Nov 1995 15:31:06   Shirley
** No change.
** 
**    Rev 1.14   21 Nov 1995 11:18:30   Shirley
** No change.
** 
**    Rev 1.13   13 Nov 1995 09:24:12   Shirley
** EasyPack/SLD Version 0.30
** 
**    Rev 1.12   12 Nov 1995 11:32:22   Shirley
** EasyPack/SLD Version 0.24
** 
**    Rev 1.11   08 Nov 1995 16:30:46   Shirley
** No change.
** 
**    Rev 1.10   08 Nov 1995 12:45:22   Shirley
** No change.
** 
**    Rev 1.9   02 Nov 1995 10:05:44   Shirley
** No change.
** 
**    Rev 1.8   27 Oct 1995 16:47:16   Shirley
** No change.
** 
**    Rev 1.7   27 Oct 1995 13:45:06   Shirley
** No change.
** 
**    Rev 1.6   25 Oct 1995 14:26:28   Shirley
** EasyPack/SLD Version 0.1f
** 
**    Rev 1.5   18 Oct 1995 14:49:22   Shirley
** No change.
** 
**    Rev 1.4   13 Oct 1995 13:23:30   Shirley
** EasyPack/SLD Version 0.1d
** 
**    Rev 1.3   29 Sep 1995 09:50:00   Shirley
** EasyPack/SLD Version 0.1c
** 
**    Rev 1.2   20 Sep 1995 10:55:18   Shirley
** No change.
** 
**    Rev 1.1   15 Sep 1995 09:47:38   Shirley
** EasyPack/SLDV0.1a 
** 
**    Rev 1.0   07 Sep 1995 09:55:02   Shirley
** Initial revision.
**
****************************************************************************/

/////////////////////////////////////////////////////////////////////////////
//
//  File name:  SRCMDL.CPP
//
//  Description:The implement file for the class: 
//                  SourceModule
//                  ModuleInfo
//
//  Author:     Roger Zhang
//
//  Date:       06/26/95
//
//  Modification:
//
//      1. 06/26/95, Initial version 0.1
//
//      2. 09/08/95  0.1a
//
//         2.1 Fixed bug No.16,17
//              Modify function: ModuleInfo::Init
//
//      3. 09/25/95  0.1c
//
//         3.1 Fixed bug No.113
//              Modify function: ModuleInfo::Init
//
//
//  Copyright (C) 1995 Microtek International. All rights reserved.
//
/////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "resource.h"

#include "zqueue.h"
#include "uicom.h"                  
#include "srccom.h"                    
#include "zlist.h"                    
#include "srclist.h"                   
#include "srcmdl.h"
#include "bwsmdl.h"
#include "symblsvr.h"   //gates
#include "ldr.h"

/////////////////////////////////////////////////////////////////////////////
// SourceModule
/////////////////////////////////////////////////////////////////////////////

//static CString EMBEDPATH = "EmbededPath";
                   
////////////////////// C(C++) Keywords //////////////////////////////////////
char * CKeywords[] = {
    "#define",
    "#defined",
    "#elif",
    "#else",  
    "#endif",
    "#ifdef",
    "#ifndef",
    "#include",
    "#pragma",
    "#warn",
    "auto",              
    "break",   
    "case", 
    "char",
//    "class",
    "const",
    "continue",
    "default",
//    "delete",
    "do",
    "double",
    "else",
    "enum",
    "extern",
    "far",
    "float",
    "for", 
//    "friend",
    "goto",
    "huge",
    "if",
//    "inline",
    "int",
    "long",    
    "near", 
//    "new", 
//    "private",
//    "protected",
//    "public",
    "register",
    "return",
    "short",
    "signed",
    "sizeof",
    "static",
    "struct",
    "switch", 
//    "this",
    "typedef",
    "union",
    "unsigned",
//    "virtual",
    "void",
    "volatile",
    "while"
};
                  
///////////////////// Source Module /////////////////////////////////////////                                           
static BOOL g_bFail=0;
/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
SourceModule::SourceModule(void)
{                           
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
SourceModule::~SourceModule(void)
{
}            

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   IsAsmFile
//
//  Description: To find out wether the file is an asm file by the file
//					extension(.asm)
//
//  Input:  The file name
//
//  Output: None
//
//  Return: TRUE -- is asm file.	FALSE -- not asm file
//
/////////////////////////////////////////////////////////////////////////////
BOOL SourceModule::IsAsmFile(const char * pszFileName) const
{
    int nLen = strlen(pszFileName);
    
    if(nLen > 4) {
        if(toupper(pszFileName[nLen - 1]) != 'M')   return FALSE;
        if(toupper(pszFileName[nLen - 2]) != 'S')   return FALSE;
        if(toupper(pszFileName[nLen - 3]) != 'A')   return FALSE;
        if(pszFileName[nLen - 4] != '.')            return FALSE;
    }                                               
    return TRUE;
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: Test if string p is a keyword by binary search
//
//  Input:  
//
//  Output: 
//
//  Return: Index found, -1 not found
//
/////////////////////////////////////////////////////////////////////////////
int SourceModule::SearchKeyword(const char * p) const
{                                                              
    ASSERT(p);
    
    int nRight = sizeof(CKeywords) / sizeof(char *) - 1;
    int nLeft = 0;
    int nMid;  
    int nResult;
    
    while(nRight >= nLeft) {
        nMid = (nRight + nLeft) / 2;
        if((nResult = strcmp(p, CKeywords[nMid])) == 0) return nMid;
        else if(nResult < 0)    nRight = nMid - 1;
        else                    nLeft  = nMid + 1;
    }                    
    return  -1;	// not found
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: Read One Line into Buffer: m_szBuf
//
//  Input:  
//
//  Output: 
//
//  Return: ERR_EOL, ERR_EOF, ERR_READFAIL, ERR_LINETOOLONG, ERR_OK
//
/////////////////////////////////////////////////////////////////////////////
int SourceModule::ReadLine(void)
{             
    int nRval;
    int i;
    for(i = 0; i < SourceList::MAX_LINELEN && !feof(m_Fp); i ++) {
        nRval = fgetc(m_Fp);
        if(feof(m_Fp)) {    // EOF
            m_szBuf[i] = '\0';  
            if(i > 0 && m_szBuf[i-1] == 0x1A)
            	m_szBuf[i-1] = '\0';
            return  ERR_EOF;            
        } else if(nRval == EOF) {    // ERROR
            m_szBuf[i] = '\0';  
            return  ERR_READFAIL;            
        } else if(nRval == '\n') {
            if(SrcOpt.m_nLineDelimit == SourceOptionClass::DELIMIT_CR) {
                if(i > 0 && m_szBuf[i - 1] == '\r') {
                    m_szBuf[i - 1] = '\0';  
                    return ERR_EOL;
                } else m_szBuf[i] = (char)nRval;
            } else {
                m_szBuf[i] = '\0';  
                return ERR_EOL;
            }
        } else  m_szBuf[i] = (char)nRval;
    } 
    if(feof(m_Fp)) {
        m_szBuf[i] = '\0';  
        if(i > 0 && m_szBuf[i-1] == 0x1A)
          	m_szBuf[i-1] = '\0';
        return  ERR_EOF;            
    } else {
        nRval = fgetc(m_Fp);
        if(nRval == '\n') {
            if(SrcOpt.m_nLineDelimit == SourceOptionClass::DELIMIT_CR) {
                if(i > 0 && m_szBuf[i - 1] == '\r') {
                    m_szBuf[i - 1] = '\0';  return ERR_EOL;
                } else {
                    ungetc(nRval, m_Fp);    return ERR_LINETOOLONG;
                }
            } else {
                m_szBuf[i] = '\0';  return ERR_EOL;
            }
        } else {
            ungetc(nRval, m_Fp);    return ERR_LINETOOLONG;
        }
    }                           
    return  ERR_OK;
}           

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: Expand Tabs, m_szBuf->m_szTab
//
//  Input:  
//
//  Output: 
//
//  Return: ERR_OK, ERR_LINETOOLONG, ERR_MEM
//
/////////////////////////////////////////////////////////////////////////////
int SourceModule::ExpandTab(void)
{                                                
    if(m_szBuf[0] == '\0') { // EOF Line
        m_szTab[0] = '\0';    
        return ERR_OK;  
    }
    
    int i = 0, j = 0, k;
    char ch;
    while((ch = m_szBuf[i++]) != '\0') {
        if(j > SourceList::MAX_LINELEN - 1)  return ERR_LINETOOLONG;
        if(ch == '\t') {
            k = (j + SrcOpt.m_nTabWidth) / SrcOpt.m_nTabWidth;
            k *= SrcOpt.m_nTabWidth;
            if(k > SourceList::MAX_LINELEN - 1)  return ERR_LINETOOLONG;    
            if(m_pLineInfo->m_Tab.AddElement(i-1, k-j) != ELIST_OK)
                return  ERR_MEM;            
            while(j < k)    m_szTab[j++] = ' ';
        } else  m_szTab[j++] = ch;
    }                       
    m_szTab[j] = '\0';      
    return ERR_OK;
}                     

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 1 True, 0 False                                     
//
/////////////////////////////////////////////////////////////////////////////
int SourceModule::IsDelimit(char ch) const
{                                   
    if(ch >= 'a' && ch <= 'z')  return  0;
    else if(ch >='A' && ch <='Z')   return  0;                
    else if(ch >='0' && ch <='9')   return  0;                
    else if(ch == '_' || ch == '#') return  0;
    else return 1;
} 
                     
/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: Scan C format comment : /* ... */
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
int SourceModule::ScanCComment(void)
{                        
    m_nFlag = FG_COMMENT;
    while(m_szTab[m_nCur]) {
        if(m_szTab[m_nCur+1] == '/' && m_szTab[m_nCur] == '*') {
            m_nFlag = FG_NORMAL;
            m_nCur += 2;
            break;                
        } else ++ m_nCur;
    }                    
        
    if(m_pLineInfo->m_Color.AddElement(m_nFirst, m_nCur - 1, 
        CSYN_COMMENT) != ELIST_OK) 
        return  ERR_MEM;
    else {
        m_nFirst = m_nCur;
        return  ERR_OK;
    }
} 

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: Scan C++ format comment : // ...
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
int SourceModule::ScanCPPComment(void)
{                        
    while(m_szTab[m_nCur+1])  ++ m_nCur;
    if(m_pLineInfo->m_Color.AddElement(m_nFirst, m_nCur, 
        CSYN_COMMENT) != ELIST_OK) 
        return  ERR_MEM;
    else {
        m_nFirst = ++ m_nCur;
        return  ERR_OK;
    }
}                     
                                
/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: Scan C String                                
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
int SourceModule::ScanString(void)
{    
    ++m_nCur; 
    while(m_szTab[m_nCur]) {
        if(m_szTab[m_nCur] == '\"' && (m_szTab[m_nCur - 1] != '\\' ||
            (m_szTab[m_nCur - 1] == '\\' && m_szTab[m_nCur - 2] == '\\'))) {   
            if(m_pLineInfo->m_Color.AddElement(m_nFirst, m_nCur, 
                CSYN_STRING) != ELIST_OK) 
            return  ERR_MEM;
            else {
                m_nFirst = ++ m_nCur;
                return  ERR_OK;
            }
        } else ++ m_nCur;
    }
    // add for error handle                                       
    if(m_pLineInfo->m_Color.AddElement(m_nFirst, m_nCur - 1, 
        CSYN_CODE) != ELIST_OK) 
        return ERR_MEM;
    else return ERR_OK;
    m_nFirst = m_nCur;
    
    return ERR_FAIL;
}
                
/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: Scan C char                
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
int SourceModule::ScanChar(void)
{    
    ++m_nCur; 
    while(m_szTab[m_nCur]) {
        if(m_szTab[m_nCur] == '\'' && (m_szTab[m_nCur - 1] != '\\' ||
            (m_szTab[m_nCur - 1] == '\\' && m_szTab[m_nCur - 2] == '\\'))) {   
            if(m_pLineInfo->m_Color.AddElement(m_nFirst, m_nCur, 
                CSYN_STRING) != ELIST_OK) 
            return  ERR_MEM;
            else {
                m_nFirst = ++ m_nCur;
                return  ERR_OK;
            }
        } else ++ m_nCur;
    }                  
    // add for error handle
    if(m_pLineInfo->m_Color.AddElement(m_nFirst, m_nCur - 1, 
        CSYN_CODE) != ELIST_OK) 
        return ERR_MEM;
    else return ERR_OK;
    m_nFirst = m_nCur;
    
    return ERR_FAIL;
}                           

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
int SourceModule::ScanToken(void)
{                     
    int i = 0;                             
    int nKey = CSYN_KEYWORD;
    while(m_szTab[m_nCur]) {
        if(nKey == CSYN_KEYWORD)   
            m_szToken[i++] = m_szTab[m_nCur];        
        if(i > MAX_KEYWORD - 1) nKey = CSYN_CODE;
        if(IsDelimit(m_szTab[m_nCur+1])) break;
        else ++ m_nCur;
    }             
    if(nKey == CSYN_KEYWORD) {
        m_szToken[i] = '\0';
        if(SearchKeyword(m_szToken) == -1)  nKey = CSYN_CODE;
    }
    if(m_pLineInfo->m_Color.AddElement(m_nFirst, m_nCur, nKey) != ELIST_OK)
        return  ERR_MEM;
    else {
        m_nFirst = ++ m_nCur;
        return ERR_OK;
    }
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
int SourceModule::ScanCode(void)
{
    int i = 0;                             
    int nKey = CSYN_KEYWORD;
    while(m_szTab[m_nCur]) {
        if(IsDelimit(m_szTab[m_nCur+1])) break;
        else ++ m_nCur;
    }             
    if(m_pLineInfo->m_Color.AddElement(m_nFirst, m_nCur, CSYN_CODE) 
        != ELIST_OK)
        return  ERR_MEM;
    else {
        m_nFirst = ++ m_nCur;
        return ERR_OK;
    }
}
            
/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
int SourceModule::ScanDelimit(void)
{                     
    while(m_szTab[m_nCur]) { 
        if(m_szTab[m_nCur] == '/' && 
            (m_szTab[m_nCur+1] == '*' || m_szTab[m_nCur+1] == '/'))  
            break;//return ERR_OK;
        else if(m_szTab[m_nCur] == '\"')    break;//return ERR_OK;
        else if(m_szTab[m_nCur] == '\'')    break;//return ERR_OK;
        else if(IsDelimit(m_szTab[m_nCur]))  ++ m_nCur;
        else break;
    }  
    if(m_nCur > m_nFirst)
        if(m_pLineInfo->m_Color.AddElement(m_nFirst, m_nCur - 1, 
            CSYN_CODE) != ELIST_OK)
            return  ERR_MEM;
    m_nFirst = m_nCur;
    return ERR_OK;
}
/*
BOOL SourceModule::IsAsmStart(void)
{
 	int nLeft, nRight;
 	int nLen = strlen(m_szTab);
 	
 	// get first token
 	nLeft = 0;
 	while(m_szTab[nLeft]) {
 	 	if(isspace(m_szTab[nLeft]))	++ nLeft;
 	}
	if(nLeft == nLen)	return FALSE;
	
	nRight = nLeft;
	while(m_szTab[nRight]) {
	 	if(isspace(m_szTab[nRight]))	break;
		++ nRight;	 	
	}             
	if(nLeft == nRight)	return FALSE;
	
	if(strncmp(m_szTab + nLeft, 
	 	
}
*/
/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return : ERR_OK, ERR_MEM, ERR_FAIL
//
/////////////////////////////////////////////////////////////////////////////
int SourceModule::ParseColor(void)
{
    if(m_szTab[0] == '\0')  return ERR_OK;  // EOF line
    
    if(IsAsmFile(m_strFileName)) {                               
        if(m_pLineInfo->m_Color.AddElement(0, strlen(m_szTab) - 1, 
            CSYN_CODE) != ELIST_OK)
            return  ERR_MEM;
        else return ERR_OK;
    }
    
    
    m_nFirst = m_nCur = 0;    
    int nRval;     
    while(m_szTab[m_nCur]) {
        if((m_szTab[m_nCur] == '/' && m_szTab[m_nCur+1] == '*') 
            || m_nFlag == FG_COMMENT) {
            if(m_nFlag != FG_COMMENT)    m_nCur += 2;
            if((nRval = ScanCComment()) != ERR_OK)    return nRval;
        } else if(m_szTab[m_nCur] == '/' && m_szTab[m_nCur+1] == '/' ) {
            if((nRval = ScanCPPComment()) != ERR_OK)    return nRval;
        } else if(m_szTab[m_nCur] == '\"') {
            if((nRval = ScanString()) != ERR_OK) return nRval;
        } else if(m_szTab[m_nCur] == '\'') {
            if((nRval = ScanChar()) != ERR_OK) return nRval;
        } else if(m_szTab[m_nCur] == '\\') {
            m_szTab[m_nCur] = '\0'; return ERR_OK;
        } else if((m_szTab[m_nCur] >= 'a' && m_szTab[m_nCur] <= 'z') ||
            m_szTab[m_nCur] == '#') {
            if((nRval = ScanToken()) != ERR_OK) return nRval;
        } else if((m_szTab[m_nCur] >= 'A' && m_szTab[m_nCur] <= 'Z') ||
            (m_szTab[m_nCur] >= '0' && m_szTab[m_nCur] <= '9') ||
            m_szTab[m_nCur] == '_') {
            if((nRval = ScanCode()) != ERR_OK) return nRval;
        } else /*if(IsDelimit(m_szTab[m_nCur]))*/ {
            if((nRval = ScanDelimit()) != ERR_OK) return nRval;
        }// else if((nRval = ScanToken()) != ERR_OK) return nRval;
    }
    return ERR_OK;
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return : ERR_OK, ERR_MEM, ERR_FAIL, ERR_READFAIL, ERR_LINETOOLONG,
//
/////////////////////////////////////////////////////////////////////////////
int SourceModule::ParseLine(void)
{
    int nRval;
    
    if((nRval = ReadLine()) == ERR_READFAIL || nRval == ERR_LINETOOLONG)
        return  nRval;
    else if(nRval == ERR_EOF)   m_nEof = 1;
    if((m_pLineInfo = new SourceElement) == 0)  return ERR_MEM;
    if((nRval = ExpandTab()) != ERR_OK) return nRval;
    m_pLineInfo->m_nLength = strlen(m_szTab);    
    if((nRval = ParseColor()) != ERR_OK) return nRval;
    if(m_pLineInfo->m_nLength) {       
        if((m_pLineInfo->m_szLine = new char [m_pLineInfo->m_nLength + 1])
            == 0)
            return ERR_MEM;
        memcpy(m_pLineInfo->m_szLine, m_szTab, m_pLineInfo->m_nLength + 1); 
    }
    if(m_Src.AddTail(m_pLineInfo) != ELIST_OK)  return ERR_MEM;
    if(m_nLine % SourceIndexList::INDEX_DELTA == 0) {
        if(m_Idx.AddElement(m_Src.m_pTail, m_nLine) != ELIST_OK)
            return ERR_MEM;
    }                      
    return ERR_OK;
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return : ERR_OK, ERR_MEM, ERR_FAIL, ERR_READFAIL, ERR_LINETOOLONG,
//           ERR_OPENFAIL, ERR_TOOMANYLINE  
//
/////////////////////////////////////////////////////////////////////////////

int SourceModule::Load(const char * pszFileName)
{                                      
    int nRval;

    m_strFileName = pszFileName;
                                      
    // Allocate Line Buffer for Load Module                                      
    m_szBuf = new char [SourceList::MAX_LINELEN + 1];
    m_szTab = new char [SourceList::MAX_LINELEN + 1];
    if(!m_szBuf||!m_szTab) {   
        if(m_szBuf) delete [] m_szBuf;
        //AfxMessageBox(IDS_ERR_MEM);
        return ERR_MEM;
    }

    // Open Module
    if((m_Fp = fopen(m_strFileName, "rb"))==0) 
        nRval = ERR_OPENFAIL; 
    else {        
        // Read Module
        m_nEof = 0;            
        m_nLine = 0;
        m_nFlag = FG_NORMAL;
        m_isAsmLine = FALSE;
        while(!m_nEof) {
            if((nRval = ParseLine()) != ERR_OK) break;
            if(++ m_nLine >= SourceList::MAX_LINES) { 
                nRval = ERR_TOOMANYLINE;
                break;
            }
        } 
        fclose(m_Fp);
    }
                      
    // Delete Line Buffer                      
    delete [] m_szBuf;
    delete [] m_szTab;
                         
    // Display Error Message                         
    // if memory error, we don't display since we may delete old modules
    if(nRval != ERR_OK) {
        Clean();
        switch(nRval) {
            case ERR_MEM:
                //AfxMessageBox(IDS_ERR_MEM);
                break;   
            case ERR_FAIL:
                AfxMessageBox(IDS_ERR_SRCFAIL);
                break;   
            case ERR_READFAIL:
                AfxMessageBox(IDS_ERR_READ);
                break;   
            case ERR_LINETOOLONG:
                AfxMessageBox(IDS_ERR_LINETOOLONG);
                break;   
            case ERR_OPENFAIL:
                AfxMessageBox(IDS_ERR_OPEN);
                break;   
            case ERR_TOOMANYLINE:
                AfxMessageBox(IDS_ERR_TOOMANYLINE);
                break;   
        }
    }    
    
    #ifdef _FDEBUG
        pSListDebug = fopen("test", "wt");
        if(pSListDebug) {
            m_Src.Dump();
            m_Idx.Dump();
            if(nRval != ERR_OK) 
                fprintf(pSListDebug, "ERROR!!!!\n");
            fclose(pSListDebug);
        }
    #endif
    
    return nRval;
}                  

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
int SourceModule::Reload(void)
{
    Clean();
    return Load(m_strFileName);
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: Return Source Line by Line Number
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
SourceElement * SourceModule::GetLine(int nIdx)
{
    SourceIndexElement * p = m_Idx.Search(nIdx);
    if(!p)  return  0;
    return m_Src.Search(p->m_pSrc, nIdx - p->m_nIdx);
}
                                    
/////////////////////////////////////////////////////////////////////////////
//
//  Name:   SearchString
//
//  Description: Search string
//
//  Input:  
//      nFlag = 0: No case, no Whole words
//              1: case sensitive
//              2: Whole words
//              3: case & whole words
//      str1: string to be searched
//      str2: string to search
//
//  Output: None
//
//  Return: The position found, -1 for not found
//
/////////////////////////////////////////////////////////////////////////////
int SourceModule::SearchString(const char * str1, const char * str2, 
	int nFlag) const
{   
    CString str = str1;
    CString strSub = str2;
    if(nFlag == 0 || nFlag == 2) {  // no case
        str.MakeUpper();
        strSub.MakeUpper();
    }
    int nRval = str.Find(strSub);
    if(nRval == -1) return  -1000;
    if(nFlag == 2 || nFlag == 3) {  // whole words
        if(nRval > 0) {
            if(!IsDelimit(str[nRval - 1]))    
            {
             g_bFail=1;
             return  -nRval;//-1;
            } 
        } 
        if(nRval + strSub.GetLength() < str.GetLength()) {
            if(!IsDelimit(str[nRval + strSub.GetLength()]))   
            {          
             g_bFail=1;   
             if(nRval==0)
                return -2000;
             return  -nRval;//-1;
            } 
        }       
    }
    return  nRval;
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
int SourceModule::SearchLine(const char * str1, const char * str2, int nCol, 
	int nFlag, BOOL isUp) const
{       
    if(str1==NULL)
       return -1;
        
    int nRval=0,nVal=-1,nRet=0;
    if(isUp){ 
      BOOL bFail=1;
	  for( ; ; ) {
	        nRet = SearchString(str1 + nRval, str2, nFlag);
	        if(nRet !=-1000) {
	            if(nRet==-2000){
	               bFail=1;
	               nRet=1; 
	            }   
	            else if(nRet<0){
	               bFail=1;
	               nRet=abs(nRet);
	            }
	            else bFail=0;
	            
	            nRval += nRet;
	               
	            if(nRval < nCol) {
   	                 if(bFail==0)
	                     nVal=nRval; 
	                nRval += strlen(str2);
	            } else break;           
	        } else break;
	    }
	    return nVal;
    
    }else{
    
    nRval = SearchString(str1 + nCol, str2, nFlag);    

    if(nRval==-1000){
       return -1;  
    
    }else if(nRval>=0){
       return int(nRval+nCol);
    
    }else{ 
       for(int nRet=abs(nRval), nLength=lstrlen(str1); 
               (nCol+nRet+1)<nLength;)
      {
        nRval = SearchString(str1 + nCol+nRet+1, str2, nFlag);    
        if(nRval>=0){
	       return int(nRet+nCol+nRval+1);
	    }else{
	     if(nRval==-1000)
	        return -1;
	     else if(nRval==-2000)
	        nRet+=1;
	     else   
	        nRet+=(1-nRval);
        }
      }//for 
       
    }
   }    
    return -1;   
    
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: Search string from specified line and column
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
BOOL SourceModule::SearchAfter(int nLine, int nCol, int nEndLine)  
{                                                             
    ASSERT(nLine >= 0 && nLine < int(m_Src.m_lCount));
    ASSERT(nEndLine >= 0 && nEndLine < int(m_Src.m_lCount));
    ASSERT(nEndLine >= nLine);
    
    int nFlag = 0;
    if(SrcSrchData.m_isCase)    nFlag |= 1;
    if(SrcSrchData.m_isMatch)   nFlag |= 2;     

    SourceElement * p;
    int nRval;  
    for(int i = nLine; i <= nEndLine; i++, nCol = 0) {  
        if((p = GetLine(i)) == 0)   continue;
        if(nCol >= int(p->m_nLength))   continue;
        nRval = SearchLine(p->m_szLine, SrcSrchData.m_strText, nCol, 
            nFlag, FALSE);
        if(nRval == -1) continue;
        SrcSrchData.m_nCurCol = nRval;
        SrcSrchData.m_nCurLine = i;
        return  TRUE;
    }
    return FALSE;       
}    

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: Search string before specified line and column
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
BOOL SourceModule::SearchBefore(int nLine, int nCol, int nEndLine)  
{
    ASSERT(nLine >= 0 && nLine < int(m_Src.m_lCount));
    ASSERT(nEndLine >= 0 && nEndLine < int(m_Src.m_lCount));
    ASSERT(nEndLine <= nLine);
    
    int nFlag = 0;
    if(SrcSrchData.m_isCase)    nFlag |= 1;
    if(SrcSrchData.m_isMatch)   nFlag |= 2;     

    SourceElement * p;  
    int nRval;                              
    nCol-=lstrlen(SrcSrchData.m_strText);
    for(int i = nLine; i >= nEndLine; i--, nCol = 32767) {
        if((p = GetLine(i)) == 0)   continue;
        nRval = SearchLine(p->m_szLine, SrcSrchData.m_strText, nCol, 
            nFlag, TRUE);                                                                                                                                                                                      
        if(nRval == -1) continue;
        SrcSrchData.m_nCurCol = nRval;
        SrcSrchData.m_nCurLine = i;
        return  TRUE;         
    }
    return FALSE;       
}                            


/////////////////////////////////////////////////////////////////////////////
// ModuleInfo
/////////////////////////////////////////////////////////////////////////////    
ModuleInfo MdlInfo;    

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
ModuleInfo::ModuleInfo(void)
: m_nModuleIdx(-1), m_pModuleValue(0), m_pModule(0), m_uModules(0)
{
    for(int i = 0; i < MAX_MODULE; i ++)    m_nModuleLoaded[i] = -1;
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void ModuleInfo::Clean(void)
{
    // Set current module to null
    m_nModuleIdx = -1;           
    
    // Clean Loaded Module Buffer
    for(int i = 0; i < MAX_MODULE; i ++) {
        m_Module[i].Clean();
        m_nModuleLoaded[i] = -1;
    }                            
    
    // Delete Module Value
    if(m_pModuleValue)  delete [] m_pModuleValue;
    m_pModuleValue = 0;
    
    // Delete Module Index Buffer
    if(m_pModule)   delete [] m_pModule;
    m_pModule = 0;               
    
    // Set Module Number to 0
    m_uModules = 0;
                             
    // Clean current asm & mixed buffer                             
    SrcCleanAsm();
    SrcCleanMix();
}                           

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
ModuleInfo::~ModuleInfo()
{
    Clean();
}                               

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
BOOL ModuleInfo::Init(void)
{
    Clean();
    
    // Clean Browsed Module List
    BrsMdl.Clean();
                                
    // Set step option
    SrcEmu.m_nStepOpt = STEP_INSTRUCTION;

    // Clear Breakpoints                                
    BptClrAllBptfromWnd();     
    
    extern void BPClrSym(void);
    BPClrSym();

    // Check is code been loaded
    /*if(SrcIsLoaded() == -1) {
        AfxMessageBox(IDS_PRM_NOSYMINFO);
        return FALSE;                                  
    }*/
                                
    // Add Load File to Loaded File List                        
    if(SrcGetLoadPath(LoadInfo.m_strFile) == -1)    return FALSE;
    AfxGetApp()->AddToRecentFileList(LoadInfo.m_strFile);
                     
    // Set Source Module Path                     
    SrcPathList.RemoveAll();
    CString strPath;         
    int n = LoadInfo.m_strFile.GetLength();
    int i;
    if(n > 0) {
        for(i = n - 1; i >= 0; i --) {        
            if(LoadInfo.m_strFile[i] == '\\') {
                strPath = LoadInfo.m_strFile.Left(i+1);
                break;
            }
        }
        if(strPath.GetLength() > 0 && strPath != ".\\")
            SrcPathList.AddTail(strPath);
    }
    SrcPathList.AddTail(".\\");   
                             
    // Get Load Information                             
    char szModule[100];       
    int nDummy;
    if(SrcGetLdrStats(szModule, &(LoadInfo.m_lSymbols),
        &((unsigned short &)(LoadInfo.m_lModules)), &(LoadInfo.m_lTypes), 
        &(LoadInfo.m_lFunctions), &(LoadInfo.m_lLines),
        &(LoadInfo.m_lBytes), &nDummy) == -1)
        return FALSE;                                
                     
    // Get Init PC                     
    if(SrcGetStartAddress((unsigned long &)(LoadInfo.m_lPC)) != 0)  
        return FALSE;    
                           
    // Get total module number                                
    if(SrcGetModuleNum(m_uModules) == -1 || m_uModules == 0) {
        //AfxMessageBox(IDS_ERR_MDLINFO);
        return FALSE;                                  
    }
                              
    // Allocate buffer to hold module index                              
    m_pModule = new unsigned long [m_uModules];  
    if(!m_pModule) {
        AfxMessageBox(IDS_ERR_MEM);
        return FALSE;
    }                    
    
    // Get module index into buffer
    if(SrcGetModuleIndex(m_uModules, m_pModule, m_uModules) == -1) {
    	/*if(LoadOpt.m_isWarnings)
	        AfxMessageBox(IDS_ERR_MDLINFO);*/
        return FALSE;                                  
    }
                                   
    // Allocate buffer for module value                                   
	ASSERT(m_uModules);
    m_pModuleValue = new unsigned [m_uModules];
    if(!m_pModuleValue) {
        AfxMessageBox(IDS_ERR_MEM);
        return FALSE;
    }           
                                       
    // Init module value                                       
    for(i = 0; i < int(m_uModules); i ++)      
        m_pModuleValue[i] = 0;            
        
    if(SrcEmu.GetPC())  SrcEmu.GetModule();
    
    return TRUE;   
}
                        
/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: Clean oldest module
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
BOOL ModuleInfo::CleanOldModule(void)
{             
    unsigned uVal = 0xFFFFU;                  
    for(int i = 0, j = -1, nModule; i < MAX_MODULE; i++) {     
        nModule = m_nModuleLoaded[i];
        if(nModule == -1)   continue;
        if(m_pModuleValue[nModule] <= uVal) {
            uVal = m_pModuleValue[nModule];
            j = i;
        }
    }              
    if(j > -1) {
        m_Module[j].Clean(); 
        m_nModuleLoaded[j] = -1; 
        return TRUE;
    } else return FALSE;
}       


/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: Get Current Module Index
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
unsigned long ModuleInfo::CurModule(void) const
{                   
    ASSERT(m_nModuleIdx != -1);
    
    return m_pModule[m_nModuleLoaded[m_nModuleIdx]]; 
}        
                           
/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: Get Module Path from Module Index
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
CString ModuleInfo::MakeModulePath(unsigned long dwModuleIdx) const
{
//	if(SrcOpenFile(dwModuleIdx))	return EMBEDPATH;

    char psz[41];                                           
    
    if(SrcGetModuleName(dwModuleIdx, psz) == -1)    return  "";
    return SrcGetModuleFullName(psz);
}                         
                       
/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: Load New Module                       
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
int ModuleInfo::LoadModuleIdx(unsigned long dwModuleIdx)
{                 
    // Get Module Path                     
    CString str = MakeModulePath(dwModuleIdx); 
    if(str.GetLength() == 0) {
    	if(LoadOpt.m_isWarnings)
        	AfxMessageBox(IDS_ERR_LOADMDL);
        return SRC_LOAD_ERROR;
    }
    const char * pName = (const char *)str;
    
                       
    // Convert module number -> module idx                       
    int nModuleIdx = -1;
    for(int i = 0; i < int(m_uModules); i ++) {
        if(m_pModule[i] == dwModuleIdx) nModuleIdx = i;    
    }                                                  
    if(nModuleIdx == -1) {
    	if(LoadOpt.m_isWarnings)
	        AfxMessageBox(IDS_ERR_LOADMDL);
        return SRC_LOAD_ERROR;
    }
    
    // check module active
    for(i = 0; i < MAX_MODULE; i ++) {
        if(m_nModuleLoaded[i] == nModuleIdx) {
            if(i == m_nModuleIdx)    // Module is the current module
                return SRC_LOAD_ALREADY;
            else {  // Module has been loaded before
                m_nModuleIdx = i;               
                ++ m_pModuleValue[nModuleIdx];
                SrcCleanAsm();
                SrcCleanMix();
                return SRC_LOAD_OK;
            }          
        }
    }
                        
    // check whether have empty cells                                          
    for(;;) {
        for(i = 0; i < MAX_MODULE; i ++) {
            if(m_nModuleLoaded[i] == -1) {  // empty cell
                int nRval = m_Module[i].Load(pName);
                if(nRval == SourceModule::ERR_OK) {
                    m_nModuleIdx = i;               
                    ++ m_pModuleValue[nModuleIdx];  
                    m_nModuleLoaded[i] = nModuleIdx;
                    SrcCleanAsm();
                    SrcCleanMix();
                    return SRC_LOAD_OK;
                } else if(nRval != SourceModule::ERR_MEM) {
                    // Load error not by memory error
                    // m_nModuleIdx = -1;	reserve old module loaded
                    
                    return SRC_LOAD_ERROR;
                } else break;
            }
        }
        if(CleanOldModule()==FALSE)    break;
    }     
 
    m_nModuleIdx = -1;
    SrcCleanAsm();
    SrcCleanMix();
    AfxMessageBox(IDS_ERR_MEM);
    return SRC_LOAD_ERROR;
}
                                                     
/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: Load Module Containing Current PC
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
int ModuleInfo::LoadPCModule(void)
{   
    // Get PC    
    if(!SrcEmu.GetPC())	return SRC_LOAD_ERROR;
    long lAddr = SrcEmu.m_lPCAddr;
    
    unsigned long dwModule;
    unsigned short uLine;
                                                              
    if(SrcAddr2Linenum(lAddr, uLine, dwModule) == -1)  
       return SRC_LOAD_ERROR;
    
    BrsMdl.AddTail(dwModule);

    if(IsModuleOn() && dwModule == CurModule()) 
       return SRC_LOAD_ALREADY;
    else 
       return LoadModuleIdx(dwModule);
}                  

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
int ModuleInfo::Reload(void)
{           
    int nRval;
    
    for(int i = 0; i < MAX_MODULE; i ++) {
        if(m_nModuleLoaded[i] != -1) {
            nRval = m_Module[i].Reload();
            if(nRval != SourceModule::ERR_OK)
                return SRC_LOAD_ERROR;        
        }
    }                                 
    return SRC_LOAD_OK;
}


/////////////////////////////////////////////////////////////////////////////
// Download File
/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
int SrcLoadFile(const char * str)
{
    extern class LoaderServer ldrObject;    // global load object .
    
    int nFlag = 0;
    if(LoadOpt.m_isCode)    nFlag |= LDR_CODE;
    if(LoadOpt.m_isCpp)     nFlag |= LDR_MANGLE;
    if(LoadOpt.m_isStatus)  nFlag |= LDR_STATUS;
    if(LoadOpt.m_isSymbol)  nFlag |= LDR_SYMBOL;
    if(LoadOpt.m_isWarnings)    nFlag |= LDR_WARNING;
    
    return ldrObject.LdrLoadProcess(LPSTR(str),LoadOpt.m_isDemand, nFlag);
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: Load Module by Current PC
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
int SrcLoadPCModule(void)
{      
	AfxGetApp()->DoWaitCursor(1);            
    int i = MdlInfo.LoadPCModule();
	AfxGetApp()->DoWaitCursor(-1);            
	return	i;
}      
                            
/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: Load Module by Module Index                            
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
int SrcLoadModule(unsigned long dwModule, BOOL isHist)
{
	AfxGetApp()->DoWaitCursor(1);            
    int nRval = MdlInfo.LoadModuleIdx(dwModule);
	AfxGetApp()->DoWaitCursor(-1);            
    if(isHist && nRval != SRC_LOAD_ERROR)
        BrsMdl.AddTail(dwModule);                        
    return nRval;
}
                              
    
/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: Convert Module Name to Module Index        
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
int SrcModuleName2Index(const char * pszModule, unsigned long & dwModule)
{                                                 
    char psz[80];  
        
    for(int i = 0; i < int(MdlInfo.m_uModules); i ++) {
        if(SrcGetModuleName(MdlInfo.m_pModule[i], psz) == 0)
            if(stricmp(pszModule, psz) == 0) {
                dwModule = MdlInfo.m_pModule[i];    
                return  0;
            }
    }         
    
    return -1;
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: Called after Load Command    
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
BOOL SrcInitModule(void)
{                           
    BOOL is = BOOL(MdlInfo.Init()&&bwsMdlInfo.Init()); 
    SrcEmu.m_nStepOpt = STEP_INSTRUCTION;
    SrcEmu.m_isStatement = BOOL(SrcIsStatement() == 0);
/*    SrcEmu.m_nStepOpt = STEP_INSTRUCTION;
    SrcEmu.m_isStatement = BOOL(SrcIsStatement() == 0);
    if(is)  SrcLoadPCModule();
    if(!isSourceOn && is) {
        SrcOpenWindow(TRUE, (CMDIFrameWnd *)(AfxGetApp()->m_pMainWnd));
    } else {
        SrcResetView();
        if(isSourceOn && pSourceWnd->IsIconic())
            pSourceWnd->ShowWindow(SW_RESTORE); 
        else if(isSourceOn)
            pSourceWnd->BringWindowToTop();
    }*/
    return is;
}      

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
void SrcPostLoad(void)
{
    SrcEmu.m_nStepOpt = STEP_INSTRUCTION;
    SrcEmu.m_isStatement = BOOL(SrcIsStatement() == 0);
    SrcLoadPCModule();
    if(!isSourceOn) {
        SrcOpenWindow(TRUE, (CMDIFrameWnd *)(AfxGetApp()->m_pMainWnd));
    } else {
        SrcResetView();
        if(isSourceOn && pSourceWnd->IsIconic())
            pSourceWnd->ShowWindow(SW_RESTORE); 
        else if(isSourceOn)
            pSourceWnd->BringWindowToTop();
    }
}             

///////////////////////////////// (EOF) /////////////////////////////////////

                   
