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

/****************************************************************************
**
**  Name: SymUserVar1.CPP
**
**  Description:
**      Entry points for Create/Delete User Defined Variables.
**
**  Status:  CODED
**
**    Rev 1.0   12 April. 1996 13:30:00pm  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 "symuser1.h"                               
#include "symimp.h"
#ifdef _LINK_WITH_ABI_
//#include "abibase.h"  
#include "abiextfn.h"
#else
typedef int STATUS;
typedef unsigned char FLAG;
typedef struct {
    FLAG addrType;
    unsigned long  addr;
} ADDR;

/* All ABI routines Return codes */
typedef enum {
        ICE_OK              = 0x0,
        ICE_FAIL_STEP,                  //target cannot step
        ICE_FAIL_MEM_WRITE,             //memory write failure
        ICE_FAIL_MAP_INCLUDE,           //map status not included
        ICE_FAIL_MAP_BOUNDARY,          //map address boundary error
        ICE_NOT_FOUND       = 0x5,
        ICE_FOUND,
        ICE_TIME_OUT        = 0x7,
        ICE_PARA_ERROR      = 0x8,
        ICE_EP_RUNNING      = 0x10,
        ICE_TRACE_RUNNING   = 0x11,
        ICE_TRACE_READ_OVER = 0x12,
        ICE_COMMAND_INVALID = 0x13,

        ICE_FLASH_SW_ERROR  = 0x40,
        ICE_FLASH_EC_ERROR  = 0x41,
        ICE_FLASH_PRG_ERROR = 0x42,
        ICE_FLASH_REC_ERROR = 0x43,
		ICE_NO_RESPONSE		= 0xff
} RET_CODE;

#endif

                       /****************************
                        *                          *
                        *     LOCAL DEFINITIONS    *
                        *                          *
                        ****************************/
class SymUserVarTable userVariables;
extern int nErrorNum;      // global error number                       

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

                       /****************************
                        *                          *
                        *     LOCAL PROTOTYPES     *
                        *                          *
                        ****************************/


                       /****************************
                        *                          *
                        *      EXECUTABLE CODE     *
                        *                          *
                        ****************************/
/***************************************************************************
*                                                                          *
*  SymUserVarCreate - create a new user defined variable to table          *
*  parameter :                                                             *
*       str      variable name                                             *
*  return value :                                                          *
*       0  ---  OK                 -1  ---  failure                        *
*                                                                          *
***************************************************************************/
int SymUserVarTable::SymUserVarCreate(char *str)
{
    struct SymUserVarNode *node;     
    int nLen;
    
	if ( GOOD == IsPC(str) ) {
        nErrorNum = 0x4004;
        return(-1);
    }
		
    node = new SymUserVarNode;
    ASSERT( node );
    nLen = strlen( str );
    if ( nLen > MAX_USE_DEFINE_SYMBOL_LENGTH+1 ) 
    	nLen = MAX_USE_DEFINE_SYMBOL_LENGTH+1;
    node->name = new char[ nLen + 1 ];
    ASSERT( node->name );
    memcpy( node->name , str , nLen );
    node->name[nLen] = '\0';
    node->nValue = 0;
    return ( SymUserVarAddNode( node ) );
}

/***************************************************************************
*                                                                          *
*  SymUserVarDelete - Delete a user defined symbol in symbol table            *
*  parameter :                                                             *
*       str      symbol name                                               *
*  return value :                                                          *
*       0  ---  OK                 -1  ---  failure                        *
*                                                                          *
***************************************************************************/
int SymUserVarTable::SymUserVarDelete(char *str)
{
    struct SymUserVarNode *temp , *temp1 , *node;
    struct SymUserVarNodeIndex *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 = 0;
            delete nameIndexPtr;
            nameIndexPtr = 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->next;
        t1->node = namePtr;
        t1->num--;  
        if ( symno > 10 && t1->num <= 10 ) {
            SymUserVarRejustNameIndex();
        }
    }     
    else {
        temp1 = temp = t2->node;
        while( temp ) {
            if ( strcmp(str,temp->name)<=0 ) break;
            temp1 = temp;
            temp = temp1->next;
        }
        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->next != temp ) {
                temp1 = temp1->next;
            }
            temp1->next = node->next;
            t2->num--;             
            t2->node = node->next;
            if ( symno > 10 && t2->num <= 10 ) {
                SymUserVarRejustNameIndex();
            }
        }   
        else {
            if ( strcmp(str,temp->name)!=0 ) return(-1);
            symno--;             
            node = temp;
            temp1->next = node->next;
            t2->num--;
            if ( symno > 10 && t2->num <= 10 ) {
                SymUserVarRejustNameIndex();
            }
        }
    }
                    
    if ( node->name ) delete node->name;
    delete node;
    
    return( 0 );
}

/***************************************************************************
*                                                                          *
*  SymUserVarSearchNodeByName - Search a varaible node by name in symbol   *
*                               table                                      *
*  parameter :                                                             *
*       str      symbol name                                               *
*  return value :                                                          *
*       0  ---  OK                 -1  ---  failure                        *
*                                                                          *
***************************************************************************/
void SymUserVarTable::SymUserVarSearchNodeByName( char *str )
{
    struct SymUserVarNode *temp , *temp1;
    struct SymUserVarNodeIndex *t1 , *t2;
    char *pName;

    matchPtr = preMatchPtr = 0;
            
    if ( namePtr == 0 ) return;
    if ( str == 0 ) return;
    pName = new char[ strlen(str) + 1 ];
    if ( pName == 0 ) return;
    strcpy( pName , str );
    if ( strlen( pName ) > MAX_USE_DEFINE_SYMBOL_LENGTH+1 ) 
    	pName[MAX_USE_DEFINE_SYMBOL_LENGTH+1] = '\0';
    temp = temp1 = namePtr;
    t1 = t2 = nameIndexPtr;
    while ( t1 ) {
//        if ( strcmp(str,t1->node->name)<=0 ) break;
        if ( strcmp(pName,t1->node->name)<=0 ) break;
        t2 = t1;
        t1 = t2->next;
    }
    temp1 = temp = t2->node;
    while( temp ) {
//        if ( strcmp(str,temp->name)<=0 ) break;
        if ( strcmp(pName,temp->name)<=0 ) break;
        temp1 = temp;
        temp = temp1->next;
    }
    if ( temp == 0 ) {
    	delete pName;
    	return;
    }
//    if ( strcmp(str,temp->name)!=0 ) return;
    if ( strcmp(pName,temp->name)!=0 ) {
    	delete pName;
    	return;
    }                
    delete pName;
    preMatchPtr = temp1;
    matchPtr = temp;
}

void SymUserVarTable::SymUserVarRejustNameIndex(void)
{
    int i;
    struct SymUserVarNode *temp1;
    struct SymUserVarNodeIndex *t1 , *t2;

    t1 = nameIndexPtr; 
    nameIndexPtr->node = namePtr;
    temp1 = namePtr;
    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 SymUserVarNodeIndex;
            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;
        }
    }
}   

/***************************************************************************
*                                                                          *
*  SymUserVarAddNode - Add a new user defined symbol to table                 *
*  parameter :                                                             *
*       node     the node which will be added                              *
*  return value :                                                          *
*       0  ---  OK                 -1  ---  failure                        *
*                                                                          *
***************************************************************************/
int SymUserVarTable::SymUserVarAddNode( struct SymUserVarNode *node )
{           
    struct SymUserVarNode *temp , *temp1;
    struct SymUserVarNodeIndex *t1 , *t2;
    
    if ( namePtr == 0 ) {
        namePtr = node;
        nameIndexPtr = new SymUserVarNodeIndex;
        ASSERT( nameIndexPtr );
        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->next = namePtr;
        namePtr = node;
        t1->node = node;
        t1->num++;  
        if ( symno > 20 && t1->num > 30 ) {
            SymUserVarRejustNameIndex();
        }
    }     
    else {
        temp1 = temp = t2->node;
        while( temp ) {
            if ( strcmp(node->name,temp->name)<=0 ) break;
            temp1 = temp;
            temp = temp1->next;
        }
        if ( temp == 0 ) {
            symno++;
            temp1->next = node;
            t2->num++; 
            if ( symno > 20 && t2->num > 30 ) {
                SymUserVarRejustNameIndex();
            }
        }
        else {
            if ( strcmp(node->name,temp->name)==0 ) {
                nErrorNum = 0x4004;
                return(-1);   
            }
            symno++;
            node->next = temp1->next;
            temp1->next = node;
            t2->num++;
            if ( symno > 20 && t2->num > 30 ) {
                SymUserVarRejustNameIndex();
            }
        }
    }               
    
    return(0);
}                             
              
int SymUserVarTable::SymUserVarList( void )
{
    char temp[255];
    struct SymUserVarNode *tt;
    
    sprintf(temp , "User defined Variables : %d" , symno);
    SymShowLine( temp );
    if ( symno == 0 ) return 0;
    tt = namePtr ;
    while ( tt ) {
        sprintf(temp,"     %s = %d (0x%04x)",tt->name, 
        	tt->nValue, tt->nValue);
        SymShowLine( temp );
        tt = tt->next;
    }
    return(0);
}
              
void SymUserVarTable::SymUserVarClearUpNode()
{                         
    struct SymUserVarNode *temp , *temp1;
    
    temp = namePtr;
    while ( temp ) {
        if ( temp->name ) delete temp->name;
        temp1 = temp->next;
        delete temp;
        temp = temp1;
    }                   
    namePtr = 0;
    symno = 0;
    matchPtr = 0;
    preMatchPtr = 0;
}

void SymUserVarTable::SymUserVarClearUpIndex()
{    
    struct SymUserVarNodeIndex *temp , *temp1;
    
    temp = nameIndexPtr;
    while ( temp ) {
        temp1 = temp->next;
        delete temp;
        temp = temp1;
    }           
    nameIndexPtr = 0;
}

SymUserVarTable::~SymUserVarTable()
{
    SymUserVarClearUpNode();
    SymUserVarClearUpIndex();
}

int SymUserVarTable::IsPC(char *str)
{
	if ( 0 == str ) return FAILURE;
	if ( 0 == strcmp(str,"$PC") ) return GOOD;
	return FAILURE;
}
                   
int SymUserVarTable::SetPC(short value)
{
#ifdef _LINK_WITH_ABI_                
	unsigned int regValue;
	
    regValue = (unsigned int)value;
    if ( ICE_OK != emuSetReg(0,0,regValue) )
        return FAILURE;
#endif        
	return GOOD;
}

int SymUserVarTable::GetPC(short& value)
{
#ifdef _LINK_WITH_ABI_                
	U32 regValue;
	
    if (ICE_OK != emuGetReg(0 ,0, &regValue))
        return FAILURE;
    value = ( short ) regValue;
#else
	value = 0;    
#endif        
	return GOOD;
}

void SymUserVarTable::SymUserVarDeleteAll(void)
{
    SymUserVarClearUpNode();
    SymUserVarClearUpIndex();
}
 
int SymUserVarTable::SymUserVarGetValue(char *str,short& value)
{                    
	if ( GOOD == IsPC(str) ) {
		return GetPC(value);
	}
	SymUserVarSearchNodeByName( str );
	if ( 0 == matchPtr ) return FAILURE;
	value = matchPtr->nValue;
	return GOOD;
}

int SymUserVarTable::SymUserVarSetValue(char *str,short value)
{                    
	if ( GOOD == IsPC(str) ) {
//		return SetPC(value);
		return FAILURE;
	}
	SymUserVarSearchNodeByName( str );
	if ( 0 == matchPtr ) return FAILURE;
	matchPtr->nValue = value;
	return GOOD;
}

int WINAPI GetUserVarValue(char *str,short& value)
{
	return userVariables.SymUserVarGetValue(str , value);
} 

int WINAPI SetUserVarValue(char *str,short value)
{
	return userVariables.SymUserVarSetValue(str , value);
} 
/******************************** E O F ***********************************/
