
/***************************************************************************
**
**    $Header:   D:/EP196/SRC/LOG/SYMSVR/SYMBLSVR.CPP   1.0   15 Aug 1997 14:04:12   ZJRD  $
**
**    $Log:   D:/EP196/SRC/LOG/SYMSVR/SYMBLSVR.CPP  $
** 
**    Rev 1.0   15 Aug 1997 14:04:12   ZJRD
** Initial revision.
** 
****************************************************************************/

/****************************************************************************
**
**  Name:  symblsrv.cpp
**
**  Description:
**      symbol server routines. symbol server extended 
**
**  Status:  CODE
**
**    Rev 1.0   1 Sept. 1995 8:30:00am   Gates Hua
** Initial revision.
**
**  Copyright (C) 1995 Microtek International.  All rights reserved.
**
*****************************************************************************/

                       /****************************
                        *                          *
                        *       INCLUDE FILES      *
                        *                          *
                        ****************************/
#include "stdafx.h"

#include "symblsvr.h"

//#include "utilext.h"

#include "sympool.h"
#include "symerrs.h"
#include "symget.h"
#include "symmgr.h"
#include "symline.h"         

#ifdef _LINK_WITH_LOADER_
#include "ldrexp.h"         
#endif

#include "stkinit.h"
#include "varinit.h"

#include "symsyn.h"
#include "symoptpr.h"
#include "symuser1.h"
#include "symimp.h"
#include "abitype.h"
#include "uicom2.h"
                       /****************************
                        *                          *
                        *     LOCAL DEFINITIONS    *
                        *                          *
                        ****************************/
char symsrvtbuf[256];

                       /****************************
                        *                          *
                        *    EXTERNAL VARIABLES    *
                        *                          *
                        ****************************/

extern void U16ToStr(U16 ui , char *tt);
extern void StrToU32(U32& ul , char *tt);
extern int SrcIsLoaded(void);
extern int SrcIsStatement(void);


extern MemPool st;
//extern class LoaderServer ldrObject;    // global load object .
extern class VarServer stkObject;
extern class VarServer varObject;
extern class SymUserVarTable userVariables;


extern int nSymModifyMemory;

                       /****************************
                        *                          *
                        *     LOCAL PROTOTYPES     *
                        *                          *
                        ****************************/
                        
RETCODE SymGetModuleNum(U16 FAR *numReturn) ;
void LowestBlockDesc(U32 addr, SYM_DESCRIPTOR& blockDesc);
int BlockAddrIsFunctionAddr(LPSTR str,ADDRESS_TYPE addr);
int CalcShellExp(int nArgc, char* pszArgv[]);

                       /****************************
                        *                          *
                        *      EXECUTABLE CODE     *
                        *                          *
                        ****************************/
extern void DisplayStack();
extern RETCODE
SymAddGetModuleName(SYM_DESCRIPTOR module, LPSTR modName);
extern RETCODE DisplayTypes(int flag);
extern RETCODE DisplaySortedSymbols();
//extern RETCODE AddressOf(LPSTR cmdString);
extern int BuildCAddr( SEGMENTTYPE type , U32 addr , char* str );


// This rountine for convert Bank Switch Address -> Bank No , Bank Offset Address  
// nBank :  1  --  no bank switch , 6 , 7, 8, 9 -- bank no.
void WINAPI SymConvertToBank(U32& uAddr ,int& nBank)
{
//	if ( g_nBankNum ) {
	if (LdrSrcSupportBankSwitch() ){
		nBank = (int)(( uAddr&0x00030000L )>>16); //+6;
		if ( uAddr != 0xFFFFFFFFL ) uAddr &= 0x0FFFFL;
	}
	else {
		if ( uAddr != 0xFFFFFFFFL ) uAddr &= 0x0FFFFL;
		nBank = 0;
	}
}

void WINAPI SymConvertToAddr(int nBank, U32& uAddr)
{
	if ( nBank < 0 ) return;
	if ( uAddr != 0xFFFFFFFFL ) {
		if (LdrSrcSupportBankSwitch() ) {                        
			if ( nBank == 0 ) uAddr &= 0x0FFFFL;
			else 
			uAddr = (uAddr&0x0FFFFL)|(((U32)nBank)<<16);
		}
		else uAddr &= 0x0FFFFL;
	}
}


/*************************
 ** SYMBOL ADD ROUTINES **
 *************************/
int SpaGetModule(CStringList* &pList)
{
    SYM_DESCRIPTOR *descArray;
    char temp[200];
    U16 numReturn , i;       
    CString result;
                   
    if ( GOOD != SymGetModuleNum( &i ) ) {
        return FAILURE;
    }
    descArray = new SYM_DESCRIPTOR[ i+1 ];
    if ( descArray == NULL ) return FAILURE; 
    if (GOOD != SymGetAllModules(descArray,i,&numReturn)){
        delete []descArray;
        return FAILURE;
    }                         
    if ( numReturn == 0 ) {
        delete []descArray;
        return FAILURE;       
    }
    for ( i = 0; i < numReturn; i++ ) {
        if (!UtilIsValidSymDescriptor(descArray[i])) {
            delete descArray;
            return FAILURE;
        }
        memset( temp , 0 , 200 );
        if ( GOOD != SymAddGetModuleName(descArray[i],temp) ){
            delete []descArray;
            return FAILURE;     
        }          
        result = temp;
        pList->AddTail( result );
    }
    delete []descArray;
    
    return GOOD;
}

int SpaGetFunction(const CString& strModule, CStringList* &pList)
{              
    SYM_DESCRIPTOR descModule , desc;
    char *temp;
    HANDLE *pHdl;
    COMMON_BLOCK_HEADER  *modPtr;         
    CString str , result;
    
    str = strModule;

    if ( GOOD != SymGetModuleDesc(str.GetBuffer(str.GetLength()),
    	"",&descModule) ) return FAILURE;
    if (!UtilIsValidSymDescriptor( descModule )) {
        return FAILURE;
    }

    modPtr=(COMMON_BLOCK_HEADER *)st.GetHugeDataPtr(descModule);
    desc = modPtr->child;
    while ( desc != NULL_SYMBOL ) {
        if (!UtilIsValidSymDescriptor( desc )) {
            return FAILURE;
        }     
	    temp = 0;
	    if ( GOOD != SymGetSymbolName( desc , &temp ) ) 
	        return FAILURE;         
	    result = temp;    
	    pList->AddTail( result );    
        if ( temp ) {
            pHdl = (HANDLE *)( temp - sizeof(HANDLE) );
            GlobalFree( *pHdl );
        }
        modPtr=(COMMON_BLOCK_HEADER *)st.GetHugeDataPtr(desc);
        desc = modPtr->symHeader.symSiblingOffset;
    }                     
    return GOOD;
}

/* These include any routines that add symbol information to the database */
void WINAPI WatchCmd(int nArgc, char* pszArgv[])
{
    CSymSyntax CExpress;     
    int nNum;
    
    nSymModifyMemory = 0;
    if ( nArgc != 2 ) return;
	CExpress.Init( pszArgv[1] );
	CExpress.GetErrorNum( nNum );
	if ( nNum ) {
        SymShowLine("Init Error!");
        
        CString strErr;
        if ( GOOD == ErrGetErrorText(ER_ID_EXP_INIT_ERR, strErr) ) {
            SymShowLine(strErr.GetBuffer( strErr.GetLength() ) );
        }
        
        return;
	}
	
	if ( GOOD != CExpress.CheckSyntax() ) {
        SymShowLine("C Expression syntax error!");
      
        CString strErr;
        if ( GOOD == ErrGetErrorText(ER_ID_EXP_SYNTAX_ERR, strErr) ) {
            SymShowLine(strErr.GetBuffer( strErr.GetLength() ) );
        }
        
        return;
	}
	if ( GOOD != CExpress.CalculateValue() ) {
        SymShowLine("C Expression calculate error!");
        
        CString strErr;
        if ( GOOD == ErrGetErrorText(ER_ID_EXP_CALC_ERR, strErr) ) {
            SymShowLine(strErr.GetBuffer( strErr.GetLength() ) );
        }
        
        return;
	}                                      
	CExpress.DisplayValue();
 
    if ( nSymModifyMemory ) {
        RepaintStack();
        RepaintVariable();
    }
    
    return ;
}

int WINAPI CheckExpressionStatus(char* pStr,BOOL& bResult)
{
    CSymSyntax CExpress;     
    int nNum;
    
	CExpress.Init( pStr );
	CExpress.GetErrorNum( nNum );
	if ( nNum ) {
		return FAILURE;
	}
	
	if ( GOOD != CExpress.CheckSyntax() ) {
		return FAILURE;
	}
	if ( GOOD != CExpress.CalculateValue() ) {
		return FAILURE;
	}          
	if ( GOOD != CExpress.GetStatus(bResult) ) {
		return FAILURE;
	}
    return GOOD;
}

void WINAPI CalcCmd(int nArgc, char* pszArgv[])
{
    nSymModifyMemory = 0;
    if ( 0 != CalcShellExp(nArgc,pszArgv) ) {
        SymShowLine("Syntax Error!!");
        CString strErr;
        if ( GOOD == ErrGetErrorText(ER_ID_EXP_SHELL_SYNTAX_ERR, strErr) ) {
            SymShowLine(strErr.GetBuffer( strErr.GetLength() ) );
        }
        return;
    }                           
    
    if ( nSymModifyMemory ) {
        RepaintStack();
        RepaintVariable();
    }
}
	
int CalcShellExp(int nArgc, char* pszArgv[])
{
    CSymSyntax CExpress;     
    int nNum;
    int nFlag;               
    char *p, *pTop;
    char c;
    char *pName;
	short value;
                    
    nFlag = 0;                
    if ( nArgc != 1 ) {
    	return FAILURE;
    }                           
    p = pszArgv[0];
    while( *p == ' ' ) {
    	p++;
    }
    if ( '$' != *p ) {
    	return FAILURE;
    }             
    pTop = p;              
    p++;	      

	c = *p;
	if ( (c!='_')&&(c!='?')&&((c>'z')||(c<'a'))&&((c>'Z')||(c<'A')) ) {
        return FAILURE;
    }       
    p++;
    nNum = 2;        
		 
    while( 1 ) {
        c = *p ;
		if ( ((c>'z')||(c<'a'))&&((c>'Z')||(c<'A')) ) {
			if ( (c!='_')&&(c!='?')&&((c<'0')||(c>'9')) ) {
				break;
	        }
	    }    
	    p++;
	    nNum++;
    }                                                 

	while( ' ' == *p ) {
		p++;
	}
                       
//	if( nNum>41 ) nNum = 41;
	if ( nNum > MAX_USE_DEFINE_SYMBOL_LENGTH+1 ) 
		nNum = MAX_USE_DEFINE_SYMBOL_LENGTH+1;
	pName = new char[ nNum+1 ];
	if ( 0 == pName ) return FAILURE;
	memcpy( pName , pTop , nNum );
	pName[nNum] = '\0';
	
	if ( '\0' == *p	) {                                       
		if ( GOOD == GetUserVarValue(pName,value) ) {
			char temp[512];
	        sprintf(temp,"     %s = %d (0x%04x)",pName,value,value); 
	        SymShowLine( temp );
	    }
	    else {
		    delete []pName;
	    	return FAILURE;
	    }
	    delete []pName;
	    return GOOD;
	}

	if ( '=' != *p ) {
	    delete []pName;
    	return FAILURE;
    }
    else {
    	p++;
		if ( '=' == *p ) {
		    delete []pName;
	    	return FAILURE;
	    }
	}
		
    if ( GOOD != GetUserVarValue(pName,value) ) {
		if ( GOOD == userVariables.SymUserVarCreate(pName) ) {
			nFlag = 1;
		}
	}
	else if ( GOOD == userVariables.IsPC(pName) ) {
        SymShowLine("$PC can not be set value!");
/*        
        CString strErr;
        if ( GOOD == ErrGetErrorText(ER_ID_EXP_SET_PC, strErr) ) {
            SymShowLine(strErr.GetBuffer( strErr.GetLength() ) );
        }
*/        
        return GOOD;
	}
	
	CExpress.Init( pszArgv[0] );
	CExpress.GetErrorNum( nNum );
	if ( nNum ) {     
		if ( nFlag ) userVariables.SymUserVarDelete(pName);
		delete []pName;
		return FAILURE;
	}
	
	if ( GOOD != CExpress.CheckSyntax() ) {
		if ( nFlag ) userVariables.SymUserVarDelete(pName);
		delete []pName;
		return FAILURE;
	}
	if ( GOOD != CExpress.CalculateValue() ) {
		if ( nFlag ) userVariables.SymUserVarDelete(pName);
		delete []pName;
		return FAILURE;
	}                                      
	if ( GOOD == GetUserVarValue(pName,value) ) {
		char temp[512];
        sprintf(temp,"     %s = %d (0x%04x)",pName,value,value); 
        SymShowLine( temp );
    }
    else {
		if ( nFlag ) userVariables.SymUserVarDelete(pName);
	    delete []pName;
    	return FAILURE;
    }
    delete []pName;
    return GOOD;
}

RETCODE WINAPI
SymAddSourceState(SOURCE_RANGE_TYPE *srcStatement,
                      ADDR_RANGE_TYPE   *codeAddrRange)
{
    LINENUM_TYPE linenum;
    U8 column;
    OFFSET_ADDR_TYPE addr;     
    if ( (codeAddrRange->startAddr == DEFAULT_START_ADDR) &&
         (codeAddrRange->endAddr == DEFAULT_END_ADDR) ) 
         return GOOD;
    if ( srcStatement->lineNumStart == srcStatement->lineNumEnd ) {
        linenum = srcStatement->lineNumStart;
        column = (U8) srcStatement->columnEnd;
    }                                        
    else if ( srcStatement->columnEnd == 1 ) {
//        linenum = srcStatement->lineNumEnd - 1;
//        column = (U8) 0;
        linenum = srcStatement->lineNumEnd;
        column = (U8) 1;
    } 
    else {      
        linenum = srcStatement->lineNumEnd;
        column = (U8) srcStatement->columnEnd;
    }
    addr = codeAddrRange->startAddr;
    return SymAddLinenum(linenum,column,addr);
}

void ModuleCmd(void)
{
    SYM_DESCRIPTOR *descArray;
    char temp[200];
    U16 numReturn , i;       
    int len;
                   
    if ( GOOD != SymGetModuleNum( &i ) ) {
        return ;
    }
    descArray = new SYM_DESCRIPTOR[ i+1 ];
    if ( descArray == NULL ) return ; 
    if (GOOD != SymGetAllModules(descArray,i,&numReturn)){
        delete descArray;
        return ;
    }                         
    if ( numReturn == 0 ) {
        delete descArray;
        return ;       
    }
    for ( i = 0; i < numReturn; i++ ) {
        if (!UtilIsValidSymDescriptor(descArray[i])) {
            delete descArray;
            return ;
        }
        COMMON_SYMBOL_HEADER  *modPtr;

        memset( temp , 0 , 200 );
        memset( temp , ' ' , 4 );
        modPtr=(COMMON_SYMBOL_HEADER *)st.GetHugeDataPtr(descArray[i]);
        if ( GOOD != SymAddGetModuleName(descArray[i],&temp[4]) ){
            delete descArray;
            return;     
        }   
        len = strlen(temp);
        sprintf(&temp[len],"    %lx %lx",
            modPtr->beginAddrInfo.startAddr ,
            modPtr->endAddrInfo.endAddr) ;
        SymShowLine( temp );
    }
    delete descArray;
    
    return ;
}

void SymbolLineCmd(void)
{
    SYM_DESCRIPTOR *descArray;
    char temp[200];
    U16 numReturn , i;       
    int len;
    int nFlag;
    LINENUM_DESCRIPTOR index ;
                   
    if ( GOOD == SrcIsStatement() ) nFlag = 1;
    else nFlag = 0;
    
    if ( GOOD != SymGetModuleNum( &i ) ) {
        return ;
    }
    descArray = new SYM_DESCRIPTOR[ i+1 ];
    if ( descArray == NULL ) return ; 
    if (GOOD != SymGetAllModules(descArray,i,&numReturn)){
        delete descArray;
        return ;
    }                         
    if ( numReturn == 0 ) {
        delete descArray;
        return ;       
    }
    for ( i = 0; i < numReturn; i++ ) {
        if (!UtilIsValidSymDescriptor(descArray[i])) {
            delete descArray;
            return ;
        }
        COMMON_SYMBOL_HEADER  *modPtr;

        memset( temp , 0 , 200 );
        memset( temp , ' ' , 4 );
        modPtr=(COMMON_SYMBOL_HEADER *)st.GetHugeDataPtr(descArray[i]);
        if ( GOOD != SymAddGetModuleName(descArray[i],&temp[4]) ){
            delete descArray;
            return;     
        }   
        len = strlen(temp);     
        U16 nBank;
        nBank = (U16)(modPtr->beginAddrInfo.startAddr >>16);
        sprintf(&temp[len],"    P%d:%x P%d:%x",nBank,
            (U16)( (modPtr->beginAddrInfo.startAddr)&0xFFFF) ,nBank,
            (U16)( (modPtr->endAddrInfo.endAddr)&0xFFFF) ) ;
        if ( GOOD == SymGetLinenumFirstIndex(descArray[i],&index) ) {
            SymShowLine( temp );                 
            if ( nFlag ) DisplayStatement( descArray[i] );
            else DisplayLinenum( descArray[i] );
        }
    }
    delete descArray;
    
    return ;
}

void LineCmd(int nArgc, char* pszArgv[])
{
    SYM_DESCRIPTOR *descArray;
    char temp[200];
    U16 numReturn , i;       
    int len;
    int nFlag;
    LINENUM_DESCRIPTOR index ;
                   
    if ( GOOD == SrcIsStatement() ) nFlag = 1;
    else nFlag = 0;
    
    if ( nArgc != 1 ) return;
    if ( !pszArgv[0][0] ) return;
    if ( GOOD != SymGetModuleNum( &i ) ) {
        return ;
    }
    descArray = new SYM_DESCRIPTOR[ i+1 ];
    if ( descArray == NULL ) return ; 
    if (GOOD != SymGetAllModules(descArray,i,&numReturn)){
        delete descArray;
        return ;
    }                         
    if ( numReturn == 0 ) {
        delete descArray;
        return ;       
    }
    for ( i = 0; i < numReturn; i++ ) {
        if (!UtilIsValidSymDescriptor(descArray[i])) {
            delete descArray;
            return ;
        }
        COMMON_SYMBOL_HEADER  *modPtr;

        memset( temp , 0 , 200 );
        memset( temp , ' ' , 4 );
        modPtr=(COMMON_SYMBOL_HEADER *)st.GetHugeDataPtr(descArray[i]);
        if ( GOOD != SymAddGetModuleName(descArray[i],&temp[4]) ){
            delete descArray;
            return;     
        }   
        len = strlen(temp);
        sprintf(&temp[len],"    %lx %lx",
            modPtr->beginAddrInfo.startAddr ,
            modPtr->endAddrInfo.endAddr) ;
        if ( GOOD == SymGetLinenumFirstIndex(descArray[i],&index) ) {
            SymShowLine( temp );                 
            if ( nFlag ) DisplayStatement( descArray[i] );
            else DisplayLinenum( descArray[i] );
        }
    }
    delete descArray;
    
    return ;
}

void VoidCmd(int nArgc, char* pszArgv[])
{             
    if ( nArgc == 3 ) {
        DisplayStack();     
        return;
    }
    if ( nArgc == 1 ) {
        char temp1[256] , temp[1000];
        U32 numSymbols;
        U16 numModules;
        U32 numTypes;
        U32 numFuncs;
        U32 linenums;                                   
        U32 bytes;                                        
        int ii;
                        
        if ( GOOD != SymSrcGetLdrStats(temp1,&numSymbols,&numModules,
                    &numTypes,&numFuncs,&linenums,&bytes,&ii ) ) {
            return ;
        }                   
        else {
            sprintf(temp ,"Last Module Name : %s, Symbols : %ld ,Modules : %d , Types : %ld , Functions : %ld ,Linenums : %ld, percentage : %d",
            temp1,numSymbols,numModules,numTypes,numFuncs,linenums,ii);
            SymShowLine( temp );
        }
        return;
    }                     
    if ( nArgc == 2 ) {
        varObject.AddVar( pszArgv[1] );
    }
    else if ( nArgc == 4 ) {
        varObject.UpdataAllNode();
        varObject.ShowVarToShell();
    }    
    else if ( nArgc == 6 ) {
//        struct VarNode *tt , *tt1;
        struct VarNode *tt ;
        
        tt = varObject.curVarNode ;
        while( tt ) {
            if ( (tt->flag&VAR_COMPLEX)&&(!(tt->flag&VAR_EXTEND)) )
                break;      
            if ( tt->son ) {
                tt = tt->son;
            }   
            else if ( tt->next ) {
                tt = tt->next;
            }    
            else if ( tt->father ) {
                tt = tt->father;
                while ( tt ) {
                    if ( tt->next ) {
                        tt = tt->next;
                        break;
                    }
                    tt = tt->father;
                }
            }
            else tt = 0;
        }
        varObject.VarExtendedNode( tt );
        varObject.ShowVarToShell();
    }       
    else {
        varObject.VarDeleteAll();
    }
/*
    if ( nArgc == 2 )
        AddressOf( pszArgv[1] );
    else 
        DisplaySortedSymbols();
*/      
}

void TypeCmd(int nArgc, char* pszArgv[])
{
    if ( nArgc != 1 ) return;
    if ( !pszArgv[0][0] ) return;
    DisplayTypes(1) ;
    DisplayTypes(0) ;
}

void CountCmd(int nArgc, char* pszArgv[])
{
    SYM_DESCRIPTOR *descArray;
    char temp[200];
    U16 numReturn , i;       
    int len;
                   
    if ( nArgc != 1 ) return;
    if ( !pszArgv[0][0] ) return;
    if ( GOOD != SymGetModuleNum( &i ) ) {
        return ;
    }
    descArray = new SYM_DESCRIPTOR[ i+1 ];
    if ( descArray == NULL ) return ; 
    if (GOOD != SymGetAllModules(descArray, i ,&numReturn)){
        delete descArray;
        return ;
    }                         
    if ( numReturn == 0 ) {
        delete descArray;
        return ;       
    }
    for ( i = 0; i < numReturn; i++ ) {
        if (!UtilIsValidSymDescriptor(descArray[i])) {
            delete descArray;
            return ;
        }
        COMMON_SYMBOL_HEADER  *modPtr;

        memset( temp , 0 , 200 );
        memset( temp , ' ' , 4 );
        modPtr=(COMMON_SYMBOL_HEADER *)st.GetHugeDataPtr(descArray[i]);
        if ( GOOD != SymAddGetModuleName(descArray[i],&temp[4]) ){
            delete descArray;
            return;     
        }   
        len = strlen(temp);
        sprintf(&temp[len],"    %lx %lx",
            modPtr->beginAddrInfo.startAddr ,
            modPtr->endAddrInfo.endAddr) ;
        SymShowLine( temp );                 
        DisplayStatement( descArray[i]);
    }
    delete descArray;
    
    return ;
}

int WINAPI SymSrcGetModuleNum(U16& num)
{
//    SYM_DESCRIPTOR *descArray;
    U16 numReturn ;       
                   
    if ( GOOD != SymGetModuleNum( &numReturn ) ) {
        return -1;
    }
    num = numReturn;
    
    return 0;
}

int WINAPI SymSrcGetModuleName(U32 moduleDesc , LPSTR str)
{
    if ( GOOD != SymAddGetModuleName(moduleDesc,str) ){
        return -1;      
    }   
    return 0;
}                   

int WINAPI SymSrcGetModuleRange(U32 moduleDesc , U32& start , U32& end, int& nBank)
{
    char moduleName[256];
    ADDR_RANGE_TYPE moduleAddrRange ;

    if ( GOOD != SymGetModule(moduleDesc,moduleName,&moduleAddrRange) ){
        return -1;      
    }   
    start = moduleAddrRange.startAddr ;
    end = moduleAddrRange.endAddr ; 
     
   // SymConvertToBank(end , nBank);
    SymConvertToBank(start , nBank);
    return 0;
}                   

int WINAPI SymSrcGetModuleIndex(U16 num , U32* buffer , U16& returnNum)
{
    U16 numReturn;       
                   
    returnNum = 0;
    if ( buffer == NULL ) return FAILURE; 
    if (GOOD != SymGetAllModules(buffer,num,&numReturn)){
        return FAILURE;
    }                         
    if ( numReturn == 0 ) {
        return FAILURE;       
    }                         
	returnNum = numReturn;
    return GOOD;
}

int SrcCheckModuleHasLineInfo(SYM_DESCRIPTOR desc)
{
    LINENUM_DESCRIPTOR index ;
	if ( !UtilIsValidSymDescriptor(desc) ) return GOOD;
    if ( GOOD == SymGetLinenumFirstIndex(desc,&index) ) {
		return GOOD;
    }               
    return FAILURE;
}

int WINAPI SymSrcAddr2Linenum(int& nBank ,U32 addr , U16& linenum , U32& moduleDesc)
{
    SYM_DESCRIPTOR modDesc;
    ADDR_RANGE_TYPE modRange;
    LINENUM_TYPE line;
    COLUMN_TYPE column;
    ADDR_RANGE_TYPE addrRange;
    LINENUM_DESCRIPTOR index;
    
    SymConvertToAddr( nBank, addr );
    if ( GOOD != SymMapAddr2LinenumModule(
        addr,    &modDesc, &modRange,  &line,
        &column,     &addrRange, &index) )  {
        return -1;
    }
    linenum =(U32) line;
    moduleDesc = modDesc;
    return 0;
}

int WINAPI SymSrcAddr2LinenumRange(int& nBank,U32 addr,U16& linenum,U32& startAddr,
									U32& endAddr)
{
    SYM_DESCRIPTOR modDesc;
    ADDR_RANGE_TYPE modRange;
    LINENUM_TYPE line;
    COLUMN_TYPE column;
    ADDR_RANGE_TYPE addrRange;
    LINENUM_DESCRIPTOR index;
    
    SymConvertToAddr( nBank, addr );
    if ( GOOD != SymMapAddr2LinenumModule(
        addr,    &modDesc, &modRange,  &line,
        &column,     &addrRange, &index) )  {
        return -1;
    }
    linenum = (U32)line;
    startAddr = addrRange.startAddr ;
    endAddr = addrRange.endAddr ;  
    if ( startAddr != 0xFFFFFFFFL ) startAddr &= 0x0FFFFL;
    if ( endAddr != 0xFFFFFFFFL ) endAddr &= 0x0FFFFL;
  
    return 0;
}

int WINAPI SymSrcAddr2Statement(int& nBank,U32 addr,U16& linenum,U16& startCol,
                    U16& endCol,U32& moduleDesc)
{
    SYM_DESCRIPTOR modDesc;
    ADDR_RANGE_TYPE modRange;
    LINENUM_TYPE line;
    COLUMN_RANGE_TYPE columnRange;
    ADDR_RANGE_TYPE addrRange;
    LINENUM_DESCRIPTOR index;
    SymConvertToAddr(nBank, addr);
    if ( GOOD != SymMapAddr2LinenumStmtModule(
        addr,    &modDesc, &modRange,  &line,
        &columnRange,  &addrRange, &index) )  {
        return -1;
    }
    linenum = (U32)line;  
    startCol = columnRange.columnStart;
    endCol = columnRange.columnEnd;
    moduleDesc = modDesc;
    return 0;
}

int WINAPI SymSrcAddr2StatementRange(int& nBank,U32 addr,U16& linenum,U16& startCol,
        U16& endCol,U32& startAddr,U32& endAddr)
{
    SYM_DESCRIPTOR modDesc;
    ADDR_RANGE_TYPE modRange;
    LINENUM_TYPE line;
    COLUMN_RANGE_TYPE columnRange;
    ADDR_RANGE_TYPE addrRange;
    LINENUM_DESCRIPTOR index;
    SymConvertToAddr(nBank, addr);
    if ( GOOD != SymMapAddr2LinenumStmtModule(
        addr,    &modDesc, &modRange,  &line,
        &columnRange,  &addrRange, &index) )  {
        return -1;
    }

    linenum =(U32) line;
    startAddr = addrRange.startAddr ;
    endAddr = addrRange.endAddr ;  

    if ( startAddr != 0xFFFFFFFFL ) startAddr &= 0x0FFFFL;
    if ( endAddr != 0xFFFFFFFFL ) endAddr &= 0x0FFFFL;

    startCol = columnRange.columnStart;
    endCol = columnRange.columnEnd;
    return 0;
}

BOOL WINAPI SymSrcIsLibFunction( U32 uAddr )
{
    U32 addr;
    U16 linenum;
    U32 startAddr , endAddr ;
    int nBank;
    addr = uAddr ;
    if ( GOOD == SymSrcAddr2LinenumRange(nBank,addr , linenum , startAddr , endAddr) ) {
        return FALSE ;
    }
    else return TRUE;
}


void WINAPI SymSrcGetStatementRange(U32 uAddr , U32& uStart , U32& uEnd )
{
    U32 addr;
    U16 linenum;
    U32 startAddr , endAddr ;
    U16 startCol , endCol;
    int nBank;
    addr = uAddr ;
    SymSrcAddr2StatementRange(nBank,addr,linenum,startCol,endCol,
                           		 startAddr, endAddr);
    if ( startAddr > endAddr ) {
        uStart = uEnd = uAddr;
    }
    else {                        
        uStart = startAddr ;
        uEnd = endAddr ;
    }
}

void WINAPI SymSrcGetLineRange(U32 uAddr , U32& uStart , U32& uEnd )
{
    U32 addr;
    U16 linenum;
    U32 startAddr , endAddr ;
    int nBank;
    addr = uAddr ;
    SymSrcAddr2LinenumRange(nBank,addr , linenum , startAddr , endAddr);
    if ( startAddr > endAddr ) {
        uStart = uEnd = uAddr;
    }
    else {                        
        uStart = startAddr ;
        uEnd = endAddr ;
    }
}

int WINAPI SymSrcAddr2LinenumStart(int& nBank,U32 addr , U16& linenum , U32& moduleDesc)
{
    SYM_DESCRIPTOR modDesc;
    ADDR_RANGE_TYPE modRange;
    LINENUM_TYPE line;
    COLUMN_TYPE column;
    ADDR_RANGE_TYPE addrRange;
    LINENUM_DESCRIPTOR index;

	SymConvertToAddr( nBank, addr );    
    if ( GOOD != SymMapAddr2LinenumModule(
        addr,    &modDesc, &modRange,  &line,
        &column,     &addrRange, &index) )  {
        return -1;
    }                   
    if ( addr != addrRange.startAddr ) return( -1 );
    linenum =(U32) line;
    moduleDesc = modDesc;
    return 0;
}
    
int WINAPI SymSrcLinenum2Addr(U32 moduleDesc , U16 linenum , U32& addr ,int& nBank)
{
    SYM_DESCRIPTOR modDesc;
    LINENUM_TYPE line;
    ADDR_RANGE_TYPE addrRange;
    LINENUM_TYPE    actualLinenum;
    COLUMN_TYPE     actualColumn;
    LINENUM_DESCRIPTOR  nextIndex;
    
    modDesc = moduleDesc;
    line = linenum; 
    if ( GOOD != SymGetLinenum(modDesc,  line,
        &addrRange, &actualLinenum, &actualColumn, &nextIndex) ) {
        return -1;
    }
    if ( linenum != actualLinenum ) {
        return -1;
    }
    addr = addrRange.startAddr;  
    SymConvertToBank(addr , nBank);
    return 0;
}    

int WINAPI SymSrcLinenum2Range(U32 moduleDesc,U16 linenum,
        U32& startAddr , U32& endAddr,int& nBank)
{
    SYM_DESCRIPTOR modDesc;
    LINENUM_TYPE line;
    ADDR_RANGE_TYPE addrRange , addrRange1;
    LINENUM_TYPE    actualLinenum;
    COLUMN_TYPE     actualColumn;
    LINENUM_DESCRIPTOR  nextIndex , index;
    
    modDesc = moduleDesc;
    line = linenum; 
    if ( GOOD != SymGetLinenum(modDesc,  line,
        &addrRange, &actualLinenum, &actualColumn, &nextIndex) ) {
        return -1;
    }
    if ( linenum != actualLinenum ) {
        return -1;
    }                                    
    index = nextIndex;
    while( GOOD == SymGetLinenumByIndex(moduleDesc,
                     index,
                     &addrRange1,
                     &nextIndex,
                     &line,
                     &actualColumn) ) {
        if ( line == linenum ) {
            if ( addrRange.startAddr > addrRange1.startAddr )
                addrRange.startAddr = addrRange1.startAddr;
            if ( addrRange.endAddr < addrRange1.endAddr )
                addrRange.endAddr = addrRange1.endAddr;
        }
        index = nextIndex;
    }                     
    
    startAddr = addrRange.startAddr;
    endAddr = addrRange.endAddr;
    
    //SymConvertToBank(endAddr , nBank);
    SymConvertToBank(startAddr , nBank);
    return 0;
}    

void DisplayLinenum( SYM_DESCRIPTOR moduleDesc ) 
{
    LINENUM_DESCRIPTOR nextIndex , index ;
    ADDR_RANGE_TYPE addrRange;
    LINENUM_TYPE linenum;
    COLUMN_TYPE column; 
    char temp[100];
    if ( GOOD != SymGetLinenumFirstIndex(moduleDesc,&index) ) {
        return ;
    }
    while( GOOD == SymGetLinenumByIndex(moduleDesc,
                     index,
                     &addrRange,
                     &nextIndex,
                     &linenum,
                     &column) ) {               
        U16 nBank;
        nBank =(U16)(addrRange.startAddr>>16 ); 
        //ASSERT(nBank == (U16)(linenum >>16));           
        sprintf(temp,"    line %u : start addr P%d:%x --- end addr P%d:%x" , (U16)linenum ,
                nBank,(U16)((addrRange.startAddr)&0xFFFF) , nBank,(U16)((addrRange.endAddr)&0xFFFF ));
        SymShowLine( temp );
        index = nextIndex;
    }                     
    return;
}   

void DisplayStatement( SYM_DESCRIPTOR moduleDesc ) 
{
    LINENUM_DESCRIPTOR nextIndex , index ;
    ADDR_RANGE_TYPE addrRange;
    LINENUM_TYPE linenum;
    COLUMN_RANGE_TYPE columnRange;
    char temp[100];
    if ( GOOD != SymGetLinenumFirstIndex(moduleDesc,&index) ) {
        return ;
    }
    while( GOOD == SymGetLinenumStmtByIndex(moduleDesc,
                     index,
                     &addrRange,
                     &linenum,
                     &columnRange,
                     &nextIndex ) ) {
		U16 nBank;
		nBank =(U16)(addrRange.startAddr>>16);                     
        sprintf(temp,"    line %u start col %u end col %u : start addr P%d:%x --- end addr P%d:%x" , (U16)linenum ,
                columnRange.columnStart , columnRange.columnEnd ,nBank,
                (U16)addrRange.startAddr , nBank,(U16)addrRange.endAddr);
        SymShowLine( temp );
        index = nextIndex;
    }                     
    return;
}   

RETCODE SymGetModuleNum(U16 FAR *numReturn) {

   HPU8 ptr;
   SYM_DESCRIPTOR headDesc, nextDesc;
   RETCODE err;

   // if the modulesList is empty we're done
   *numReturn = 0;
   
   // get the module head descriptor
   if ((err = SymGetModuleListHead(&headDesc)) != GOOD)
      return err;
   
   // make sure the symbol descriptor is ok
   if (!UtilIsValidSymDescriptor(headDesc))
      return ER_INVALID_SYM_DESCRIPTOR;

   ptr=st.GetHugeDataPtr(headDesc);
   // make sure it is module type
   if (SYM_MODULE != (((COMMON_SYMBOL_HEADER *)ptr)->typeIndex.symType & 0xF))
      return ER_SYMBOL_HAS_NO_LISTS;
   *numReturn = 1;
   // get all modules until reach NULL_DESCRIPTOR or 
   while (((nextDesc =
          ((COMMON_BLOCK_HEADER *)ptr)->symHeader.symSiblingOffset)
                       != NULL_SYMBOL) ) {
      ++(*numReturn);                    // count it 
      ptr = st.GetHugeDataPtr(nextDesc); // advance to next one
   }
       
   return GOOD;
}  // end of SymGetAllModules

int SpaGetRangeEnd(const CString& strSymbol, CString& strEnd)
{
    RETCODE           err;
    ADDR_RANGE_TYPE   addrRange;
    SYM_DESCRIPTOR    symDesc = 0L;
    LINENUM_TYPE      actualLinenum;
    COLUMN_RANGE_TYPE actualColumnRange;
    LPSTR             lpParam;
    char              *tt;
    char              temp[100];
    int i , j;

    tt = new char [ strSymbol.GetLength()+2 ];
    if ( tt == 0 ) return FAILURE;
    strcpy( tt , strSymbol );
    lpParam = tt;
    err = SymGetAddrFromName(lpParam,
                            SYM_UNKNOWN_ADDR,
                            &symDesc,
                            &addrRange,
                            &actualLinenum,
                            &actualColumnRange);
    delete tt;
    if ( err != GOOD ) {
	    tt = new char [ strSymbol.GetLength()+3 ];
	    if ( tt == 0 ) return FAILURE;
	    strcpy( tt , strSymbol );
        i = strSymbol.GetLength();
        j = i;
        while( j ) {
            if ( tt[j-1] == '#') {
                for(int ii=i;ii>=j;ii--) {
                    tt[ii+1] = tt[ii];
                }
                tt[j] = '_';
                lpParam = tt;
                err = SymGetAddrFromName(lpParam,
                                        SYM_UNKNOWN_ADDR,
                                        &symDesc,
                                        &addrRange,
                                        &actualLinenum,
                                        &actualColumnRange);
                delete tt;
                tt = 0;
                if ( err != GOOD ) return FAILURE;
                break;
            }
            j--;
        }
	    if ( tt ) {
	    	delete tt;
	    	tt = 0;
	    }
	    if ( j == 0 ) return FAILURE;
    }
    
	if ( GOOD != BuildCAddr(addrRange.segType,addrRange.endAddr,temp) ) {
		return FAILURE;
	}
	else {
		strEnd = temp;
	}		
    return GOOD ;
}

RETCODE SymServerSymToAddr(char *lpStr , U8* lpType , U32 * lpAddr)
{
    RETCODE           err;
    ADDR_RANGE_TYPE   addrRange;
    SYM_DESCRIPTOR    symDesc = 0L;
    LINENUM_TYPE      actualLinenum;
    COLUMN_RANGE_TYPE actualColumnRange;
    LPSTR             lpParam;
    char              *tt;
    int i , j;

    tt = new char [ strlen(lpStr)+1 ];
    if ( tt == 0 ) return FAILURE;
    strcpy( tt , lpStr );
    lpParam = tt;
    err = SymGetAddrFromName(lpParam,
                            SYM_UNKNOWN_ADDR,
                            &symDesc,
                            &addrRange,
                            &actualLinenum,
                            &actualColumnRange);
    delete tt;
    if ( err != GOOD ) {
        tt = new char[ strlen(lpStr)+2 ];
	    if ( tt == 0 ) return FAILURE;
        strcpy( tt, lpStr );
        i = strlen(lpStr);
        j = i;
        while( j ) {
            if ( tt[j-1] == '#') {
                for(int ii=i;ii>=j;ii--) {
                    tt[ii+1] = tt[ii];
                }
                tt[j] = '_';
                lpParam = tt;
                err = SymGetAddrFromName(lpParam,
                                        SYM_UNKNOWN_ADDR,
                                        &symDesc,
                                        &addrRange,
                                        &actualLinenum,
                                        &actualColumnRange);
                delete tt;
                tt = 0;
                if ( err != GOOD ) return( err );
                break;
            }
            j--;
        }              
        if ( tt ) {
        	delete tt;
        	tt = 0;
        }
        if ( j == 0 ) return (err);
    }

    switch( addrRange.segType ) {
    case SEG_CODE :
        *lpType = MEM_P0;//2;     
        
        int nBank;
        SymConvertToBank( addrRange.startAddr , nBank );
        *lpType += nBank;
		*lpAddr = (addrRange.startAddr&0x0FFFFL);
        break;
    case SEG_DATA :
        *lpType = MEM_I;//4;
        break;
    case SEG_XDATA :
//        int nBank; 
        *lpType = MEM_X0;
        SymConvertToBank( addrRange.startAddr , nBank );
        *lpType += nBank;
		*lpAddr = (addrRange.startAddr&0x0FFFFL);
//        *lpType = MEM_X0;//3;
        break;
    case SEG_BIT :
        *lpType = MEM_I;//6;
        break;
    case SEG_REGISTER :
        *lpType =MEM_I;// 5;
        break;
    case SEG_SFR :
        *lpType =MEM_I;// 7;
        break;
    default :
        *lpType = MEM_UNDEFINED;//0;
        break;
    }
    *lpAddr = addrRange.startAddr;
    return GOOD ;
}

RETCODE SymServerAddrToSym(U8 type , U32 addr , char *lpStr)
{
   RETCODE    err;
   BOOLEAN    noSymbolsLoaded;
   ADDRESS_TYPE   inputAddr;
   MEM_ADDR_CLASS memoryClass;
   SYM_TYPE_TYPE  symbolType;
   U32            offset;
   SYM_DESCRIPTOR outputSymbol;
   SYM_DESCRIPTOR funcDescriptor;
   SYM_DESCRIPTOR moduleDescriptor;
   HANDLE *pHdl;
   
   if (GOOD != (err = SymCheckForNoSymbols(&noSymbolsLoaded)))
      return FAILURE;
   if (noSymbolsLoaded) {
      return FAILURE;  // reports "no symbols are loaded"
   }
                      
   inputAddr.addr = addr;   
   inputAddr.segType = (SEGMENTTYPE) SEG_CODE;
   switch ( type ) {
   case MEM_X0 :         
   case MEM_X1 : 
   case MEM_X2 :
   case MEM_X3 :
        inputAddr.segType = (SEGMENTTYPE) SEG_XDATA;
        break;
   case MEM_I :
        inputAddr.segType = (SEGMENTTYPE) SEG_DATA;
        break;
 
   case MEM_P0 :
   case MEM_P1 :
   case MEM_P2 :
   case MEM_P3 :
   		SymConvertToAddr(type-MEM_P0,inputAddr.addr);
   		inputAddr.segType = (SEGMENTTYPE) SEG_CODE;
   		break;
   default :
        break;
   }
            
   if ( GOOD != SymMapAddr2Symbol(inputAddr,
                  &memoryClass,
                  &symbolType,
                  &offset,
                  &outputSymbol,
                  &funcDescriptor,
                  &moduleDescriptor) ) {
        return FAILURE ;
    }    
   
    if ( offset != 0 ) return FAILURE ;

    char *temp1;
    
    temp1 = 0;
    if ( GOOD != SymGetSymbolName( outputSymbol ,
                                   &temp1 ) ) 
        return FAILURE;         
    
    if( *temp1 == '\0' ) {
        if ( temp1 ) {
            pHdl = (HANDLE *)( temp1 - sizeof(HANDLE) );
            GlobalFree( *pHdl );
        }
        temp1 = 0;
        if ( GOOD != SymGetSymbolName( funcDescriptor ,
                                       &temp1 ) ) 
            return FAILURE;         
        if ( GOOD != BlockAddrIsFunctionAddr(temp1, inputAddr) )
            return FAILURE;
    }
    
    if( *temp1 == '\0' ) {
        if ( temp1 ) {
            pHdl = (HANDLE *)( temp1 - sizeof(HANDLE) );
            GlobalFree( *pHdl );
        }
        temp1 = 0;
        return FAILURE;
    }
/*
    if ( *temp1 == '?' ) {
        if ( temp1 ) {
            pHdl = (HANDLE *)( temp1 - sizeof(HANDLE) );
            GlobalFree( *pHdl );
        }
        return FAILURE;
    }    
*/
    sprintf(lpStr,"#%s",temp1);

    if ( temp1 ) {
        pHdl = (HANDLE *)( temp1 - sizeof(HANDLE) );
        GlobalFree( *pHdl );
    }

    return GOOD;
}

int BlockAddrIsFunctionAddr(LPSTR str,ADDRESS_TYPE addr)
{
char *tt;                              
U8 tType;
U32 tAddr;

    tt = new char[ strlen(str)+3 ];
    if ( tt == 0 ) return FAILURE;
    sprintf(tt , "#%s" , str ); 
    if ( GOOD != SymServerSymToAddr(tt,&tType ,&tAddr) ) {
        if (tt) delete tt;
        tt = 0;
        return FAILURE;   
    }
    
    if( tt ) delete tt;
    tt = 0; 
        
    if ( tAddr != addr.addr ) return FAILURE;
    if ( (tType != 1)||(addr.segType != SEG_CODE) ) return FAILURE;
    return GOOD;    

}

int WINAPI SymSrcGetLdrStats(LPSTR moduleName,U32 *numSymbols,U16 *numModules,
    U32 *numTypes , U32 *numFuncs , U32 *linenums , U32 *bytes , int *percent)
{
#ifdef _LINK_WITH_LOADER_
    *bytes = LdrGetLoadBytes(); //uLoadBytes;
#else 
    *bytes = 0;
#endif    
    *numFuncs = 0;
    *linenums = 0;
    *numSymbols = 0;
    *numModules = 0;
    *numTypes = 0;
    *moduleName = '\0';
    if ( SrcIsLoaded() == GOOD ) {
        *percent = 100;
    }
    else {       
        long l1 , l2;

#ifdef _LINK_WITH_LOADER_        
        LdrGetFileLength( l1 );
        LdrGetFileCurPos( l2 );   
#else
		l1 = l2 = 0;
#endif
        
        if ( l2 > l1 ) *percent = 100;
        else if ( l2 > 0x800000 ) {
            *percent = (int) ( ( (l2>>8)*100 ) / (l1 >> 8 ) );
        }
        else if ( l1 == 0 ) *percent = 0;
        else *percent = (int) ( (l2*100)/l1 ); 
    }       

    if ( GOOD != SymGetLdrStats(moduleName,numSymbols,numModules,
                   numTypes) ) {
        *numSymbols = 0;           
        *numModules = 0;
        *numTypes = 0;
        return GOOD;  
    }                   
    if ( (*numModules==0)&&(*numSymbols==1)&&(*numTypes==0xff) ) {
        *numSymbols = 0;           
        *numModules = 0;
        *numTypes = 0;
        return GOOD;  
    }                   
                                                              
    SYM_DESCRIPTOR *descArray;
    U16 numReturn , i;       
                   
    if ( GOOD != SymGetModuleNum( &i ) ) {
        return GOOD;
    }
    descArray = new SYM_DESCRIPTOR[ i+1 ];
    if ( descArray == NULL ) return FAILURE; 
    if (GOOD != SymGetAllModules(descArray,i,&numReturn)){
        delete descArray;
        return GOOD;
    }                         
    if ( numReturn == 0 ) {
        delete descArray;
        return GOOD;
    }
    for ( i = 0; i < numReturn; i++ ) {
        if (!UtilIsValidSymDescriptor(descArray[i])) {
            delete descArray;
            return GOOD;
        }
        COMMON_SYMBOL_HEADER  *modPtr;
        SYM_TYPE_MODULE *modulePtr;

        modulePtr = (SYM_TYPE_MODULE *)st.GetHugeDataPtr(descArray[i]);

        if (modulePtr->linenumOffsetEnd>modulePtr->linenumOffsetStart)
            *linenums=*linenums+(U16)(((modulePtr->linenumOffsetEnd-
               modulePtr->linenumOffsetStart)/LINENUM_STRUCT_SIZE)+ 1);
        if ( modulePtr->symHeader.child != NULL_SYMBOL ) {
            if (!UtilIsValidSymDescriptor( modulePtr->symHeader.child )) {
                delete descArray;
                return GOOD;
            }
            modPtr=(COMMON_SYMBOL_HEADER *)st.GetHugeDataPtr(
                modulePtr->symHeader.child);
            if ( ((modPtr->typeIndex.symType)&0x0F) == SYM_FUNCTION )
                *numFuncs = *numFuncs+1;
            while ( modPtr->symSiblingOffset != NULL_SYMBOL ) {
                if (!UtilIsValidSymDescriptor( modPtr->symSiblingOffset )) {
                    delete descArray;
                    return GOOD;
                }
                modPtr=(COMMON_SYMBOL_HEADER *)st.GetHugeDataPtr(
                    modPtr->symSiblingOffset);
                if ( ((modPtr->typeIndex.symType)&0x0F) == SYM_FUNCTION )
                    (*numFuncs)++ ;
            }
        }
    }
    delete descArray;
    return GOOD;
}

int WINAPI SymSrcGetFirstFuncIndex(SYM_DESCRIPTOR moduleDesc,
    SYM_DESCRIPTOR& funcDesc)
{
    COMMON_SYMBOL_HEADER  *modPtr;
    SYM_TYPE_MODULE *modulePtr;

    if (!UtilIsValidSymDescriptor(moduleDesc)) {
        return FAILURE;
    }

    modulePtr = (SYM_TYPE_MODULE *)st.GetHugeDataPtr(moduleDesc);
    if ( ((modulePtr->symHeader.symHeader.typeIndex.symType)&0x0F) !=
        SYM_MODULE )
        return FAILURE;

    if ( modulePtr->symHeader.child != NULL_SYMBOL ) {
        if (!UtilIsValidSymDescriptor( modulePtr->symHeader.child )) {
            return FAILURE;
        }
        modPtr=(COMMON_SYMBOL_HEADER *)st.GetHugeDataPtr(
                modulePtr->symHeader.child);
        if ( ((modPtr->typeIndex.symType)&0x0F) == SYM_FUNCTION ) {
            funcDesc = modulePtr->symHeader.child;
        }
        else {
            while ( modPtr->symSiblingOffset != NULL_SYMBOL ) {
                if (!UtilIsValidSymDescriptor( modPtr->symSiblingOffset )) {
                    return FAILURE;
                }
                funcDesc = modPtr->symSiblingOffset;
                modPtr=(COMMON_SYMBOL_HEADER *)st.GetHugeDataPtr(
                    modPtr->symSiblingOffset);
                if ( ((modPtr->typeIndex.symType)&0x0F) == SYM_FUNCTION ) 
                    break;
            }
        }
        return GOOD;
    }
    return FAILURE;
}

int WINAPI SymSrcGetNextFunc(SYM_DESCRIPTOR funcDesc,LPSTR funcName,
    SYM_DESCRIPTOR& nextDesc)
{
    COMMON_SYMBOL_HEADER  *modPtr;
    HANDLE *pHdl;
    char *temp1;
    
    temp1 = 0;
    if ( funcDesc == NULL_SYMBOL )
        return FAILURE;
    if (!UtilIsValidSymDescriptor(funcDesc)) {
        return FAILURE;
    }

    modPtr=(COMMON_SYMBOL_HEADER *)st.GetHugeDataPtr(funcDesc);
    if ( ((modPtr->typeIndex.symType)&0x0F) == SYM_FUNCTION ) {
        if ( GOOD != SymGetSymbolName( funcDesc , &temp1 ) ) 
            return FAILURE;                       
        strcpy( funcName , temp1 );         
        if ( temp1 ) {
            pHdl = (HANDLE *)( temp1 - sizeof(HANDLE) );
            GlobalFree( *pHdl );
        }
        nextDesc = NULL_SYMBOL;
        while ( modPtr->symSiblingOffset != NULL_SYMBOL ) {
            if (!UtilIsValidSymDescriptor( modPtr->symSiblingOffset )) {
                break;
            }
            nextDesc = modPtr->symSiblingOffset;
            modPtr=(COMMON_SYMBOL_HEADER *)st.GetHugeDataPtr(
                   modPtr->symSiblingOffset);
            if ( ((modPtr->typeIndex.symType)&0x0F) == SYM_FUNCTION ) 
                break;
        }
    }
    else {
        return FAILURE;
    }
    return GOOD;

}
                              
void LowestBlockDesc(U32 addr, SYM_DESCRIPTOR& blockDesc)
{
    SYM_DESCRIPTOR desc1;
    COMMON_BLOCK_HEADER  *modPtr;
    
    modPtr=(COMMON_BLOCK_HEADER *)st.GetHugeDataPtr(blockDesc);
    desc1 = modPtr->child;
    while ( desc1 != NULL_SYMBOL ) {
        if (!UtilIsValidSymDescriptor( desc1 )) {
            return ;
        }
        modPtr=(COMMON_BLOCK_HEADER *)st.GetHugeDataPtr(desc1);
        if ( (addr>=modPtr->symHeader.beginAddrInfo.startAddr)&&
            (addr<=modPtr->symHeader.endAddrInfo.endAddr) ) {
            blockDesc = desc1;
            LowestBlockDesc(addr, blockDesc);
            break;
        }
        desc1 = modPtr->symHeader.symSiblingOffset;
    }
}
                                  
int StackAddrMapBlock(U32 addr , SYM_DESCRIPTOR& moduleDesc ,
            SYM_DESCRIPTOR& funcDesc , SYM_DESCRIPTOR& blockDesc)
{
    SYM_DESCRIPTOR *descArray;
    SYM_DESCRIPTOR desc , desc1 ;
    U16 numReturn , i;       

    moduleDesc = NULL_SYMBOL;
    funcDesc = NULL_SYMBOL;
    blockDesc = NULL_SYMBOL;
                       
    if ( GOOD != SymGetModuleNum( &i ) ) {
        return FAILURE;
    }
    descArray = new SYM_DESCRIPTOR[ i+1 ];
    if ( descArray == NULL ) return FAILURE; 
    if (GOOD != SymGetAllModules(descArray,i,&numReturn)){
        delete descArray;
        return FAILURE;
    }                         
    if ( numReturn == 0 ) {
        delete descArray;
        return FAILURE;       
    }
    i = 0;
    while( i < numReturn ) {
        if (!UtilIsValidSymDescriptor(descArray[i])) {
            delete descArray;
            return FAILURE;
        }
        COMMON_BLOCK_HEADER  *modPtr;

        modPtr=(COMMON_BLOCK_HEADER *)st.GetHugeDataPtr(descArray[i]);
        if ( (addr>=modPtr->symHeader.beginAddrInfo.startAddr)&&
            (addr<=modPtr->symHeader.endAddrInfo.endAddr) ) {
            moduleDesc = descArray[i];
            desc = modPtr->child;
            while ( desc != NULL_SYMBOL ) {
                if (!UtilIsValidSymDescriptor( desc )) {
                    delete descArray;
                    return FAILURE;
                }
                modPtr=(COMMON_BLOCK_HEADER *)st.GetHugeDataPtr(desc);
                if ( (addr>=modPtr->symHeader.beginAddrInfo.startAddr)&&
                    (addr<=modPtr->symHeader.endAddrInfo.endAddr) ) {
                    funcDesc = desc;
                    desc1 = modPtr->child;
                    while ( desc1 != NULL_SYMBOL ) {
                        if (!UtilIsValidSymDescriptor( desc1 )) {
                            delete descArray;
                            return FAILURE;
                        }
                        modPtr=(COMMON_BLOCK_HEADER *)st.GetHugeDataPtr(desc1);
                        if ( (addr>=modPtr->symHeader.beginAddrInfo.startAddr)&&
                            (addr<=modPtr->symHeader.endAddrInfo.endAddr) ) {
                            blockDesc = desc1;                               
                            LowestBlockDesc(addr,blockDesc);
                            break;
                        }
                        desc1 = modPtr->symHeader.symSiblingOffset;
                    }
                    break;
                }
                desc = modPtr->symHeader.symSiblingOffset;
            }
            break;
        }
        i++;
    }
    delete descArray;

    if ( moduleDesc )   
        return GOOD;
    else 
        return FAILURE; 
}

void ClearStkAndVar(void)
{
    stkObject.VarDeleteAll();  
    varObject.VarDeleteAll();
}

int FrankGetFuncRange(U32 addr , U32& uStart , U32& uEnd)
{
    SYM_DESCRIPTOR *descArray;
    SYM_DESCRIPTOR desc;
    U16 numReturn , i;       

    if ( GOOD != SymGetModuleNum( &i ) ) {
        return FAILURE;
    }
    descArray = new SYM_DESCRIPTOR[ i+1 ];
    if ( descArray == NULL ) return FAILURE; 
    if (GOOD != SymGetAllModules(descArray,i,&numReturn)){
        delete descArray;
        return FAILURE;
    }                         
    if ( numReturn == 0 ) {
        delete descArray;
        return FAILURE;       
    }
    i = 0;
    while( i < numReturn ) {
        if (!UtilIsValidSymDescriptor(descArray[i])) {
            delete descArray;
            return FAILURE;
        }
        COMMON_BLOCK_HEADER  *modPtr;

        modPtr=(COMMON_BLOCK_HEADER *)st.GetHugeDataPtr(descArray[i]);
        if ( (addr>=modPtr->symHeader.beginAddrInfo.startAddr)&&
            (addr<=modPtr->symHeader.endAddrInfo.endAddr) ) {
            desc = modPtr->child;
            while ( desc != NULL_SYMBOL ) {
                if (!UtilIsValidSymDescriptor( desc )) {
                    delete descArray;
                    return FAILURE;
                }
                modPtr=(COMMON_BLOCK_HEADER *)st.GetHugeDataPtr(desc);
                if ( (addr>=modPtr->symHeader.beginAddrInfo.startAddr)&&
                    (addr<=modPtr->symHeader.endAddrInfo.endAddr) ) {
                    uStart = modPtr->symHeader.beginAddrInfo.startAddr;
                    uEnd = modPtr->symHeader.endAddrInfo.endAddr;
                    delete descArray;
                    return GOOD;
                }
                desc = modPtr->symHeader.symSiblingOffset;
            }
            delete descArray;
            return FAILURE;
        }
        i++;
    }
    delete descArray;
    return FAILURE; 
}

/******************************** E O F ***********************************/
