// ldromf96.cpp : implementation file
//

#include "stdafx.h"
#include <sys\stat.h>
#include "io.h"

#include "abiextfn.h"
#include "ldrsvr.h"
#include "ldromf96.h" 
#include "srcexp.h"
#include "cpusvr.h"

#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif


#ifdef _dubugdump_
#define dumpMessage(s) AfxMessageBox(s)
#else
#define dumpMessage(s) 
#endif

/////////////////////////////////////////////////////////////////////////////
// CLdrOMF96

CLdrOMF96::CLdrOMF96(LPCSTR lpsczFile , int nFlag, int where)
{
// Load File Full Path
 m_strFile = lpsczFile; 
 // Compiler Type
 m_nCompilerType = LDR_OMF96;  
 // flag of loader
 m_nLdrOptFlag = nFlag;
 // Hi Byte before or after 
 m_bHiLoFlag = 1; 
 //initialize list of ...
 m_SegmentHdr = NULL;
 m_ModSeg = NULL;
 m_IndexList = NULL;
 m_NameList = NULL;
 m_OffsetList = NULL;
 m_IndexListHdr = NULL;
 m_NameListHdr = NULL;
 m_OffsetListHdr = NULL;
 //initialize index of type
 m_nTypeIndex = 0x1f;
 m_bSpecSymbol =  LOAD_SYSTEM(nFlag)?1:0;
 
 if(nFlag&0xff00) m_nLoadToBank = U16((nFlag&0xff00)>>8);
 
 //for multiple loaded
#ifndef _LONG_ 
 if(where == 0) SymRemoveSymbols();
#endif
}

CLdrOMF96::~CLdrOMF96()
{       
  ClearSegList(m_SegmentHdr);
  ClearSegList(m_ModSeg);
  InitList();
}

void CLdrOMF96::Omf96SegIdToEnum(U8 segId , SEGMENTTYPE* type)
{
    switch (segId) {
    case 0 :
        *type = ( SEGMENTTYPE ) SEG_CODE ;
        break;
    /*case 1 :            
        *type = ( SEGMENTTYPE ) SEG_XDATA ;
        break;*/
    case 1 :
    case 2 :       
    case 3 :
    case 4 :
    case 5 :
        *type = ( SEGMENTTYPE ) SEG_DATA ;
        break;
    case 7 :                              
        *type = ( SEGMENTTYPE ) SEG_CONST;
        break;
    default :
        *type = ( SEGMENTTYPE ) SEG_UNTYPED ;
        break;
    }
}

void CLdrOMF96::ClearSegList(struct Segment *& list)
{
       // clear segment list of module
    struct Segment *tmp, *hdr;  
    hdr = list;
    while(hdr){
       tmp=hdr;
       tmp = tmp->Brother;
       while(tmp){
             ClearSegList(tmp);
       }
       tmp=hdr->next;
       delete hdr;
       hdr = tmp ;
    }
    list = NULL;
}
   
//get the first three bytes of one record   
BOOL CLdrOMF96::GetOneRecHdr()
 {
  int rtn;
  if((rtn = GetBytes(m_uKey , 3)) == 0) {
      m_dwErrMsg = ER_LDR_READ_FILE;	
      return 0;
  }
  m_uCurRecLen = BinToU16(&m_uKey[1]);
  return 1;
 }

// convert id to type
U8 CLdrOMF96::SegIdConvToType(U8 byte)
{
 byte = U8(byte & 0x1f);
 if(byte > 15){
    m_dwErrMsg = ER_LDR_RELOCATE;
    return -1;
 }
 return (byte);
}

//for linking with symbol server 
void CLdrOMF96::Omf96TypeConv(U16& temp)
{ 
     
  if(temp > 0x1F){
     if(m_bAppSym) temp += (U16)m_typeDelta;
     else temp += 224;
     return ;
  }
  switch(temp) {
  case TYPE_C_CHAR :     //signed char 
       temp = BI_S8_CHAR;            
       break;
  case TYPE_C_INT :
       temp = BI_S16_SINT;
       break;
  case TYPE_C_LONG :
  case TYPE_ASM_LONG:
       temp = BI_S32_LONG;
       break;
  case TYPE_C_FLOAT :
       temp = BI_F32;
       break;
  case TYPE_C_UCHAR :
  case TYPE_ASM_BYTE:
       temp = BI_U8_UCHAR;
       break;
  case TYPE_C_UINT : 
  case TYPE_ASM_WORD:            
       temp = BI_U16_UINT;
       break;
  case TYPE_C_ULONG :             
       temp = BI_U32_ULONG;
       break;
  case TYPE_ASM_ENTRY:
  case TYPE_ASM_LABEL:
       temp = BI_JUMP;
       break;
  case TYPE_ASM_NULL:
       temp = BI_P_VOID;
       break;
  default :
       temp = BI_UNKNOWN;
       break;
  }
} //end of func          
                 
//get attribute of segment
BOOL CLdrOMF96::GetSegAttr(struct Segment*& segList)
{
 struct Segment * List=NULL;
 struct Segment * tmp=NULL;        
 U8  data[10], temp;

 int len = m_uCurRecLen;

 while(len > 1){
   //get ID of Segment
    GetOneByte(&m_uCurByte);
    len--;
    
    List = segList; 

    while(List){

     if(List->segId == m_uCurByte){
      //if segID have already existed, take segment as its brother
      //link segment with its list of brother
        while(List){ 
              tmp = List;
              List = List->Brother;
         }
        List = new Segment;
        if(List == 0){
           m_dwErrMsg = ER_LDR_MEMORY_ALLOC;
           return 0;
         } 
        tmp->Brother = List;
        break;
     } //end of if       
        
     tmp = List;
     List = List->next;
    } //end of while
    if(List == NULL){
      //if segID have not existed, take segment as its next
       List = new Segment;    
       if(List == 0){
          m_dwErrMsg = ER_LDR_MEMORY_ALLOC;
          return 0;
       }
       if(segList==NULL) segList = List; 
       else tmp->next = List;
    } 
    
    List->segId = SegIdConvToType(m_uCurByte);
    if(List->segId == -1){
       m_dwErrMsg = ER_LDR_FILE_FORMAT;
       return 0;
    }
    if(!GetBytes(data, 4)){
       m_dwErrMsg = ER_LDR_READ_FILE;
       return 0;
    }
    len = len-4; 
    
    temp = U8(m_uCurByte >> 7);
    if(temp & 1){
       m_dwErrMsg = ER_LDR_RELOCATE;
       return 0;
    }
    else{
       List->bFlag = SEG_ABSOLUTE;
    }
     
    switch(m_uCurByte & 0x60){
    case 0x00:
         List->Based_Var = SEG_NONBASED;
         break;
    case 0x40:
         List->Based_Var = SEG_BASED16;
         break;
    case 0x60:
         List->Based_Var = SEG_BASED24;
         break;
    default:
         m_dwErrMsg = ER_LDR_FILE_FORMAT; //may be not same with format
         return 0;
    }
    
    List->BaseAddr = BinToU16(data);
    List->segSize = BinToU16(&data[2]);
  }//end of while 
  
  ASSERT(len == 1);
  GetOneByte(&m_uCurByte);
  
  return 1;
} //end of GetSegAttr


void CLdrOMF96::DelNameListMem(NameList* tmp)
{
  NameList * temp;
  
  while(tmp){
	  if(tmp->name) {
	     delete tmp->name;
	     tmp->name=NULL;
	  }
      temp = tmp->next;
      tmp->next = 0;
      delete tmp; 
      tmp = temp;
  }
}

void CLdrOMF96::InitList()
{
  struct IndexListList * list1;
  struct IndexList* list11;
  struct NameListList * list2;
  struct OffsetListList* list3;
  struct OffsetList* list33;
  
  while(m_IndexListHdr){
        list1=m_IndexListHdr->next;
        while(m_IndexListHdr->m_IndexList){
              list11 = (m_IndexListHdr->m_IndexList)->next;
              delete m_IndexListHdr->m_IndexList;
              m_IndexListHdr->m_IndexList = list11;
        }
        delete m_IndexListHdr;
        m_IndexListHdr = list1;
   }
  while(m_NameListHdr){
        list2=m_NameListHdr->next;
        
        DelNameListMem(m_NameListHdr->m_NameList);
        
        delete m_NameListHdr;
        m_NameListHdr = list2;
   }
  while(m_OffsetListHdr){
        list3=m_OffsetListHdr->next;
        while(m_OffsetListHdr->m_OffsetList){
              list33 = (m_OffsetListHdr->m_OffsetList)->next;
              delete m_OffsetListHdr->m_OffsetList;
              m_OffsetListHdr->m_OffsetList = list33;
        }
        delete m_OffsetListHdr;
        m_OffsetListHdr = list3;
   }
  m_IndexListHdr = NULL;
  m_NameListHdr = NULL;
  m_OffsetListHdr = NULL;
}//end of function

//for process type
int CLdrOMF96::GetSize(int& len, U32& off)
{
   U8  data[4];    
   
   if(!GetOneByte(&m_uCurByte)){
      m_dwErrMsg = ER_LDR_READ_FILE;
      return -1;
   }
   len--;
   
   switch(m_uCurByte&0x007f){
   case  NIL_LEAF        :
         m_dwErrMsg = ER_LDR_FILE_FORMAT;
         return -2; 
   case  TWO_BYTE_SGNINT :
         if(!GetBytes(data, 2)){
            m_dwErrMsg = ER_LDR_READ_FILE;
            return -1;
         }
         len = len-2;
         off = BinToU16(data);
         return 1;
   case  FOUR_BYTE_SGNINT:
         if(!GetBytes(data, 4)){
            m_dwErrMsg = ER_LDR_READ_FILE;
            return -1;
         }
         len = len-4;
         off = BinToU32(data);
         return 1;
   default              :
         off = (m_uCurByte&0x7f);
         return 1;
  } 
  //return 1;
}//end of function   

//for process type
int CLdrOMF96::GetBitSize(int& len, IndexList* off)
{
   U8  data[4];    
   
   if(!GetOneByte(&m_uCurByte)){
      m_dwErrMsg = ER_LDR_READ_FILE;
      return -1;
   }
   len--;
   
   switch(m_uCurByte&0x007f){
	   case  SBIT_LEAF        :
	   case  UBIT_LEAF        :
	         if(!GetBytes(data, 2)){
	            m_dwErrMsg = ER_LDR_READ_FILE;
	            return -1;
	         }
	         len = len-2;
	         off->BitPos = data[0];
	         off->BitLen = data[1];
	         off->BitFlag = 1;
	         off->index = BI_UNKNOWN;
	         return 1;
	   default              :
	         return -1;
   }
  //return 1;
}//end of function   

BOOL CLdrOMF96::GetIndex(int& len, U16& index)
{
   U8 data[2];
   
   if(!GetOneByte(&m_uCurByte)){
      m_dwErrMsg = ER_LDR_READ_FILE;
      return 0;
   }
   
   len--; 
   if(m_uCurByte==0xe4){
      index = BI_VOID;
      return 1;
   }
   
   ASSERT( U8(m_uCurByte&0x7f) == INDEX_LEAF );
   
   if(!GetOneByte(&data[0])){
      m_dwErrMsg = ER_LDR_READ_FILE;
      return 0;
   }
   len--;
   if(int(data[0]>>7)==1){
      data[0] = U8(data[0]&0x7f);
      GetOneByte(&data[1]);
      len --;
      m_bHiLoFlag = 0;//for special use
      index = BinToU16(data);
      m_bHiLoFlag = 1;
   }
   else{
      index = data[0];
   }
   return 1;
}

BOOL CLdrOMF96::GetListName(int& len, U8*& name)
{
   U8 byte ;
   
   if(!GetOneByte(&m_uCurByte)){
      m_dwErrMsg = ER_LDR_READ_FILE;
      return 0;
   }
   
   len--;       
   
   ASSERT( (m_uCurByte&0x7f) == STRING_LEAF );
   
   if(!GetOneByte(&byte)){
      m_dwErrMsg = ER_LDR_READ_FILE;
      return 0;
   }
   len--;
   if(byte==0) name = NULL;        
   ASSERT(byte != 0);

   name = new U8[byte+1];
   ASSERT(name != NULL);
   if(!GetBytes(name,byte)){
       m_dwErrMsg = ER_LDR_READ_FILE;
      return 0;
   }  
   len = len-byte;
   name[byte] = '\0';
   return 1;
}
   
BOOL CLdrOMF96::AddIndexToList(int& len, U8 IndexOrBit)
{
   int err;
   struct IndexList * temp=NULL;
   struct IndexListList * tmp=NULL, *mtp=NULL;
   
   if(m_IndexListHdr == NULL){
      m_IndexListHdr = new IndexListList();
      if(m_IndexListHdr == NULL){
         m_dwErrMsg = ER_LDR_MEMORY_ALLOC;
         return 0;
      }
      tmp = m_IndexListHdr;
   }
   else{
      tmp = m_IndexListHdr;
      while(tmp){
        mtp = tmp;
        tmp = tmp->next;
      }
      tmp = new IndexListList();
      if(tmp==NULL){
         m_dwErrMsg = ER_LDR_MEMORY_ALLOC;
         return 0;
      }
      mtp->next = tmp;
  }
        
   tmp->index = m_nTypeIndex;    
   
   m_IndexList = new IndexList;
   temp = m_IndexList;
   
   while(1){
     if(IndexOrBit==INDEX_LEAF){
	     if((err=GetIndex(len, temp->index))!=1){
	         return 0;
	     }
	 }
	 else if(IndexOrBit==SBIT_LEAF||IndexOrBit==UBIT_LEAF){
	     if((err=GetBitSize(len, temp))!=1){
	         return 0;
	     }
     }
     if(!PeekByte(&m_uCurByte)){
        m_dwErrMsg = ER_LDR_READ_FILE;
        return 0;
     }  
     if((m_uCurByte&0x7f) == EOB||len==1){
        tmp->m_IndexList = m_IndexList;
        return 1;
     }      
     
     IndexOrBit = U8(m_uCurByte&0x7f);
     ASSERT(IndexOrBit==INDEX_LEAF||IndexOrBit==SBIT_LEAF
            ||IndexOrBit==UBIT_LEAF);
     temp->next = new IndexList;
     temp = temp->next;
     ASSERT( temp!= NULL );
   }//end of while
}//end of function

BOOL CLdrOMF96::AddNameToList(int& len)
{
   int err;
   struct NameList * temp=NULL;
   struct NameListList * tmp=NULL, *mtp=NULL;
   
   if(m_NameListHdr == NULL){
      m_NameListHdr = new NameListList();
      if(m_NameListHdr == NULL){
         m_dwErrMsg = ER_LDR_MEMORY_ALLOC;
         return 0;
      }
      tmp = m_NameListHdr;
   }
   else{
      tmp = m_NameListHdr;
      while(tmp){
        mtp = tmp;
        tmp = tmp->next;
      }
      tmp = new NameListList();
      if(tmp==NULL){
         m_dwErrMsg = ER_LDR_MEMORY_ALLOC;
         return 0;
      }
      mtp->next = tmp;
  }
        
  tmp->index = m_nTypeIndex;    
   
   m_NameList = new NameList;
   temp = m_NameList;
   
   while(1){
     if((err=GetListName(len, temp->name))!=1){
         return 0;
     }
     if(!PeekByte(&m_uCurByte)){
        m_dwErrMsg = ER_LDR_READ_FILE;
        return 0;
     }  
     if((m_uCurByte&0x7f) == EOB||len == 1){
        tmp->m_NameList = m_NameList;
        return 1;
     }
  
     ASSERT((m_uCurByte&0x7f) == STRING_LEAF);
     temp->next = new NameList;
     temp = temp->next;
     ASSERT( temp!= NULL );
   }//end of while
}//end of function

BOOL CLdrOMF96::AddOffsetToList(int& len)
{
   int err;
   struct OffsetList * temp=NULL;
   struct OffsetListList * tmp=NULL, *mtp=NULL;
   
   if(m_OffsetListHdr == NULL){
      m_OffsetListHdr = new OffsetListList();
      if(m_OffsetListHdr == NULL){
         m_dwErrMsg = ER_LDR_MEMORY_ALLOC;
         return 0;
      }
      tmp = m_OffsetListHdr;
   }
   else{
      tmp = m_OffsetListHdr;
      while(tmp){
        mtp = tmp;
        tmp = tmp->next;
      }
      tmp = new OffsetListList();
      if(tmp==NULL){
         m_dwErrMsg = ER_LDR_MEMORY_ALLOC;
         return 0;
      }
      mtp->next = tmp;
  }
        
  tmp->index = m_nTypeIndex;    

   m_OffsetList = new OffsetList;
   temp = m_OffsetList;
   
   while(1){
     err = GetSize(len, (temp->Offset));
     if(err != 1){
        return 0;
     }   
        
     if(!PeekByte(&m_uCurByte)){
        m_dwErrMsg = ER_LDR_READ_FILE;
        return 0;
     }  
     if((m_uCurByte&0x7f) == EOB||len == 1){
        tmp->m_OffsetList = m_OffsetList;
        return 1;
     }
     temp->next = new OffsetList;
     temp = temp->next;
     ASSERT( temp!= NULL );
   }//end of while
}//end of function
      

BOOL CLdrOMF96::GetList(int& len)
{
   
   if(!PeekByte(&m_uCurByte)){
      m_dwErrMsg = ER_LDR_READ_FILE;
      return 0;
   }  
  
   switch(m_uCurByte&0x7f){
   case  INDEX_LEAF:
   case  SBIT_LEAF:
   case  UBIT_LEAF:
         if(!AddIndexToList(len,U8(m_uCurByte&0x7f))){
            return 0;
         }
         break;
   case  STRING_LEAF:
         if(!AddNameToList(len)){
            return 0;
         }
         break;
   case  EOB    :
         break; 
   default          :
         if(!AddOffsetToList(len)){
            return 0;
         }
         break;
  }//end of switch 
  return 1;
}//end of function  

BOOL CLdrOMF96::ProcessTypeStruct(int& len)
{
   int err; 
   BOOL flag = 0;
   U8  *name;
   U16 data[3];
   U32 size, num;               
   
   name = 0;
   
   long pos = GetFileCurPos();
   
   if((err=GetSize(len, size))!=1){
       return 0;
   }
   if((err=GetSize(len, num))!=1){
       return 0;
   }
   for(int i=0;i<3;i++){
       if(!GetIndex(len, data[i])){
	      m_dwErrMsg = ER_LDR_READ_FILE;
	      return 0;
	   }
   }
   if(!PeekByte(&m_uCurByte)){
      m_dwErrMsg = ER_LDR_READ_FILE;
      return 0;
   }
   if((m_uCurByte&0x7f)==STRING_LEAF){
      if((err=GetListName(len, name))!=1){
          if(name) delete name;
          return 0;
      }
      flag = 1;
   }
#ifndef _LONG_   
   if(LOAD_SYM(m_nLdrOptFlag)){
      if(!AddStructToSym(size,num,data,name))
         return 0;
   }
#endif
   if(name) delete name;
   return 1;
 }//end of function 

BOOL CLdrOMF96::ProcessTypeUnion(int& len)
{  
   int err;      
   BOOL flag = 0;
   U8 *name;
   U16 data[3];
   U32 size, num;               
   
   name = 0; //
   
  if((err=GetSize(len, size))!=1){
       return 0;
   }
   if((err=GetSize(len, num))!=1){
       return 0;
   }
   for(int i=0;i<2;i++){
       if(!GetIndex(len,data[i])){
	      m_dwErrMsg = ER_LDR_READ_FILE;
	      return 0;
	   }
   }
   if(!PeekByte(&m_uCurByte)){
      m_dwErrMsg = ER_LDR_READ_FILE;
      return 0;
   }
   if((m_uCurByte&0x7f)==STRING_LEAF){
      if((err=GetListName(len, name))!=1){
         if(name) delete name;
         return 0;
      } 
      flag = 1;
   }  
#ifndef _LONG_   
   if(LOAD_SYM(m_nLdrOptFlag)){
      if(!AddUnionToSym(size,num,data,name))
         return 0;
   }
#endif
   if(name) delete name;
   return 1;
 }//end of function 
    
BOOL CLdrOMF96::ProcessTypeEnum(int& len)
{  
   int err;      
   BOOL flag = 0;
   U8  *name;
   U16 baseType,data[3];
   U32 num;               
   
   if((err=GetSize(len, num))!=1){
       return 0;
   }   
   if(!GetIndex(len, baseType)){
      m_dwErrMsg = ER_LDR_READ_FILE;
      return 0;
   }
   for(int i=0;i<2;i++){
	   if(!GetIndex(len, data[i])){
	      m_dwErrMsg = ER_LDR_READ_FILE;
	      return 0;
	   }
   }
   if(!PeekByte(&m_uCurByte)){
      m_dwErrMsg = ER_LDR_READ_FILE;
      return 0;
   }
   if((m_uCurByte&0x7f)==STRING_LEAF){
      if((err=GetListName(len, name))!=1){
         if(name) delete name;
         return 0;
      } 
      flag = 1;
   }
   else name=NULL;  
#ifndef _LONG_   
   if(LOAD_SYM(m_nLdrOptFlag)){
      if(!AddEnumToSym(baseType,num,data,name))
         return 0;
   }
#endif
   if(name) delete name;
   return 1;
 }//end of function 

BOOL CLdrOMF96::ProcessTypeEntry(int& len)
{
   int err;
   U8 data[5];
   U16 dd[3],index;
   U32 num;               
   
   if(!GetBytes(data,2)){
       m_dwErrMsg = ER_LDR_READ_FILE;
       return 0;
   }                       
   len = len-2;
   ASSERT(data[0]==NIL_LEAF&&data[1]==TYPE_VPL_PROCEDURE);
   
   if(!PeekByte(&m_uCurByte)){
      m_dwErrMsg = ER_LDR_READ_FILE;
      return 0;
   }
   index = U16(m_uCurByte);
   if(index == U16(0xe4)){
      if(!GetOneByte(&m_uCurByte)){
         m_dwErrMsg = ER_LDR_READ_FILE;
         return 0;
      }
      len--;
      index = BI_VOID;
   }
   else{
	   if(!GetIndex(len,index)){
	      return 0;
	   }
   }
   err=GetSize(len, num);
   if(err == -2){
      if(LOAD_SYM(m_nLdrOptFlag)){ 
#ifndef _LONG_
         if(!AddProcToSym(0,index, 0, NULL)) return 0;
#endif
      }
      return 1;
   }
   if(num == 0){
      if(LOAD_SYM(m_nLdrOptFlag)){
#ifndef _LONG_
         if(!AddProcToSym(1,index, 1, NULL)) return 0;
#endif
	   }
      return 1;
   }
   
   for(int i=0;i<2;i++){
	   if(!GetIndex(len, dd[i])){
	      m_dwErrMsg = ER_LDR_READ_FILE;
	      return 0;
	   }
	   if(!PeekByte(&m_uCurByte)){
	      m_dwErrMsg = ER_LDR_READ_FILE;
	      return 0;
	   }
	   if(m_uCurByte==0x6a) break;
   }                                                
#ifndef _LONG_
   if(LOAD_SYM(m_nLdrOptFlag)){
      if(!AddProcToSym(0, index, num, dd)) return 0;
   }
#endif
   return 1;
 }//end of function 
    
// process define of type     
BOOL CLdrOMF96::ProcessTypDef()
{
   int len, err ;

   U8 uCurByte;
   U16 index;
   U32 size;
   
  //initialize list of index,name,offset
  // InitList();
   len = m_uCurRecLen;
   
   long pos = GetFileCurPos();

   if(!GetOneByte(&uCurByte)){
      m_dwErrMsg = ER_LDR_READ_FILE;
      return 0;
   }
   len --;
   
   while(1){
        switch(uCurByte){
        case  TYPE_ARRAY         :       //length , index
        case  TYPE_POINTER       :
        case  TYPE_SCALAR        : 
        case  TYPE_WSR_POINTER   :
              m_nTypeIndex ++;
              if((err=GetSize(len, size))!=1){
                 return 0;
               }
              if((err=GetIndex(len,index))!=1){
                 return 0;
               }
#ifndef _LONG_ 
              if(uCurByte==TYPE_ARRAY){     
                 if(LOAD_SYM(m_nLdrOptFlag)&&
                    (!AddArrToSym(size,index))){
                    return 0;
                 }
              }
              else if(uCurByte==TYPE_POINTER||uCurByte==TYPE_SCALAR){     
                 if(LOAD_SYM(m_nLdrOptFlag)&&
                    (!AddPointerToSym(size,index))){
                    return 0;
                 }
              }
#endif
              break;
        case  TYPE_LIST          :
              m_nTypeIndex ++;
              if(!GetList(len)){
                 return 0;
              }
              break;
        case  TYPE_STRUCTURE     :
              m_nTypeIndex ++;
              if(!ProcessTypeStruct(len)){
                 return 0;
              }
              break;
        case  TYPE_UNION         :
              m_nTypeIndex ++;
              if(!ProcessTypeUnion(len)){
                 return 0;
              }
              break;
        case  TYPE_ENUM          :
              m_nTypeIndex ++;
              if(!ProcessTypeEnum(len)){
                 return 0;
              }
              break;
        case  TYPE_ENTRY         :
              m_nTypeIndex ++;
              if(!ProcessTypeEntry(len)){
                 return 0;
              }
              break;
        default                  : 
              //for too much members of struct, enum
              //for example, type def of one struct may be
              //more than one record 
              if(!UngetOneByte()){
                 m_dwErrMsg = ER_LDR_READ_FILE;
                  return 0;
              }                
              len++;
              if(!GetList(len)){
		         return 0;
			  }    
			  break;
       } //end of switch
       
       if(len == 1) break;
       if(!GetOneByte(&uCurByte)){
           m_dwErrMsg = ER_LDR_READ_FILE;
           return 0;
        }
       len --;
       if(uCurByte != EOB){
          m_dwErrMsg = ER_LDR_FILE_FORMAT;
          return 0;
       }
       if(len == 1){
          break;
       }
       else if(!GetOneByte(&uCurByte)){
            m_dwErrMsg = ER_LDR_READ_FILE;
            return 0;
        }
       len --;  
    } //end of while
    //get chksum
    if(!GetOneByte(&uCurByte)){
        m_dwErrMsg = ER_LDR_READ_FILE;
        return 0;
    }
    return 1;
}  // end of function

//process public symbol 
int CLdrOMF96::ProcessPubDef()              
{
   struct _preSymbol * sym=NULL;
   int len ,symNo ;         
   U8 temp[3], segId,data[2];

   len = m_uCurRecLen;
   symNo = 0;
  
   if(!GetOneByte(&m_uCurByte)){
      m_dwErrMsg = ER_LDR_READ_FILE;
      return -1;
   }
   len--;   
   segId = SegIdConvToType(m_uCurByte);
   if(segId == -1){
      return 0;
   }
   
   while(len > 1){      
        sym = (struct _preSymbol*)(new char[sizeof(struct _preSymbol)/sizeof(char)]);    
        //sym->init();
        
        sym->segId = segId;
       //get definition of public symbol
        if(!GetBytes(temp, 2)){
           m_dwErrMsg = ER_LDR_READ_FILE;
           return -1;
        }
        len = len-2;
        sym->Addr = BinToU16(temp);
        if(!GetName(sym->name)){
           return -1;
        }
        if(sym->name[0] != '?'||LOAD_SYSTEM(m_nLdrOptFlag)){
           symNo ++;
        }
        len = len-int(m_uCurByte+1);
        if(!GetOneByte(data)){
           m_dwErrMsg = ER_LDR_READ_FILE;
           return -1;
        }
        len --;
        if(int(data[0]>>7)==1){
            if(!GetOneByte(&data[1])){
               m_dwErrMsg = ER_LDR_READ_FILE;
               return -1;
            }
            len--; 
            data[0] = U8(data[0]&0x7f);
            m_bHiLoFlag = 0;
            sym->Type_Index = BinToU16(data);
            m_bHiLoFlag = 1;
         }
        else sym->Type_Index=U16(data[0]&0x7f);
        Omf96TypeConv(sym->Type_Index);
#ifndef _LONG_
        if(LOAD_SYM(m_nLdrOptFlag)){
           if(!AddPublicToSym(sym)){
               if(sym->name) delete sym->name;
 	           delete sym;
	           return -1;
	        }
	    }
#endif
        // delete struct
        
        if(sym->name){
           delete sym->name;
           sym->name=0;
        }
        delete sym;    
        sym=0;
        
   }//end of while
       
   ASSERT ( len == 1);
  // fetch chksum of PubDef Record
   if(!GetOneByte(&m_uCurByte)){
        m_dwErrMsg = ER_LDR_FILE_FORMAT;
        return -1;
   }
   return symNo;
} //end of function

// get code of block
BOOL CLdrOMF96::ProcessContent()
{    
   int codeFlag;
   U8  data[3] ;
   U16 codelen, startAddr, endAddr ;    
   U8  segtype,chksum;           
#ifdef _LINK_ABI                
   RET_ADDR ret;
   int err;
#endif   
#ifdef _DUMP_                 
   m_dwRecStartPos = GetFileCurPos();
#endif

   codeFlag = LOAD_CODE(m_nLdrOptFlag);  

   if(!GetBytes(data , 3)){
      m_dwErrMsg = ER_LDR_FILE_FORMAT;
      return 0;
    }     
// convert id to types 
   segtype = SegIdConvToType(data[0]); 
   if(segtype == -1){
      return 0;
    }
// get start address  
   startAddr = BinToU16(&data[1]);
   ASSERT(startAddr > 0xff);
// get length of code
   codelen = m_uCurRecLen - 4;   
// get end address 
   endAddr = startAddr + codelen -1;
 
   if(codelen < 120 ) {                   
      if ( !GetBytes( m_ptrData , codelen) ){
           m_dwErrMsg = ER_LDR_READ_FILE;	
           return 0;
       }
#ifdef _LINK_ABI                
      if(codeFlag) {           
         ADDR stAddr , edAddr;
         
         if(m_nLoadToBank){
            stAddr.addrType = edAddr.addrType = (U8)m_nLoadToBank;
         }
         else{
            stAddr.addrType = edAddr.addrType = 1;
         }
         stAddr.addr = startAddr;
         edAddr.addr = endAddr;
         err=emuSetMemN(stAddr, m_ptrData, codelen, &ret);
         if ( err != ICE_OK ) {
              m_dwErrMsg = ER_ICE_ERROR_WRITE;	
              return 0;
          }
         m_dwLoadBytes += (U32)codelen;
      }
#endif
   }
 else {
     U32 ii;
     ii = startAddr;
     while( codelen >= 120 ) {
       if ( !GetBytes( m_ptrData , 120) ) {
           m_dwErrMsg = ER_LDR_READ_FILE;	
           return 0;
       }
#ifdef _LINK_ABI                
       if (codeFlag){           
           ADDR stAddr , edAddr;
           
           if(m_nLoadToBank){
              stAddr.addrType = edAddr.addrType = (U8)m_nLoadToBank;
           }
           else{
              stAddr.addrType = edAddr.addrType = 1;
           }
           stAddr.addr = ii;
           edAddr.addr=(ii+119);
           err=emuSetMemN(stAddr, m_ptrData, 120, &ret);
           if ( err != ICE_OK ) {
                m_dwErrMsg = ER_ICE_ERROR_WRITE;	
                return 0;
           }
           m_dwLoadBytes += 120L;
       }
#endif       
       ii += 120;
       codelen -= 120;
     } // end of while
    if ( !GetBytes( m_ptrData , codelen)){
          m_dwErrMsg = ER_LDR_READ_FILE;	
          return 0;
     }
#ifdef _LINK_ABI                
    if ( codelen && codeFlag )   {           
         ADDR stAddr , edAddr;
         if(m_nLoadToBank){
            stAddr.addrType = edAddr.addrType = (U8)m_nLoadToBank;
         }
         else{
            stAddr.addrType = edAddr.addrType = 1;
         }
         stAddr.addr = ii;
         edAddr.addr= (ii+codelen-1);
         err=emuSetMemN(stAddr, m_ptrData, codelen, &ret);
         if ( err != ICE_OK ) {
              m_dwErrMsg = ER_ICE_ERROR_WRITE;	
              return 0;
         }
         m_dwLoadBytes += (U32)codelen;
    }    
#endif
  }
  //Get chksum
  GetOneByte(&chksum);
  return 1;
} //end of function

BOOL CLdrOMF96::GetSrcFile()
{                
   int len;
   U8 *data, chksum ;
   CString strFile;
 
   len = m_uCurRecLen;
   while(len > 1){
   //get number of char 
    if(!GetOneByte(&m_uCurByte)){
         m_dwErrMsg = ER_LDR_READ_FILE;
         return 0;
     }
     len--; 
    data = new U8[m_uCurByte];
    ASSERT(data != NULL);
    if(!GetBytes(data, m_uCurByte)){
        m_dwErrMsg = ER_LDR_READ_FILE;
        return 0;
     }
    _fmemcpy((LPSTR)(strFile.GetBuffer(m_uCurByte)),LPSTR(data),m_uCurByte);
    if(data) delete data;
     
    len = len - int(m_uCurByte);
    m_strSrcFile.AddTail(strFile);
    m_ModSrcFile.AddTail(strFile);
   
    strFile.ReleaseBuffer();
  }
 
  ASSERT( len == 1);
  GetOneByte(&chksum); 
  return 1;
}

// get lines of source   
int CLdrOMF96::ProcessFileLineRec()
{                     
   U8  data[6] ,chksum, segId;
   U16 FileId , LinNum;
   U32 LinAddr; 
   int Lines , len ;
#ifndef _LONG_ 
   RETCODE retCode;                   
#endif
   U8 col = 1;
   
   len = m_uCurRecLen;
   Lines = 0;
  
   if (m_modNode.linecnt == 0 ) {
#ifndef _LONG_ 
       if(LOAD_SYM(m_nLdrOptFlag)){
	       retCode = SymAddLinenumStart(m_uCurModDesc);
	       if ( retCode != GOOD ) {
	           m_dwErrMsg = ER_LDR_SYM_SERVER;	
	           return(0);
	       }
	   }
#endif
   } 
 
   GetOneByte(&m_uCurByte);
   len --;
   segId = SegIdConvToType(m_uCurByte);
   if(segId == -1){
      return 0;
    }
 
   while(len > 1){
 
     if(!GetBytes(data , 6)){
        m_dwErrMsg = ER_LDR_FILE_FORMAT;
        return 0;
     } 
     len = len-6;
     FileId = BinToU16(data);
     LinAddr = BinToU16(&data[2]);
	 //for multiple loaded
	 if(m_nLoadToBank) ConvertAddrToBank(LinAddr);
     
     LinNum = BinToU16(&data[4]);
   
 // set current range of module
     if(m_uStart>LinAddr) m_uStart = LinAddr;
     if(m_uEnd<LinAddr) m_uEnd = LinAddr;
 // Set current status of block 
     if(m_pCurBlock){
        if(m_pCurBlock->codeaddr.startAddr>LinAddr)
           m_pCurBlock->codeaddr.startAddr = LinAddr;
        if(m_pCurBlock->codeaddr.endAddr<LinAddr)
           m_pCurBlock->codeaddr.startAddr = LinAddr; 
        if(m_pCurBlock->srcRange.lineNumStart>LinNum)
           m_pCurBlock->srcRange.lineNumStart=LinNum;
        if(m_pCurBlock->srcRange.lineNumEnd<LinNum)
           m_pCurBlock->srcRange.lineNumEnd=LinNum;
     }
  // send line info to symserver
#ifndef _LONG_ 
     if(LOAD_SYM(m_nLdrOptFlag)){
	     retCode = SymAddLinenum(LinNum , col , LinAddr); 
	     if(retCode != 0){
	        m_dwErrMsg = ER_LDR_SYM_SERVER;
	        return 0;
	      }
	 }
#endif
     Lines++;
    }// end of while
  
    ASSERT(len==1);
   //get checksum
    GetOneByte(&chksum);
 
    return Lines;
 } //end of function 

//process local symbol          
int CLdrOMF96::ProcessLocSym()              
{
   struct _preSymbol * sym;
   int len ,symNo ;         
   U8 temp[3], segId, segType,data[2];

   len = m_uCurRecLen;
   symNo = 0;
   
   long pos = GetFileCurPos();//for special reason
   
   if(!GetOneByte(&m_uCurByte)){
      m_dwErrMsg = ER_LDR_READ_FILE;
      return -1;
    }
   len--;
   segId = m_uCurByte;
   segType = SegIdConvToType(m_uCurByte);
   if(segType == -1){
      return 0;
   }
 
   while(len > 1){
        sym = new _preSymbol;
        //sym->init(); 
        sym->segId = segType;
       //get definition of public symbol
        if(!GetBytes(temp, 2)){
           m_dwErrMsg = ER_LDR_FILE_FORMAT;
           return -1;
        }
        len = len-2;
        sym->Addr = BinToU16(temp);
      
        if(!GetName(sym->name)){
           return -1;
        }
        if(sym->name[0] != '?'||LOAD_SYSTEM(m_nLdrOptFlag)){
           symNo ++;
        }
        len = len-int(m_uCurByte+1);
       
        if(!GetOneByte(&m_uCurByte)){
           m_dwErrMsg = ER_LDR_READ_FILE;
           return -1;
        }
        len --;
        //Get typeindex of local symbol
        if((m_uCurByte>>7)==0){ 
           sym->Type_Index = U16(m_uCurByte&0x7f);
        }
        else{
           data[0] = U8(m_uCurByte&0x7f);
           if(!GetOneByte(&data[1])){
              m_dwErrMsg = ER_LDR_READ_FILE;
              return -1;
           }
           len--;
           m_bHiLoFlag = 0;
           sym->Type_Index = BinToU16(data);
           m_bHiLoFlag = 1;
         }
        Omf96TypeConv(sym->Type_Index);
#ifndef _LONG_
        if(LOAD_SYM(m_nLdrOptFlag)){ 
           if(!AddLocToSym(segId, sym->Addr, sym->Type_Index, (LPSTR)(sym->name))){
              return 0;
           }
        }
#endif        
        // delete struct
        if(sym->name){
           delete sym->name;
        }
        delete sym;   
    }//end of while
       
    ASSERT (len == 1);
  // fetch chksum of LocDef Record
    if(!GetOneByte(&m_uCurByte)){
        m_dwErrMsg = ER_LDR_READ_FILE;
        return -1;
    }
    return symNo;
} //end of function

BOOL CLdrOMF96::ProcessExternDef()
{
   if(!SkipRecord(m_uCurRecLen)){
       return 0;
    }
    return 1;
}

BOOL CLdrOMF96::LoadProcess()
{
  
  CString filename;
#ifndef _LONG_ 
  int rtn;
  RETCODE retCode;
#endif
  struct _stat tmpstat;
  struct tm * tmptm;

#ifndef _LONG_ 
  // load Omf96 file all information 
  if ((rtn = TestKey(VK_ESCAPE)) == 1 ) { 
       m_dwErrMsg = ER_LDR_ABORT;	
       return 0;
     }                  
  if ((m_where == LOAD_FROM_DIALOG)&&(m_nLdrOptFlag & LDR_STATUS)){
       if(SrcIsLoadAbort()){
         m_dwErrMsg = ER_LDR_ABORT;	
         return 0;
       }                  
       TestMessage();
    }  
#endif
    dumpMessage("1");
    
    filename = m_strFile;                         
    if (_stat((const char *)filename,&tmpstat) == 0) {
        m_time.year = -1;
        m_time.hour = -1;
    }
    else { 
        tmptm = gmtime( &tmpstat.st_mtime );
                           
        m_time.second = (U8) tmptm->tm_sec;
        m_time.minute = (U8) tmptm->tm_min;
        m_time.hour = (U8) tmptm->tm_hour;
        m_time.day = (U8) tmptm->tm_mday;
        m_time.month = (U8) tmptm->tm_mon;                
        m_time.year = (U16) 1900 ;
        m_time.year +=  (U16) tmptm->tm_year ; 
    }
  
  if(!GetOneRecHdr()){
     return 0;        
   }
  if(LOAD_SYM(m_nLdrOptFlag)){ 
       filename = m_strFileName;
#ifndef _LONG_
       if(!m_bAppSym){
	       retCode = SymAddLoadStart(
	                 filename.GetBuffer(filename.GetLength()) ,
	                 FALSE, &m_time );
	       if(retCode != 0){
	          m_dwErrMsg = ER_LDR_SYM_SERVER;
	          return 0;
	       } 
	   }
	   else{
	       retCode = SymAddLoadStartAgain();
           if ( retCode != GOOD ) {
                m_dwErrMsg = ER_LDR_SYM_SERVER;	
                return 0;
            }
       }
#endif
    }
  while (1) {
   switch(m_uKey[0]){
   case REC_MODULE_HEADER:    
   case REC_LIBRARY_HEADER:    
        if(!LdrGetOMF96Module()){
            return 0;             
        }
        break;
   case REC_EOF:
        if(!GetOneByte(&m_uCurByte)){
           m_dwErrMsg = ER_LDR_READ_FILE;
           return 0;
        }
        return 1;
   default: 
#ifdef _DUMP_
     Message("\r\n???Unknown record at file %lx",
			GetFileCurPos()-3);
#endif
     m_dwErrMsg = ER_LDR_FILE_FORMAT;		
     return 0;
   } // end of switch
// get position of current file 
#ifdef _DUMP_
	m_dwRecStartPos = GetFileCurPos();
#endif                       

#ifndef _LONG_   
// canced by user ?            
   if(TestKey(VK_ESCAPE) == 1 ) { 
      m_dwErrMsg = ER_LDR_ABORT;	
      return 0;
   }                  
   if((m_where == LOAD_FROM_DIALOG)&&(m_nLdrOptFlag & LDR_STATUS)){
       if(SrcIsLoadAbort()){
         m_dwErrMsg = ER_LDR_ABORT;	
         return 0;
       }                  
      TestMessage();
   }                   
#endif
   if(!GetOneRecHdr()){
      return 0;      
   }                  
  }  // end of while
 } // end of function

// start to read out all modules's information   
BOOL CLdrOMF96::LdrGetOMF96Module()
 {
    U8 *data, tmp;     
    BOOL rtn;
  
    data = new U8[m_uCurRecLen + 10];
    if(data == 0){
       m_dwErrMsg = ER_LDR_MEMORY_ALLOC;
       return 0;
    }    
    if((rtn = GetBytes(data , m_uCurRecLen))==0){
       m_dwErrMsg = ER_LDR_READ_FILE;
       return 0;
    }
//Get information of module header

//Get name of Object Module 
    _fmemcpy((LPSTR)(m_strModuleName.GetBuffer(data[0])),(LPSTR)&data[1],data[0]);
  
//Get Translator,version and generator
    tmp = data[data[0]+1];
  //get translator
    switch(tmp & 0xE0){
     case 0x00:
          m_nTranslator = TRANSLATOR_ASM196;
          break;
     case 0x20:
          m_nTranslator = TRANSLATOR_PLM96;
          break;
     case 0x40:
          m_nTranslator = TRANSLATOR_C196;
          break;
     case 0xE0:
          m_nTranslator = TRANSLATOR_UNSPECIFIED;
          break;
     default:
          m_dwErrMsg = ER_LDR_FILE_FORMAT;
          return 0;
    }    
  
  //get version
    switch(tmp & 0x1e){
     case 0x00:
          m_nVersion = OMF96_VERSION_10;
          break;  
     case 0x02:
          m_nVersion = OMF96_RESERVED;
          break;  
     case 0x04:
          m_nVersion = OMF96_VERSION_20;
          break;  
     case 0x06:
          m_nVersion = OMF96_VERSION_31;
          break;  
     case 0x08:
          m_nVersion = OMF96_VERSION_32;
          break;
     default:
          m_dwErrMsg = ER_LDR_VERSION_FORMAT;
          return 0;
    }  
 //get generator
    switch(tmp & 0x01){
     case 0x00:
          m_nGenerator = OMF96_TRANSLATOR96;
          break;
     case 0x01:
          m_nGenerator = OMF96_RL196;
          break;
     default:
          m_dwErrMsg = ER_LDR_FILE_FORMAT;
          return 0;
     }
   if(data) delete data;
    
//get creation date of module
   if(!GetComponentofMod()) {
       return 0;
    } 
   return 1;
 }

BOOL CLdrOMF96::GetComponentofMod()
{
  U8 * data;
  int rtn;
  
  if(!GetOneRecHdr()){
     return 0;
   }
  
#ifdef _DUMP_
   m_dwRecStartPos = GetFileCurPos();
#endif
   
  while(1) {
	switch (m_uKey[0]) {
    case REC_MODULE_INFO: 
    case REC_COMMENT:
    case REC_PUBLIC2_DEF:
    case REC_EXTERNAL_DEFS:    
         if(!SkipRecord(m_uCurRecLen)){
            return 0;
         }
         break;
    case REC_SEGMENT_DEFS: // may be repeated
         if(!GetSegAttr(m_SegmentHdr)){
            return 0;
          }
        break; 
    case REC_PUBLIC_DEFS: // may be repeated
         if(ProcessPubDef()==-1){
            return 0;
          }
         break;
    case REC_TYPE_DEFS: // may be repeated
         if(!ProcessTypDef()) return 0;
         break;
    case REC_CONTENT:
         if(!ProcessContent()){
            return 0;
         }
         break;
    case debug_records:  //may be repeated
         m_moduleNo++;
         if(!GetModAnsOfPrj()){
             return 0;
         }
         break;
    case REC_MODULE_END://can't be repeated
         data = new U8[m_uCurRecLen];
         ASSERT(data != NULL);
      
         if(!GetBytes(data , m_uCurRecLen)){
             m_dwErrMsg = ER_LDR_READ_FILE;
             return 0;
          } 
         if(data[1]){
            m_dwErrMsg = ER_LDR_MODULE_ERRONEOUS;
            return 0;
          }
         delete data;
         return 1;
    default : 
#ifdef _DUMP_
         Message("\r\n???Unknown record at file %lx",
			GetFileCurPos()-3);
#endif
         m_dwErrMsg = ER_LDR_FILE_FORMAT;		
         return 0;
     } //end of switch  
   
#ifdef _DUMP_
     m_dwRecStartPos = GetFileCurPos();
#endif

#ifndef _LONG_
  // judge whether is canceled by user  
     if ((rtn = TestKey(VK_ESCAPE)) == 1 ){ 
          m_dwErrMsg = ER_LDR_ABORT;	
          return 0;
      }                  
     if ((m_where == LOAD_FROM_DIALOG)&&(m_nLdrOptFlag & LDR_STATUS)){
          if(SrcIsLoadAbort()){
             m_dwErrMsg = ER_LDR_ABORT;	
             return 0;
           }                  
         TestMessage();
     }  
#endif

     if(!GetOneRecHdr()){
         return 0;       
      }
    }      // end of while
  } // end of function
 
// Get all mod info of project
BOOL CLdrOMF96::GetModAnsOfPrj()
{
   SYM_DESCRIPTOR moduleDesc;
   int symFlag , codeFlag, rtn ;
#ifndef _LONG_ 
   RETCODE retCode;
#endif   
   ClearUpModuleBlock();
   //for omf96
   ClearSegList(m_ModSeg);
  
  //for clear source file of module
   if(!m_ModSrcFile.IsEmpty()){
      m_ModSrcFile.RemoveAll();
    } 

   m_pCurBlock = 0;
   symFlag = LOAD_SYM(m_nLdrOptFlag);
   codeFlag = LOAD_CODE(m_nLdrOptFlag);
    
   ModuleNodeInit();                       
   m_modNode.offset = m_uBufInFilePos + m_uBufPos - 3 ;
   m_modNode.time.day = -1;
   m_modNode.time.hour = -1;
   m_uStart = DEFAULT_START_ADDR;
   m_uEnd = DEFAULT_END_ADDR;
   m_modNode.scope = 1;
   
   GetOneByte(&m_uCurByte);
   
   // get name of module                          
   m_modNode.name = new U8[m_uCurByte+1];
   ASSERT( m_modNode.name );
   if(!GetBytes(m_modNode.name , m_uCurByte)) {
       m_dwErrMsg = ER_LDR_READ_FILE;	
       return(0);                        
   }  
   m_modNode.name[m_uCurByte] = '\0'; 
   
   m_uCurRecLen = m_uCurRecLen - (m_uCurByte+1);
  // get segment of module
  
   if(!GetSegAttr(m_ModSeg)){
      return 0;
   }
  
   //skip ?name 
   if(m_modNode.name[0] == '?' && !m_bSpecSymbol) symFlag = 0;                                 
    
   if ( symFlag ) {
#ifndef _LONG_ 
       retCode = SymAddModuleCreate(
                (LPSTR)m_modNode.name ,
                &m_modNode.time ,
                &m_modNode.codeaddr ,
                m_modNode.offset ,
                (BOOLEAN) FALSE ,
                0,
                &moduleDesc );
     if (retCode != 0 ){
         m_dwErrMsg = ER_LDR_SYM_SERVER;	
         return 0;
      }
#endif
     m_uCurModDesc = moduleDesc;
   }
   if (!GetOneRecHdr()) {
       m_dwErrMsg = ER_LDR_FILE_FORMAT;	
       return 0;                        
   }                            
   while (1) { 
  
#ifndef _LONG_  
     if ( (TestKey(VK_ESCAPE)) == 1 ) {
          m_dwErrMsg = ER_LDR_ABORT;	
          return 0;
      } 
     if ( (m_where == LOAD_FROM_DIALOG)&&(m_nLdrOptFlag & LDR_STATUS) ) {
           if(SrcIsLoadAbort() ) {
                m_dwErrMsg = ER_LDR_ABORT;	
                return(0);
           }                  
           TestMessage();
      }       
#endif
     switch(m_uKey[0]) {
      case REC_MODULE_ANCESTOR:         
      case REC_MODULE_END:
           if(symFlag){ 
              if(!CloseModToSym()){
                 return 0;
               }
            }   
           if (!SeekLoadFile( -3L , 1 )){
                m_dwErrMsg = ER_LDR_READ_FILE;	
                return 0;
            }
           return 1;       
      case REC_FILENAME :  
       //only get src file name , other file not be gotten
           if(!GetSrcFile()){
               return 0;
            }
           break;
      case REC_FILELINE: 
           if((rtn = ProcessFileLineRec())==0){
              return 0;
           }
           m_modNode.linecnt += rtn;
           break;
      case REC_TYPE_DEFS:// may be repeated
           if(!ProcessTypDef()){
               return 0;
            }  
           break;
      case REC_LOCALS_SYMBOLS:
           if((rtn=ProcessLocSym()) == -1){
              return 0;
           } 
           break;
      case REC_BLOCK_DEF:
           if(!SeekLoadFile( -3L , 1 )){
               m_dwErrMsg = ER_LDR_READ_FILE;	
               return 0;
           }
           if(!GetBlockofModAnc()){
              return 0;
           }
           break;
      case REC_CONTENT:
           if(!ProcessContent()){
               return 0;
           }
           break;
      case REC_FIXUP :
           if(!SkipRecord(m_uCurRecLen))  return 0;
           break;   
      default :
#ifdef _DUMP_
	    	Message("\r\n???Unknown record at file %lx",
		   			GetFileCurPos()-3);
#endif
          m_dwErrMsg = ER_LDR_FILE_FORMAT;		
          return 0;
      } 

#ifdef _DUMP_
     m_dwRecStartPos = GetFileCurPos();
#endif
     
      if(!GetOneRecHdr()){
         m_dwErrMsg = ER_LDR_READ_FILE;
         return 0;
      }
    }// end of while          
 } //end of function  
      

BOOL CLdrOMF96::GetBlockofModAnc()
{               
   U8 * data, segId;       
   BOOL bNameFlag=0, bLocFlag=0, bProcFlag=0;
   struct BlockBlock *temp;
   U16 BlkSize, index;
   U32 StartValue, EndValue=0L;
   int symFlag , rtn, len = 0; 
#ifndef _LONG_ 
   RETCODE retCode;
#endif   
   symFlag = LOAD_SYM(m_nLdrOptFlag);
 
   m_modNode.scope++; 
 
   if(!GetOneRecHdr()){
       m_dwErrMsg = ER_LDR_READ_FILE;
       return 0;
    }
   if(m_uKey[0]!=REC_BLOCK_DEF){
      m_dwErrMsg = ER_LDR_FILE_FORMAT;
      return 0;
    } 
   //alloc memory
   data = new U8[m_uCurRecLen];
   ASSERT(data);
   if(GetBytes(data , m_uCurRecLen) == 0 ) {
      m_dwErrMsg = ER_LDR_READ_FILE;	
      return 0;
    }
   
   if(!symFlag){
      goto skip;
   }            
   
   FUNC_CLASS funcClass;
   temp = new BlockBlock;                 
   if ( temp == 0 ) {
        m_dwErrMsg = ER_LDR_MEMORY_ALLOC;		
        return(0);
   }
   if ( m_modNode.scope == 2 ) {
        m_pCurBlock = temp;
        funcClass = FUNC_GLOBAL; 
   }
   else{
        m_pCurBlock->son = temp;
        temp->father = m_pCurBlock;
        m_pCurBlock = temp; 
        funcClass = FUNC_LOCAL;
   }
 //initialize current block
   m_pCurBlock->scope = m_modNode.scope;
   m_pCurBlock->codeaddr.segType = ( SEGMENTTYPE ) SEG_CODE ;
   m_pCurBlock->codeaddr.startAddr = DEFAULT_START_ADDR ;
   m_pCurBlock->codeaddr.endAddr = DEFAULT_END_ADDR ;
   m_pCurBlock->srcRange.lineNumStart = 0xFFFFFF;
   m_pCurBlock->srcRange.lineNumEnd = 0; 
   m_pCurBlock->srcRange.columnStart = 1;
   m_pCurBlock->srcRange.columnEnd = 0; 
     
   len = data[0];
   if(data[0]){
      bNameFlag = 1;
      m_pCurBlock->funcName = new char[len + 1]; 
      memcpy(m_pCurBlock->funcName, (LPSTR)(&data[1]), len);
      (m_pCurBlock->funcName)[len] = '\0';
   }
   len ++;    
  // set current status of block from record
   segId = SegIdConvToType(data[len]);
    
   ASSERT(segId == 0);
    
   len++;
   StartValue = BinToU16(&data[len]);
   if(m_nLoadToBank) {
      ConvertAddrToBank(StartValue);            
   }
   len = len + 2;
   
   BlkSize = BinToU16(&data[len]);
   len = len + 2;
    
   EndValue = StartValue + BlkSize-1;
    
   if ( m_pCurBlock->codeaddr.startAddr > StartValue){ 
        m_pCurBlock->codeaddr.startAddr = StartValue;
   }
   if ( m_pCurBlock->codeaddr.endAddr < StartValue){ 
        m_pCurBlock->codeaddr.endAddr = StartValue;
   }
  // get current status of module  
   if (m_uStart > StartValue) m_uStart = StartValue;
   if (m_uEnd < StartValue) m_uEnd = StartValue;
 
  // block flag  Do or Proc
   if((data[len] & 0x40)==0x40){
      bProcFlag = 1;
   }
   if(!bProcFlag||!(data[len] & 0x80)){
      bLocFlag = 1;
   }
    
   len++;
    
   //name of block exist?
   if(bNameFlag){
      if((data[len]>>7)==0){
         index = data[len];
         Omf96TypeConv(index);
         m_pCurBlock->typeIndex = index;
         len ++;            
      }
      else{
         data[len] = U8(data[len]&0x7f);
         m_bHiLoFlag = 0;
         index = BinToU16(&data[len]);
         m_bHiLoFlag = 1;
         Omf96TypeConv(index);
         m_pCurBlock->typeIndex = index;
         len = len+2;
      }
   }
 // local or external    
   if(bProcFlag){
      long pos = GetFileCurPos(); //for debug
      
      if(bLocFlag){
         if(data[len]==6/*SEG_NULL*/){
            len += 3;  //no frame pointer
            m_pCurBlock->bFramePtr = 0;
         }
         else{
	         len++;
	         m_pCurBlock->bFramePtr = 1;
	         m_pCurBlock->Frame_Ptr = BinToU16(&data[len]);
	         len=len+2;
	     }
      }
      else{
         len = len+2;
         m_pCurBlock->bFramePtr = 1;
         m_pCurBlock->Frame_Ptr = BinToU16(&data[len]);
         len=len+2;
      }
	   m_pCurBlock->Ret_Offset = BinToU16(&data[len]);
	   len = len+2;                 
	    
	   m_pCurBlock->Prologue_Size = data[len];
	   len ++;
   }
   // for chksum
   len++;
   if(len!=int(m_uCurRecLen)){
      m_dwErrMsg = ER_LDR_FILE_FORMAT;
      return 0;
   }

#ifndef _LONG_ 
   retCode = SymAddFuncCreate(m_pCurBlock->funcName ,
                               funcClass ,
                               m_pCurBlock->stacksize ,
                               &m_pCurBlock->codeaddr ,
                               m_pCurBlock->typeIndex,
                               m_pCurBlock->Frame_Ptr,
                               m_pCurBlock->Ret_Offset,
                               m_pCurBlock->bFramePtr,
                               m_pCurBlock->Prologue_Size );
   if ( retCode != GOOD ) {
        m_dwErrMsg = ER_LDR_SYM_SERVER;
        return 0;
   }
#endif
skip:

   if(data) delete data;   
   // get one record 
   if(!GetOneRecHdr()){
       m_dwErrMsg = ER_LDR_READ_FILE;
       return 0;
   }
 
   while(1){ 
      if(m_uKey[0] == REC_BLOCK_END){
         break;
      }
      switch(m_uKey[0]){
      case REC_BLOCK_DEF: 
           if(!SeekLoadFile( -3L , 1 )){
              m_dwErrMsg = ER_LDR_READ_FILE;	
              return 0;
           }
           if(!GetBlockofModAnc()){
              return 0;
           }
           break;
      case REC_LOCALS_SYMBOLS:
           if((rtn=ProcessLocSym()) == -1){
              return 0;
            }
           else if(symFlag){
                   m_pCurBlock->localsymno += (U16)rtn; 
            }
           break;
      case REC_TYPE_DEFS:
	       if(!ProcessTypDef()) return 0;
	       break;
      default:
#ifdef _DUMP_
           Message("\r\n???Unknown record at file %lx",
   	    	GetFileCurPos()-3);
#endif
           m_dwErrMsg = ER_LDR_FILE_FORMAT;		
           return 0;
     }  // end of switch
      if(!GetOneRecHdr()){
         m_dwErrMsg = ER_LDR_READ_FILE;
         return 0;
      }
    }// end of while
#ifdef _DUMP_
    m_dwRecStartPos = GetFileCurPos();
#endif

    ASSERT(m_uKey[0]==REC_BLOCK_END);
     //get chksum
    GetOneByte(&m_uCurByte);

    if(!symFlag){
       m_modNode.scope--;
       return 1;
    }
    
    if ( m_uStart > EndValue ) m_uStart = EndValue;
    if ( m_uEnd < EndValue ) m_uEnd = EndValue;
 // reset status of current block 
    if(m_pCurBlock->codeaddr.startAddr > EndValue) 
       m_pCurBlock->codeaddr.startAddr = EndValue;
    if(m_pCurBlock->codeaddr.endAddr < EndValue) 
       m_pCurBlock->codeaddr.endAddr = EndValue;
    if(m_modNode.scope>2){          
       if(m_pCurBlock->father->codeaddr.startAddr
                >m_pCurBlock->codeaddr.startAddr){
          m_pCurBlock->father->codeaddr.startAddr = m_pCurBlock->codeaddr.startAddr;
       }
       if(m_pCurBlock->father->codeaddr.endAddr 
                < m_pCurBlock->codeaddr.endAddr) {
          m_pCurBlock->father->codeaddr.endAddr = m_pCurBlock->codeaddr.endAddr;
       }
     }

#ifndef _LONG_ 
    
    retCode = SymAddFuncClose();
    if ( retCode != GOOD ) {
        m_dwErrMsg = ER_LDR_SYM_SERVER;	
        return(0);
    }

#endif

    QUAL_ADDR_RANGE_TYPE qaddr;
    qaddr.startAddr = m_pCurBlock->codeaddr.startAddr;
    qaddr.endAddr = m_pCurBlock->codeaddr.endAddr;
    qaddr.startValid = TRUE;
    qaddr.endValid = TRUE;                      
    if(qaddr.startAddr > qaddr.endAddr ) {
       qaddr.startValid = FALSE;
       qaddr.endValid = FALSE;
     }
    if (qaddr.startValid || qaddr.endValid) {
#ifndef _LONG_     
        if(m_nLoadToBank){
        	if(qaddr.startAddr != DEFAULT_START_ADDR &&
        		qaddr.endAddr != DEFAULT_END_ADDR ) {
           		ConvertAddrToBank(qaddr.startAddr);
           		ConvertAddrToBank(qaddr.endAddr);
           	}
         }

        retCode = SymAddSymbolSetAddr( &qaddr );
        if ( retCode != 0 ) {
             m_dwErrMsg = ER_LDR_SYM_SERVER;	
             return 0 ;
         }
#endif
     } 
    if ( m_pCurBlock->father ) {                                                         
         m_pCurBlock = m_pCurBlock->father;
         ClearUpBlockBlock(m_pCurBlock->son);
         delete m_pCurBlock->son;
         m_pCurBlock->son = 0;
     }
     else {
         ClearUpBlockBlock(m_pCurBlock);
         delete m_pCurBlock;
         m_pCurBlock = 0;
     } 
     m_modNode.scope--;
     return 1;
  }   // end of function
    
BOOL CLdrOMF96::AddPointerToSym(U32 size,U16 index)
{ 
   	U16 ti;
	RETCODE retCode;
	TYPE_HEADER_TYPE typeHdrInfo;
	     
	ti = m_nTypeIndex;
	Omf96TypeConv(ti);
    typeHdrInfo.typeChoice = (TYPE_CLASS) COMPLEX_TYPE_CLASS;
	
	typeHdrInfo.typeName = "\0";                    
    typeHdrInfo.sizeCalculated = TRUE;
    typeHdrInfo.sizeInMAUs = size;
    typeHdrInfo.t.complexType = TY_SMALL_PTR;
    retCode = SymAddTypeHeader(ti , &typeHdrInfo);
    if (retCode != GOOD ) {
        m_dwErrMsg = ER_LDR_SYM_SERVER;
        return 0;
    }
    Omf96TypeConv(index);
    
    retCode = SymAddTypePointerTypeIndex(ti,index);
    if (retCode != GOOD ) {
        m_dwErrMsg = ER_LDR_SYM_SERVER;	
        return 0;
    }
    return 1;
 }//

// To Symbol
BOOL CLdrOMF96::AddArrToSym(U32 size,U16 index)
{
   U16 ti;                   
   RETCODE retCode;
   TYPE_HEADER_TYPE typeHdrInfo;
   TYPE_C_ARRAY_STRUCT arr;
   TYPE_HEADER_TYPE  baseTypeHdr;
   
   ti = m_nTypeIndex;
   Omf96TypeConv(ti);
   Omf96TypeConv(index);
   
   baseTypeHdr.typeName = new char[255];                    
   typeHdrInfo.typeChoice = (TYPE_CLASS) COMPLEX_TYPE_CLASS;
   
   typeHdrInfo.typeName = NULL;                    
   typeHdrInfo.sizeCalculated = TRUE;
   typeHdrInfo.sizeInMAUs = size;
   typeHdrInfo.t.complexType = TY_C_ARRAY;
   arr.typeIndex = index;
  
   retCode = SymAddTypeHeader(ti , &typeHdrInfo);
   if(retCode != GOOD ) {
      m_dwErrMsg = ER_LDR_SYM_SERVER;	
      return 0;
   }

   retCode = SymGetTypeHeader(index, &baseTypeHdr);
   if(retCode != GOOD ) {
      m_dwErrMsg = ER_LDR_SYM_SERVER;	
      delete baseTypeHdr.typeName;   
      return 0;
   }
   arr.highBound = size/(baseTypeHdr.sizeInMAUs) - 1;
   retCode = SymAddTypeCArray(ti , &arr);
   if(retCode != GOOD){
      m_dwErrMsg = ER_LDR_SYM_SERVER;	
      delete baseTypeHdr.typeName;   
      return 0;
   }                   
   delete baseTypeHdr.typeName;   
   return 1;
 } 
 
 BOOL CLdrOMF96::AddStructToSym(U32 size,U32 num,U16* index,U8* name)
 {
   ASSERT(index != NULL);
   
   U16 ti;
   U32 mem;
   TYPE_HEADER_TYPE typeHdrInfo;          
   TYPE_S_U_STRUCT member;
   //TYPE_G_STRUCT bitmember;
   
   RETCODE retCode;
   
   //for special reason
   mem = num;
   ti = m_nTypeIndex;
   Omf96TypeConv(ti);

   typeHdrInfo.typeChoice = (TYPE_CLASS) COMPLEX_TYPE_CLASS;
   typeHdrInfo.typeName = (LPSTR)name;
   typeHdrInfo.sizeCalculated = TRUE;
   typeHdrInfo.sizeInMAUs = size;
   typeHdrInfo.t.complexType = TY_STRUCT;

   retCode = SymAddTypeHeader(ti , &typeHdrInfo);
   if(retCode != GOOD) {
	  m_dwErrMsg = ER_LDR_SYM_SERVER;	
	  return 0;
   } 
   
   struct IndexList * m_tList;
   struct NameList * m_nList;
   struct OffsetList * m_oList;
   
   FindList(m_tList,m_nList,m_oList,index);      
   ASSERT(m_tList!=NULL&&m_nList!=NULL&&
            m_oList!=NULL);
   
   mem = 0;
   while(m_tList!=NULL&&m_nList!=NULL&&
            m_oList!=NULL)
    { 
      mem ++;
      if(m_tList->BitFlag==0){
	      member.offset = (U16)(m_oList->Offset);
	      member.name = (LPSTR)m_nList->name;
	      Omf96TypeConv(m_tList->index);
	      member.typeIndex = m_tList->index;
	      member.bBit = 0;
    	  m_tList = m_tList->next;
	      retCode = SymAddTypeStructUnion(ti , &member);
	  }
	  else if(m_tList->BitFlag){
	      member.name = (LPSTR)m_nList->name;
	      member.offset = m_tList->BitPos+U16(m_oList->Offset)*8;
	      member.size = m_tList->BitLen;
	      member.bBit = 1;
    	  member.typeIndex = BI_UNKNOWN;
    	  m_tList = m_tList->next;
	      retCode = SymAddTypeStructUnion(ti , &member);
	  }
	  if(retCode != GOOD ) {
	     m_dwErrMsg = ER_LDR_SYM_SERVER;
	     return 0;
	  }
	  m_nList = m_nList->next;
	  m_oList = m_oList->next;
    }
   ASSERT(m_tList==NULL&&m_nList==NULL&&
            m_oList==NULL);
   ASSERT(num == mem);
   return 1;
  }//end of function  
    
 BOOL CLdrOMF96::AddUnionToSym(U32 size,U32 num,U16* index,U8* name)
 {
   ASSERT(index != NULL);

   U16 ti;            
   U32 mem;
   TYPE_S_U_STRUCT member;
  // TYPE_G_STRUCT bitmember;
   TYPE_HEADER_TYPE typeHdrInfo;
   RETCODE retCode;
   
   //for special reason
   mem = num;
   
   ti = m_nTypeIndex;
   Omf96TypeConv(ti);
     
   typeHdrInfo.typeChoice = (TYPE_CLASS) COMPLEX_TYPE_CLASS;

   typeHdrInfo.typeName = (LPSTR)name;
   typeHdrInfo.sizeCalculated = TRUE;
   typeHdrInfo.sizeInMAUs = size;
   typeHdrInfo.t.complexType = TY_UNION;
   
   retCode = SymAddTypeHeader((U32)ti , &typeHdrInfo);
   if(retCode != GOOD) {
	  m_dwErrMsg = ER_LDR_SYM_SERVER;	
	  return 0;
   } 

   struct IndexList * m_tList;
   struct NameList * m_nList;
   struct OffsetList * m_oList;            
   
   index[2]=0;
   FindList(m_tList, m_nList, m_oList, index);
   ASSERT(m_tList!=NULL&&m_nList!=NULL);
   
   mem = 0;
   while(m_tList!=NULL&&m_nList!=NULL)
    {
      if(m_tList->BitFlag==0){
	      mem ++;
	      member.offset = 0;
	      member.bBit = 0;
	      member.name = (LPSTR)m_nList->name;
	      Omf96TypeConv(m_tList->index);
	      member.typeIndex = m_tList->index;
	      m_tList = m_tList->next;
	      retCode = SymAddTypeStructUnion((U32)ti , &member);
	  }
	  else if(m_tList->BitFlag==1){
	      member.name = (LPSTR)m_nList->name;
	      member.offset = m_tList->BitPos;
	      member.bBit = 1;
	      member.size = m_tList->BitLen;
          member.typeIndex = BI_UNKNOWN;
	      m_tList = m_tList->next;
	      retCode = SymAddTypeStructUnion(ti , &member);
	  }
	  if(retCode != GOOD ) {
	     m_dwErrMsg = ER_LDR_SYM_SERVER;
	     return 0;
	  }
	  m_nList = m_nList->next;
    }
   ASSERT(m_nList==NULL&&m_tList==NULL);
   ASSERT(mem == num);
   return 1;
  }//end of function
    
 BOOL CLdrOMF96::AddEnumToSym(U16 basetype,U32 num,U16* index,U8* name)
 {
   ASSERT(index != NULL);

   TYPE_HEADER_TYPE typeHdrInfo;
   TYPE_HEADER_TYPE baseTypeHdr;
   RETCODE retCode;
   
   U16 ti, temp;
   U32 mem;
   
   ti = m_nTypeIndex;
   Omf96TypeConv(ti);
   Omf96TypeConv(basetype);
   
   typeHdrInfo.typeChoice = (TYPE_CLASS) COMPLEX_TYPE_CLASS;
   typeHdrInfo.typeName = (LPSTR)name;
   typeHdrInfo.sizeCalculated = TRUE;

   baseTypeHdr.typeName = new char[255];
   
   retCode = SymGetTypeHeader((U32)basetype, &baseTypeHdr);
   if(retCode != GOOD){
      m_dwErrMsg = ER_LDR_SYM_SERVER;
      delete baseTypeHdr.typeName;
      return 0;
   }
   typeHdrInfo.sizeInMAUs = baseTypeHdr.sizeInMAUs;  
   typeHdrInfo.t.complexType = TY_ENUM_C;
   
   retCode = SymAddTypeHeader((U32)ti , &typeHdrInfo);
   if(retCode != GOOD) {
	  m_dwErrMsg = ER_LDR_SYM_SERVER;	
      delete baseTypeHdr.typeName;
      return 0;
   } 
   
   struct IndexList * m_tList;
   struct NameList * m_nList;
   struct OffsetList * m_oList;

   temp = index[1];
   index[1] = index[0];
   index[2] = temp;
   index[0] = 0;
   
   FindList(m_tList, m_nList, m_oList, index);
   ASSERT(m_oList!=NULL&&m_nList!=NULL);

   mem = 0;
   while(m_oList!=NULL&&m_nList!=NULL)
    {
      mem ++;
      retCode = SymAddTypeEnum(ti ,m_oList->Offset,
                 (LPSTR)(m_nList->name) );
	  if(retCode != GOOD ) {
	     m_dwErrMsg = ER_LDR_SYM_SERVER;
	     return 0;
	  }
	  m_oList = m_oList->next;
	  m_nList = m_nList->next;
    }
   ASSERT(m_oList==NULL&&m_nList==NULL);
   ASSERT(mem == num);

   delete baseTypeHdr.typeName;
   return 1;
  }//end of function  
   
 BOOL CLdrOMF96::AddProcToSym(BOOL voidflag,U16 index,U32 num,U16 *data)
 {
   
   U16 ti, typeindex;
   TYPE_HEADER_TYPE typeHdrInfo;
   RETCODE retCode;
   
   ti = m_nTypeIndex;
   Omf96TypeConv(ti);  

   typeHdrInfo.typeChoice = (TYPE_CLASS) COMPLEX_TYPE_CLASS;
   typeHdrInfo.typeName = "\0";
   typeHdrInfo.sizeCalculated = FALSE;
   typeHdrInfo.t.complexType = TY_FUNC_DEP;
   retCode = SymAddTypeHeader(ti , &typeHdrInfo);
   if(retCode != GOOD){
      m_dwErrMsg = ER_LDR_SYM_SERVER;	
      return 0;
   }
   if(index != BI_VOID) Omf96TypeConv(index);
   if(!voidflag){

      retCode = SymAddTypeFunc(ti,0,0,0L,index,U8(num),0,"");
      if(retCode != GOOD ){
         m_dwErrMsg = ER_LDR_SYM_SERVER;
         return 0;
	  }
	  if(num==0) return 1;
   }
   else{ //for void
       retCode = SymAddTypeFunc(ti,0,0,0L,index,1,0,"");
	   if(retCode != GOOD ){
	      m_dwErrMsg = ER_LDR_SYM_SERVER;
	      return 0;
	   }
	  retCode = SymAddTypeFuncParam(ti,BI_VOID);
      if(retCode != GOOD ){
         m_dwErrMsg = ER_LDR_SYM_SERVER;
         return 0;
      }
      return 1;
   }

   ASSERT(data != NULL);
    
   struct IndexList * m_tList;
   struct NameList * m_nList;
   struct OffsetList * m_oList;
   
   data[1]=0;
   data[2]=0;
   FindList(m_tList,m_nList,m_oList,data);
   
   if(!voidflag){
      for(int i=0;i<(int)num;i++){
          ASSERT(m_tList!=NULL);

          typeindex = m_tList->index;
          m_tList = m_tList->next;

          Omf96TypeConv(typeindex);

          retCode = SymAddTypeFuncParam(ti,typeindex);
          if(retCode != GOOD){
             m_dwErrMsg = ER_LDR_SYM_SERVER;	
             return 0;
          }
      }
   }                                             
   return 1;
 }//end of function

 BOOL CLdrOMF96::AddLocToSym(U8 segId, U16 address, U16 index, LPSTR name)
  {
	 ASSERT( name!=NULL );
     if (name[0] == '?' && !m_bSpecSymbol ) return 1;
	 
	 U8 segType;
	 RETCODE retCode;
	 VAR_STORAGE_CLASS varStorage;
	 VAR_REGISTER_CLASS registerClass;
     BOOLEAN isConst , isValid ;
     ADD_VAR_ADDR_UNION addr;
     SYM_DESCRIPTOR symDesc;

	 //for multiple loaded
	 U32 Address;
	 Address = address;
	 segType = SegIdConvToType(segId);
     if(segType==-1){
        m_dwErrMsg = ER_LDR_RELOCATE;
        return 0;
     }
     
     if(m_nLoadToBank) {
        if(segType == 0) ConvertAddrToBank(Address);               
     }

	 /*if(segType==2||segType==3)   
        registerClass = LIVING_REG;
     else*/
        registerClass = NOT_REG;
     if(segType==4||segType==5){   
        varStorage = AUTO_VAR_CLASS;
     }
     else
        varStorage = STATIC_VAR_CLASS;
	    
     isValid = TRUE;
     if(segType == 3) isConst = TRUE;
	 else isConst = FALSE;
	 
     if(segType==4||segType==5){   
        addr.autoVar = Address;
     }
     else{
        addr.addr.addr = Address;
        Omf96SegIdToEnum(segType,&addr.addr.segType); 
        if(addr.addr.segType==SEG_DATA){
           CPUMEMORYRANGE cmr;
           
           GetMemoryRange(cmr);
           if(cmr.iMax < ((U16)Address)){
              ConvertAddrToBank(Address);
              addr.addr.segType=SEG_XDATA;
           }
        }
     }
	 
     retCode = SymAddVar((LPSTR)name,index,varStorage,
	                registerClass,&addr,
	                isConst,isValid,&symDesc);
     if(retCode != GOOD){
        m_dwErrMsg = ER_LDR_SYM_SERVER;
        return 0;
	 }
	 return 1;
 }
 
 BOOL CLdrOMF96::AddPublicToSym(struct _preSymbol* sym)
 {
   if((sym->name)[0] == '?'&&!m_bSpecSymbol) return 1;
   
   ADDRESS_TYPE addr;
   TYPE_HEADER_TYPE   typeHeader;
   RETCODE retCode;
   CHAR typeName[MAX_STRING_SIZE] = "";

   typeHeader.typeName = LPSTR(typeName);
   
   addr.addr = sym->Addr;
   if(m_nLoadToBank) {
      ConvertAddrToBank(addr.addr);
   }
   
   Omf96SegIdToEnum(U8(sym->segId) ,&addr.segType);
   retCode = SymGetTypeHeader(sym->Type_Index, &typeHeader);
   //for special reason
   
   //if(retCode != GOOD) return 0;
   if(typeHeader.t.complexType != TY_FUNC_DEP){
      if(sym->Type_Index != BI_JUMP)
         retCode = SymAddVarPublic((LPSTR)sym->name,sym->Type_Index, addr);
      else 
         retCode = SymAddLabelPublic((LPSTR)sym->name, addr.addr);
  //for multiple loaded
/*      if(retCode != GOOD){
           m_dwErrMsg = ER_LDR_SYM_SERVER;
           return 0;
      } */
   }                                      
   return 1;
}

 void CLdrOMF96::FindList(IndexList*& tList,NameList*& nList,
                       OffsetList*& oList,U16 *index)
  {
   struct IndexListList * m_tListList;
   struct NameListList * m_nListList;
   struct OffsetListList * m_oListList;
   
   IndexList *ttemp;
   NameList *ntemp;
   OffsetList *otemp;
   
   tList=NULL;
   nList=NULL;
   oList=NULL;
   
   BOOL flag;
   
   m_tListList = m_IndexListHdr;
   m_nListList = m_NameListHdr;
   m_oListList = m_OffsetListHdr; 
   
   flag=0;
   //find index list or bit list
   if(index[0]){
      ASSERT(m_tListList!=NULL);
      while(m_tListList){
	         if(m_tListList->index==index[0]){
	            if(!flag) tList = m_tListList->m_IndexList;
	            else{
	               ttemp = tList;
	               while(ttemp->next) ttemp = ttemp->next;
	               ttemp->next = m_tListList->m_IndexList;
	               m_tListList->m_IndexList = 0;
	            }
	            if(!flag) flag=1;
	         }
	         m_tListList = m_tListList->next;
	   }
   }
   flag=0;
   if(index[1]){
	  ASSERT(m_nListList!=NULL);
	  while(m_nListList){
            if(m_nListList->index==index[1]){
	            if(!flag) nList = m_nListList->m_NameList;
	            else{
	               ntemp = nList;
	               while(ntemp->next) ntemp = ntemp->next;
	               ntemp->next = m_nListList->m_NameList;
	               m_nListList->m_NameList = 0;
	            }
	            if(!flag) flag=1;
	         }
	         m_nListList = m_nListList->next;
	   }
   }      
   flag=0;
   if(index[2]){
	  ASSERT(m_oListList!=NULL);
	  while(m_oListList){
	         if(m_oListList->index==index[2]){
	            if(!flag) oList = m_oListList->m_OffsetList;
	            else{
	               otemp = oList;
	               while(otemp->next) otemp = otemp->next;
	               otemp->next = m_oListList->m_OffsetList;
	               m_oListList->m_OffsetList = 0;
	            }
	            if(!flag) flag=1;
	         }
	         m_oListList = m_oListList->next;
	   }
  }
} 

/////////////////////////////////////////////////////////////////////////////////

