/***************************************************************************
** 
** File name : dadob.CPP               
** Author:John Zhou
** Description:
**    class implement of dad class
**
**
**    Finished date: 1996.9
**
**
**    Copyright (C) 1995 Microtek International, Inc.
**    All Rights Reserved
**
****************************************************************************/

#include "stdafx.h"        
#include "dadob.h"

/********************** for class CBaseDAD *******************************/
// 
//	CLASS NAME : CBaseDAD
//
//  HEAD FILE  : DADOB.H
//
/**************************************************************************/

BOOL CBaseDAD :: Asm(CBaseDADMem& mem)
{
	if (!PreAsm(mem)) {
		m_nError = ERR_PRE;
		return FALSE;
	}
	
	if (!ProcessAsm(mem)) {
		m_nError = ERR_PROCESS;
		return FALSE;
	}	
                              
	if (!AfterAsm(mem)) {
		m_nError = ERR_AFTER;
		return FALSE;
	} 
	
	m_nError = ERR_NO;
	return TRUE;
}

BOOL CBaseDAD :: Das(CBaseDADMem& mem)
{
	if (!PreDisasm(mem)) {
		m_nError = ERR_PRE;
		return FALSE;
	}
	
	if (!ProcessDisasm(mem)) {
		m_nError = ERR_PROCESS;
		return FALSE;
	}	
	if (!AfterDisasm(mem)) {
		m_nError = ERR_AFTER;
		return FALSE;
	} 
	m_nError = ERR_NO;
	return TRUE;
}	                             

/********************** for class ppCDADValue *******************************/
// 
//	CLASS NAME : CDADValue
//
//  HEAD FILE  : DADOB.H
//
/**************************************************************************/
BOOL CDADValue::StrToValue()
{             
	int nLen = m_strValue.GetLength();
	int i;
	BYTE bTmp;
	
	if ( 0 == nLen ) return FALSE;
	m_strValue.MakeUpper();
	for(i=nLen-1;i>=0;i--) {
		bTmp = 0;
		//check syntax 
		char tmpC = m_strValue[i];
	    if( (!(m_strValue[i]>='0' && m_strValue[i]<='9')) && 
	        (!(m_strValue[i]>='A' && m_strValue[i]<='F')) ) {
	        Clear();
	    	return FALSE;
	    }	    
	    if(m_strValue[i]>='A' && m_strValue[i]<='F') 
	    	bTmp = (BYTE)(m_strValue[i]-'A'+10);
	    else bTmp = (BYTE)(m_strValue[i]-'0');	
	    if( 0 != i) {
	    	//get high 4 bit of this byte
	    	i--;                                
	    	//check syntax
		    if( !(m_strValue[i]>='0' && m_strValue[i]<='9') && 
		        !(m_strValue[i]>='A' && m_strValue[i]<='F') ) {
		        Clear();
		    	return FALSE;
		    }	
		    if(m_strValue[i]>='A' && m_strValue[i]<='F') 
		    	bTmp = (BYTE)(bTmp + (BYTE)((m_strValue[i]-'A'+10)<<4));
		    else bTmp = (BYTE)(bTmp + (BYTE)((m_strValue[i]-'0')<<4));	
	    	
	    } 
	    
	    m_bWidth++;
	    Add(bTmp);
	}
	
	ASSERT (m_bWidth == GetSize());
        //remove head 0
        for (i=m_bWidth-1;i>=1;i--) 
            if ( 0 == CByteArray::GetAt(i) ) {
                    RemoveAt(i);
                    m_bWidth--;
            } else {
                    break;
            }
	
	ASSERT (m_bWidth == GetSize());
	return TRUE;
 }                          
                
//convert decimal      
BOOL CDADValue::StrToValueDec()
{             
	int nLen = m_strValue.GetLength();
	int i;
	BYTE bTmp;
	DWORD dwTmp;
	
	if ( 0 == nLen ) return FALSE;
	
    i = sscanf( m_strValue.GetBuffer(nLen+2), "%ld", &dwTmp );
    m_strValue.ReleaseBuffer();                              
    if ( 1 != i ) return FALSE;
    
    bTmp = (BYTE)(dwTmp&0x000000ff);
    m_bWidth++;
	Add(bTmp);
	bTmp = (BYTE)((dwTmp&0x0000ff00)>>8);
    m_bWidth++;
	Add(bTmp);
	bTmp = (BYTE)((dwTmp&0x00ff0000)>>16);
    m_bWidth++;
	Add(bTmp);  
	bTmp = (BYTE)((dwTmp&0xff000000)>>24);
    m_bWidth++;
	Add(bTmp);
    
    //remove head 0
    for (i=m_bWidth-1;i>=1;i--) 
        if ( 0 == CByteArray::GetAt(i) ) {
                RemoveAt(i);
                m_bWidth--;
        } else {
                break;
        }
	
	ASSERT (m_bWidth == GetSize());
	return TRUE;
 }                          

 
BOOL CDADValue::ValueToStr()
{               
	BYTE pcTmp[30];                 
	ASSERT (m_bWidth == GetSize());
	
	if ( 0 == m_bWidth ) return FALSE;
	
	int j=0; BYTE bTmp,bTmpH,bTmpL;
	for (int i=m_bWidth-1;i>=0;i--) {       
		bTmp = GetAt(i);
		if(j==0 && bTmp>=0xa0) {
			pcTmp[j++] = '0';
		}                         
		bTmpH = (BYTE)(bTmp>>4); bTmpL = (BYTE)(bTmp&0x0f);
		pcTmp[j++]=(BYTE)((bTmpH<=9)?'0'+bTmpH:'A'+bTmpH-10);
		pcTmp[j++]=(BYTE)((bTmpL<=9)?'0'+bTmpL:'A'+bTmpL-10);
	}
	pcTmp[j] = 0;
	m_strValue = (char*)pcTmp;
	return TRUE;	     
		
 }                                

//convert decimal
BOOL CDADValue::ValueToStrDec()
{                                        
	char pcTmp[25];                 
	ASSERT (m_bWidth == GetSize());
	m_strValue = "";
	if ( 0 == m_bWidth ) return FALSE;
	
	DWORD dwTmp = GetDWord();
	switch (m_bWidth) {
		case 1 : sprintf(pcTmp,"%02d",dwTmp); break;
		case 2 : sprintf(pcTmp,"%04d",dwTmp); break;
		case 3 : sprintf(pcTmp,"%06d",dwTmp); break;
		case 4 : sprintf(pcTmp,"%08d",dwTmp); break;
		default : ASSERT(FALSE);
	}	
		
	m_strValue += pcTmp;
	
	if(0 == m_strValue.GetLength()) return FALSE;
	
	return TRUE;	     
 }                                

 
void CDADValue::SetWord(WORD wValue) 
{
	Clear();                   
	Add((BYTE)((wValue<<8)>>8));
	m_bWidth++;
	Add((BYTE)(wValue>>8));
	m_bWidth++;
 }

void CDADValue::SetDWord(DWORD dwValue) 
{
	Clear();                   
	Add((BYTE)((dwValue<<24)>>24));
	Add((BYTE)((dwValue<<16)>>24));
	Add((BYTE)((dwValue<<8)>>24));
	Add((BYTE)(dwValue>>24));
	m_bWidth+=4;
 }       

void CDADValue::AddWord(WORD wValue) 
{
	Add((BYTE)((wValue<<8)>>8));
	m_bWidth++;
	Add((BYTE)(wValue>>8));
	m_bWidth++;
 }       

void CDADValue::AddDWord(DWORD dwValue) 
{
	Add((BYTE)((dwValue<<24)>>24));
	Add((BYTE)((dwValue<<16)>>24));
	Add((BYTE)((dwValue<<8)>>24));
	Add((BYTE)(dwValue>>24));
	m_bWidth+=4;
 }              
 
void CDADValue::Set24(DWORD dwValue)
{                   
	
    SetWord((WORD)(dwValue&0x0000ffff));
    AddByte((BYTE)((dwValue&0x00ff0000)>>16));
 } 
 
void CDADValue::Add24(DWORD dwValue)
{ 
    AddWord((WORD)(dwValue&0x0000ffff));
    AddByte((BYTE)((dwValue&0x00ff0000)>>16));
 } 


DWORD CDADValue::Get24() 
{       
	DWORD pdwTmp[7];
	pdwTmp[6] = 0;
	for (int i=0; i<GetSize() && i<3; i++) {
		pdwTmp[i] = GetAt(i);
		pdwTmp[6] += pdwTmp[i]<<(8*i);
	}               
	
	return pdwTmp[6];						   
 }       

DWORD CDADValue::GetDWord() 
{                    
	DWORD pdwTmp[7];
	pdwTmp[6] = 0;
	for (int i=0; i<GetSize() && i<4; i++) {
		pdwTmp[i] = GetAt(i);
		pdwTmp[6] += pdwTmp[i]<<(8*i);
	}               
	
	return pdwTmp[6];
 }
 

/********************** for class CAnalyseInstruction *******************************/
// 
//	CLASS NAME : CAnalyseInstruction
//
//  HEAD FILE  : DADOB.H
//
/**************************************************************************/
void CAnalyseInstruction::Clear() {
	int i;		                       
		                       
	m_Instruction = "";
	m_CodeSet.RemoveAll();
	m_bNum = 0;
	m_bNeedNum = 0;
	m_isDirtyResult = FALSE;
	m_nInstructionType = TYPE_NORMAL;
	
	for (i=m_OpSetSet.GetSize()-1; i>=0; i--)	{
		delete m_OpSetSet[i];
	}
	m_OpSetSet.RemoveAll();       
	for (i=m_OpDealSet.GetSize()-1; i>=0; i--)	{
		delete m_OpDealSet[i];
	}
	m_OpDealSet.RemoveAll(); 
	for (i=m_NextAddrSet.GetSize()-1; i>=0; i--)	{
		delete m_NextAddrSet[i];
	}
	m_NextAddrSet.RemoveAll(); 
	
	
	};                                           
	
BOOL CAnalyseInstruction::Do(CDADAddress* pCurrentAddr)
{                                       
	ASSERT ( 0 != m_OpDealSet.GetSize() );
	/*
	if(!m_isAsm) { 
		ASSERT( 0 == m_Instruction.GetSize() );
		 
	} else {
		ASSERT( 0 == m_CodeSet.GetSize() ); 
	}*/
	
	int nIndexInstr = 0;
	int nIndexCode = 0;
	for (int i=0; i<m_OpDealSet.GetSize(); i++) {                  
		if(!((COpDeal*)(m_OpDealSet[i]))->Do(*this,pCurrentAddr)) {
		    m_nErrCode = ((COpDeal*)(m_OpDealSet[i]))->GetErrCode();
			return FALSE;		 	
		}				      
	}	 				  
		 				  
	ASSERT( m_bNum == m_CodeSet.GetSize() );
	
	return TRUE;
	
 }      
 
CString CAnalyseInstruction::GetCodeStr() {

	char strTmp[30],ch;         
	BYTE bTmp[15];
	int nLen(0),i,j;
	
	for (i = 0; i<m_CodeSet.GetSize(); i++) {
		bTmp[nLen++] =(BYTE)m_CodeSet[i];
	}
	j = 0;  
	for (i = 0; i<nLen; i++) {        
		ch = (BYTE)(bTmp[i]>>4);
		strTmp[j++]=(BYTE)((ch<=9)?'0'+ch:'A'+ch-10);
		ch = (BYTE)(bTmp[i]&0x0f);
		strTmp[j++]=(BYTE)((ch<=9)?'0'+ch:'A'+ch-10);
	}
	strTmp[j] = 0;  
	
	return m_strCodeHead + strTmp;
} 

DWORD CAnalyseInstruction::GetLeftCodeLen() {
	ASSERT (m_bNum >= m_bNeedNum);
	return m_bNum - m_bNeedNum; 
} 

/********************** for class CInstruction *******************************/
// 
//	CLASS NAME : CInstruction
//
//  HEAD FILE  : DADOB.H
//
/**************************************************************************/
void CInstruction::operator=(const CString& str)
{                                 
	Clear();          
	m_strTotal = str;             
	//m_strTotal.MakeUpper();
	
	Devide();
 }

void CInstruction::operator=(const char* str)
{                                   
	Clear();
	CString strTmp = str;
	//strTmp.MakeUpper();
	m_strTotal = strTmp;
	Devide();
 }  

void CInstruction::Devide()
{   
	CString strTmp = "";   
	int i = 0;                      
	BOOL isRe = FALSE;
	int nLen = m_strTotal.GetLength();
	if ( 0 == nLen) return;
	
	//remove space
	while (i<nLen && m_cDevide1 == m_strTotal[i]) i++;
	
	//GET HEAD INSTRUCTION
	while (i<nLen && m_cDevide1!=m_strTotal[i] && m_cDevide2!=m_strTotal[i]) {
		strTmp += m_strTotal[i];
		i++;
	}                
	if ("" == strTmp) return;
	Add(strTmp);
	
	//remove between head instruction and opcode
	while (i<nLen && m_cDevide1==m_strTotal[i]) i++;
	
	//Get opcode
	
	while (i<nLen) {
		strTmp = "";
		isRe = FALSE;
		while (i<nLen && m_cDevide1!=m_strTotal[i] 
			   && m_cDevide2!=m_strTotal[i]) {
			strTmp += m_strTotal[i];
			i++;
		}
		if ("" == strTmp) return;
		Add(strTmp);
		
		while (i<nLen && (m_cDevide1==m_strTotal[i] 
			   || m_cDevide2==m_strTotal[i])) {
			if (m_cDevide2 != m_cDevide1 && m_cDevide2==m_strTotal[i]) {
				if(isRe) {
					Clear();
					return;
				}          
				isRe = TRUE;	
			}
			i++;
		}          
		
	}
		
 }  

//for value convert (str to digit or digit to str)
//*********only for HEX***********
 
/********************** for class CDADAddress *******************************/
// 
//	CLASS NAME : CDADAddress
//
//  HEAD FILE  : DADOB.H
//
/**************************************************************************/
//deal with HEX DAD address
BYTE CDADAddress::operator<<(CString str) 
{                        
	//get rid of last 'h'
	if( str.GetLength() >0 &&
		'H' ==  toupper(str[str.GetLength()-1]) ) {
		str = str.Left(str.GetLength()-1);
	}
		
	if(!GetPrefix(str)) {
		Clear();
		return 0;
	}
	return *(CDADValue*)(this)<<(str);
 }

BYTE CDADAddress::operator<<(char* pCh) 
{
	CString str = pCh;
	if( str.GetLength() >0 &&
		'H' ==  toupper(str[str.GetLength()-1]) ) {
		str = str.Left(str.GetLength()-1);
	}              
		
	if(!GetPrefix(str)) {
		Clear();
		return 0;
	}
	return *(CDADValue*)(this)<<(str);
 }  

CString CDADAddress::GetStr() {
	//add last 'h'        
    //if ("" == CDADValue::GetStr()) return "";
	return AddPrefix() + CDADValue::GetStr()+'H';
}   

void CDADAddress::SetByte(BYTE bAttribute,BYTE bValue) 
{
	CDADValue::SetByte(bValue);
	m_bAttribute = bAttribute;
 }

void CDADAddress::AddByte(BYTE bValue) 
{
	CDADValue::AddByte(bValue);
 }                    

void CDADAddress::SetWord(BYTE bAttribute,WORD wValue) 
{
	CDADValue::SetWord(wValue);
	m_bAttribute = bAttribute;
 }

void CDADAddress::AddWord(WORD wValue) 
{
	CDADValue::AddWord(wValue);
 }

void CDADAddress::SetDWord(BYTE bAttribute,DWORD dwValue) 
{
	CDADValue::SetDWord(dwValue);
	m_bAttribute = bAttribute;
 }

void CDADAddress::AddDWord(DWORD dwValue) 
{
	CDADValue::AddDWord(dwValue);
 }   
 
void CDADAddress::Set24(BYTE bAttribute,DWORD dwValue) 
{   
	CDADValue::Set24(dwValue);
	m_bAttribute = bAttribute;
	                             
 }
    
/********************** for class CDADDOLLARS *******************************/
// 
//	CLASS NAME : CDADDOLLARS
//
//  HEAD FILE  : DADOB.H
//
/**************************************************************************/
//deal with HEX DAD address

//for operator '$'
BOOL CDADDOLLARS::operator<<(CString str)
{                                          
	Clear();
	m_strTotal = str;                
	WORD wLen = (WORD)(m_strTotal.GetLength());
	if ( 0 == wLen || 2 == wLen) return FALSE;
	
	if ('$' != m_strTotal[0]) return FALSE;
	
	if ( 1 == wLen ) {
		m_cOperator = '+';
		m_Offset<<0;
		return TRUE;
	}
	
	                          
	switch ( m_strTotal[1] ) {
		case '+' : m_cOperator = '+'; break;
		case '-' : m_cOperator = '-'; break;
		default  : return FALSE;
	}                           
	CString strTmp = m_strTotal.Right(m_strTotal.GetLength()-2);
	
	if ( 'H' == (toupper(strTmp[strTmp.GetLength()-1])) ){
		if ( 1 == strTmp.GetLength()) return FALSE;
		strTmp = strTmp.Left(strTmp.GetLength()-1);	    
	}	                         
	if ( (m_Offset<<strTmp) == 0 ) return FALSE;
	return TRUE;	                               
	
 }

/***********************  end of file **********************************/
