 
/***************************************************************************
**
**    $Header:   D:/EPSLDV1/SRC/LOG/SYMUSER.CPP   1.8   20 Jun 1996 09:26:28   ZJRD  $
**
**    $Log:   D:/EPSLDV1/SRC/LOG/SYMUSER.CPP  $
** 
**    Rev 1.8   20 Jun 1996 09:26:28   ZJRD
** EasyPack/SLD Version 1.20a
** 
**    Rev 1.6   10 Jun 1996 10:21:08   ZJRD
** EasyPack/SLD Version 1.20
** 
**    Rev 1.4   29 May 1996 09:31:08   ZJRD
** EasyPack/SLD Version 1.95
** 
**    Rev 1.3   16 May 1996 09:04:24   ZJRD
** No change.
** 
**    Rev 1.2   10 May 1996 09:13:18   ZJRD
** No change.
** 
**    Rev 1.1   02 May 1996 10:23:54   ZJRD
** EasyPack/SLD Version 1.92
** 
**    Rev 1.31   18 Apr 1996 13:03:18   Shirley
** EasyPack/SLD Version 1.91
** 
**    Rev 1.30   12 Apr 1996 10:37:20   Shirley
** EasyPack/SLD Version 1.90
** 
**    Rev 1.28   15 Feb 1996 08:57:20   Shirley
** No change.
** 
**    Rev 1.27   12 Feb 1996 14:08:40   Shirley
** No change.
** 
**    Rev 1.26   06 Feb 1996 15:35:08   Shirley
** No change.
** 
**    Rev 1.25   06 Feb 1996 13:49:26   Shirley
** No change.
** 
**    Rev 1.24   01 Feb 1996 10:15:26   Shirley
** EasyPack/SLD Version 0.35b
** 
**    Rev 1.23   26 Jan 1996 09:18:50   Shirley
** No change.
** 
**    Rev 1.22   25 Jan 1996 13:18:44   Shirley
** No change.
** 
**    Rev 1.21   24 Jan 1996 10:34:56   Shirley
** No change.
** 
**    Rev 1.20   23 Jan 1996 11:25:44   Shirley
** No change.
** 
**    Rev 1.19   18 Jan 1996 10:07:50   Shirley
** EasyPack/SLD Version 0.34b
** 
**    Rev 1.17   04 Jan 1996 11:08:48   Shirley
** EasyPack/SLD Version 0.34
** 
**    Rev 1.16   30 Nov 1995 09:11:30   Shirley
** No change.
** 
**    Rev 1.15   28 Nov 1995 15:32:08   Shirley
** No change.
** 
**    Rev 1.14   21 Nov 1995 11:19:00   Shirley
** No change.
** 
**    Rev 1.13   13 Nov 1995 09:23:12   Shirley
** No change.
** 
**    Rev 1.12   12 Nov 1995 11:34:08   Shirley
** EasyPack/SLD Version 0.24
** 
**    Rev 1.11   08 Nov 1995 16:34:34   Shirley
** No change.
** 
**    Rev 1.10   08 Nov 1995 12:44:30   Shirley
** EasyPack/SLD Version 0.22
** 
**    Rev 1.9   02 Nov 1995 10:05:58   Shirley
** No change.
** 
**    Rev 1.8   27 Oct 1995 16:48:08   Shirley
** No change.
** 
**    Rev 1.7   27 Oct 1995 13:46:10   Shirley
** No change.
** 
**    Rev 1.6   25 Oct 1995 14:27:28   Shirley
** No change.
** 
**    Rev 1.5   18 Oct 1995 14:47:20   Shirley
** No change.
** 
**    Rev 1.4   13 Oct 1995 13:19:20   Shirley
** No change.
** 
**    Rev 1.3   29 Sep 1995 09:51:48   Shirley
** No change.
** 
**    Rev 1.2   20 Sep 1995 10:55:38   Shirley
** No change.
** 
**    Rev 1.1   15 Sep 1995 09:45:16   Shirley
** EasyPack/SLDV0.1a 
** 
**    Rev 1.0   07 Sep 1995 09:55:30   Shirley
** Initial revision.
**
****************************************************************************/

/****************************************************************************
**
**  Name: SYMUSER.CPP
**
**  Description:
**      Entry points for Create/Delete User Defined Symbols.
**
**  Status:  CODED
**
**    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 <string.h>
#include <io.h>
#include <fcntl.h>
#include <sys\stat.h>

#include "symblsvr.h"
#include "uicom.h"
#include "symuser.h"
#include "symuser1.h"
#include "abibase.h"
#include "hosterrs.h"

                       /****************************
                        *                          *
                        *     LOCAL DEFINITIONS    *
                        *                          *
                        ****************************/
extern class SymUserVarTable userVariables;
class SymUserTable userSymbols;
int nErrorNum = 0;      // global error number 

                       /****************************
                        *                          *
                        *    EXTERNAL VARIABLES    *
                        *                          *
                        ****************************/
extern STATUS AbiGetMemN(ADDR addr1, ADDR addr2,char* pchBuff);     
extern void ShlReshowLine(char * , int);
extern void SrcUpdate();
extern void SymbolLineCmd(void);

                       /****************************
                        *                          *
                        *     LOCAL PROTOTYPES     *
                        *                          *
                        ****************************/
void CreateCmd(int nArgc, char* pszArgv[]);
void DeleteCmd(int nArgc, char* pszArgv[]);
void SymbolCmd(int nArgc, char* pszArgv[]);
void QueryCmd(int nArgc, char* pszArgv[]);
void UploadCmd(int nArgc, char* pszArgv[]);
void SsaveCmd(int nArgc, char* pszArgv[]);
void SrecallCmd(int nArgc, char* pszArgv[]);
void prn_err( int num );
//void win_err( int num );
int SymToAddr( char *lpStr , U8* lpType , U32* lpAddr );
int AddrToSym( U8 type , U32 addr , char * str );

void U16ToStr(U16 ui , char *tt);
void U8ToStr(U8 ui , char *tt);
void StrToU32(U32& ul , char *tt);
void changeN(char *uc ,char *result, int n);
void showPC(U16 addr);

                       /****************************
                        *                          *
                        *      EXECUTABLE CODE     *
                        *                          *
                        ****************************/
extern RETCODE DisplaySymbols(LPSTR cmdString, int flag);
extern RETCODE AddressOf(LPSTR cmdString);
extern RETCODE NameOf(LPSTR cmdString);
extern RETCODE SymServerSymToAddr(char *lpStr , 
        U8* lpType , U32 * lpAddr);
extern RETCODE SymServerAddrToSym(U8 type , U32 addr , char *lpStr);

/***************************************************************************
*                                                                          *
*  SymToAddr - convert symbol to addr                                      *
*                                                                          *
*  parameter :                                                             *
*       input :                                                            *
*           str - symbol name                                              *
*       output :                                                           *
*           type - symbol segment area                                     *
*           addr - symbol address                                          * 
*                                                                          *
*  return value :                                                          *
*       None                                                               *
*                                                                          *
***************************************************************************/
int SymToAddr(char *lpStr , U8* lpType , U32 * lpAddr)
{                                                
    if ( GOOD != SymServerSymToAddr( lpStr , lpType , lpAddr) )
        return userSymbols.Sym2Addr( lpStr , lpType , lpAddr );
    else return GOOD;
}
                                                      
int SymUserTable::Sym2Addr( char *str , U8* type , U32 *addr )                             
{
    SymUserSearchNodeByName( str );
    if ( matchPtr == 0 ) return(-1);
    *type = matchPtr->type;
    *addr = matchPtr->addr;
    return(0);
}
    
/***************************************************************************
*                                                                          *
*  AddrToSym - convert address to symbol                                   *
*                                                                          *
*  parameter :                                                             *
*       output :                                                           *
*           str - symbol name                                              *
*       input :                                                            *
*           type - symbol segment area                                     *
*           addr - symbol address                                          * 
*                                                                          *
*  return value :                                                          *
*       None                                                               *
*                                                                          *
***************************************************************************/
int AddrToSym(U8 type , U32 addr , char *str)
{                                                
    if ( GOOD != SymServerAddrToSym(type , addr , str) )
        return userSymbols.Addr2Sym( type , addr , str );
    else return GOOD;
}
                                                      
int SymUserTable::Addr2Sym( U8 type , U32 addr , char *str )                             
{
    SymUserSearchNodeByAddr( addr , type );
    if ( matchPtr == 0 ) return(-1);
    int i = strlen( matchPtr->name );
    if ( i > 40 ) i = 40;
    memcpy( str , matchPtr->name , i );
    str[i] = '\0';
    return(0);
}
    
/***************************************************************************
*                                                                          *
*  SsaveCmd - Shell window SSave Command    entry pointer                  *
*                                                                          *
*  parameter :                                                             *
*       input :                                                            *
*           argc - argument count                                          *
*           argv - argument string array                                   *
*                                                                          *
*  return value :                                                          *
*       None                                                               *
*                                                                          *
***************************************************************************/
void SsaveCmd(int nArgc, char* pszArgv[])
{
    if ( nArgc != 2 ) return;
    if ( userSymbols.SymUserSSave( pszArgv[1] ) != 0 ) 
        prn_err( nErrorNum );
}

/***************************************************************************
*                                                                          *
*  SrecallCmd - Shell window SSave Command  entry pointer                  *
*                                                                          *
*  parameter :                                                             *
*       input :                                                            *
*           argc - argument count                                          *
*           argv - argument string array                                   *
*                                                                          *
*  return value :                                                          *
*       None                                                               *
*                                                                          *
***************************************************************************/
void SrecallCmd(int nArgc, char* pszArgv[])
{
    if ( nArgc != 2 ) return;
    if ( userSymbols.SymUserSRecall( pszArgv[1] ) !=  0 ) 
        prn_err( nErrorNum );
}

/***************************************************************************
*                                                                          *
*  UploadCmd - Shell window upload Command  entry pointer                  *
*                                                                          *
*  parameter :                                                             *
*       input :                                                            *
*           argc - argument count                                          *
*           argv - argument string array                                   *
*                                                                          *
*  return value :                                                          *
*       None                                                               *
*                                                                          *
***************************************************************************/
void UploadCmd(int nArgc, char* pszArgv[])
{          
    char filename[256];
    char olddata[256] , newdata[512];
    U32 staddr , endaddr , len;
    ADDR addr1 , addr2;
    int i , uploadFile;
    U16 count ;
    U8 uCheckSum;

    addr1.addrType = addr2.addrType = 1;
    switch ( pszArgv[1][0] ) {
    case 'X' :
    case 'x' :
        addr1.addrType = addr2.addrType = 2;
        break;
    case 'I' :
    case 'i' :
        addr1.addrType = addr2.addrType = 3;
        break;
    case 'R' :
    case 'r' :
        addr1.addrType = addr2.addrType = 4;
        break;
    case 'B' :
    case 'b' :
        addr1.addrType = addr2.addrType = 5;
        break;
    default :
        break;
    }
    
    if ( nArgc == 4 ) {
        strcpy( filename , pszArgv[3] );
        StrToU32( staddr , pszArgv[1] );
        StrToU32( endaddr , pszArgv[2] );
        len = endaddr - staddr + 1;
    }
    else {
        strcpy( filename , pszArgv[4] );
        StrToU32( staddr , pszArgv[1] );
        StrToU32( endaddr , pszArgv[3] );
        len = endaddr;
        endaddr += staddr-1;
    }

    uploadFile = _open(filename,_O_CREAT|_O_RDWR|_O_BINARY,
                                _S_IREAD|_S_IWRITE);
    if ( uploadFile == -1 ) {
        nErrorNum = 0x4003;
        prn_err( nErrorNum );
        return;
    }               

    ShowLine("Upload file : ");
    addr1.addr = (unsigned short) staddr ;
    count = (U16)(len>>7) ;
    newdata[0] = ':';
    newdata[7] = '0';
    newdata[8] = '0';
    newdata[265] = 'F';
    newdata[266] = 'F';
    newdata[267] = 0x0d;
    newdata[268] = 0x0a;
    U8ToStr( 0x80 , &newdata[1] );
    for( i = 0 ; (U16)i < count ; i++) {            
        showPC( (U16) addr1.addr );
        addr2.addr = addr1.addr + 127;

#ifdef _ZLR_
        
        if ( AbiGetMemN( addr1 , addr2 , olddata ) != ICE_OK ) {
            nErrorNum = 0x4001;
            prn_err( nErrorNum );
            return;
        }
        
#endif 
       
        U16ToStr( addr1.addr , &newdata[3]);
        changeN( olddata , &newdata[9] , 128 );
        uCheckSum = 0;             
        int j;
        for( j = 0;j < 128;j++ ) {
            uCheckSum = (unsigned char)(uCheckSum + olddata[j]);
//            uCheckSum += (U8) olddata[j];
        }                    
        uCheckSum = (unsigned char)(uCheckSum+0x80);
        uCheckSum = (unsigned char)(uCheckSum+(addr1.addr&0xFF));
        uCheckSum = (unsigned char)(uCheckSum+
            ((addr1.addr>>8)&0xFF));
        
        j = 0x100 - uCheckSum;
        uCheckSum = (unsigned char)(j&0xFF);
        changeN( (char *)&uCheckSum, &newdata[265], 1 );
//        uCheckSum = ~uCheckSum + 1;    
        _write( uploadFile , newdata , 269 );
        addr1.addr += 128;        

        if ( TestKey(VK_ESCAPE) == 1 ) { 
            nErrorNum = 0x4010;
            prn_err( nErrorNum );
		    U8ToStr( 0x0 , &newdata[1] );
		    U16ToStr( 0x0 , &newdata[3] );
		    U8ToStr( 0x1 , &newdata[7] );
		    i = 9 ;     
		    newdata[i++] = 'F';
		    newdata[i++] = 'F';
		    newdata[i++] = 0x0d;
		    newdata[i++] = 0x0a;
		    _write( uploadFile , newdata , i );
		    _close( uploadFile );
            return;
        }                  

    }
    count = (U16)( len & 0x7F );
    if ( count ) {
        i = 9 + count*2 ;     
        newdata[i++] = 'F';
        newdata[i++] = 'F';
        newdata[i++] = 0x0d;
        newdata[i++] = 0x0a;
//        U8ToStr( 0x80 , &newdata[1] );
        U8ToStr( (U8)count , &newdata[1] );
        showPC( (U16) addr1.addr );
        addr2.addr = addr1.addr + count - 1;
        
#ifdef _ZLR_
        
        if ( AbiGetMemN( addr1 , addr2 , olddata ) != ICE_OK ) {
            nErrorNum = 0x4001;
            prn_err( nErrorNum );
            return;
        }
        
#endif
        
        U16ToStr( addr1.addr , &newdata[3]);
        changeN( olddata , &newdata[9] , count );

        uCheckSum = 0;             
        int j;
        for( j = 0;j < (int)count;j++ ) {
            uCheckSum = (unsigned char)(uCheckSum + olddata[j]);
//            uCheckSum += (unsigned char)olddata[j];
        }    
        uCheckSum = (unsigned char)(uCheckSum+count);
        uCheckSum = (unsigned char)(uCheckSum+(addr1.addr&0xFF));
        uCheckSum = (unsigned char)(uCheckSum+
            ((addr1.addr>>8)&0xFF));

        j = 0x100 - uCheckSum;
        uCheckSum = (unsigned char)(j&0xFF);
//        i = 9 + count*2 ;     
        changeN( (char *)&uCheckSum, &newdata[9 + count*2], 1 );

        _write( uploadFile , newdata , i );
    }         
    U8ToStr( 0x0 , &newdata[1] );
    U16ToStr( 0x0 , &newdata[3] );
    U8ToStr( 0x1 , &newdata[7] );
    i = 9 ;     
    newdata[i++] = 'F';
    newdata[i++] = 'F';
    newdata[i++] = 0x0d;
    newdata[i++] = 0x0a;
    _write( uploadFile , newdata , i );
    _close( uploadFile );
}   

/***************************************************************************
*                                                                          *
*  CreateCmd - Shell window create Command  entry pointer                  *
*                                                                          *
*  parameter :                                                             *
*       input :                                                            *
*           argc - argument count                                          *
*           argv - argument string array                                   *
*                                                                          *
*  return value :                                                          *
*       None                                                               *
*                                                                          *
***************************************************************************/
void CreateCmd(int nArgc, char* pszArgv[])
{          
    char temp[41];
    U32 addr;
    U8 addrType;
    int i;
                     
    if ( nArgc != 3 ) return;                     
    i = strlen( pszArgv[1] );
//    if (i>40) i=40;
    if (i>41) i=41;
    memcpy( temp , pszArgv[1] , i );
    temp[i] = '\0'; 
    addrType = 1;
    switch ( pszArgv[2][0] ) {
    case 'X' :
    case 'x' :
        addrType = 2;
        break;
    case 'I' :
    case 'i' :
        addrType = 3;
        break;
    case 'R' :
    case 'r' :
        addrType = 4;
        break;
    case 'B' :
    case 'b' :
        addrType = 5;
        break;
    default :
        break;
    }
    StrToU32(addr , pszArgv[2]);    
    i = userSymbols.SymUserCreate(temp , addrType , addr);
    if ( i == 0 ) {
        ShowLine("Create symbol OK!");
        if ( addrType == 1 ) SrcUpdate();
    }        
    else 
        prn_err( nErrorNum );
            
}   

/***************************************************************************
*                                                                          *
*  DeleteCmd - Shell window create Command  entry pointer                  *
*                                                                          *
*  parameter :                                                             *
*       input :                                                            *
*           argc - argument count                                          *
*           argv - argument string array                                   *
*                                                                          *
*  return value :                                                          *
*       None                                                               *
*                                                                          *
***************************************************************************/
void DeleteCmd(int nArgc, char* pszArgv[])
{          
    char temp[41];
    int i;
                                  
    if ( nArgc != 2 ) return;                                  
    if ( pszArgv[1][0] == '#' ) {
        i = strlen( pszArgv[1] );
        if (i>40) i=40;
        memcpy( temp , pszArgv[1] , i );
        temp[i] = '\0'; 
        i = userSymbols.SymUserDelete(temp);
    }
    else if ( pszArgv[1][0] == '$' ) {
        i = strlen( pszArgv[1] );
        if (i>40) i=40;
        memcpy( temp , pszArgv[1] , i );
        temp[i] = '\0'; 
        i = userVariables.SymUserVarDelete(temp);
    }
    else {
        userSymbols.SymUserDeleteAll();
        userVariables.SymUserVarDeleteAll();
        i = 0;
    }
    if ( i == 0 ) {
        ShowLine("Delete symbol OK!");
        SrcUpdate();
    }
    else 
        prn_err( nErrorNum );
        
}   

/***************************************************************************
*                                                                          *
*  SymbolCmd - Shell window symbol Command  entry pointer                  *
*                                                                          *
*  parameter :                                                             *
*       input :                                                            *
*           argc - argument count                                          *
*           argv - argument string array                                   *
*                                                                          *
*  return value :                                                          *
*       None                                                               *
*                                                                          *
***************************************************************************/
void SymbolCmd(int nArgc, char* pszArgv[])
{                            
//  if ( nArgc != 1 ) return;
//  if ( pszArgv[0] == 0 ) return;
    if ( nArgc == 1 ) {  
        DisplaySymbols( 0 , 8 );
    }
    else if ( nArgc == 2 ) {
        if ( *pszArgv[1] == '#' ) {
            DisplaySymbols( &pszArgv[1][1] , 0 );
        }
        else if ( stricmp( pszArgv[1] , "global")==0 ) {
            DisplaySymbols( 0 , 4 );
        }
        else if ( stricmp( pszArgv[1] , "module")==0 ) {
            DisplaySymbols( 0 , 2 );
        }   
        else if ( stricmp( pszArgv[1] , "lines")==0 ) {
	        SymbolLineCmd();
        }   
    }   
        
    if ( nArgc == 1 ) {
        userSymbols.SymUserList();
        userVariables.SymUserVarList();
    }
}   

/***************************************************************************
*                                                                          *
*  QueryCmd - Shell window query Command    entry pointer                  *
*                                                                          *
*  parameter :                                                             *
*       input :                                                            *
*           argc - argument count                                          *
*           argv - argument string array                                   *
*                                                                          *
*  return value :                                                          *
*       None                                                               *
*                                                                          *
***************************************************************************/
void QueryCmd(int nArgc, char* pszArgv[])
{       
    int i;
    char *ss ;
    
    i = 0;
    if ( nArgc != 2 ) return;                     
    ss = new char [ strlen( pszArgv[1] ) + 1 ];
    if ( ss == 0 ) return;                     
    strcpy( ss , pszArgv[1] );
    if ( *ss == '#' )
//          AddressOf( ss );
    {
        if ( AddressOf( ss ) != GOOD ) {
//          ShowLine("Address of Return Error!");
            i = 1;
        }
    }    
    else
//          NameOf( ss );
    {
        if ( NameOf( ss ) != GOOD ) {
            i = 1;
//          ShowLine("Name of Return Error!");
        }
    }    
    if ( userSymbols.SymUserQuery( pszArgv[1] ) != 0 ) {
        if ( i ) {
//            if ( *pszArgv[1] == '#' ) ShowLine("This symbol does not exist!");
//            else ShowLine("This address can not query symbol!");
            CString strErr;
            if ( *pszArgv[1] == '#' ) {
                
                if ( GOOD == ErrGetErrorText(ER_ID_SYM_NOT_EXIST, strErr) ) {
                    ShowLine(strErr.GetBuffer( strErr.GetLength() ) );
                }
            }
            else {
                if ( GOOD == ErrGetErrorText(ER_ID_SYM_ADDR_TO_SYM, strErr) ) {
                    ShowLine(strErr.GetBuffer( strErr.GetLength() ) );
                }
            }
        }
        i = 1;
    }
//    i = userSymbols.SymUserQuery( pszArgv[1] );
    delete ss;
    if ( i != 0 ) 
        nErrorNum = 0;             
//      prn_err( nErrorNum );
        
}

/***************************************************************************
*                                                                          *
*  SymUserSSave - save user defined symbol to file                         *
*  parameter :                                                             *
*       str      symbol file name                                          *
*  return value :                                                          *
*       0  ---  OK                 -1  ---  failure                        *
*                                                                          *
***************************************************************************/
int SymUserTable::SymUserSSave(char *str)
{
    struct SymUserNode *temp;
    int symbolFile ,  i;     
    U32 num;
    char buf[200];
    
    if ( symno == 0 ) {
        nErrorNum = 0x4009;
        return(-1);                         
    }
    symbolFile = _open( str,_O_CREAT|_O_RDWR|_O_BINARY,
                                _S_IREAD|_S_IWRITE);
    if ( symbolFile == -1 ) {
        nErrorNum = 0x4003;
        return -1;
    }               
    buf[0] = 0x0;
    buf[1] = 0x1A;
    memcpy( &buf[2] , &symno , 4 );
    _write( symbolFile , buf , 6 );
    temp = namePtr; 
    num = 0;
    while( temp ) {
        memset( buf , 0 , 50 );
        i = strlen( temp->name );
        if ( i > 40 ) {
            memcpy( buf , temp->name , 40 );
        }
        else {
            strcpy( buf , temp->name );
        }
        memcpy(&buf[41] , &temp->type , 1);
        memcpy(&buf[42] , &temp->addr , 4);
        _write( symbolFile , buf , 46 );
        temp = temp->ptr;               
        num++;
    }       
    _close( symbolFile );
    if ( num != symno ) {
        nErrorNum = 0x400A;
        return(-1);
    }
    return 0;       
}

/***************************************************************************
*                                                                          *
*  SymUserSRecall - recall user defined symbol to file                     *
*  parameter :                                                             *
*       str      symbol file name                                          *
*  return value :                                                          *
*       0  ---  OK                 -1  ---  failure                        *
*                                                                          *
***************************************************************************/
int SymUserTable::SymUserSRecall(char *str)
{
    int symbolFile ;     
    U32 num ;
    U8 t ;
    U32 a ;
    char buf[200];
    
    symbolFile = _open( str,_O_RDONLY|_O_BINARY);
    if ( symbolFile == -1 ) {
        nErrorNum = 0x4003;
        return -1;
    }                          
    if ( _read( symbolFile , buf , 6 ) == -1 ) {
        nErrorNum = 0x4008;
        _close( symbolFile );
        return(-1);
    }
    if ( (buf[0]!=0x0) || (buf[1] != 0x1A) ) {
        nErrorNum = 0x400B;
        _close( symbolFile );
        return(-1);
    }
    memcpy( &num , &buf[2] , 4 );
    while( num > 0 ) {
        if ( _read( symbolFile , buf , 46 ) == -1 ) {
            nErrorNum = 0x400C;
            _close( symbolFile );
            return(-1);
        }
        memcpy(&t , &buf[41] , 1 );
        memcpy(&a , &buf[42] , 4 );
        SymUserCreate( buf , t , a );
        num--;
    }       
    _close( symbolFile );
    return 0;       
}

/***************************************************************************
*                                                                          *
*  SymUserQuery - query a symbol to address or from address to name        *
*  parameter :                                                             *
*       str      query information                                         *
*  return value :                                                          *
*       0  ---  OK                 -1  ---  failure                        *
*                                                                          *
***************************************************************************/
int SymUserTable::SymUserQuery( char *str )
{ 
    char temp[41] , temp1[256];
    U32 addr;        
    U8 addrType;
    int i , j;
               
    j = 0;                
    if (*str == '#') {                     
        i = strlen( str );
        if (i>40) i=40;
        memcpy( temp , str , i );
        temp[i] = '\0'; 
        userSymbols.SymUserSearchNodeByName( temp );
        if ( matchPtr == 0 ) {
            nErrorNum = 0x4005;
            return( -1 );
        }
        else {
            switch( matchPtr->type ) {     
            case 2:
                sprintf(temp1,"      X:");
                break;
            case 3:
                sprintf(temp1,"      I:");
                break;
            case 4:
                sprintf(temp1,"      R:");
                break;
            case 5:
                sprintf(temp1,"      B:");
                break;
            default:
                sprintf(temp1,"      P:");
                break;
            }
//          sprintf( temp1,"     " );
            U16ToStr( (U16)matchPtr->addr , &temp1[8] );
            temp1[12] = temp1[13] = ' ';
            strcpy(&temp1[14] , matchPtr->name);
            ShowLine( temp1 );
            j = 1;
        }
    }
    else {
        StrToU32(addr , str);   
        addrType = 1;
        switch ( str[0] ) {
        case 'X' :
        case 'x' :
            addrType = 2;
            break;
        case 'I' :
        case 'i' :
            addrType = 3;
            break;
        case 'R' :
        case 'r' :
            addrType = 4;
            break;
        case 'B' :
        case 'b' :
            addrType = 5;
            break;
        default :
            break;
        }
        userSymbols.SymUserSearchNodeByAddr( addr , addrType );
        if ( matchPtr == 0 ) {
            return( -1 );
        }
        else {
            while( matchPtr->addr == addr ) {
                if ( matchPtr->type == addrType ) {
                    sprintf( temp1,"     " );
                    switch( addrType ) {     
                    case 2:
                        sprintf(temp1,"      X:");
                        break;
                    case 3:
                        sprintf(temp1,"      I:");
                        break;
                    case 4:
                        sprintf(temp1,"      R:");
                        break;
                    case 5:
                        sprintf(temp1,"      B:");
                        break;
                    default:
                        sprintf(temp1,"      P:");
                        break;
                    }
                    U16ToStr( (U16)matchPtr->addr , &temp1[8] );
                    temp1[12] = temp1[13] = ' ';
                    strcpy(&temp1[14] , matchPtr->name);
                    ShowLine( temp1 );
                    j = 1;
                }
                matchPtr = matchPtr->next;
                if ( matchPtr == 0 ) break;
            }
        }
    }
    if ( j == 0 ) return FAILURE;
    return GOOD;
}   

/***************************************************************************
*                                                                          *
*  SymUserCreate - create a new user defined symbol to table               *
*  parameter :                                                             *
*       str      symbol name                                               *
*       type     symbol type                                               *
*       addr     symbol address                                            *
*  return value :                                                          *
*       0  ---  OK                 -1  ---  failure                        *
*                                                                          *
***************************************************************************/
int SymUserTable::SymUserCreate(char *str , U8 type , U32 addr)
{
    struct SymUserNode *node;
    
    node = new SymUserNode;
    ASSERT( node );
    node->name = new char[ strlen( str ) + 1 ];
    ASSERT( node->name );
    strcpy( node->name , str );
    node->type = type;
    node->addr = addr;
    return ( SymUserAddNode( node ) );
}

/***************************************************************************
*                                                                          *
*  SymUserDelete - Delete a user defined symbol in symbol table            *
*  parameter :                                                             *
*       str      symbol name                                               *
*  return value :                                                          *
*       0  ---  OK                 -1  ---  failure                        *
*                                                                          *
***************************************************************************/
int SymUserTable::SymUserDelete(char *str)
{
    struct SymUserNode *temp , *temp1 , *node;
    struct SymUserNodeIndex *t1 , *t2;
    
    if ( symno == 0 ) {
        nErrorNum = 0x4005;
        return( -1 );      
    }
    if ( symno == 1 ) {
        if ( strcmp(str , namePtr->name) == 0 ) {
            if ( namePtr->name ) delete namePtr->name;
            delete namePtr;
            namePtr = addrPtr = 0;
            delete nameIndexPtr;
            delete addrIndexPtr;
            nameIndexPtr = addrIndexPtr = 0;
            symno = 0;
            return 0;
        }            
        else {
            nErrorNum = 0x4005;
            return (-1);  
        }
    }
        
    temp = temp1 = namePtr;
    t1 = t2 = nameIndexPtr;
    while ( t1 ) {
        if ( strcmp(str,t1->node->name)<=0 ) break;
        t2 = t1;
        t1 = t2->next;
    }
    if ( t1 == nameIndexPtr ) {
        if ( strcmp(str,t1->node->name)!=0 ) {
            nErrorNum = 0x4005;
            return(-1);
        }
        symno--;
        node = namePtr;
        namePtr = namePtr->ptr;
        t1->node = namePtr;
        t1->num--;  
        if ( symno > 10 && t1->num <= 10 ) {
            SymUserRejustNameIndex();
        }
    }     
    else {
        temp1 = temp = t2->node;
        while( temp ) {
            if ( strcmp(str,temp->name)<=0 ) break;
            temp1 = temp;
            temp = temp1->ptr;
        }
        if ( temp == 0 ) {
            nErrorNum = 0x4005;
            return ( -1 );
        }
        else if ( temp == t2->node ) {
            if ( strcmp(str,temp->name)!=0 ) return(-1);
            symno--;
            node = temp;
            temp1 = namePtr;
            while( temp1->ptr != temp ) {
                temp1 = temp1->ptr;
            }
            temp1->ptr = node->ptr;
            t2->num--;             
            t2->node = node->ptr;
            if ( symno > 10 && t2->num <= 10 ) {
                SymUserRejustNameIndex();
            }
        }   
        else {
            if ( strcmp(str,temp->name)!=0 ) return(-1);
            symno--;             
            node = temp;
            temp1->ptr = node->ptr;
            t2->num--;
            if ( symno > 10 && t2->num <= 10 ) {
                SymUserRejustNameIndex();
            }
        }
    }
                    
    temp = temp1 = addrPtr;
    t1 = t2 = addrIndexPtr;
    if ( addrPtr == node ) {
        addrPtr = node->next;
    }
    else {
        while ( temp->next != node ) {
            temp = temp->next;
        }
        temp->next = node->next;
    }
    SymUserRejustAddrIndex();

    if ( node->name ) delete node->name;
    delete node;
    
    return( 0 );
}

/***************************************************************************
*                                                                          *
*  SymUserSearchNodeByName - Search a symbol node by name in symbol table  *
*  parameter :                                                             *
*       str      symbol name                                               *
*  return value :                                                          *
*       0  ---  OK                 -1  ---  failure                        *
*                                                                          *
***************************************************************************/
void SymUserTable::SymUserSearchNodeByName( char *str )
{
    struct SymUserNode *temp , *temp1;
    struct SymUserNodeIndex *t1 , *t2;
        
    matchPtr = preMatchPtr = 0;
            
    if ( namePtr == 0 ) return;
    temp = temp1 = namePtr;
    t1 = t2 = nameIndexPtr;
    while ( t1 ) {
        if ( strcmp(str,t1->node->name)<=0 ) break;
        t2 = t1;
        t1 = t2->next;
    }
    temp1 = temp = t2->node;
    while( temp ) {
        if ( strcmp(str,temp->name)<=0 ) break;
        temp1 = temp;
        temp = temp1->ptr;
    }
    if ( temp == 0 ) return;
    if ( strcmp(str,temp->name)!=0 ) return;
    preMatchPtr = temp1;
    matchPtr = temp;
}

/***************************************************************************
*                                                                          *
*  SymUserSearchNodeByAddr - Search a symbol node by address               *
*  parameter :                                                             *
*       addr       symbol address                                          *
*  return value :                                                          *
*       0  ---  OK                 -1  ---  failure                        *
*                                                                          *
***************************************************************************/
void SymUserTable::SymUserSearchNodeByAddr( U32 addr , U8 type )
{
    struct SymUserNode *temp , *temp1;
    struct SymUserNodeIndex *t1 , *t2;
        
    matchPtr = preMatchPtr = 0;
            
    if ( addrPtr == 0 ) return ;
    temp = temp1 = addrPtr;
    t1 = t2 = addrIndexPtr;
    while ( t1 ) {
        if ( addr<=t1->node->addr ) break;
        t2 = t1;
        t1 = t2->next;
    }
    temp1 = temp = t2->node;
    while( temp ) {
        if ( addr<=temp->addr ) break;
        temp1 = temp;
        temp = temp1->next;
    }
    if ( temp == 0 ) return;
    if ( addr != temp->addr ) return;
    preMatchPtr = temp1;
    matchPtr = temp; 
    while ( matchPtr ) {
        if ( addr != matchPtr->addr ) break;
        if ( type == matchPtr->type ) return;
        preMatchPtr = matchPtr;
        matchPtr = preMatchPtr->next;
    }
    matchPtr = preMatchPtr = 0;
}
            
void SymUserTable::SymUserRejustNameIndex(void)
{
    int i;
    struct SymUserNode *temp1;
    struct SymUserNodeIndex *t1 , *t2;

    t1 = nameIndexPtr; 
    nameIndexPtr->node = namePtr;
    temp1 = namePtr;
    while( 1 ) {
        i = 0; 
        while ( temp1 && ( i < 20 ) ) {
            i++;
            temp1 = temp1->ptr;
        }
        t1->num = i;
        if ( temp1 == 0 ) break;
        if ( t1->next ) {
            t1 = t1->next;
            t1->node = temp1;
        }
        else {
            t1->next = new SymUserNodeIndex;
            ASSERT ( t1->next );
            t1 = t1->next;
            t1->node = temp1;
        }
    }
    if ( t1->next ) {
        t2 = t1->next;
        t1->next = 0;
        while( t2 ) {
            t1 = t2->next;
            delete t2;
            t2 = t1;
        }
    }
}   

void SymUserTable::SymUserRejustAddrIndex(void)
{
    int i;
    struct SymUserNode *temp1;
    struct SymUserNodeIndex *t1 , *t2;

    t1 = addrIndexPtr;           
    addrIndexPtr->node = addrPtr;
    temp1 = addrPtr;
    while( 1 ) {
        i = 0; 
        while ( temp1 && ( i < 20 ) ) {
            i++;
            temp1 = temp1->next;
        }
        t1->num = i;
        if ( temp1 == 0 ) break;
        if ( t1->next ) {
            t1 = t1->next;
            t1->node = temp1;
        }
        else {
            t1->next = new SymUserNodeIndex;
            ASSERT ( t1->next );
            t1 = t1->next;
            t1->node = temp1;
        }
    }
    if ( t1->next ) {
        t2 = t1->next;
        t1->next = 0;
        while( t2 ) {
            t1 = t2->next;
            delete t2;
            t2 = t1;
        }
    }
}   

/***************************************************************************
*                                                                          *
*  SymUserAddNode - Add a new user defined symbol to table                 *
*  parameter :                                                             *
*       node     the node which will be added                              *
*  return value :                                                          *
*       0  ---  OK                 -1  ---  failure                        *
*                                                                          *
***************************************************************************/
int SymUserTable::SymUserAddNode( struct SymUserNode *node )
{           
//  int i;
    struct SymUserNode *temp , *temp1;
    struct SymUserNodeIndex *t1 , *t2;
    
    
    if ( namePtr == 0 ) {
        addrPtr = namePtr = node;
        addrIndexPtr = new SymUserNodeIndex;
        nameIndexPtr = new SymUserNodeIndex;
        ASSERT( addrIndexPtr );
        ASSERT( nameIndexPtr );
        addrIndexPtr->node = addrPtr;
        addrIndexPtr->num = 1;
        nameIndexPtr->node = namePtr;
        nameIndexPtr->num = 1;
        symno++;
        return( 0 );        
    }
    temp = temp1 = namePtr;
    t1 = t2 = nameIndexPtr;
    while ( t1 ) {
        if ( strcmp(node->name,t1->node->name)<=0 ) break;
        t2 = t1;
        t1 = t2->next;
    }
    if ( t1 == nameIndexPtr ) {
        if ( strcmp(node->name,t1->node->name)==0 ) {
            nErrorNum = 0x4004;
            return(-1);
        }
        symno++;
        node->ptr = namePtr;
        namePtr = node;
        t1->node = node;
        t1->num++;  
        if ( symno > 20 && t1->num > 30 ) {
            SymUserRejustNameIndex();
        }
    }     
    else {
        temp1 = temp = t2->node;
        while( temp ) {
            if ( strcmp(node->name,temp->name)<=0 ) break;
            temp1 = temp;
            temp = temp1->ptr;
        }
        if ( temp == 0 ) {
            symno++;
            temp1->ptr = node;
            t2->num++; 
            if ( symno > 20 && t2->num > 30 ) {
                SymUserRejustNameIndex();
            }
        }
        else {
            if ( strcmp(node->name,temp->name)==0 ) {
                nErrorNum = 0x4004;
                return(-1);   
            }
            symno++;
            node->ptr = temp1->ptr;
            temp1->ptr = node;
            t2->num++;
            if ( symno > 20 && t2->num > 30 ) {
                SymUserRejustNameIndex();
            }
        }
    }               
    
    temp = temp1 = addrPtr;
    t1 = t2 = addrIndexPtr;
    while ( t1 ) {
        if ( node->addr <= t1->node->addr ) break;
        t2 = t1;
        t1 = t2->next;
    }
    if ( t1 == addrIndexPtr ) {
        node->next = addrPtr;
        addrPtr = node;
        t1->node = node;
        t1->num++;  
        if ( symno > 20 && t1->num > 30 ) {
            SymUserRejustAddrIndex();
        }
    }     
    else {
        temp1 = temp = t2->node;
        while( temp ) {
            if ( node->addr <= temp->addr ) break;
            temp1 = temp;
            temp = temp1->next;
        }
        if ( temp == 0 ) {
            temp1->next = node;
            t2->num++; 
            if ( symno > 20 && t2->num > 30 ) {
                SymUserRejustAddrIndex();
            }
        }
        else {
            node->next = temp1->next;
            temp1->next = node;
            t2->num++;
            if ( symno > 20 && t2->num > 30 ) {
                SymUserRejustAddrIndex();
            }
        }
    }               
    return(0);
}                             
              
int SymUserTable::SymUserList( void )
{
    char temp[255];
    struct SymUserNode *tt;
    int i;
    
    sprintf(temp , "User defined symbols : %d" , symno);
    ShowLine( temp );
    if ( symno == 0 ) return 0;
    tt = namePtr ;
    while ( tt ) {
        i = strlen( tt->name );
        switch( tt->type ) {     
        case 2:
            sprintf(temp,"      X:");
            break;
        case 3:
            sprintf(temp,"      I:");
            break;
        case 4:
            sprintf(temp,"      R:");
            break;
        case 5:
            sprintf(temp,"      B:");
            break;
        default:
            sprintf(temp,"      P:");
            break;
        }
//      sprintf(temp,"     ");
        U16ToStr( (U16)tt->addr , &temp[8] );
        temp[12] = temp[13] = ' ';
        strcpy(&temp[14] , tt->name);
        ShowLine( temp );
        tt = tt->ptr;
    }
    return(0);
}
              
void SymUserTable::SymUserClearUpNode()
{                         
    struct SymUserNode *temp , *temp1;
    
    temp = addrPtr;
    while ( temp ) {
        if ( temp->name ) delete temp->name;
        temp1 = temp->next;
        delete temp;
        temp = temp1;
    }                   
    addrPtr = 0;
    namePtr = 0;
    symno = 0;
    matchPtr = 0;
    preMatchPtr = 0;
}

void SymUserTable::SymUserClearUpIndex()
{    
    struct SymUserNodeIndex *temp , *temp1;
    
    temp = addrIndexPtr;
    while ( temp ) {
        temp1 = temp->next;
        delete temp;
        temp = temp1;
    }
    temp = nameIndexPtr;
    while ( temp ) {
        temp1 = temp->next;
        delete temp;
        temp = temp1;
    }           
    addrIndexPtr = nameIndexPtr = 0;
}

SymUserTable::~SymUserTable()
{
    SymUserClearUpNode();
    SymUserClearUpIndex();
}

void SymUserTable::SymUserDeleteAll(void)
{
    SymUserClearUpNode();
    SymUserClearUpIndex();
}
 
void U16ToStr(U16 ui , char *tt)
{
    U16 u;
    int i;
    
    u = ui;
    for( i = 0; i < 4; i++ ) {
        if ( (u&0x000F) < 10 ) {
            tt[3-i] = (char)( '0' + (char)(u&0x000F) );
        }
        else {
            tt[3-i] = (char)( 'A' + (char)((u&0x000F) - 10) );
        }  
        u = (U16) u>>4;
    }
}   

void U8ToStr(U8 ui , char *tt)
{
    U8 u;
    int i;
    
    u = ui;    
    for( i = 0; i < 2; i++ ) {
        if ( (u&0x0F) < 10 ) {
            tt[1-i] = (char)( '0' + (char)(u&0x0F) );
        }
        else {
            tt[1-i] = (char)( 'A' + (char)((u&0x0F)-10) );
        }  
        u = (U8) (u>>4);
    }
}   
    
void StrToU32(U32& ul , char *tt)
{   
    char *s , c;
    
    ul = 0;       
    s = tt;
    
    if ( *(tt+1) == ':' ) s += 2;
    while( *s != '\0' ) {
        ul = (U32) ul<<4;
        c = *s;
        if ( (c>='0')&&(c<='9') ) c -= '0';
        else if ( (c>='A')&&(c<='F') ) c = (char)(c-'A'+10);
        else if ( (c>='a')&&(c<='f') ) c = (char)(c-'a'+10);
        else c = 0;
        ul += (U32)c;      
        s++;
    }
}

void changeN(char *uc ,char *result, int n)
{
    int i,j,k;

    for( i = 0; i < n;i++) {
        j = (uc[i]&0x00FF)>>4;
        k = uc[i]&0x000F;
        if( j < 10 ) result[2*i] = (char)('0'+j);
        else result[2*i] = (char)('A'+j-10);
        if( k < 10 ) result[2*i+1] = (char)('0'+k);
        else result[2*i+1] = (char)('A'+k-10);
    }
}

/***************************************************************************
*                                                                          *
*  displayPC - display pc value string                                     *
*  parameter :                                                             *
*       addr  ----     pc value                                            *
*  return value :                                                          *
*       NONE                                                               *
*                                                                          *
***************************************************************************/
void showPC(U16 addr)
{
    char tempStr[100];
    int l , i , j;

    sprintf(tempStr , "Upload file : ");
    l = strlen(tempStr);
    for( i=0; i < 4;i++) {
        j = addr & 0x000F;
        if ( j < 10 ) tempStr[3-i+l] = (char) ('0' + j);
        else tempStr[3-i+l] = (char) ('A' + j - 10);
        addr = addr >> 4;
    }
    tempStr[4+l] = '\0';                         

    ShlReshowLine(tempStr , 4+l);
}        /* end of showPC() */

void prn_err( int num ) 
{
    CString strErr;

    if ( num > 0x4000 ) {
//        num -= 0x4000;
//        ShowLine(strErrMsg[num]);
//        ShowLine("Load Failure!");
        if ( GOOD == ErrGetErrorText((U32)num, strErr) ) {
            ShowLine(strErr.GetBuffer( strErr.GetLength() ) );
        }
        nErrorNum = 0;                         
    }
}    

/*
void win_err( int num ) 
{
    if ( num > 0x4000 ) {
        num -= 0x4000;
//        AfxMessageBox(strErrMsg[num]);
        AfxMessageBox("Load Failure!");
        nErrorNum = 0;                         
    }
}
*/
/******************************** E O F ***********************************/
