/***************************************************************************
**
**    $Header:   D:/ECB2S/SRC/LOG/C51ADR.CPP   1.2.1.5   17 Apr 1997 15:42:42   ZJRD  $
**
**    $Log:   D:/ECB2S/SRC/LOG/C51ADR.CPP  $
** 
**    Rev 1.2.1.5   17 Apr 1997 15:42:42   ZJRD
** No change.
** 
**    Rev 1.2.1.4   16 Apr 1997 10:17:18   ZJRD
** No change.
** 
**    Rev 1.2.1.3   10 Apr 1997 15:28:40   ZJRD
** 2.09F
** 
**    Rev 1.2.1.1   03 Apr 1997 15:10:08   ZJRD
** No change.
** 
**    Rev 1.2.1.0   28 Mar 1997 10:15:08   ZJRD
** easy pack sld 2.09d
** 
**    Rev 1.1   19 Mar 1997 11:26:22   ZJRD
** No change.
** 
**    Rev 1.0   12 Mar 1997 14:44:52   ZJRD
** Initial revision.
** 
**    Rev 1.7.1.0.1.2   09 Dec 1996 10:14:20   ZJRD
** EasyPack/SLD Version 2.0P
** 
**    Rev 1.7.1.0.1.0   11 Nov 1996 12:57:36   ZJRD
** EasyPack/SLD Version 2.01
** 
**    Rev 1.7.1.4   09 Sep 1996 13:13:52   ZJRD
** No change.
** 
**    Rev 1.7.1.3   05 Sep 1996 11:25:24   ZJRD
** No change.
** 
**    Rev 1.7.1.2   02 Sep 1996 09:52:32   ZJRD
** No change.
** 
**    Rev 1.7.1.1   28 Aug 1996 15:44:58   ZJRD
** No change.
** 
**    Rev 1.7.1.0   12 Aug 1996 10:50:10   ZJRD
** EasyPack/SLD Version 1.98
** 
**    Rev 1.5   05 Jun 1996 14:52:18   ZJRD
** No change.
** 
**    Rev 1.4   29 May 1996 09:28:28   ZJRD
** No change.
** 
**    Rev 1.3   16 May 1996 09:08:50   ZJRD
** EasyPack/SLD Version 1.94
** 
**    Rev 1.2   10 May 1996 09:08:18   ZJRD
** EasyPack/SLD Version 1.93
** 
**    Rev 1.1   02 May 1996 10:26:00   ZJRD
** EasyPack/SLD Version 1.92
** 
**    Rev 1.1   18 Apr 1996 12:56:22   Shirley
** EasyPack/SLD Version 1.91
** 
**    Rev 1.0   12 Apr 1996 10:35:52   Shirley
** Initial revision.
** 
****************************************************************************/

/****************************************************************************
**
**  Name:      C51adr.cpp
**
**  Description:  The sub class C51adr deprived from the CFormatAddress
**                This class is process the 51 base family address
**                51 base family address has the format as following
**                      prefix:address
**                prefix is the space area. Those are :
**                      p: program
**                      x: external
**                      i: internal
**                      b: bit area
**                      r: SFR
**                The address has two format: Hex and Dec
**                      Hex has the prefix before address that is 0x
**                      Dec has no prefix
**
**                Another : the address is a symbol. The symbol has the format
**                as following:
**                      #ModuleName#SymbolName etc.
**                The process must deal all the statment described as before.
**
**  Status: Initialization
**          1996/02/27        Daniel Lin
**
**  Copyright (C) 1996 Microtek International.  All rights reserved.
*****************************************************************************

                       /****************************
                        *                          *
                        *       INCLUDE FILES      *
                        *                          *
                        ****************************/
#include "stdafx.h"                        
#include "address.h"                // Include main head file

                       /****************************
                        *                          *
                        *    EXTERNAL VARIABLES    *
                        *                          *
                        ****************************/
//extern int GetMemoryRange(CPUMEMORYRANGE *stRange);
extern int g_nBankNum; 
extern int GetCurrentBank(void);

                       /****************************
                        *                          *
                        *     LOCAL DEFINITIONS    *
                        *                          *
                        ****************************/                        
char  *SpaceStr[10] = {
             "UndefineSpace",       // Undefine space
             "Program",             // Program area
             "External(Data)",      // External area(Data)
             "Internal(OnChip)",    // Internal area(On chip)
             "SFR",                 // Special function register area
             "Bit",                 // Bit area
             "Bank1",				// Program area bank1	
             "Bank2",               // Program area bank2
             "Bank3",               // Program area bank3
             "Bank4",               // Program area bank4
      };

char  *SpacePrefix[10] = {
             "",        // Undefine space
             "P",       // Program area
             "X",       // External area(Data)
             "I",       // Internal area(On chip)
             "R",       // Special function register area
             "B",       // Bit area
             "P0",      // Program area bank1
             "P1",      // Program area bank2
             "P2",      // Program area bank3
             "P3",      // Program area bank4
      };

                       /****************************
                        *                          *
                        *       GLOBAL VARS        *
                        *                          *
                        ****************************/
ADDR_SIZE  dwpMax;        // program  max address
ADDR_SIZE  dwpMin;        // program  min address
ADDR_SIZE  dwxMax;        // external max address
ADDR_SIZE  dwxMin;        // external min address
ADDR_SIZE  dwiMax;        // internal max address
ADDR_SIZE  dwiMin;        // internal min address
ADDR_SIZE  dwrMax;        // SFR max address
ADDR_SIZE  dwrMin;        // SFR min address
ADDR_SIZE  dwbMax;        // bit max address
ADDR_SIZE  dwbMin;        // bit min address

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

                       /****************************
                        *                          *
                        *      EXECUTABLE CODE     *
                        *                          *
                        ****************************/

/****************************************************************************
**  Name:   C51Address
**
**  Description: Constructor
**
**  Parameters:
**     input:  any possible
**
**     output: none
**
*****************************************************************************/

// From CString
//
C51Address::C51Address(const CString &str)
{
   Initialize();

   m_strOriginAdr = str;   // Only set the origin string
   m_nDefaultIsHex = 0;
   IsString = TRUE;        // Construct from string
}

// From char*
//
C51Address::C51Address(const LPSTR str)
{
   Initialize();
   
   m_strOriginAdr = str;   // Only set the origin string
   m_nDefaultIsHex = 0;
   IsString = TRUE;        // Construct from string
}

// From CString
//
C51Address::C51Address(const CString &str, const UINT isHex)
{
   Initialize();

   m_strOriginAdr = str;   // Only set the origin string
   m_nDefaultIsHex = isHex;
   IsString = TRUE;        // Construct from string
}

// From char*
//
C51Address::C51Address(const LPSTR str, const UINT isHex)
{
   Initialize();
   
   m_strOriginAdr = str;   // Only set the origin string
   m_nDefaultIsHex = isHex;   
   IsString = TRUE;        // Construct from string
}

// Can not construct from only numberica, must construct form the ADDR struct
// From DWORD(no use)
//
C51Address::C51Address(ADDR_SIZE dw)
{
   Initialize();
   m_dwAddress = dw;
}

// From ADDR struct
//
C51Address::C51Address(ADDRESS adr)
{
   Initialize();
   m_dwAddress = adr.adrAddress;
   m_enumSpace = adr.adrSpace;
   m_strSpace  = SpaceStr[m_enumSpace];
   m_strPrefix = SpacePrefix[m_enumSpace];
}

// Copy constructor
//
/*
C51Address::C51Address(const C51Address &c51adr)
{
   Initialize();
   // Can not copy the m_strOriginAdr because the c51adr has checked OK
   m_strSpace     = c51adr.m_strSpace;    // Space string
   m_enumSpace    = c51adr.m_enumSpace;   // Space style
   m_strPrefix    = c51adr.m_strPrefix;   // prefix string
   m_strAddress   = c51adr.m_strAddress;  // address text string
   IsString       = TRUE;                 // Construct from string
}
*/  
  
/****************************************************************************
**  Name:   Initialize
**
**  Description: Initialize the C51Address. Call this function before any
**               Implenmentation but after the SetAdrRange();
**
**  Parameters:
**     input: none
**
**     output: none
*****************************************************************************/

void
C51Address :: Initialize()
{
   // Init base class 
      m_strOriginAdr = "";    // Original address string. No any change
                              // Get from construct or Set function
      m_dwAddress = 0;        // The data of address(converted form string,
                              // or get from constructor)
                              // After converted successful, the m_dwAddress
                              // is the address.
                              // In
      m_strPrefix = "";       // Prefix front the address.
                              // Such as in 51 base family the prefix of
                              // p:0x987 is "p"
                              // In 86 family, the prefix is the segment or
                              // descriptor
                              // etc;
      m_strAddress = "";      // After split the prefix,
                              // In 51 family, it is the absoluted address
                              // In 86 family, it is the offset
                              // etc;

      m_strAddressHex = "";   // The converted hex address
      m_strAddressDec = "";   // The converted dec address
   
      m_strSpace     = "";
      m_enumSpace    = SPACE_UNDEFINE;
      IsString       = FALSE;
      m_enumRetCode  = ADR_OK;
      m_nDefaultIsHex = 0;
}


/****************************************************************************
**  Name:   ConvertCheck
**
**  Description:  The virtual function deprived from parent class.
**                Call this function to convert the address between text 
**                string and numberic. Check the address.
**                This function call the main processor -- Process()
**
**  Parameters:
**     input:  none
**
**     output: none
*****************************************************************************/

BOOL
C51Address :: ConvertCheck()
{
   char  *lpszTemp1;
   FORMATTYPE ft;
   BOOL  bProcessOk = FALSE;

   if (IsString) {            // Construct from string
      // If the input text string is empty, return false
      if (m_strOriginAdr.IsEmpty()) {
         m_enumRetCode = ADR_EMPTY;
         return FALSE;
      }         
      
      lpszTemp1 = new char[m_strOriginAdr.GetLength()+2];
      ASSERT(NULL != lpszTemp1);
      if (NULL == lpszTemp1) {
         AfxMessageBox("memory alloc error");
         return FALSE;
      }         
      memset(lpszTemp1, 0, m_strOriginAdr.GetLength()+2);
      strcpy(lpszTemp1, m_strOriginAdr.GetBuffer(m_strOriginAdr.GetLength()));
      
      SkipHeadWS(lpszTemp1);     // Skip the leading white space
      CutTailWS(lpszTemp1);      // Skip the tail white space

      if (!SplitPrefix(lpszTemp1)) { // Split the prefix and the address text
         delete []lpszTemp1;
         m_enumRetCode = ADR_FORMATERROR;
         return FALSE;
      }
      // Has already set m_enumSpace, m_strSpace, m_strAddress by SplitPrefix
      delete []lpszTemp1;
      
	   if ( (m_enumSpace >= SPACE_BANK1) && (m_enumSpace <= SPACE_BANK4) ) {
			if ( g_nBankNum == 2 ) {   
				if ( (m_enumSpace == SPACE_BANK3) ||
			     	  (m_enumSpace == SPACE_BANK4) ) { 
					m_enumRetCode = ADR_BANKERROR;
					return FALSE;     
				}     
			}			
		}   
/*		
		if ( m_enumSpace == SPACE_PROGRAME ) {
			if ( g_nBankNum != 0 ) {
				m_enumSpace = (ADDR_SPACE) (GetCurrentBank());
			}
		}          
*/      
      ft = IsWhichFormat();
      
      CFormatHexStr   fmtHex(m_strAddress);
      CFormatDecStr   fmtDec(m_strAddress);
      CFormatSymbol   fmtSymbol(m_strAddress);

      switch (ft) {
         case  IS_HEX:          
               bProcessOk = Process(&fmtHex);
               if (!bProcessOk) {
                  m_enumRetCode = ADR_INVALIDCHAR;
                  return FALSE;
               }
               else {                             
                  m_strAddressHex = fmtHex.GetHexString();
                  m_dwAddress     = fmtHex.GetAddress();
               }
               /*
               strcpy(tempAddr,
                      m_strAddress.GetBuffer(m_strAddress.GetLength())+2);
               SkipHeadZero(tempAddr);                       
               if (!CheckLength(IS_HEX, tempAddr)) {
                  m_enumRetCode = ADR_OVERFLOW;                  
                  return FALSE;
               }
               delete []tempAddr;
               */
               break;

         case  IS_DEC:
               bProcessOk = Process(&fmtDec);
               if (!bProcessOk) {
                  m_enumRetCode = ADR_INVALIDCHAR;
                  return FALSE;
               }
               else {
                  m_strAddressDec = fmtDec.GetDecString();
                  m_dwAddress  = fmtDec.GetAddress();
               }
               /*
               strcpy(tempAddr,
                       m_strAddress.GetBuffer(m_strAddress.GetLength()));
               SkipHeadZero(tempAddr);
               if (!CheckLength(IS_DEC, tempAddr)) {
                  m_enumRetCode = ADR_OVERFLOW;                  
                  return FALSE;
               }
               */
               break;
               
         case  IS_SYM:
               fmtSymbol.m_uSymData = 0;             // Symbol 0
               if (SPACE_UNDEFINE != m_enumSpace) {
                  m_enumRetCode = ADR_FORMATERROR;
                  return FALSE;   
               }
               bProcessOk = Process(&fmtSymbol);
               if (!bProcessOk) {
                  m_enumRetCode = ADR_NOSYMBOL;
                  return FALSE;
               }
               else {
                  m_dwAddress  = (DWORD)fmtSymbol.GetAddress();
                  m_enumSpace = (ADDR_SPACE)fmtSymbol.GetSpace();
               }
               break;                       
         
         case  IS_SYM_DATA:
               fmtSymbol.m_uSymData = 1;             // Symbol Data 1
               if (SPACE_UNDEFINE != m_enumSpace) {
                    m_enumRetCode = ADR_FORMATERROR;
                    return FALSE;   
               }
               bProcessOk = Process(&fmtSymbol);
               if (!bProcessOk) {
                  m_enumRetCode = ADR_NOSYMBOL;
                  return FALSE;
               }
               else {
                  m_dwAddress  = (DWORD)fmtSymbol.GetAddress();
                  m_enumSpace = SPACE_UNDEFINE; //(ADDR_SPACE)fmtSymbol.GetSpace();
               }
               break;                       
               
         case  IS_UNKNOWN:
               return FALSE;         
      }
   }
   else {               // Construct from others
      CFormatNumber   fmtNumber(m_dwAddress);
      
      bProcessOk = Process(&fmtNumber);
      if (!bProcessOk) {
         m_enumRetCode = ADR_INVALIDCHAR;
         return FALSE;
      }
      else {
         m_strAddressHex = fmtNumber.GetHexString();
         m_strAddressDec = fmtNumber.GetDecString();
      }
   }

   // Check the range
   //
   if (SPACE_UNDEFINE != m_enumSpace) {
      switch(m_enumSpace) {
         case  SPACE_PROGRAME  :
               if (m_dwAddress > dwpMax || m_dwAddress < dwpMin) {
                  m_enumRetCode = ADR_OUTRANGE;
                  return FALSE;
               }
               break;
         
         case  SPACE_EXTERNAL  :
               if (m_dwAddress > dwxMax || m_dwAddress < dwxMin) {
                  m_enumRetCode = ADR_OUTRANGE;
                  return FALSE;
               }
               break;

         case  SPACE_INTERNAL  :
               if (m_dwAddress > dwiMax || m_dwAddress < dwiMin) {
                  m_enumRetCode = ADR_OUTRANGE;
                  return FALSE;
               }
               break;

         case  SPACE_SFR       :
               if (m_dwAddress > dwrMax || m_dwAddress < dwrMin) {
                  m_enumRetCode = ADR_OUTRANGE;
                  return FALSE;
               }
               break;

         case  SPACE_BIT       :
               if (m_dwAddress > dwbMax || m_dwAddress < dwbMin) {
                  m_enumRetCode = ADR_OUTRANGE;
                  return FALSE;
               }
               break;
         
         case  SPACE_BANK1:      
               if (m_dwAddress > dwpMax || m_dwAddress < dwpMin) {
                  m_enumRetCode = ADR_OUTRANGE;
                  return FALSE;
               }
               break;     
               
         case  SPACE_BANK2:      
               if (m_dwAddress > dwpMax || m_dwAddress < dwpMin) {
                  m_enumRetCode = ADR_OUTRANGE;
                  return FALSE;
               }
               break;
               
         case  SPACE_BANK3:      
               if (m_dwAddress > dwpMax || m_dwAddress < dwpMin) {
                  m_enumRetCode = ADR_OUTRANGE;
                  return FALSE;
               }
               break;
               
         case  SPACE_BANK4:      
               if (m_dwAddress > dwpMax || m_dwAddress < dwpMin) {
                  m_enumRetCode = ADR_OUTRANGE;
                  return FALSE;
               }
               break;

      }
   }

   m_enumRetCode = ADR_OK;
   
   return TRUE;
}

/****************************************************************************
**  Name:   Process
**
**  Description: Process the format. Call the format Convert() processor
**
**  Parameters:
**     input:  CFormatType &format
**
**     output: BOOL  TRUE if convert successful
*****************************************************************************/

BOOL
C51Address :: Process(CFormatType *format)
{
   format->Convert();
   return format->m_bIsOk;
   // if m_IsOk is FALSE, the format may include invalid char
}

/****************************************************************************
**  Name: SplitPrefix
**
**  Description: Split the origin address text string. Set the m_strAddress
**               and m_strPrefix
**
**  Parameters:
**     input:    char *lpsz
**
**     output:   BOOL   the format is correct, return TRUE
*****************************************************************************/

BOOL
C51Address :: SplitPrefix(const char* lpsz)
{
   int   nCount = 0;
   int   nstrLength = strlen(lpsz);
   char  *lpszPrefix;
   char  *lpszAddr;
      
   do {
      if (':' == lpsz[nCount]) {
         lpszPrefix = new char[nCount+1];
         if (NULL == lpszPrefix)
            return FALSE;
         memset(lpszPrefix, 0, nCount+1);   
         strncpy(lpszPrefix, lpsz, nCount);
         lpszAddr = new char[nstrLength-nCount+1];
         if (NULL == lpszAddr)
            return FALSE;
         memset(lpszAddr, 0, nstrLength-nCount+1);   
         strcpy(lpszAddr, lpsz+nCount+1);
         
         if (0 == strlen(lpszAddr)) {
            delete []lpszPrefix;
            delete []lpszAddr;
            return FALSE;
         }            
         else   
            m_strAddress= lpszAddr;
         m_strPrefix = lpszPrefix;            
         
         // Process the case: "p   :   0x100"
         // Area has tail space
         //
         if (strlen(lpszPrefix) > 2) {
            delete []lpszPrefix;
            delete []lpszAddr;
            return FALSE;            
         }
                  
         if (' ' == lpszPrefix[strlen(lpszPrefix)-1]) {
            delete []lpszPrefix;
            delete []lpszAddr;
            return FALSE;            
         }
         // Address string has leading space           
         //
         if (' ' == lpszAddr[0]) {
            delete []lpszPrefix;
            delete []lpszAddr;
            return FALSE;
         }
                    
         delete []lpszPrefix;
         delete []lpszAddr;
      }
      nCount++;
   }while ((nCount < nstrLength) && (':' != lpsz[nCount-1]));

   if ("" == m_strPrefix) {
      m_strAddress = lpsz;    // no any prefix
      m_enumSpace = SPACE_UNDEFINE;
      m_strSpace = SpaceStr[m_enumSpace];
   }
   else {
      m_strPrefix.MakeUpper();
      char charPrefix = m_strPrefix.GetBuffer(m_strPrefix.GetLength())[0];
      if ( g_nBankNum != 0 ) {
	      if ( (m_strPrefix.GetLength() == 2) && (charPrefix == 'P') ) {
	      	 switch ( m_strPrefix[1] ) {		
	      	 	case '0':
	      	 		m_enumSpace = SPACE_BANK1;	
	                m_strSpace = SpaceStr[m_enumSpace];
	                break;
	      	 	case '1':
	      	 		m_enumSpace = SPACE_BANK2;	
	                m_strSpace = SpaceStr[m_enumSpace];
	                break;
	      	 	case '2':
	      	 		m_enumSpace = SPACE_BANK3;	
	                m_strSpace = SpaceStr[m_enumSpace];
	                break;
	      	 	case '3':
	      	 		m_enumSpace = SPACE_BANK4;	
	                m_strSpace = SpaceStr[m_enumSpace];
	                break;
	            default:                        
	            	m_enumRetCode = ADR_FORMATERROR;
	            	return FALSE;
	      	 }	
	      }                      
	      else {
		      if ( m_strPrefix.GetLength() == 2 ) {
               m_enumRetCode = ADR_FORMATERROR;
               return FALSE;		      
		      }
		      switch(charPrefix) {
		         case  'X':
		               m_enumSpace = SPACE_EXTERNAL;
		               m_strSpace = SpaceStr[m_enumSpace];
		               break;
		
		         case  'I':
		               m_enumSpace = SPACE_INTERNAL;
		               m_strSpace = SpaceStr[m_enumSpace];
		               break;
		
		         case  'R':
		               m_enumSpace = SPACE_SFR;
		               m_strSpace = SpaceStr[m_enumSpace];
		               break;
		
		         case  'B':
		               m_enumSpace = SPACE_BIT;
		               m_strSpace = SpaceStr[m_enumSpace];
		               break;
		
		         default:
		               m_enumRetCode = ADR_FORMATERROR;
		               return FALSE;
		      } 
		   }   
		}
		else {      
			if (m_strPrefix.GetLength() == 2) {
            m_enumRetCode = ADR_FORMATERROR;
            return FALSE;				
			}
	      switch(charPrefix) {                  
	      	case  'P':
	      			m_enumSpace = SPACE_PROGRAME;
	      			m_strSpace = SpaceStr[m_enumSpace];
	      			break;
	      			
	         case  'X':
	               m_enumSpace = SPACE_EXTERNAL;
	               m_strSpace = SpaceStr[m_enumSpace];
	               break;
		
	         case  'I':
	               m_enumSpace = SPACE_INTERNAL;
	               m_strSpace = SpaceStr[m_enumSpace];
	               break;
		
	         case  'R':
	               m_enumSpace = SPACE_SFR;
	               m_strSpace = SpaceStr[m_enumSpace];
	               break;
		
	         case  'B':
	               m_enumSpace = SPACE_BIT;
	               m_strSpace = SpaceStr[m_enumSpace];
	               break;
		
	         default:
	               m_enumRetCode = ADR_FORMATERROR;
	               return FALSE;
	      } 
			
		}   			   
   }

   return TRUE;
}

///////////////////////////////////////////
//Return value

CString
C51Address :: GetHexAddr()
{
   return   m_strAddressHex;
}

CString
C51Address :: GetDecAddr()
{
   return   m_strAddressDec;
}

ADDR_RETCODE
C51Address :: GetRetCode()
{
   return   m_enumRetCode;
}

ADDR_SPACE
C51Address :: GetSpace()
{
   return   m_enumSpace;
}

ADDR_SIZE   
C51Address :: GetAddress()
{
   return CFormatAddress::m_dwAddress;
};

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

