
/***************************************************************************
**
**    $Header:   D:/ECB2S/SRC/LOG/LDR695.CPP   1.2.1.4   17 Apr 1997 15:54:12   ZJRD  $
**
**    $Log:   D:/ECB2S/SRC/LOG/LDR695.CPP  $
** 
**    Rev 1.2.1.4   17 Apr 1997 15:54:12   ZJRD
** No change.
** 
**    Rev 1.2.1.3   16 Apr 1997 10:25:34   ZJRD
** No change.
** 
**    Rev 1.2.1.2   10 Apr 1997 15:36:08   ZJRD
** No change.
** 
**    Rev 1.2.1.1   03 Apr 1997 15:15:54   ZJRD
** No change.
** 
**    Rev 1.2.1.0   28 Mar 1997 10:21:02   ZJRD
** easy pack sld 2.09d
** 
**    Rev 1.1   19 Mar 1997 11:31:20   ZJRD
** Easy Pack SLD 2.09c
** 
**    Rev 1.0   12 Mar 1997 14:47:24   ZJRD
** Initial revision.
** 
**    Rev 1.7.1.0.1.2   09 Dec 1996 10:15:54   ZJRD
** EasyPack/SLD Version 2.0P
** 
**    Rev 1.7.1.0.1.0   11 Nov 1996 12:59:10   ZJRD
** EasyPack/SLD Version 2.01
** 
**    Rev 1.7.1.4   09 Sep 1996 13:17:36   ZJRD
** No change.
** 
**    Rev 1.7.1.3   05 Sep 1996 11:29:06   ZJRD
** No change.
** 
**    Rev 1.7.1.2   02 Sep 1996 09:56:10   ZJRD
** No change.
** 
**    Rev 1.7.1.1   28 Aug 1996 15:52:00   ZJRD
** EasyPack/SLD Version 1.9b
** 
**    Rev 1.7   11 Jun 1996 10:29:56   ZJRD
** EasyPack/SLD Version 1.97
** 
**    Rev 1.5   05 Jun 1996 14:58:34   ZJRD
** EasyPack/SLD Version 1.96
** 
**    Rev 1.4   29 May 1996 09:30:58   ZJRD
** No change.
** 
**    Rev 1.3   16 May 1996 09:04:14   ZJRD
** No change.
** 
**    Rev 1.2   10 May 1996 09:13:08   ZJRD
** No change.
** 
**    Rev 1.1   02 May 1996 10:28:00   ZJRD
** EasyPack/SLD Version 1.92
** 
**    Rev 1.14   18 Apr 1996 12:58:52   Shirley
** EasyPack/SLD Version 1.91
** 
**    Rev 1.13   12 Apr 1996 10:38:56   Shirley
** EasyPack/SLD Version 1.90
** 
**    Rev 1.11   15 Feb 1996 08:51:50   Shirley
** EasyPack/SLD Version 1.01
** 
**    Rev 1.10   12 Feb 1996 14:06:22   Shirley
** No change.
** 
**    Rev 1.9   06 Feb 1996 15:32:52   Shirley
** No change.
** 
**    Rev 1.8   06 Feb 1996 13:47:06   Shirley
** No change.
** 
**    Rev 1.7   01 Feb 1996 10:13:40   Shirley
** No change.
** 
**    Rev 1.6   26 Jan 1996 09:17:54   Shirley
** No change.
** 
**    Rev 1.5   25 Jan 1996 13:17:50   Shirley
** No change.
** 
**    Rev 1.4   24 Jan 1996 10:33:34   Shirley
** EasyPack/SLD Version 0.34d
** 
**    Rev 1.3   23 Jan 1996 11:22:26   Shirley
** EasypPack/SLD Version 0.34c
** 
**    Rev 1.2   18 Jan 1996 10:13:24   Shirley
** EasyPack/SLD Version 0.34b
** 
**    Rev 1.0   04 Jan 1996 11:13:40   Shirley
** Initial revision.
**
****************************************************************************/

/****************************************************************************
**
**  Name:  LDR695.CPP
**
**  Description:
**      Entry points for IEEE695 Loader.
**
**  Status:  CODED
**
**    Rev 1.0   1 Dec. 1995 8:30:00am   Gates Hua, Jamoon Chow
** Initial revision.
**
**  Copyright (C) 1995 Microtek International.  All rights reserved.
**
*****************************************************************************/

                       /****************************
                        *                          *
                        *       INCLUDE FILES      *
                        *                          *
                        ****************************/

#include "stdafx.h"
//#include <ctype.h>
//#include <io.h>
//#include <sys\timeb.h>
//#include <time.h>
//#include <fcntl.h>
#include <sys\stat.h>

#include "symblsvr.h"
#include "abibase.h"
#include "ldr.h"           
#include "ldr695.h"
#include "uicom.h"

                       /****************************
                        *                          *
                        *     LOCAL DEFINITIONS    *
                        *                          *
                        ****************************/

                       /****************************
                        *                          *
                        *    EXTERNAL VARIABLES    *
                        *                          *
                        ****************************/
extern struct StoreExtendVar *varExtHdrPtr,*varExtPtr;
extern U32 start , end;
extern U8 LineNumInfo[16] , SymDefInfo[51] ; // OldKey;
extern struct BlockBlock far *curBlock ;
extern SYM_DESCRIPTOR curModDesc;
//extern int m_dwErrorNum;
extern U32 uLoadBytes;
                       /****************************
                        *                          *
                        *     LOCAL PROTOTYPES     *
                        *                          *
                        ****************************/
//struct ListDescType *listPtrHeader = 0, *listPtr = 0;
//struct TypeDescType *nameHeader = 0, *namePtr = 0;

#define IS_BBFUNCTION(x) ((x)==4 || (x)==6)
#define IS_ASMMODULE(x) ((x)==10 || (x)==11)

void L695OffsetToAddr(U32 lvalue,ADDRESS_TYPE  *addr);
int StripPathString(LPSTR moduleName, LPSTR *newName);

U32 curTypeDelta;

U32 startAddr_ASW[8] ;
U8 curByte;

                       /****************************
                        *                          *
                        *      EXECUTABLE CODE     *
                        *                          *
                        ****************************/
extern STATUS AbiFill(ADDR addr1, ADDR addr2,char* pchBuff,UINT uPatternLen);
extern RETCODE SymAddLoadStartAgain();

/***************************************************************************
*                                                                          *
*  Ldr695LoadProcess - IEEE695 Loader main process routine                 *
*  parameter :                                                             *
*       None                                                               *
*  return value :                                                          *
*       0  ---  OK                 -1  ---  failure                        *
*                                                                          *
***************************************************************************/
int LoaderServer::Ldr695LoadProcess(void)
{       
//    int err , flag , codeFlag;       
//    U8 key[3] , *dd;  
//    U16 recLen , uj , ui;                 
//    RETCODE retCode;
//    U8 *ptrData;
//    U8 data[3];                 
//    U32 nBytes;
                  
//    flag = 0;                  
    m_absflag = 0;
//    codeFlag = LOAD_CODE(m_ldrFlags);
    if (m_lpModuleName) {
		// load module only 
		// Get the module descriptor from moduleName and moduleReference 
        return Ldr695LoadModuleOnly() ;
    }
    else {
        m_startaddress = 0;                                                   
		// load IEEE695 file all information 
                              
        if ( TestKey(VK_ESCAPE) == 1 ) { 
            m_dwErrorNum = ER_LDR_ABORT;	// 0x4010;
            return( FAILURE );
        }                  
        if ( (m_window == LOAD_FROM_DIALOG)&&(m_ldrFlags & LDR_STATUS) ) {
            if ( IsLoadCanceled() ) {
                m_dwErrorNum = ER_LDR_ABORT;	// 0x4010;
                return( FAILURE );
            }                  
            TestMessage();
        }
        
#ifdef _DUMP_
		Message("Load Header Part");
#endif
        if ( Ldr695LoadStarter() == FAILURE ){
#ifdef _DUMP_        
			DisplayErrorRecord(recordStartPos);
#endif
        	return FAILURE;
        }

#ifdef _DUMP_
		Message("\r\nLoad Environment Part");
#endif
        if ( Ldr695EnvPart() == FAILURE ) {
#ifdef _DUMP_        
			DisplayErrorRecord(recordStartPos);
#endif
        	return FAILURE;
        }

#ifdef _DUMP_
		Message("\r\nLoad Section Part");
#endif
        if ( Ldr695SectionPart() == FAILURE ) {
#ifdef _DUMP_        
			DisplayErrorRecord(recordStartPos);
#endif
        	return FAILURE;
        }

        if ( LOAD_SYM( m_ldrFlags ) ) {
//            CString filename;
        
//            filename = m_lpFileName;
//            retCode = SymAddLoadStart(
//                        filename.GetBuffer(filename.GetLength()) ,
//                        FALSE,
//                        &m_time );
//            if ( retCode != GOOD ) {
//                m_dwErrorNum = 0x4025;
//                return( FAILURE );
//            }

#ifdef _DUMP_
			Message("\r\nLoad Debug Part");
#endif
            if ( Ldr695DebugPart() != GOOD ) {
#ifdef _DUMP_            
				if( m_dwErrorNum != ER_LDR_ABORT )	//0x4010 ) 
					DisplayErrorRecord(recordStartPos);
#else				
            	return FAILURE;
#endif				
            }

#ifdef _DUMP_
			Message("\r\nLoad External Part");
#endif
      		if ( Ldr695ExtPart() != GOOD ) {
#ifdef _DUMP_      		
				if( m_dwErrorNum != ER_LDR_ABORT)	//0x4010 ) 
					DisplayErrorRecord(recordStartPos);
#endif				
//                return( FAILURE );
            }
        }
        if ( LOAD_CODE( m_ldrFlags ) ) {
			// Process and load code and constant data record  
    		//U32 nBytes;
            //if ( Ldr695DataPart(&nBytes) != GOOD)	return FAILURE;
#ifdef _DUMP_
			Message("\r\nLoad Data Part");
#endif
            if ( Ldr695DataPart(&uLoadBytes) != GOOD) {
#ifdef _DUMP_            
				if( m_dwErrorNum != ER_LDR_ABORT)	//0x4010 ) 
					DisplayErrorRecord(recordStartPos);
#else
            	return FAILURE;
#endif
            }
        }
    
		// Now always do this, even if code is not loaded
#ifdef _DUMP_
		Message("\r\nLoad Trailer Part");
#endif
        if ( Ldr695TrailPart() != GOOD )		return FAILURE;
    }
    return GOOD;
}


/***************************************************************************
*                                                                          *
*  Ldr695LoadModuleOnly - IEEE695 Loader a module only                     *
*  parameter :                                                             *
*       None                                                               *
*  return value :                                                          *
*       0  ---  OK                 -1  ---  failure                        *
*                                                                          *
***************************************************************************/
int LoaderServer::Ldr695LoadModuleOnly(void)
{
//  SYM_DESCRIPTOR moduleDesc;
    int err;                                                       
//    char *lpStr;                           
//    char *lpModule;                    
    U32 moduleOffset , ul;    
    RETCODE retCode;
    
/*    
    char *lpStr;                           
    char *lpModule;                    
    err = lstrlen(m_lpModuleName);
    lpModule = new char[err+1];
    if ( lpModule == 0 ) {
        m_dwErrorNum = 0x4000;
        return (FAILURE);
    }
    lstrcpy(lpModule , m_lpModuleName);
    lpStr = strstr(lpModule,".");
    if (lpStr) *lpStr = '\0';        
*/
    retCode = SymAddLoadStart(
            m_lpFileName,
//          m_onDemand,
            TRUE,
            &m_time );
    if ( retCode != GOOD ) {
        m_dwErrorNum = ER_LDR_SYM_SERVER;	// 0x4025;
        return( FAILURE );
    }
    err = (U16) SymAddModuleOpenByDesc( curModDesc , &moduleOffset , &ul );
    if ( err != GOOD ) {
        m_dwErrorNum = ER_LDR_LOAD_MODULE;		// 0x4021;
        return(FAILURE);
    }
    curTypeDelta = ul;
    if ( m_onDemand == FALSE ) {
        m_dwErrorNum = ER_LDR_MOD_INFO_LOADED;	// 0x4022;
        return GOOD;
    }
    if ( SeekLoadFile( moduleOffset , 0 )   != GOOD ) {
        m_dwErrorNum = ER_LDR_READ_FILE;	// 0x400F;
        return(FAILURE);
    }
    err = Ldr695GetModule( moduleOffset , TRUE );
    return(err);               
}

/***************************************************************************
*                                                                          *
*  Ldr695LoadModuleByDesc - Load a module local information for OnDemand   *
*                   load Only loader block,symbol and linenum information  *
*  parameter :                                                             *
*       offset  --  this module in load file position .                    *
*  return value :                                                          *
*       0  ---  OK                 -1  ---  failure                        *
*                                                                          *
***************************************************************************/
int LoaderServer::Ldr695LoadModuleByDesc( U32 offset )
{                    
    int err;                                                       
    int nOldFlags;
    
    nOldFlags = m_ldrFlags;
    m_ldrFlags = 0x1;
    if ( SeekLoadFile( offset , 0 ) != 0 ) {
        m_dwErrorNum = ER_LDR_READ_FILE;	// 0x400F;
        return(-1);
    }
    err = Ldr695GetModule( offset , TRUE );
    m_ldrFlags = nOldFlags;
//    if (err == -1) return(err);    
//    return 0;
	return err;
}
                        
/***************************************************************************
*                                                                          *
*  Ldr695LoadModule - Load a module information by ldrFlags and onDemand   *
*  parameter :                                                             *
*       None (Information all in class LoaderServer)                       *
*  return value :                                                          *
*       0  ---  OK                 -1  ---  failure                        *
*                                                                          *
***************************************************************************/
int LoaderServer::Ldr695LoadModule(void)
{           
    return 0;
}
                                            
/***************************************************************************
*                                                                          *
*  Ldr695LoadStarter - Load IEEE695 start section                          *
*  parameter :                                                             *
*       None (Information all in class LoaderServer)                       *
*  return value :                                                          *
*       0  ---  OK                 -1  ---  failure                        *
*                                                                          *
***************************************************************************/
int LoaderServer::Ldr695LoadStarter(void)
{       
//    U8 data[7];     
    RETCODE retCode;
    struct _stat tmpstat;
    struct tm *tmptm;
    CString filename;
    char *str;       
    U16 len; 
    U8  ch;
    int i;
//    int j;
                     
    for( i = 0;i < 8;i++) {
        startAddr_ASW[i] = 0L;
    }
//    filename = m_lpFileRef;
//    filename += m_lpFileName;                         
    filename = m_lpFileRef;                         
    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 ; 
    }

#ifdef _DUMP_
	recordStartPos = GetFileCurPos();
#endif

	// MB record  
    if ( MatchRecord(IEEE_MB) != GOOD ) {
        m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x4014;
        m_bDispOff = 1;
        m_dwOffset = GetFileCurPos();
        return FAILURE;
    }
    if ( Get695Idn(str) != GOOD ) {  
        m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x4014
        m_bDispOff = 1;
        m_dwOffset = GetFileCurPos();
        return FAILURE;
    }
#ifdef _DUMP_
	Message("	CPU TYPE: %s\r\n",str);
#endif    
//    if ( strstr(str,"51") == NULL && strstr(str,"52") == NULL ) {
//        m_dwErrorNum = 0x4026;
//        return FAILURE;
//    }
    if ( str ) delete str;
    if ( Get695Idn(str) != GOOD ) {  
        m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x4014;
        m_bDispOff = 1;
        m_dwOffset = GetFileCurPos();
        return FAILURE;
    }
    if ( str ) delete str;
  
	// AD record    
    if ( MatchRecord(IEEE_AD) != GOOD ) {
        m_bDispOff = 1;
        m_dwOffset = GetFileCurPos();
        m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x4014;
        return FAILURE;
    }
    if ( Get695Number(&len) != GOOD ) {  
        m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x4014;
        m_bDispOff = 1;
        m_dwOffset = GetFileCurPos();
        return FAILURE;
    }                     
    if ( Get695Number(&len) != GOOD ) {  
        m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x4014;
        m_bDispOff = 1;
        m_dwOffset = GetFileCurPos();
        return FAILURE;
    }                     
    m_addrunit = ( int ) len; 
//    if ( MatchRecord(IEEE_AS) != GOOD ) {
    if ( Get695Letter( &curByte ) == GOOD ) { 
        if ( curByte == 0xCC ) {
            m_absflag = 1;
        }
        else if ( curByte == 0xCD ) {
            m_absflag = 0;
        }    
        else {
            m_dwErrorNum = ER_LDR_FILE_FORMAT;	// 0x400F;
            m_bDispOff = 1;
            m_dwOffset = GetFileCurPos();
            return FAILURE;
        } 
    }
    for (i=0;i<8;i++) {
#ifdef _DUMP_
		recordStartPos = GetFileCurPos();
#endif
		// ASW record
        if ( MatchRecord(IEEE_AS) != GOOD || MatchRecord(IEEE_ASW) != GOOD ) {
            m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
            m_bDispOff = 1;
            m_dwOffset = GetFileCurPos();
            return FAILURE;
        }            
        if ( GOOD != GetOneByte(&ch) ) {
            m_dwErrorNum = ER_LDR_READ_FILE;		// 0x400F;
            m_bDispOff = 1;
            m_dwOffset = GetFileCurPos();
            return FAILURE;
        }            
        if ( ch >= 8 ) {
            m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
            m_bDispOff = 1;
            m_dwOffset = GetFileCurPos();
            return FAILURE;
        }            
        if ( GOOD != Get695Offset(&startAddr_ASW[ch]) ) {
            m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
            m_bDispOff = 1;
            m_dwOffset = GetFileCurPos();
            return FAILURE;
        }            

#ifdef _DUMP_
		Message("	ASW[%1d] = %lX",(U16)ch,startAddr_ASW[ch]);
#endif

    }
    if( LOAD_SYM( m_ldrFlags )&&m_bAppSym&&m_bLoadInit){
            retCode = SymAddLoadStartAgain();
            if ( retCode != GOOD ) {
                m_dwErrorNum = ER_LDR_SYM_SERVER;	// 0x4025;
                return( FAILURE );
            }
        }

    if ( LOAD_SYM( m_ldrFlags )&&(!m_bAppSym||!m_bLoadInit)) {
        filename = m_lpFileName;
        retCode = SymAddLoadStart(
                        filename.GetBuffer(filename.GetLength()) ,
                        FALSE,
                        &m_time );
        if ( retCode != GOOD ) {
            m_dwErrorNum = ER_LDR_SYM_SERVER;	// 0x4025 ;
            return( FAILURE );
        }
    }
    return(GOOD);       
}

/******************************************************************************
**
**  Ldr695EnvPart
**
** This Part is processed, and interesting information returned to caller,
** which sends it to the project presenter, or anyone else interested.
** Currently, only certain pieces of information are kept:
**      timestamp of loadfile
**      generation status (successful link, failure, etc.)
**      host OS
**      toolchain id
******************************************************************************/
int LoaderServer::Ldr695EnvPart(void)
{
    U16 uTmp16 , atn_type;
    U32 uTmp32 , uType;
    char *str , *str1 ;
    U8	ch ;    
    U16 toolVersion, toolRevision;

    // first, seek to Environmental Part of file 
    if ( startAddr_ASW[1] == 0L )
        return GOOD;
         
	// ASW1  --  Environment Part
    if ( GOOD != SeekLoadFile(startAddr_ASW[1],SEEK_SET) ) {
        m_dwErrorNum = ER_LDR_READ_FILE;	// 0x400F;
        m_bDispOff = 1;
        m_dwOffset = GetFileCurPos();
        return FAILURE;
    }
#ifdef _DUMP_
	recordStartPos = GetFileCurPos();
#endif
    // single NN 
    if (MatchRecord(IEEE_NN) != GOOD ||   
    	Get695Nrecord(&uTmp32, (LPSTR)str) != GOOD ) 
    {
        m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
        m_bDispOff = 1;
        m_dwOffset = GetFileCurPos();
        return FAILURE;
    }
    if ( str ) delete str;            

	// loop over ATN records found 
    while (1) {
#ifdef _DUMP_
		recordStartPos = GetFileCurPos();
#endif
		// Since we're processing an entire Part of the file here, its
   		// ok if we eat too many bytes; the next Part will re-seek 
        if (Match2Record(IEEE_AT , IEEE_ATN) != GOOD)
            break; 
           
        ProcessATN(&uTmp32, &uType, &atn_type);
        switch(atn_type) {
        case 50 : 		// 0x32 - x1 [x2 [x3 [x4 [x5 [x6]]]]]
            if ( GOOD != Get695Time(&m_time) ) {
                m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
                m_bDispOff = 1;
                m_dwOffset = GetFileCurPos();
                return FAILURE;
            }            
            break;
        case 51 :		// 0x33 - Id
			// we don't care about the link commandline 
            if ( GOOD != Get695Idn((LPSTR)str1) ) {
                m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
                m_bDispOff = 1;
                m_dwOffset = GetFileCurPos();
                return FAILURE;
            }            
            if ( str1 ) delete str1;
            break;
        case 52 :		// Execution status  - x1
        case 53 :		// Host environment  - x1
            if ( GOOD != Get695Number(&uTmp16) ) {
                m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
                m_bDispOff = 1;
                m_dwOffset = GetFileCurPos();
                return FAILURE;
            }            
            break; 
        case 54 :  // ATN54 - x1 x2 x3 [x4]
			// Most toolchains set toolcode in ATN54, refer to Appx P
   			// in 695 specification 'Tool Type Codes'.

            if ( GOOD != Get695Offset(&uTmp32) ||
				 GOOD != Get695Number(&toolVersion) ||
				 GOOD != Get695Number(&toolRevision) )
			{
                m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
                m_bDispOff = 1;
                m_dwOffset = GetFileCurPos();
                return FAILURE;
            }            
            Get695Letter( &ch );		// [x4]
            break;
               
        case 55 :  // ATN55 - Id
			// Cosmic is the only exception: read string in ATN55 
            if ( GOOD != Get695Idn((LPSTR)str1) ) {
                m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
                m_bDispOff = 1;
                m_dwOffset = GetFileCurPos();
                return FAILURE;
            }            
            if ( str1 ) delete str1;
            break;
        default:
            return(GOOD);
        }
    }  // while (1) 
    
    return(GOOD);
}  // ProcessEnvPart 
                                            
/******************************************************************************
**
**  Ldr695ExtPart
**
** Process public symbols from Public Part of file - place info into Symbol
** Table.  Note that this part of the file is processed *after* the Debug
** Part (which contains more attribute information for those symbols it
** knows about).
**
******************************************************************************/
int LoaderServer::Ldr695ExtPart(void)
{
   LPSTR sname;  /* pointer to underscore-stripped name */
   U16 at_typeid, nfields, atn_type;
   U32 nindex; 
   U16 adefn, nelts;
   U32 lvalue;
   U32 tindex;  /* type index */
   //U32 toffset=0;  /* place-holder */
   //RETCODE err = GOOD;
   char *str;
   ADDRESS_TYPE addr;      

	// Check for not empty extern part 
    if ( startAddr_ASW[3] == 0L) return GOOD;
   
	// ASW3  --  External Part
    if ( GOOD != SeekLoadFile(startAddr_ASW[3],SEEK_SET) ) {
        m_dwErrorNum = ER_LDR_READ_FILE;	// 0x400F;
        m_bDispOff = 1;
        m_dwOffset = GetFileCurPos();
        return FAILURE;
    }            

    while (1) {
#ifdef _DUMP_
		recordStartPos = GetFileCurPos();
#endif
		// NOTES: we are abandoning the checking of name index for successive
		// (i.e., ATI) records to match the preceding NN record.  Likewise,
		// abandoning re-checking the section index.  It is assumed that this
		// is a valid .ABS file.  If this proves untrue empirically, then this
		// code can have this error-checking added to it.
        if ( GOOD != GetOneByte(&curByte) ) {
//            m_dwErrorNum = ER_LDR_READ_FILE;	// 0x400F;
            m_bDispOff = 1;
            m_dwOffset = GetFileCurPos();
            return FAILURE;
        }            
            
        switch (curByte) {
        case IEEE_NN:  /* certain module names only */
        case IEEE_NX:  /* external function name - not loaded */
            if ( GOOD != Get695Nrecord(&nindex, (LPSTR)str) ) {
//                m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
                m_bDispOff = 1;
                m_dwOffset = GetFileCurPos();
                return FAILURE;
            }
            if ( str ) delete str;
            break;
        case IEEE_NI:  /* public (external) symbol - code or data */
            if ( GOOD != Get695Nrecord(&nindex, (LPSTR)str) ) {
//                m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
                m_bDispOff = 1;
                m_dwOffset = GetFileCurPos();
                return FAILURE;
            }
            sname = StripName((LPSTR)str);
			/* ATI, ASI records follow */
			/* ATI: attribute record */
            if ( GOOD != Match2Record(IEEE_AT,IEEE_ATI) ) {
//                m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
                m_bDispOff = 1;
                m_dwOffset = GetFileCurPos();
                return FAILURE;
            }
            if ( GOOD != ProcessATI(&nindex, &tindex, &adefn, &nelts) ) {
//                m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
                m_bDispOff = 1;
                m_dwOffset = GetFileCurPos();
                return FAILURE;
            }
			/* ASI: value record */ 
			if ( Match2Record( IEEE_AS,IEEE_ASI ) != GOOD ) {
//                m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
                m_bDispOff = 1;
                m_dwOffset = GetFileCurPos();
                return FAILURE;
			}
            if ( GOOD != Get695Offset(&nindex) ) {
//                m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
                m_bDispOff = 1;
                m_dwOffset = GetFileCurPos();
                return FAILURE;
            }
            if ( GOOD != PeekByte(&curByte) ) {
//                m_dwErrorNum = 0x400F;
                m_bDispOff = 1;
                m_dwOffset = GetFileCurPos();
                return FAILURE;
            }
            
            if ( curByte == 0xCC ) {
                if ( GetExpression(addr) != GOOD ) {
//                    m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
                    m_bDispOff = 1;
                    m_dwOffset = GetFileCurPos();
                    return FAILURE;
                }
                lvalue = addr.addr;                      
            }
            else {
                Get695Offset(&lvalue);
                addr.addr = lvalue & 0x0000FFFFL;
                addr.segType = SEG_CODE;
            }                    
            if (tindex == 0x0F) {  /* code -- label */    
                lvalue = (U32) ( lvalue & 0x0000FFFFL );
                if ( sname && (*sname != '?' || m_bSpecSymbol))
                    //for load to specified bank
                    if(m_bLoadToBank&&m_window==LOAD_FROM_SHELL){
                       ConvertAddrToBank(lvalue);
                    }
                	SymAddLabelPublic((LPSTR)sname,lvalue);
            } else {  /* data */
//                ADDRESS_TYPE addr;
//                L695OffsetToAddr(lvalue,&addr);
                //for load to specified bank
                if(m_bLoadToBank&&m_window==LOAD_FROM_SHELL){
                   ConvertAddrToBank(addr.addr);
                }
                SymAddVarPublic((LPSTR)sname, tindex, addr);
            }
            if( str ) delete str;
            break;
			//
			// Note: these are listed as '80960 call optimization'
			// records in the 695 addendum (?).  They don't appear to
			// give any useful information, so we eat up the bytes and
			// ignore them.

//         case RP_ATTR:  // lone ATN records - var misc records 
        case IEEE_AT :
            if ( GOOD != UngetOneByte() ) {
//                m_dwErrorNum = 0x400F;
                m_bDispOff = 1;
                m_dwOffset = GetFileCurPos();
                return FAILURE;
            }
            if ( Match2Record(IEEE_AT , IEEE_ATN ) != GOOD) {
//                m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
                m_bDispOff = 1;
                m_dwOffset = GetFileCurPos();
                return FAILURE;
            }
//            if ( ProcessATN(&nindex, &tindex, &atn_type) != GOOD) || (atn_type != 63)) {
            if ( ProcessATN(&nindex, &tindex, &atn_type) != GOOD ) {
//                m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
                m_bDispOff = 1;
                m_dwOffset = GetFileCurPos();
                return FAILURE;
            }
            /* We don't need this stuff */
            Get695Number(&at_typeid);
            Get695Number(&nfields);
            break;

        default:
			/* either end-extern part, or out of synch:
			check for RT_AT type records */
            return (GOOD);
        }
    }  	/* while */
}  	/* ProcessExtPart */

/****************************************************************************
**
**  Ldr695DataPart
**
**  This function is called from ldr.c after the section info has
**  been obtained from Section Part of file.
**   
**  This function picks out LD (load constant byte) and RE (repeat)
**  records from the data section of the file and writes them to
**  memory.  ASP records indicate a change in address; otherwise
**  successive LD and RE records are contiguous in memory.
**
**  Note that this code supports LD and RE records of arbitrary size.
**  IEEE-695 specifies a maximum of 128 bytes in LD and RE records.
**  This support is needed since some compilers are not quite IEEE-compliant.
**
*****************************************************************************/
int LoaderServer::Ldr695DataPart(U32 *bytesLoaded)
{
    U32 ASPaddr, addrBitsChanged;
    U32 sindex;   // section number -- ignored 
    SEGMENTTYPE curType, ttType;
    U32 currentLoadAddr;
    unsigned char *data;
    U32 i , j;
    U32 blockPos;
    int err;

    currentLoadAddr = 0L;       
    curType = SEG_CODE;
    *bytesLoaded = 0L;

	// Seek to data part of file
    if ( startAddr_ASW[5] == 0L) return GOOD;
   
	// ASW5  --  Data Part
    if ( GOOD != SeekLoadFile(startAddr_ASW[5],SEEK_SET) ) {
        m_dwErrorNum = ER_LDR_READ_FILE;		// 0x400F;
        return FAILURE;
    }            

	// Process SB/ASP/{LD|RE}* records until encountering another type 
    while (1) {
#ifdef _DUMP_
		recordStartPos = GetFileCurPos();
#endif
		// Expects record type SB or ASP (SR_AS_PREFIX:SR_ASP) 
        blockPos = (U32) (m_uBufInFilePos+m_uBufPos);
        if ( startAddr_ASW[6] && blockPos >= startAddr_ASW[6] ) 
            return GOOD;

        if ( TestKey(VK_ESCAPE) == 1 ) { 
            m_dwErrorNum = ER_LDR_ABORT;	// 0x4010;
            return FAILURE;
        }                  
        if ( (m_window == LOAD_FROM_DIALOG)&&(m_ldrFlags & LDR_STATUS) ) {
            if ( IsLoadCanceled() ) {
                m_dwErrorNum = ER_LDR_ABORT;	// 0x4010;
                return FAILURE;
            }                  
            TestMessage();
        }
        if ( GOOD != PeekByte(&curByte) ) {
            m_dwErrorNum = ER_LDR_READ_FILE;	// 0x400F;
            m_bDispOff = 1;
            m_dwOffset = GetFileCurPos();
            return FAILURE;
        }
        if (curByte != IEEE_SB && curByte != IEEE_AS)
            break;
		// skip optional SB record - sets current section 
        if (curByte == IEEE_SB)
            if ( GOOD != Get695Srecord(&sindex, &ASPaddr) ) {
                m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
                m_bDispOff = 1;
                m_dwOffset = GetFileCurPos();
                return FAILURE;
            }

		// ASP record gives load address for this chunk of data 
        if ( GOOD != Get695Srecord(&sindex, &ASPaddr) ) {
            m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
            m_bDispOff = 1;
            m_dwOffset = GetFileCurPos();
            return FAILURE;
        }    
        if ( GetSegType(sindex,ttType) != GOOD ) {
            m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
            m_bDispOff = 1;
            m_dwOffset = GetFileCurPos();
            return FAILURE;
        }    
        if ( curByte != IEEE_ASP ) 
            break;
		// Send new address record, changing as few bytes as possible 
        if ((addrBitsChanged = ASPaddr ^ currentLoadAddr) != 0) {
            currentLoadAddr = ASPaddr;
        }
        curType = ttType;
      
		// Now the file should have a sequence of LD and/or RE records 
        while (1) {
#ifdef _DUMP_
			recordStartPos = GetFileCurPos();
#endif
            if ( TestKey(VK_ESCAPE) == 1 ) { 
                m_dwErrorNum = ER_LDR_ABORT;	// 0x4010;
                return FAILURE;
            }                  
            if ( (m_window == LOAD_FROM_DIALOG)&&(m_ldrFlags & LDR_STATUS) ) {
                if ( IsLoadCanceled() ) {
                    m_dwErrorNum = ER_LDR_ABORT;	// 0x4010;
                    return FAILURE;
                }                  
                TestMessage();
            }
            if ( GOOD != GetOneByte(&curByte) ) {
                m_dwErrorNum = ER_LDR_READ_FILE;	// 0x400F
                m_bDispOff = 1;
                m_dwOffset = GetFileCurPos();
                return FAILURE;
            }
            if (curByte == IEEE_RE || curByte == IEEE_LD) {
				// RE record : {RE}{repeat count}{LD}{byte count}{data}
				// LD record : {LD}{byte count}{data}

                U32 repCount, byteCount;
                if( curByte == IEEE_RE ) {
                	if (Get695Offset(&repCount)!=GOOD) {
                    	m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
                    	m_bDispOff = 1;
                        m_dwOffset = GetFileCurPos();
                        return FAILURE;
                	}
                	if (MatchRecord(IEEE_LD)!=GOOD) {
                    	m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
                    	m_bDispOff = 1;
                        m_dwOffset = GetFileCurPos();
                        return FAILURE;
                	}
                }
                else repCount = 1;
                if (Get695Offset(&byteCount)!=GOOD) {
                    m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
                    m_bDispOff = 1;
                    m_dwOffset = GetFileCurPos();
                    return FAILURE;
                }

/*
            if ((err = LdrQueueDataRecord(&hfile, ReadBytes,
               currentLoadAddr, repCount, byteCount)) != GOOD) return(err);
*/                  
                data = new unsigned char[byteCount];
                if ( data == 0 ) {
                    m_dwErrorNum = ER_LDR_MEMORY_ALLOC;		//0x4000;
                    return FAILURE;
                }
                if ( GOOD != GetBytes(data,(int)byteCount) ) {
                	delete data;
                    m_dwErrorNum = ER_LDR_READ_FILE;	// 0x400F;
                    m_bDispOff = 1;
                    m_dwOffset = GetFileCurPos();
                    return FAILURE;
                }
                    
                j = currentLoadAddr;
                for(i=0;i<repCount;i++) {
                    ADDR stAddr , endAddr;               
                    U32 tt;
                    int ii;
                    
                    ii = 0;                                        
                    
                    //for load to x area                    
                    if ( LOAD_TODATA( m_ldrFlags ) ){
                        //m_dwErrorNum = ER_LDR_X_AREA;
                        return -1;
                    }
                    if ( curType == SEG_CODE ) 
                        stAddr.addrType = endAddr.addrType = 1;
                    else if ( curType == SEG_XDATA )    
                        stAddr.addrType = endAddr.addrType = 2;
                    else if ( curType == SEG_DATA )
                        stAddr.addrType = endAddr.addrType = 3;
                    else if ( curType == SEG_BIT )
                        stAddr.addrType = endAddr.addrType = 5;    
                    else 
                        stAddr.addrType = endAddr.addrType = 1;    
                    //for load to specified bank
                    if(g_nBankNum){
                       stAddr.addrType = endAddr.addrType = 6;
                       if(m_bLoadToBank&&m_window==LOAD_FROM_SHELL){
                          stAddr.addrType = endAddr.addrType = U8(m_bLoadToBank);    
                       }
                    }
                    else   
                        stAddr.addrType = endAddr.addrType = 1;    
                    
#ifdef _ZLR_                    
                    while( ii < (int)byteCount ) {
                    	tt = ( byteCount-ii > 254 ) ? 254 : byteCount-ii ;
                        stAddr.addr = (unsigned short)j;
                        endAddr.addr=(unsigned short)(stAddr.addr+tt-1);
                        err=AbiFill(stAddr , endAddr ,(char *)&data[ii], 
                                (unsigned short)tt );
                        j  += tt;    
                        ii += (int)tt;
                        if ( err != ICE_OK ) {
                        	delete data;
                            m_dwErrorNum = ER_ICE_FAIL_MEM_WRITE;	// 0x4020;
                            return FAILURE;
                        }              
                    }           
#endif                  
                }                    
                
                delete data;    
                *bytesLoaded += repCount*byteCount;
                currentLoadAddr += repCount*byteCount;                    
            } else {
				// Not LD or RE record 
            	if( UngetOneByte() == FAILURE ) {
            		m_dwErrorNum=ER_LDR_READ_FILE;	// 0x400F;
            		m_bDispOff = 1;
                    m_dwOffset = GetFileCurPos();
                    return FAILURE;
            	}
                break;
            }
        }            
    }
	// send partially filled load buffer to box 
    return( GOOD );
}

/******************************************************************************
**
**  Ldr695TrailPart
**
******************************************************************************/
int LoaderServer::Ldr695TrailPart(void) 
{
	// Seek to Trailer part of file
    if ( startAddr_ASW[6] == 0L) return GOOD;
   
	// ASW6  --  Trailer Part
    if ( GOOD != SeekLoadFile(startAddr_ASW[6],SEEK_SET) ) {
        m_dwErrorNum = ER_LDR_READ_FILE;	// 0x400F;
        m_bDispOff = 1;
        m_dwOffset = GetFileCurPos();
        return FAILURE;
    }            

    if ( GOOD != Match2Record(IEEE_AS, IEEE_ASG) ) {
//        m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
//        return FAILURE;
		return GOOD;
    }            

    if ( GOOD != MatchRecord(0xBE) ) {
        m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
        m_bDispOff = 1;
        m_dwOffset = GetFileCurPos();
        return FAILURE;
    }            

    if ( GOOD != Get695Offset(&m_startaddress) ) {
        m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
        m_bDispOff = 1;
        m_dwOffset = GetFileCurPos();
        return FAILURE;
    }  
#ifdef _DUMP_
	Message("	Starting Address: %lx",m_startaddress);
#endif

    return GOOD;
}  	// ProcessTrailPart 

/******************************************************************************
**
** Ldr695DebugPart
**
******************************************************************************/
int LoaderServer::Ldr695DebugPart(void) 
{
    BOOL createAsm;
    BOOL updateModule;
    char *blockName,*pdot;
    char highLevelBlockName[512] = "";
    U16 blockType;
    U32 blockPos , blockSize;

	// Seek to Debug part of file
    if ( startAddr_ASW[4] == 0L) return GOOD;
   
	// ASW4  --  Debug Part
    if ( GOOD != SeekLoadFile(startAddr_ASW[4],SEEK_SET) ) {
        m_dwErrorNum = ER_LDR_READ_FILE;	// 0x400F;
        m_bDispOff = 1;
        m_dwOffset = GetFileCurPos();
        return FAILURE;
    }
    m_dwErrorNum = 0;            
        
    // blockName = 0;    
	// Main block-processing loop for loading symbols 
    while (1) {
        if ( TestKey(VK_ESCAPE) == 1 ) { 
            m_dwErrorNum = ER_LDR_ABORT;	// 0x4010;
            return FAILURE;
        }                  
        if ( (m_window == LOAD_FROM_DIALOG)&&(m_ldrFlags & LDR_STATUS) ) {
            if ( IsLoadCanceled() ) {
                m_dwErrorNum = ER_LDR_ABORT;	// 0x4010;
                return FAILURE;
            }                  
            TestMessage();
        }
#ifdef _DUMP_
		recordStartPos = GetFileCurPos();
#endif

		// Need this in case we need to seek here later for ondemandloading
        blockPos = (U32) (m_uBufInFilePos+m_uBufPos);
        if ( MatchRecord(IEEE_BB) == GOOD) {
            if (GOOD!=Get695BB(&blockSize,(LPSTR)blockName,&blockType)) {
                m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
                m_bDispOff = 1;
                m_dwOffset = GetFileCurPos();
                return FAILURE;
            }            
            //if (blockSize > 0)
            //    nextBlockPos = blockPos + blockSize;
        } 
        else {
			// NOTES: 03/03/94 - Nghia
			// Make sure that the <blockPos> is at the end of debug part
			// else scan to the next BB and continue processing
			// BUG: Introl compiler - BB10 does not have BB11, which cause
			// the block to be out of synch and exit, although the <blockPos>
			// has not reached the end of debug part.
            LONG dummyPos;
            if (startAddr_ASW[5] && (blockPos < startAddr_ASW[5]) &&
                ( SyncTo(IEEE_BB, &dummyPos)== GOOD ) ) 
                continue; // scan BB block again
         
         	// Exit process debug part 
            break;
        }
      
        switch (blockType) {
        case 1 :		// BB1
        case 3 :		// BB3
            if ( Ldr695GetModule(blockPos,FALSE) != GOOD ) { 
            	if ( m_dwErrorNum == ER_LDR_ABORT )	// 0x4010 ) 
            		return FAILURE;
                if ( SkipOver(blockPos, blockSize, blockType)!= GOOD ) 
                    return FAILURE;
            }
			// Remember BB3 block name to skip over its BB10 
            lstrcpy((LPSTR)highLevelBlockName, (LPSTR)blockName);
            pdot = strstr(highLevelBlockName,".");
            if( pdot ) *pdot='\0';
            
            // even if ondemand is given, we still need to skip over 
            // NOTES: Nghia - 08/19/93
            // In case of error, ProcessDbgLines() will set the nextBlockPos
            // to the input position or the new block to continue.
            // This to handle both error recovery and a module does not have
            // a BB5 block follow a BB3 block.
            
            break;
        case 10 :		// BB10
			// 09/14/93 - Nghia
			// Only process BB10 that does not associate with a previously
			// processed BB3. - If name matched then they're the same.
			// Skip over to the next block. It's very wasteful to scan the
			// BB10 block that associates with a already loaded high level
			// block.
			// 09/29/93 - Nghia
			// Process BB10 if blockSize is 0 to makesure file load OK.
			// 10/27/94 - Nghia
			// Process BB10 to get address range of ASM source module.
            createAsm = TRUE;
            updateModule = FALSE;
            if ( 0 == lstrcmpi((LPSTR) highLevelBlockName,
                                        (LPSTR) blockName) ) {
                createAsm = FALSE;
                if ( start > end ) updateModule = TRUE;
            }
            // Reset the block name for the next module
            highLevelBlockName[0] = '\0';
            if ( createAsm || !blockSize || updateModule ) {
#ifdef _DUMP_
				Message("Load Asm BB10 at %4lX",recordStartPos);
#endif
                if ( ProcessDbgAsmBlock(blockSize, 
                    (LPSTR) blockName,createAsm,updateModule) == GOOD) {
                     // Reset the block name for the next module
                    // highLevelBlockName[0] = '\0';
                    break; // out of switch 
                }
            }
            else if ( m_dwErrorNum == ER_LDR_ABORT )	// 0x4010 ) 
            	return FAILURE;		// ESC Break
			// Handle Error recovery 
            else {
#ifdef _DUMP_
				Message("SkipOver Asm BB10 at %4lX",recordStartPos);
#endif
            	if ( SkipOver(blockPos, blockSize,blockType,TRUE) != GOOD ) {
                	m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
                	m_bDispOff = 1;
                    m_dwOffset = GetFileCurPos();
                    return FAILURE;    
            	}
            }
            break;
            
        case 2 : 		// BB2
			// Don't process but also don't want to error out 
            if ( SkipOver(blockPos, blockSize, blockType) != GOOD ) {
                m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
                m_bDispOff = 1;
                m_dwOffset = GetFileCurPos();
                return FAILURE;
            }            
            break;
            
        default:
            // Skip to the next block 
            if ( SkipOver(blockPos, blockSize, blockType) != GOOD ) {
                m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
                m_bDispOff = 1;
                m_dwOffset = GetFileCurPos();
                return FAILURE;
            }            
            break;
        } 	// switch() 

        if( blockName ) delete blockName;
    } 	// end of while 
   
    return (GOOD);
}	// ProcessDebugPart 

/*****************************************************************************
**
**  ProcessDbgTypes - BB1
**
** In general, we call the Symbol Table to add the type header information
** here; any member information (struct/union) or information particular
** to the type we are dealing with (arrays), we pass off to another routine,
** which adds the item to the Symbol Table.
**
*****************************************************************************/
int LoaderServer::Ldr695LoadTypes(void) 
{
    TYPE_HEADER_TYPE typeHdrInfo;
    U32 nindex;
    U16 cbyte, stype;
    U32 tindex;  // for type fix-up 
    LONG filePos;           
    char *str;
    int k;

    if ( m_typeNum ) {
        m_typeDelta += m_typeNum;
        m_typeNum = 0;
    }                         
                                                
    str = 0;  
    k = 0;
#ifdef _DUMP_
	recordStartPos = GetFileCurPos();
#endif

	// Record NN/TY pair defined symbol type information 
    while ( MatchRecord( IEEE_NN ) == GOOD ) {
        if ( Get695Nrecord(&nindex, (LPSTR)str) != GOOD ) {
         	// Fall through to continue processing
            m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
            m_bDispOff = 1;
            m_dwOffset = GetFileCurPos();
            return FAILURE;
        }            
        k++;
        if ( MatchRecord(IEEE_TY) != GOOD ||
          ( ProcessTY(&tindex, m_typeDelta, &nindex, &stype) != GOOD) ) {
			// If error occurred, SyncTo the next posible NN 
            SyncTo(IEEE_NN, &filePos);
            continue; 	// next type 
        }
		// Construct general type header info 
        typeHdrInfo.typeChoice    = COMPLEX_TYPE_CLASS;
        typeHdrInfo.t.complexType = (COMPLEX_TYPE) stype;
        typeHdrInfo.sizeInMAUs    = 0L;		// default MAU size for all type
        typeHdrInfo.typeName      = str;  
		// pointer assign 
		// Symbol type - see Appx A 
        switch (stype) {
        case 0x21 :		// TY_UNKNOWN (!) - [n4]
            typeHdrInfo.sizeCalculated = TRUE;
            Get695Offset(&typeHdrInfo.sizeInMAUs);	// optinal
            if ( SymAddTypeHeader(tindex, &typeHdrInfo)!=GOOD ) {
                m_dwErrorNum = ER_LDR_SYM_SERVER;	// 0x4025;
                return( FAILURE );
            }
            break;

        case 0x4E : 	// TY_ENUM_C (N) - n4 n5 [n6 n7]*
			// check for size of packed enums (supported by MRI) 
			// default size for enum members is sizeof(int).  Note
			// that MRI treats as signed/unsigned depending on values
			// found in enumeration - we don't care, always unsigned.

            typeHdrInfo.sizeInMAUs = 2;
            if ( PeekByte(&curByte) != GOOD ) {
                m_dwErrorNum = ER_LDR_READ_FILE;	// 0x400F;
                m_bDispOff = 1;
                m_dwOffset = GetFileCurPos();
                return( FAILURE );
            }            
            if ( (curByte) == 0 ) {
               	// size byte follows 
                if ( GetOneByte(&curByte) != GOOD ||
                	 Get695Number(&cbyte) != GOOD ) {
                    m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
                    m_bDispOff = 1;
                    m_dwOffset = GetFileCurPos();
                    return( FAILURE );
                }            
                typeHdrInfo.sizeInMAUs = cbyte;
            }
            
            typeHdrInfo.sizeCalculated = TRUE;
            if ( SymAddTypeHeader(tindex, &typeHdrInfo) != GOOD ) {
                m_dwErrorNum = ER_LDR_SYM_SERVER;	// 0x4025;
                return( FAILURE );
            }
            if ( GOOD != GetTypeEnum(tindex) ) {
                m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
                m_bDispOff = 1;
                m_dwOffset = GetFileCurPos();
                return( FAILURE );
            }            
            break;

        case 0x4F :		// TY_SMALL_PTR (O) - n4
        case 0x50 :     // TY_LARGE_PTR (P)
            typeHdrInfo.t.complexType = TY_OMF51_PTR;
            if (stype == 0x4F)
                typeHdrInfo.sizeInMAUs = 1;
            else 
                typeHdrInfo.sizeInMAUs = 2;
            typeHdrInfo.sizeCalculated = TRUE;
            if ( SymAddTypeHeader(tindex, &typeHdrInfo) != GOOD) {
                m_dwErrorNum = ER_LDR_SYM_SERVER;	// 0x4025;
                return( FAILURE );
            }
/*
            if (stype == 0x4F)
                typeHdrInfo.sizeInMAUs = 3;
            else 
                typeHdrInfo.sizeInMAUs = 3;
            typeHdrInfo.sizeCalculated = TRUE;
            if ( SymAddTypeHeader(tindex, &typeHdrInfo) != GOOD) {
                m_dwErrorNum = 0x4025;
                return( FAILURE );
            }
*/            
			// NOTES:
			// even some of these *look* to us like built-in types
			// (like, pointer to int), if they are defined here and
			// given a new type index, we'd better capture them, because
			// subsequent symbol declarations will probably use these.

            if ( GOOD != GetTypePtr(tindex, stype, m_typeDelta) ) {
                m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
                m_bDispOff = 1;
                m_dwOffset = GetFileCurPos();
                return FAILURE;
            }            
            break;

        case 0x47 :		// TY_G_STRUCT (G) - n4 [n5 n6 n7 n8]*
        	// Green Hills compiler may generate this record
        case 0x53 :		// TY_STRUCT (S) - n4 [n5 n6 n7]*
        case 0x55 :     // TY_UNION  (U)
            if ( GOOD != Get695Offset(&typeHdrInfo.sizeInMAUs) ) {
                m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
                m_bDispOff = 1;
                m_dwOffset = GetFileCurPos();
                return FAILURE;
            }
            typeHdrInfo.sizeCalculated = TRUE;
            if ( SymAddTypeHeader(tindex, &typeHdrInfo) != GOOD) {
                m_dwErrorNum = ER_LDR_SYM_SERVER;	// 0x4025;
                return( FAILURE );
            }
			// possible undefined struct (because of pointer to it) 
            if (typeHdrInfo.sizeInMAUs != 0L) {
                if ( GOOD != GetTypeSU(tindex, stype, m_typeDelta) ) {
                    m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
                    m_bDispOff = 1;
                    m_dwOffset = GetFileCurPos();
                    return FAILURE;
                }
            }
            break;

        case 0x54:		// TY_TYPE (T) - n4
			// NOTES: 09/15/93 - Nghia
			// Defer sizeInMAUs calculation to access time
            typeHdrInfo.sizeCalculated = FALSE; 
            if ( GetTypeTypedef(tindex,&typeHdrInfo,m_typeDelta)!=GOOD) {
                m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
                m_bDispOff = 1;
                m_dwOffset = GetFileCurPos();
                return FAILURE;
            }
            break;

        case 0x56 :		// TY_VOID (V)
			// undocumented by 695; used by MRI C 
            typeHdrInfo.sizeCalculated = TRUE;
            if ( SymAddTypeHeader(tindex, &typeHdrInfo) != GOOD ) {
                m_dwErrorNum = ER_LDR_SYM_SERVER;	// 0x4025;
                return( FAILURE );
            }
            if ( GOOD != MapTypeVoid(tindex) ) {
                m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
                m_bDispOff = 1;
                m_dwOffset = GetFileCurPos();
                return( FAILURE );
            }
            break;

        case 0x5A :		// TY_C_ARRAY (Z) -n4 n5
			// NOTES: Defer sizeInMAUs calculation until access time 
            typeHdrInfo.sizeCalculated = FALSE;
            if ( GetTypeArr(tindex,m_typeDelta, &typeHdrInfo) != GOOD ) {
                m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
                m_bDispOff = 1;
                m_dwOffset = GetFileCurPos();
                return( FAILURE );
            }
            break;

        case 0x67 : 	// TY_BITFIELD (g) -n4 n5 n6
			// NOTES: Defer sizeInMAUs calculation until access time 
            typeHdrInfo.sizeCalculated = FALSE;
            if ( GetTypeBit(tindex, &typeHdrInfo)!=GOOD ) {
                m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
                m_bDispOff = 1;
                m_dwOffset = GetFileCurPos();
                return( FAILURE );
            }
            break;
        
        // IEEE-695 V4.0 ERRATA P.12
        case 0x6E :   // Type qualifier (n) - n4 n5 [...]
            typeHdrInfo.t.complexType = (COMPLEX_TYPE)0x54;
            if ( GOOD!=GetType6E(tindex,stype,m_typeDelta,typeHdrInfo) ) {
                m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
                m_bDispOff = 1;
                m_dwOffset = GetFileCurPos();
                return FAILURE;
            }            
            break;

        case 0x78 : 	// TY_FUNC_DEP (x) n4 n5 n6 n7 n8 [n9]* n11 [I]
			// Size of procedure type is 0 and calculated 
            typeHdrInfo.sizeCalculated = TRUE;
			// Note: don't need to demangle function names as type entries
			// (they will get demangled when stored inside the BB3 module).

            if ( SymAddTypeHeader(tindex, &typeHdrInfo)!=GOOD ) {
                m_dwErrorNum = ER_LDR_SYM_SERVER;	// 0x4025;
                return( FAILURE );
            }
            if ( GetTypeProc(tindex, m_typeDelta) != GOOD ) {
                m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
                m_bDispOff = 1;
                m_dwOffset = GetFileCurPos();
                return( FAILURE );
            }
            break;

        case 0x58 :		// TY_FUNC_NODEP (X) - n4 n5 n6 [n7]*
        	// Green Hills compiler may generate this record
			// Size of procedure type is 0 and calculated 
            typeHdrInfo.sizeCalculated = TRUE;
			// Note: don't need to demangle function names as type entries
			// (they will get demangled when stored inside the BB3 module).

            if ( SymAddTypeHeader(tindex, &typeHdrInfo)!=GOOD ) {
                m_dwErrorNum = ER_LDR_SYM_SERVER;	// 0x4025;
                return( FAILURE );
            }
            if ( GetTypeProc(tindex, m_typeDelta, FALSE) != GOOD ) {
	            if ( SyncTo(IEEE_NN, &filePos) != GOOD ) {
	                m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
	                m_bDispOff = 1;
                    m_dwOffset = GetFileCurPos();
                    return( FAILURE );
	            }
            }
            break;        

        default:
            // 02/24/94 - Nghia
            // Collect all TY types that are not handle and report only
            // once, or when another new TY type is occurred.
			// If error occurred, SyncTo the next posible NN and report error
            if ( SyncTo(IEEE_NN, &filePos) != GOOD ) {
                m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
                m_bDispOff = 1;
                m_dwOffset = GetFileCurPos();
                return( FAILURE );
            }
//            continue;
        } 	// switch() 
        
        if( str ) delete str;
        if ( TestKey(VK_ESCAPE) == 1 ) { 
            m_dwErrorNum = ER_LDR_ABORT;	// 0x4010;
            return FAILURE;
        }                  
        if ( (m_window == LOAD_FROM_DIALOG)&&(m_ldrFlags & LDR_STATUS) ) {
            if ( IsLoadCanceled() ) {
                m_dwErrorNum = ER_LDR_ABORT;	// 0x4010;
                return FAILURE;
            }                  
            TestMessage();
        }
#ifdef _DUMP_
		recordStartPos = GetFileCurPos();
#endif
    }  // while NN 
    
	// 02/24/94 - Nghia
	// report the last type not handle
    m_typeNum = k;
    if ( GOOD != UngetOneByte() ) {
        m_dwErrorNum = ER_LDR_READ_FILE;	// 0x400F;
        m_bDispOff = 1;
        m_dwOffset = GetFileCurPos();
        return FAILURE;
    }                        
	// close block 
    return( MatchRecord(IEEE_BE) );
}  	// Ldr695LoadTypes 
                                                             
/***************************************************************************
*                                                                          *
*  Ldr695GetModule - Load IEEE695 one module information                   *
*  parameter :                                                             *
*       reclen  --  record length                                          *
*       onDemandFlag -- on demand load flag                                *
*  return value :                                                          *
*       0  ---  OK                 -1  ---  failure                        *
*                                                                          *
***************************************************************************/
int LoaderServer::Ldr695GetModule(U32 blockPos , BOOL onDemandFlag) 
{
    char *blockName;
    U16 blockType;
    U32 blockSize, nextBlockPos = 0L;
    U32 typeOffset = 0L;
    LONG dummyPos;

    ClearUpModuleBlock();
                           
    curBlock = 0;
    start = DEFAULT_START_ADDR;
    end = DEFAULT_END_ADDR;
    ModuleNodeInit();                       
    m_modNode.offset = blockPos;
    
	// Seek To Module Begin
    if ( GOOD != SeekLoadFile(blockPos, SEEK_SET) ) {
        m_dwErrorNum = ER_LDR_READ_FILE;	// 0x400F;
        m_bDispOff = 1;
        m_dwOffset = GetFileCurPos();
        return FAILURE;
    }            

#ifdef _DUMP_
	recordStartPos = GetFileCurPos();
#endif
    if ( MatchRecord(IEEE_BB) != GOOD) {
        if (startAddr_ASW[5] && (blockPos < startAddr_ASW[5]) &&
            (SyncTo(IEEE_BB, &dummyPos)== GOOD ) ) {
             dummyPos = 0L;                           
             if ( MatchRecord(IEEE_BB) != GOOD) {
                 m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
                 m_bDispOff = 1;
                 m_dwOffset = GetFileCurPos();
                 return FAILURE;
             }            
        }
        else {
            UngetOneByte();
            return GOOD;
        }    
    }
        
    if (GOOD!=Get695BB(&blockSize,(LPSTR)blockName,&blockType)) {
        m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
        m_bDispOff = 1;
        m_dwOffset = GetFileCurPos();
        return FAILURE;
    }            
    if (blockSize > 0)
        nextBlockPos = blockPos + blockSize;

    if ( blockType == 0x01 ) {
#ifdef _DUMP_
		Message("Load Type BB1 at %4lX",recordStartPos);
#endif
        if ( Ldr695LoadTypes() != GOOD) {
           	// Reset to the next block and continue processing 
           	if ( m_dwErrorNum == ER_LDR_ABORT )	//  0x4010 ) 
           		return FAILURE;
            if ( SkipOver(blockPos, blockSize, blockType)!=GOOD ) {
                m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
                m_bDispOff = 1;
                m_dwOffset = GetFileCurPos();
                return FAILURE;
            }            
        }  
        blockPos = (U32) (m_uBufInFilePos+m_uBufPos);
        
        if ( MatchRecord(IEEE_BB) != GOOD) {
            if (startAddr_ASW[5] && (blockPos < startAddr_ASW[5]) &&
                ( SyncTo(IEEE_BB, &dummyPos)== GOOD ) ) {
                dummyPos = 0L;
                if ( MatchRecord(IEEE_BB) != GOOD) {
                    m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
                    m_bDispOff = 1;
                    m_dwOffset = GetFileCurPos();
                    return FAILURE;
                }            
            }
            else {     
                UngetOneByte();
                return GOOD;
            }
        }
        if ( blockName ) delete blockName;
        if (GOOD!=Get695BB(&blockSize,(LPSTR)blockName,&blockType)) {
            m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
            m_bDispOff = 1;
            m_dwOffset = GetFileCurPos();
            return FAILURE;
        }            
    }
        
    if ( blockType == 0x03 ) {
        if ( Ldr695GetBB3(blockPos , blockName , blockSize, 
            onDemandFlag) != GOOD ) {
           	// Reset to the next block and continue processing 
           	if ( m_dwErrorNum == ER_LDR_ABORT)	//  0x4010 ) 
           		return FAILURE;
            if ( SkipOver(blockPos, blockSize, blockType)!=GOOD ) {
                m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
                m_bDispOff = 1;
                m_dwOffset = GetFileCurPos();
                return FAILURE;
            }            
        }                                       
        blockPos = (U32) (m_uBufInFilePos+m_uBufPos);
        
        if ( MatchRecord(IEEE_BB) != GOOD) {
            if (startAddr_ASW[5] && (blockPos < startAddr_ASW[5]) &&
                ( SyncTo(IEEE_BB, &dummyPos)== GOOD ) ) {
                dummyPos = 0L;
                if ( MatchRecord(IEEE_BB) != GOOD) {
                    m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
                    m_bDispOff = 1;
                    m_dwOffset = GetFileCurPos();
                    return FAILURE;
                }            
            }
            else {     
                UngetOneByte();
                return GOOD;
            }
        }
        if ( blockName ) delete blockName;
        if (GOOD!=Get695BB(&blockSize,(LPSTR)blockName,&blockType)) {
            m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
            m_bDispOff = 1;
            m_dwOffset = GetFileCurPos();
            return FAILURE;
        }            
        if ( blockName ) delete blockName;
    }
        
    if ( blockType == 0x05 ) {
#ifdef _DUMP_
		Message("Load Line B5 at %4lX",recordStartPos);
#endif
        if (blockSize > 0)
            nextBlockPos = blockPos + blockSize;
        else 
            nextBlockPos = 0L;    
        if ( GOOD != SeekLoadFile(blockPos, SEEK_SET) ) {
            m_dwErrorNum = ER_LDR_READ_FILE;	// 0x400F;
            m_bDispOff = 1;
            m_dwOffset = GetFileCurPos();
            return FAILURE;
        }            
        if ( GOOD != ProcessDbgLines(&nextBlockPos, &blockSize,
                                onDemandFlag ) ) {
           	if ( m_dwErrorNum == ER_LDR_ABORT)	//  0x4010 ) 
           		return FAILURE;
            if ( SkipOver(blockPos, blockSize, blockType)!=GOOD ) {
                m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
                m_bDispOff = 1;
                m_dwOffset = GetFileCurPos();
                return FAILURE;
            }            
        }                                       
        blockPos = (U32) (m_uBufInFilePos+m_uBufPos);
    }
    else {
        SeekLoadFile(blockPos , 0);
    }
    return GOOD;
}

/******************************************************************************
**
**  GetTypePtr - Process Pointer type
**
******************************************************************************/
int LoaderServer::GetTypePtr(U32 tindexParent, U16 stype, U32 toffset) 
{
    U32 tindex;
    TYPE_OMF51_PTR_STRUCT omf51Ptr;

	// Used to finish processing the following symbol types for RT_TY records:
	// O (16-bit pointer) - obtain target type index
	// P (32-bit pointer) - "

    if ( Get695Offset(&tindex) != GOOD ) return FAILURE;
    if ( tindex >= 0x100 ) tindex += toffset;
    switch (stype) {
    case 0x4F :		// O
    case 0x50 :		// P
		// add: pointer type, target type 
        if ( stype == 0x4F ) {
            omf51Ptr.memSpace = IDATA_51 ;
            omf51Ptr.typeIndex = tindex;
            omf51Ptr.attribute = 2;
            omf51Ptr.ptrSpec = 1;
        }
        else {
            omf51Ptr.memSpace = XDATA_51 ;
            omf51Ptr.typeIndex = tindex;
            omf51Ptr.attribute = 2;
            omf51Ptr.ptrSpec = 1;
        }                                           
        if ( SymAddTypePointer51(tindexParent , &omf51Ptr) != GOOD) {
            return FAILURE;
        }
        
/*
        if ( SymAddTypePointerTypeIndex(tindexParent,tindex) != GOOD) {
            return FAILURE;
        }
*/
        break;
    default:
        return FAILURE;
    }
    return(GOOD);
}  	// GetTypePtr 

/******************************************************************************
**
**  GetType6E - Process unknown type 6E type
**
******************************************************************************/
int LoaderServer::GetType6E(U32 tindexParent, U16 /*stype*/, U32 toffset,
    TYPE_HEADER_TYPE& typeHdrInfo) 
{
/*
    U32 tindex;
    U16 attr,attr1;
    TYPE_OMF51_PTR_STRUCT omf51Ptr;

    if ( Get695Number(&attr) != GOOD ) return FAILURE;
    if ( Get695Offset(&tindex) != GOOD ) return FAILURE;
    if ( Get695Number(&attr1) != GOOD ) return FAILURE;
    if ( tindex >= 0x100 ) tindex += toffset;            
    typeHdrInfo.sizeInMAUs = attr1;
    typeHdrInfo.sizeCalculated = TRUE;
    if ( SymAddTypeHeader(tindexParent, &typeHdrInfo) != GOOD) {
//        m_dwErrorNum = 0x4025;
        return( FAILURE );
    }
    switch (stype) {
    case 0x6E:
        switch ( attr ) {
        case 1 :
            omf51Ptr.memSpace = CODE_51 ;
            break;            
        case 2 :
            omf51Ptr.memSpace = XDATA_51 ;
            break;            
        case 3 :
            omf51Ptr.memSpace = IDATA_51 ;
            break;            
        case 4 :
            omf51Ptr.memSpace = IDATA_51 ;
            break;            
        case 5 :
            omf51Ptr.memSpace = IDATA_51 ;
            break;            
        default :    
            omf51Ptr.memSpace = UNKNOWN_51 ;
            break;            
        }
        if ( stype == 0x6E ) {
            omf51Ptr.typeIndex = tindex;
            omf51Ptr.attribute = 2;
            omf51Ptr.ptrSpec = 1;
        }
        if ( SymAddTypePointer51(tindexParent , &omf51Ptr) != GOOD) {
            return FAILURE;
        }                      
        break;
    default:
        return FAILURE;
    }
    return(GOOD);
*/
//    TYPE_HEADER_TYPE baseTypeHdr;
    char typeName[512] = "";
    U32 tindex;
    U16 attr,attr1;       
    TYPE_TYPE typeType;

    if ( Get695Number(&attr) != GOOD ) return FAILURE;
    if ( Get695Offset(&tindex) != GOOD ) return FAILURE;
    if ( Get695Number(&attr1) != GOOD ) return FAILURE;
    if ( tindex >= 0x100 ) tindex += toffset;            

    typeHdrInfo.sizeInMAUs = 0;
    typeHdrInfo.sizeCalculated = FALSE;
    if ( SymAddTypeHeader(tindexParent, &typeHdrInfo) != GOOD) {
        return( FAILURE );
    }                  
    typeType.typeIndex = tindex;
    switch( attr1 ) {
    case 5 :
        typeType.segType = SEG_BIT;
        break;
    case 4 :
    case 0 :
    case 3 :
        typeType.segType = SEG_DATA;
        break;
    case 2 :
        typeType.segType = SEG_XDATA;
        break;
    case 1 :
        typeType.segType = SEG_CODE;
        break;
    default :
        typeType.segType = SEG_UNTYPED;
        break;
    }                                 
    SymAddTypeTypeType(tindexParent, tindex , typeType.segType);
//    SymAddTypeTypeIndex(tindexParent, tindex);

    return GOOD;
}  /* GetTypePtr */

/******************************************************************************
**
**  GetTypeTypedef - Process typedef type
**
******************************************************************************/
int LoaderServer::GetTypeTypedef(U32 tindexParent,
                       TYPE_HEADER_TYPE *parentTypehdr,
                       U32 toffset) 
{
    U32 baseTypeIndex;
    TYPE_HEADER_TYPE baseTypeHdr;
    char typeName[512] = "";
   
	// TypeDef Record: {$F2} {n1} {$CE} {n2} [n3] [n4]..
	// Where: n3 = typedef index $54 - See Appendix A1 and A2
	// Following by a {n4} = type index of the underlying type.
   
	// Get underlying type and its type header 
    if ( Get695Offset(&baseTypeIndex) != GOOD ) return FAILURE;
    if ( baseTypeIndex >= 0x100 ) baseTypeIndex += toffset;
   
	// 08/20/93 - Nghia
	// Sierra compiler generate baseTypeIndex = 0xFFFFFFFF for
	// a typedef of union type.

//   if (baseTypeIndex >= MAX_INDEX_TYPE) { /* 0x0FFFFFFFL */
//      /* Still need to add the typedef to the symbol table */
//      parentTypehdr->sizeCalculated = TRUE;
//      if ((err = SymAddTypeHeader(tindexParent, parentTypehdr)) != GOOD)
//         return err;
//      return ER_SYM_TYPE;
//   }
         
	// Notes: Nghia 09/15/93 
	// Forward reference type will be resolved when the type gets accessing.
	// The defined type does not need to known any information about its
	// underlying type (or base type) to create the new type.

    baseTypeHdr.typeName = (LPSTR)typeName;
    if ( SymGetTypeHeader(baseTypeIndex, &baseTypeHdr) == GOOD ) {
        parentTypehdr->sizeInMAUs = baseTypeHdr.sizeInMAUs;
        parentTypehdr->sizeCalculated = TRUE;
    }
	// Create the new type and
	// Add the underlying type of typedef type      
    if ( SymAddTypeHeader(tindexParent, parentTypehdr)!=GOOD ||
        SymAddTypeTypeIndex(tindexParent, baseTypeIndex)!=GOOD ) { 
        return FAILURE;
    }
    return GOOD;
}  	// GetTypeTypedef 

/******************************************************************************
**
**  MapTypeVoid - Map type void
**
******************************************************************************/
/* For 'V' void type, create a fake mapping to typedef.  It is not 
   documented by 695, but used by MRI C in the case of functions
   returning 'void *' types.  A type for 'void' gets created, then
   a pointer type which points to target 'void', then a procedure
   which has return type this pointer to void type.
   In other words, we can't throw it out, since later compiler type
   output will reference this type.
*/
int LoaderServer::MapTypeVoid(U32 tindexParent) 
{
    U32 tindex;
   
	// underlying type is void (built-in type) 
//    tindex = T695_VOIDP;
    tindex = BI_VOID;
	// type of typedef, underlying type 
    if ( SymAddTypeTypeIndex(tindexParent, tindex) != GOOD ) {
        return FAILURE;
    }
    return GOOD;
}  /* MapTypeVoid */

/******************************************************************************
**
**  GetTypeSU - Process type structure/union
**  tindexParent - type index for parent
**  stype - type (struct/union) (not used currently)
**  toffset - type fix-up value
**
******************************************************************************/
int LoaderServer::GetTypeSU(U32 tindexParent, U16 stype, U32 toffset) 
{
//    char mbrName[512] = ""; /* REQUIRE by SYMBOL SERVER */
//    char *pname = "";  /* pointer to demangled name */
    char *str;
    U32 tindex;
    U16 mbrOffset, mbrSize;
    TYPE_S_U_STRUCT su;
    TYPE_G_STRUCT gst;

	// NOTES: assumes type header has already opened scope in symbol table;
	// we can thus add the individual members here.
	// We allow for > 64K structures (and hence, member offsets), in case
	// 'huge' or ... wait, we are in 68K land, this is just possible!

	// loop over all members of structure (no, we don't know how many) 
    //str = 0;
    while (1) {
    	if ( stype == 0x47 ) {
	        if ( Get695Idn(str)!=GOOD ||      		// member name 
	            Get695Offset(&tindex)!=GOOD || 		// member type 
	            Get695Number(&mbrOffset)!=GOOD ||  	// member offset
	            Get695Number(&mbrSize)!=GOOD )   	// member size
	            return FAILURE;
	        if ( tindex >= 0x100 ) tindex += toffset;    
	        gst.typeIndex = tindex;  	// element type 
	        gst.bitOffset = mbrOffset;
	        gst.bitSize = mbrSize;
	        gst.name = (LPSTR)str;
	    }
	    else {
	       	// may be unnamed struct/union members which are bitfields 
	        if ( Get695Idn(str)!=GOOD ||      		// member name 
	            Get695Offset(&tindex)!=GOOD || 		// member type 
	            Get695Number(&mbrOffset)!=GOOD )   	// member offset
	            return FAILURE;
	        if ( tindex >= 0x100 ) tindex += toffset;    
	        su.typeIndex = tindex;  	// element type 
	        su.offset = mbrOffset;
			// demangle member name before load (C++) 
//        if (ldrDemangle)
//            LdrCppFixupMember(mbrName, &pname);
//        else
//              pname = mbrName;  /* pointer assign */
//        su.name = (LPSTR)pname;  /* pointer assign */
	        su.name = (LPSTR)str;  		// pointer assign 
	        if ( SymAddTypeStructUnion(tindexParent, &su) != GOOD ) {
	            return FAILURE;
	        }
	    }
        if ( str ) delete str;
        if ( GOOD != PeekByte(&curByte) ) return FAILURE;
        if ( curByte == IEEE_NN || curByte == IEEE_BE )
            break;
    }
    return (GOOD);
}  	// GetTypeSU 

/******************************************************************************
**
**  GetTypeEnum - Process enum type
**
** tindexParent - type index for parent 
**
******************************************************************************/
int LoaderServer::GetTypeEnum(U32 tindexParent) 
{
    char *str;
    U32 mbrValue;   
   
	// loop over all members of enum (no, we don't know how many) 
    while (1) {
		// NOTES: 09/20/93 - Nghia
		// Enum type might not have any member - file VME14.X by K&S
        if ( GOOD != PeekByte(&curByte) ) return FAILURE;
        if ( curByte == IEEE_NN || curByte == IEEE_BE )
            break;
		// Get member name and member value 
        if ( Get695Idn(str)!=GOOD || Get695Offset(&mbrValue)!= GOOD ) 
            return FAILURE;
        if ( SymAddTypeEnum(tindexParent,mbrValue,str)!=GOOD ) 
            return FAILURE;
        if ( str ) delete str;
    }
    return (GOOD);
}  	// GetTypeEnum 

/******************************************************************************
**
**  GetTypeProc
**
******************************************************************************/
int LoaderServer::GetTypeProc(U32 tindex, U32 toffset, BOOL bDepent) 
{
    U16 frame, level;
    U32 rtntype, attr, pushmask, nargs;
    int i;
    U32 argtype;
    U32 *pargtypelist = NULL;
    char parentName[1] = "";  // 'fathername' field is not used for C 

	// If the ST doesn't need some of this stuff, just
	// throw it into a 'junk' field and throw it away into the garbage.
	if ( bDepent ) {
	    if ( Get695Offset(&attr) != GOOD ||
	        Get695Number(&frame) != GOOD ||
	        Get695Offset(&pushmask) != GOOD ||
	        Get695Offset(&rtntype) != GOOD ||
	        Get695Offset(&nargs) != GOOD )
	        return FAILURE;
	}
	else {
	    if ( Get695Offset(&attr) != GOOD ||
	        Get695Offset(&rtntype) != GOOD ||
	        Get695Offset(&nargs) != GOOD )
	        return FAILURE;
	}

    if ( rtntype >= 0x100 ) rtntype += toffset;
       
	// unknown nargs (See IEEE695 V 4.1 - page A-5) 
    if ( (nargs == 0xFFFFL) || (nargs == 0xFFFFFFFFL) )  
        nargs = 0L;
                               
    if ( nargs ) {
        pargtypelist = (U32 *) new U32[ nargs ];
        if ( pargtypelist == 0 ) return FAILURE;
    }    
   
    for (i=0;(U32)i<nargs;i++) {
        if ( GOOD != Get695Offset(&argtype) ) return FAILURE;
        if ( argtype >= 0x100 ) argtype += toffset;
        pargtypelist[i] = argtype;
    }

	// if allocation error, we still need to eat the bytes so we remain
	// in sync in the loadfile
	if ( bDepent ) {
    	if ( GOOD != Get695Number(&level) ) return FAILURE;
	}   
	// note: size for function *type* definition has no meaning 
    if ( SymAddTypeFunc(tindex, attr, (U8)frame, pushmask, rtntype,
            (U8) nargs, (U8) level, (LPSTR)parentName) != GOOD) {
      return FAILURE;
    }
	// don't add parms if function can't be created 
    for (i = 0; (U32)i < nargs; i++) {
        if ( SymAddTypeFuncParam(tindex, pargtypelist[i]) != GOOD ) {
            return FAILURE;
        }
    }
    if (pargtypelist != NULL) delete pargtypelist;
    return GOOD;
}  	// GetTypeProc 

/******************************************************************************
**
**  GetTypeArr - Process type array
**
******************************************************************************/
int LoaderServer::GetTypeArr(U32 tindexParent, U32 toffset,
                   TYPE_HEADER_TYPE *parentTypeHdr) 
{
    TYPE_C_ARRAY_STRUCT arrayHdrStruct;
    TYPE_HEADER_TYPE elementTypeHdr;
    char typeName[512] = "";
   
	// Get element type and boundary 
    if ( Get695Offset(&arrayHdrStruct.typeIndex)!=GOOD ||
        Get695Offset((U32 *)&arrayHdrStruct.highBound)!=GOOD )
        return FAILURE;

    if ( arrayHdrStruct.typeIndex >= 0x100 ) 
        arrayHdrStruct.typeIndex += toffset;
        
	/* NOTES: 09/16/93 - Nghia
	** We don't need the sizeInMAUs of element of array to create its type.
	** If it's a forward reference type then until the array type is accessed
	** then the symbol table will calculate the sizeInMAUs of element
	** and update the sizeInMAUs of the array type. 
	** This applies to both BUILT-IN and USER-DEFINED types.
	*/

	// Get the sizeInMAUs of the element type 
    elementTypeHdr.typeName = (LPSTR)typeName;
    if ( SymGetTypeHeader(arrayHdrStruct.typeIndex, &elementTypeHdr)==GOOD) {
		// Array size = size of element * number of element 
        parentTypeHdr->sizeInMAUs = elementTypeHdr.sizeInMAUs *
                                     (arrayHdrStruct.highBound+1);
        parentTypeHdr->sizeCalculated = TRUE;
    }
	// Add a new type header for the type and
	// Add information about its basetype and its boundary
	
    if ( SymAddTypeHeader(tindexParent, parentTypeHdr)!=GOOD ||
        SymAddTypeCArray(tindexParent, &arrayHdrStruct)!=GOOD ) {
        return FAILURE;
    }
    return(GOOD);
}  	// GetTypeArr 

/******************************************************************************
**
**  GetTypeBit - Process type bit
**
******************************************************************************/
int LoaderServer::GetTypeBit(U32 tindexParent,TYPE_HEADER_TYPE *parentTypehdr) 
{
    TYPE_BITFIELD_STRUCT bfHdrStruct;
    TYPE_HEADER_TYPE baseTypeHdr;
    char typeName[512] = "";
   
	// Get bitfield size and bitfieldsigned 
    if ( Get695Number((U16 *)&bfHdrStruct.bitfieldSigned)!=GOOD ||
        Get695Number(&bfHdrStruct.size)!=GOOD ) {              
        return FAILURE;
    }
	// The underlying type may not be given - then assume default 
	// Get the base type index 
    if ( Get695Offset(&bfHdrStruct.baseTypeIndex)!=GOOD )
    {         
        bfHdrStruct.baseTypeIndex = 4;
    }

	/* NOTES: 09/16/93 - Nghia
	** We don't need the sizeInMAUs of the underlying type to create the
	** bitfield type.  Until the type get accessing then the symbol table
	** will calculate the sizeInMAUs accordingly.
	** This applies to both BUILT-IN and USER-DEFINED types.
	*/
	/* Get the sizeInMAUs of the underlying type - if fail defer it */
    baseTypeHdr.typeName = (LPSTR)typeName;
    if ( SymGetTypeHeader(bfHdrStruct.baseTypeIndex, &baseTypeHdr)==GOOD ) {
        parentTypehdr->sizeInMAUs = baseTypeHdr.sizeInMAUs;
        parentTypehdr->sizeCalculated = TRUE;
    }
	/* Add a new type header for the type and its underlying info */
    if ( SymAddTypeHeader(tindexParent, parentTypehdr)!=GOOD ||
        SymAddTypeBitfield(tindexParent, &bfHdrStruct)!=GOOD ) {
        return FAILURE;
    }
    return GOOD;
}  	// GetTypeBit 

/*****************************************************************************
**
**  ProcessDbgModule - BB3
**
*****************************************************************************/
int LoaderServer::Ldr695GetBB3(U32 modulePos , LPSTR& moduleName ,
        U32 /*moduleSize*/ , BOOL onDemandFlag )
{
    char *str;
    QUAL_ADDR_RANGE_TYPE qaddr;
    SYM_DESCRIPTOR moduleDesc;
    char *blockName;
    U16 len;
    U16 blockType;
    U32 blockPos , blockSize;
    U32 typeOffset = 0L;         
    RETCODE retCode;
    
    ClearUpModuleBlock();   // mask
                           
    curBlock = 0;

    str = strstr(moduleName,".");
    if ( str ) *str = '\0';    
    len = (U16) strlen( moduleName );
    blockName = new char [len+1];
    strcpy(blockName,moduleName);
    
    ModuleNodeInit();    // mask
    m_modNode.offset = modulePos;
    m_modNode.time.day = -1;
    m_modNode.time.hour = -1;
    m_modNode.name = blockName;
    if(IsModuleExist(m_modNode.name)) m_IsModExist=1;
    else m_IsModExist = 0;
                               
    start = DEFAULT_START_ADDR;
    end = DEFAULT_END_ADDR;
    m_modNode.scope = 1;
  
	// Enter module symbol into Symbol Table
	// Get back module descriptor to load other debug info
	// Strip off path include in the moduleName
    if ( onDemandFlag == TRUE||m_IsModExist ) {
        moduleDesc = curModDesc;
        typeOffset = curTypeDelta;
    }
    else {
        retCode = SymAddModuleCreate(
            m_modNode.name ,
            &m_modNode.time ,
            &m_modNode.codeaddr ,
            m_modNode.offset ,
            (BOOLEAN) m_onDemand ,
            0,
            &moduleDesc );
        if ( retCode != GOOD ) {
            m_dwErrorNum = ER_LDR_SYM_SERVER;	// 0x4025;
            return( FAILURE );
        }
        curModDesc = moduleDesc;   
        typeOffset = m_typeDelta;
    }

	/*
	 Loading just an individual module will propagate thru this code,
	 don't load globals, don't load functions, just the locals inside them.
	 Loading for the first time also needs to know - all or just globals.
	 Also, loop over globals/functions (can be interspersed) 
	*/

	/* set state to boolean result, will be passed to ModuleClose */

    while (1) {
		// save current file offset in case we are ondemand, code moved
 		// to *before* peek, since peek advances the file position
#ifdef _DUMP_
		recordStartPos = GetFileCurPos();
#endif
        blockPos = (U32) (m_uBufInFilePos+m_uBufPos);
        if ( GOOD != PeekByte(&curByte) ) return FAILURE;
        if ( curByte != IEEE_NN && curByte != IEEE_BB )
            break;
		// Process globals 
        if ( curByte == IEEE_NN) {
            if ( /*onDemandFlag == FALSE&&*/!m_IsModExist ) {
                if ( GOOD != ProcessDbgGlobals(typeOffset,TRUE) ) {
                    m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
                    m_bDispOff = 1;
                    m_dwOffset = GetFileCurPos();
                    return( FAILURE );
                }
            }
            else { 	// module-only load, just process 
                if ( GOOD != ProcessDbgGlobals(typeOffset, FALSE) ) {
                    m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
                    m_bDispOff = 1;
                    m_dwOffset = GetFileCurPos();
                    return( FAILURE );
                }
            }
            continue;  // Processing
        }
		/* process functions */
/*
        if ( onDemandFlag == FALSE && m_onDemand ) {
            if ( GOOD != SkipOver(modulePos , moduleSize , 3) ) {
                m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
                return( FAILURE );
            }
            if ( GOOD != UngetOneByte() ) return FAILURE;
            break;
        }
*/            
        if ( curByte == IEEE_BB ) {
            if ( GOOD != MatchRecord(IEEE_BB) ) {
                m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
                m_bDispOff = 1;
                m_dwOffset = GetFileCurPos();
                return( FAILURE );
            }
            if ( GOOD != PeekByte(&curByte) ) return FAILURE;
			// NOTES: Nghia - 08/17/93 - Page 31 IEEE695 Spec.
			// A BB3 must have at least one BB4, BB4 can have BB6s nested but not
			// BB4, and a BB6 can have another BB6 nested, but not a BB4.

            if (IS_BBFUNCTION(curByte)) {
            	// Get BB signature 
                Get695BB(&blockSize, blockName, &blockType);
                if ( ProcessDbgFunctions(blockType, blockPos,
                        blockSize, blockName, typeOffset,
                        onDemandFlag)!=GOOD ) {
					// 02/24/94 - Nghia
					// close module in case of function block error
                    if ( /*onDemandFlag == FALSE&&*/!m_IsModExist ) {
                        retCode = SymAddModuleClose( 
                            (BOOLEAN)(!m_onDemand) );
                        if ( retCode != GOOD ) {
                            m_dwErrorNum = ER_LDR_SYM_SERVER;	// 0x4025;
                            return( FAILURE );
                        }
                    }
                    /*else {
                        retCode = SymAddModuleClose( TRUE );
                        if ( retCode != GOOD ) {
                            m_dwErrorNum = ER_LDR_SYM_SERVER;	// 0x4025;
                            return( FAILURE );
                        }
                    } */
                    return FAILURE;
                }
                if ( blockName ) delete blockName;
            }    
            else
                UngetOneByte();  // unget BB 
        }               
    }  	// while process globals/functions 

    if ( /*onDemandFlag == FALSE&&*/!m_IsModExist ) {
        retCode = SymAddModuleClose( 
            (BOOLEAN)(!m_onDemand) );
        if ( retCode != GOOD ) {
            m_dwErrorNum = ER_LDR_SYM_SERVER;	// 0x4025;
            return( FAILURE );
        }
    }
    /*else {
        retCode = SymAddModuleClose( TRUE );
        if ( retCode != GOOD ) {
            m_dwErrorNum = ER_LDR_SYM_SERVER;	// 0x4025;
            return( FAILURE );
        }
    } */

	// NOTES: Nghia - 10/26/94
	// Revised to support MRI ASM module with line numbers
	// Update module range info if valid

    m_modNode.codeaddr.segType = ( SEGMENTTYPE ) SEG_CODE;
    m_modNode.codeaddr.startAddr = start;
    m_modNode.codeaddr.endAddr = end;

    qaddr.startAddr = start;
    qaddr.endAddr = end;
    qaddr.startValid = TRUE;
    qaddr.endValid = TRUE;                      

    if ( start > end ) {
        qaddr.startValid = FALSE;
        qaddr.endValid = FALSE;
    }

    if ( qaddr.startValid || qaddr.endValid ) {
        //for load to specified bank
        if(!m_IsModExist){
           if(m_bLoadToBank&&m_window==LOAD_FROM_SHELL){
              if ( qaddr.startAddr != DEFAULT_START_ADDR &&
                		   qaddr.endAddr != DEFAULT_END_ADDR ) {
                   ConvertAddrToBank(qaddr.startAddr);
                   ConvertAddrToBank(qaddr.endAddr);
              }
           }
           retCode = SymAddSymbolSetAddr( &qaddr );
           if ( retCode != GOOD ) {
               m_dwErrorNum = ER_LDR_SYM_SERVER;	// 0x4025;
               return( FAILURE );
           }
        }
    }

    return( MatchRecord(IEEE_BE) );
}  	// Ldr695GetBB3 

/*****************************************************************************
**
**  ProcessDbgGlobals
**
*****************************************************************************/
int LoaderServer::ProcessDbgGlobals(U32 typeOffset, BOOLEAN addsym) 
{
    BOOLEAN isConst;
    char *pname; 
    LONG filePos;
    U16 nitems;
    U32 nindex; 
    U16 atnType,  reg_index;
    U32 lvalue, tindex,ln8;
    VAR_STORAGE_CLASS varClass;
    ADD_VAR_ADDR_UNION addr;
    SYM_DESCRIPTOR symDesc;

	// Process all NN, ATN, ASN records 
    //blockName = 0;
    while ( MatchRecord(IEEE_NN) == GOOD ) {
#ifdef _DUMP_
		recordStartPos = GetFileCurPos()-1;
#endif
        if ( GOOD != Get695Nrecord(&nindex, (LPSTR)pname) ) 
            return FAILURE;
        if ( Match2Record(IEEE_AT , IEEE_ATN) != GOOD ||
            ProcessATN(&nindex,&tindex,&atnType)!=GOOD ) {
			// NOTES - Nghia
			// Resync to the next possible NN record

            SyncTo(IEEE_NN, &filePos);
            continue;
        }                                                            
        if ( tindex >= 0x100 ) tindex += typeOffset; 
		// Process ATN record according to its type 
        switch (atnType) {
		// Kludge to get Cosmic stuff to load!
		// to695 seems to be generating ATN_AUTO records at the wrong
		// level for supporting their #define.
        case 1 :	// Auto variable - x1 
        	// not existence in bb3
            if ( GOOD != Get695Offset(&lvalue) ) return FAILURE;
            break;
        case 2 : 	// Register variable - x1
        	// not existence in BB3
            Get695Number(&reg_index);
			// NOTES: Usually there are ATN9 following ATN2 - ignore for now 
			// Return err indicates cannot seek file: serious error 
            if ( SyncTo(IEEE_NN, &filePos)!=GOOD )
                return FAILURE;
            break;

            
		// The following ATN types are handled at this (global) level:
		// ATN 3/4/5/8 - module misc 64 - global var register 2
        case 3 :	// Static variable - ASN 
        case 8 :	// Global variable - ASN
        			// Global - x1 ASN for BSO
        	Get695Offset(&ln8);
			// Get symbol address 
            if ( Match2Record(IEEE_AS , IEEE_ASN) != GOOD ) {
                SyncTo(IEEE_NN, &filePos);
                break;
            }
			/* Only demangle name if user said so */
            if ( Get695Offset(&nindex) != GOOD ) {
                SyncTo(IEEE_NN, &filePos);
                break;
            }
            if ( PeekByte(&curByte) != GOOD ) {
                SyncTo(IEEE_NN, &filePos);
                break;
            }
            if ( curByte == 0xCC ) {
                if ( GOOD != GetExpression(addr.addr) ) {
                    SyncTo(IEEE_NN, &filePos);
                    break;
                }
            }
            else {
                Get695Offset(&lvalue);
                addr.addr.segType = SEG_UNTYPED;
                addr.addr.addr = lvalue & 0x0000FFFFL;
            }                
            
            if (addsym) {
                isConst = FALSE;
                if (atnType == 3)
                    varClass = STATIC_VAR_CLASS;
                else
                    varClass = GLOBAL_VAR_CLASS;
//                L695OffsetToAddr(lvalue,&addr.addr);    
                if(m_bLoadToBank&&m_window==LOAD_FROM_SHELL){
                   ConvertAddrToBank(addr.addr.addr);     
                }
                SymAddVar( (LPSTR)pname,tindex,varClass,
                           NOT_REG,&addr,
                           isConst,TRUE,&symDesc);
            }
            break;

		// Process extern vars - note there may be more than one of these
		// generated for a program (hence a duplicate is ok)
        case 5 :	// External variable - NN/ATN5 only
            if (addsym) {
                if(m_bLoadToBank&&m_window==LOAD_FROM_SHELL){
                   ConvertAddrToBank(addr.addr.addr);     
                }
                SymAddVar( (LPSTR)pname,tindex,GLOBAL_VAR_CLASS,
                            NOT_REG,&addr,
                            FALSE,FALSE,&symDesc);
            }            
            break;

		// Extern functions (defined by 'x' type) 
        case 4 :	// NN/ATN4 only
            break;
        case 16 :	// Constant - x1 x2 x3 x4 
        {
			// NOTES: MRI V4.3d generates ATN16 - C's #define constant 
			// 09/20/93 - Nghia - Process ATN 16 
            char *defName = 0;
            U32  constValue = 0L;
            if ( GOOD != ProcessATN16(&constValue, (LPSTR) defName) )
                return FAILURE; 
            if( defName ) delete defName;
            break;
        }    
        case 64 :		// module misc
        	ProcessATNMisc(atnType,&ln8,typeOffset,&nitems);
            break;
        
        case 12 :
        {
        	U16 x2, x3, x4;
            
            if ( 	Get695Offset(&addr.basedVar.offsetVal) != GOOD ||
	            	Get695Number(&x2) != GOOD ||
		            Get695Number(&x3) != GOOD ||
		            Get695Number(&x4) != GOOD ||
		            Get695Offset(&addr.basedVar.baseSize) != GOOD ||
		        	Match2Record(IEEE_AS,IEEE_ASN) != GOOD ||
		            ProcessASN(&nindex, &ln8) != GOOD ) {
	            SyncTo(IEEE_NN, &filePos);
	            continue;
	        }
            addr.basedVar.controlNum = (U8)x2;
            addr.basedVar.publicLocal = (U8)x3;
            addr.basedVar.memorySpace = (U8)x4;
            if (addsym) {
                if(m_bLoadToBank&&m_window==LOAD_FROM_SHELL){
                   ConvertAddrToBank(addr.addr.addr);     
                }
                SymAddVar( (LPSTR)pname,tindex,BASED_VAR_CLASS,
                            NOT_REG,&addr,
                            FALSE,TRUE,&symDesc);
            }            
        	break;
        }
        default:
            // atnErr = atnType;
            // Return err indicates cannot seek file: serious error 
            if ( SyncTo(IEEE_NN, &filePos)!=GOOD )
                return FAILURE;
            break; 	// Process the next NN record 
        }
        if ( pname ) delete pname;
    }  	// while RT_NN 

    if ( GOOD != UngetOneByte() ) return FAILURE;
    return (GOOD);
}  	// ProcessDbgGlobals 

/*****************************************************************************
**
** ProcessDbgFunctions - BB4/BB6
**
** blockType  - function type (indicates global or static)
** blockPos   - file offset for BB record (in case we are skipping over locals)
** blockSize  - function block size
** fnname     - function name
** pmodRange  - pointer to module address range (gets updated here)
** typeOffset - type fix-up for all type indices
** oflag      - MCREATE or MOPEN (for function symbol)
** lflags     - what to load (globals, locals - see lflags.h)
**
*****************************************************************************/
int LoaderServer::ProcessDbgFunctions(U16 blockType, U32 blockPos,
                            U32 blockSize, LPSTR& fnname,
                            U32 typeOffset, BOOL onDemandFlag) 
{
    char *pname;
    FUNC_CLASS fnClass;
    long filePos;
    U32 oldBlockPos = 0L, endBlockPos = 0L;
    U32 fStartOffset, fEndOffset = 0L;
    U32 nstack, rtn_type;
    ADDRESS_TYPE addr;
    char *blockName;
    struct BlockBlock *temp;

	// Process Functions (global (BB4) and nested static (BB6) functions)
	// Also called (recursively) for unnamed blocks in C {}.
	// Always calculate expected endBlockPos (end of function block), in case
	// we need to resync. 
	
    while ( IS_BBFUNCTION(blockType) ) {
#ifdef _DUMP_
		recordStartPos = GetFileCurPos()-1;
#endif
        endBlockPos = blockPos + blockSize;
        PBBFunction(&nstack, &rtn_type, typeOffset, &fStartOffset);
        pname = fnname;  	// pointer assign 
      
		// Enter Function symbol -> Symbol Table 
        if ( m_modNode.scope == 1 ) 
            fnClass = FUNC_GLOBAL;
        else 
            fnClass = FUNC_LOCAL;    

        m_modNode.scope++;

        if ( onDemandFlag || !m_onDemand ) {
            temp = new BlockBlock;                 
            if ( temp == 0 ) {
                m_dwErrorNum = ER_LDR_MEMORY_ALLOC;		// 0x4000;
                return(FAILURE);
            }
            if ( m_modNode.scope == 2 ) {
                curBlock = temp;
            }
            else {
                curBlock->son = temp;
                temp->father = curBlock;
                curBlock = temp;
            }
            
            curBlock->scope = m_modNode.scope;
            curBlock->codeaddr.segType = ( SEGMENTTYPE ) SEG_CODE ;
            curBlock->codeaddr.startAddr = DEFAULT_START_ADDR ;
            curBlock->codeaddr.endAddr = DEFAULT_END_ADDR ;
            curBlock->srcRange.lineNumStart = 0xFFFF;
            curBlock->srcRange.lineNumEnd = 0;
    
            if(!m_IsModExist){
               if ( SymAddFuncCreate((LPSTR)pname, fnClass, nstack, 
                    &curBlock->codeaddr, rtn_type)!=GOOD ) {
                  if ( SkipOver(blockPos, blockSize, blockType)!= GOOD ) {
                       m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
                       m_bDispOff = 1;
                       m_dwOffset = GetFileCurPos();
                       return FAILURE;    
                  }
                  goto ContinueProcessing;
               }
            }
        }
        
        // Update module start address range 
        L695OffsetToAddr(fStartOffset,&addr); 
        if ( start > addr.addr ) start = addr.addr;
        if ( end < addr.addr ) end = addr.addr;
        if ( onDemandFlag || !m_onDemand ) {
            if ( curBlock->codeaddr.startAddr > addr.addr ) 
                curBlock->codeaddr.startAddr = addr.addr;
            if ( curBlock->codeaddr.endAddr < addr.addr ) 
                curBlock->codeaddr.endAddr = addr.addr;
        }
            
        /* user wants mangled names */
      
		// NOTES: Within a BB4 record, either NN or a BB6 can exist randomly
		// See Page 30 of IEEE 695 Spec. - Nghia 03/17/93 

		// NOTES: 02/24/94 - Nghia
		// Force load all local symbol if blockSize == 0,
		// SkipOver does not work correctly to get the end_address of symbol
        if ( onDemandFlag || !m_onDemand ) {
            while (1) {
#ifdef _DUMP_
				recordStartPos = GetFileCurPos();
#endif
                if ( GOOD != PeekByte(&curByte) ) return FAILURE;
				// Check for not a NN, BB and ATN record - Nghia - 05/26/93 
                if ( curByte!=IEEE_NN && curByte!=IEEE_BB 
                    && curByte!=IEEE_AT ) {
                    break; 	// exit while loop 
                }
				// Check for either an NN/ATN or a BB6 
                switch ( curByte ) {
                case IEEE_AT :
                case IEEE_NN :
                    ProcessDbgLocals(typeOffset);
                    break;				
                case IEEE_BB:		// BB6 record - nested block 
                    blockPos = (U32) (m_uBufInFilePos+m_uBufPos);
                    MatchRecord(IEEE_BB);
                    Get695BB(&blockSize, blockName, &blockType);
                    endBlockPos = blockPos + blockSize;
                    if ( blockType == 6 ) {
						// NOTES: Process all BB6 - Call recursively 
                        ProcessDbgFunctions(blockType, blockPos,
                                         blockSize, blockName,
                                         typeOffset, onDemandFlag);
                    } 
                    else {
                        if ( oldBlockPos != blockPos ) 
                            oldBlockPos = blockPos;
                        else
                            if ( SyncTo(IEEE_NN, &filePos)!=GOOD )
                                return FAILURE;
                        if ( SkipOver(blockPos, blockSize,
                            blockType)!=GOOD ) return FAILURE;
                    }
                    break;
                } 	// switch 
            }  	// while 
         
			// NOTES: 09/08/93 - Nghia
			// If for some reasons that the end function block is not found,
			// it will recover to the 'recoverBlockPos' and get the function
			// block end address.

            if ( MatchRecord(IEEE_BE) != GOOD) {
                goto SkipToEnd;  
            } else {
            	/* Get End address of function or block */
                Get695Offset(&fEndOffset);
            }
        } else {
			// NOTES: SKIP OVER FUNCTION BLOCK
			// Do not loading locals and also skipping over nested blocks 
			// Recalculate endBlockPos for each function

SkipToEnd:                  
            if (!blockSize) {
                if ( SkipOver(blockPos, blockSize, blockType)!=GOOD) 
                    return FAILURE;
                endBlockPos = (U32) (m_uBufInFilePos+m_uBufPos);
            } else {
                endBlockPos = blockPos + blockSize;
            }
			// NOTES: 02/24/94 - Nghia
			// failed to get the end address of function, so make the end
			// address = startaddress+1 and warns the user
            if ( getBlockEndAddress(endBlockPos, fStartOffset,
                                &fEndOffset)!=GOOD ) {
                fEndOffset = fStartOffset+1;
            }
         
			/* Reset file position to the end of block regardless */
            SeekLoadFile(endBlockPos, SEEK_SET);
            blockPos = (U32) (m_uBufInFilePos+m_uBufPos);
        } 	/* Skip over function */
 
		/* close fn scope */
        if ( /*onDemandFlag || !m_onDemand*/!m_IsModExist ) {
            SymAddFuncClose();        
        }    
        L695OffsetToAddr(fEndOffset,&addr); 
        if ( start > addr.addr ) start = addr.addr;
        if ( end < addr.addr ) end = addr.addr;
        if ( onDemandFlag || !m_onDemand ) {
            if ( curBlock->codeaddr.startAddr > addr.addr ) 
                curBlock->codeaddr.startAddr = addr.addr;
            if ( curBlock->codeaddr.endAddr < addr.addr ) 
                curBlock->codeaddr.endAddr = addr.addr;
            
            if ( curBlock->father ) {
                if (curBlock->father->codeaddr.startAddr
                        > curBlock->codeaddr.startAddr) {
                    curBlock->father->codeaddr.startAddr =
                            curBlock->codeaddr.startAddr;
                }
                if (curBlock->father->codeaddr.endAddr
                        < curBlock->codeaddr.endAddr) {
                    curBlock->father->codeaddr.endAddr =
                            curBlock->codeaddr.endAddr;
                }
            }
            QUAL_ADDR_RANGE_TYPE qaddr;
            qaddr.startAddr = curBlock->codeaddr.startAddr;
            qaddr.endAddr = curBlock->codeaddr.endAddr;
            qaddr.startValid = TRUE;
            qaddr.endValid = TRUE;                      
            if ( qaddr.startAddr > qaddr.endAddr ) {
                qaddr.startValid = FALSE;
                qaddr.endValid = FALSE;
            }
            if ( qaddr.startValid || qaddr.endValid ) {
                if(!m_IsModExist){
                   if(m_bLoadToBank&&m_window==LOAD_FROM_SHELL){
                      if ( qaddr.startAddr != DEFAULT_START_ADDR &&
                	 	   qaddr.endAddr != DEFAULT_END_ADDR ) {
                   	       ConvertAddrToBank(qaddr.startAddr);
                           ConvertAddrToBank(qaddr.endAddr);
                      }
                   }
                   if ( GOOD != SymAddSymbolSetAddr( &qaddr ) ) {
                        m_dwErrorNum = ER_LDR_SYM_SERVER;	// 0x4025;
                       return( FAILURE );
                   }
               }
            }   
            if ( curBlock->father ) {
                curBlock = curBlock->father;
                ClearUpBlockBlock(curBlock->son);
                delete curBlock->son;
                curBlock->son = 0;
            }
            else {
                ClearUpBlockBlock(curBlock);
                delete curBlock;
                curBlock = 0;
            }                                        
        }
/* Error recover from adding function */     
ContinueProcessing:
        
        m_modNode.scope--;
        blockPos = (U32) (m_uBufInFilePos+m_uBufPos);
		/* Get next item to process */
		if ( fnname ) {
			delete fnname;
			fnname = 0;
		}
        if ( MatchRecord( IEEE_BB ) == GOOD &&
            Get695BB(&blockSize, fnname, &blockType) == GOOD ) {
            continue;
        } else {
        	/* Thru processing BB-function records */
            UngetOneByte();
            return(GOOD);
        }
    }  	/* while BB_FUNCTION */
                  
    m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;                  
    m_bDispOff = 1;
    m_dwOffset = GetFileCurPos();
    return FAILURE;
}  	/* ProcessDbgFunctions */
       
/*****************************************************************************
**
**  ProcessDbgLocals - Locals to BB4 or BB6
**
*****************************************************************************/
int LoaderServer::ProcessDbgLocals(U32 typeOffset) 
{
    BOOLEAN isConst; 
    char *pname = 0;
    long filePos;
    SYM_DESCRIPTOR symP;
    U32 nindex;
    U16 atnType;
    U16 nrecs, reg_index;  // misc  record type 
    U32 lvalue, offset, tindex, typeid;
    ADD_VAR_ADDR_UNION addr;
    VAR_STORAGE_CLASS varClass;
    VAR_REGISTER_CLASS regClass;                      ;
    
    while (1) {
#ifdef _DUMP_
		recordStartPos = GetFileCurPos();
#endif
		// Process NN/ATN - local vars 
		if( pname ) {
			delete pname;
			pname = 0;
		}
        if ( MatchRecord(IEEE_NN) == GOOD ) 
            Get695Nrecord(&nindex, (LPSTR)pname);
        else	UngetOneByte();

		// NOTES: ATN9 records are not preceded by NN,
		// they follow ATN2 (usually) in direct succession

        if ( GOOD != PeekByte(&curByte) ) return FAILURE;
        if ( curByte != IEEE_AT ) {
            break;  // big while loop
        }
      
        if ( Match2Record(IEEE_AT, IEEE_ATN)!=GOOD ||
            ProcessATN(&nindex, &tindex, &atnType)!=GOOD ) {
         	// Recover to the next possible NN record
            if ( SyncTo(IEEE_NN, &filePos)!=GOOD ) {
                m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
                m_bDispOff = 1;
                m_dwOffset = GetFileCurPos();
                return FAILURE;
            }
            continue;
        }
        if ( tindex >= 0x100 ) tindex += typeOffset;
        isConst = FALSE;
        switch (atnType) {
		// The following ATN types are handled at this (local) level:
		// ATN 1/2/3/9/10 - proc misc 62
        case 1 :		// Auto variable - x1  stack-based
			// Notes: parameters will have a positive stack offset,
			// locals will have negative stack offset
            Get695Offset(&offset);
            addr.addr.segType = SEG_UNTYPED;
            addr.addr.addr = offset & 0x0000FFFFL;
            varClass = AUTO_VAR_CLASS;
//                L695OffsetToAddr(lvalue,&addr.addr);    
            if(!m_IsModExist){
               SymAddVar( (LPSTR)pname,tindex,varClass,
                          NOT_REG,&addr,
                          isConst,TRUE,&symP);
            }
            break;

        case 2 :		// Living register - x1
            Get695Number(&reg_index);
           	regClass = LIVING_REG ;
            addr.registerIndex = reg_index ;
            varClass = AUTO_VAR_CLASS;
            if(!m_IsModExist){
               SymAddVar( (LPSTR)pname,tindex,varClass,
                        regClass,&addr,
                        isConst,TRUE,&symP);
            }
            break;
        case 10 :		// locked register - x1 [x2]
            Get695Number(&reg_index);
			// NN or BB or BE signal end of this record 
			lvalue = 0 ;
            Get695Offset(&lvalue);		
           	regClass = LOCKED_REG ;
           	addr.lockedReg.regIndex = reg_index;
           	addr.lockedReg.autoVarOffset = lvalue;
            if(!m_IsModExist){
                SymAddVar( (LPSTR)pname,tindex,varClass,
                        regClass,&addr,
                        isConst,TRUE,&symP);
            }
            break;
       	case 3 :        // static var - ASN
        case 8 :		// no existence in BB4 BB6
			// Get symbol address 
            if ( Match2Record(IEEE_AS , IEEE_ASN) != GOOD ) { 
                SyncTo(IEEE_NN, &filePos);
                break;
            }
			/* Only demangle name if user said so */
            if ( Get695Offset(&nindex) != GOOD ) {
                SyncTo(IEEE_NN, &filePos);
                break;
            }
            if ( PeekByte(&curByte) != GOOD ) {
                SyncTo(IEEE_NN, &filePos);
                break;
            }
            if ( curByte == 0xCC ) {
                if ( GOOD != GetExpression(addr.addr) ) {
                    SyncTo(IEEE_NN, &filePos);
                    break;
                }
            }
            else {
                Get695Offset(&lvalue);
                addr.addr.segType = SEG_UNTYPED;
                addr.addr.addr = lvalue & 0x0000FFFFL;
            }                

            isConst = FALSE;
            if (atnType == 3)
                varClass = STATIC_VAR_CLASS;
            else
                varClass = GLOBAL_VAR_CLASS;
//            L695OffsetToAddr(lvalue,&addr.addr);    
            if(!m_IsModExist){
                SymAddVar( (LPSTR)pname,tindex,varClass,
                         NOT_REG,&addr,
                         isConst,TRUE,&symP);
            }
            break;
        case 9 :		// variable lifetime information - x1 [x2]
            Get695Offset(&offset);  // PC offset of activation 
            if (!nindex) {
                Get695Offset(&nindex); 
            }
            break;
        case 62 :		// procedure miscellaneous - x1 x2 [ATN65 | ASN]
        case 63 :		// variable  miscellaneous - x1 x2 [ATN65 | ASN]
            ProcessATNMisc(atnType,&typeid, typeOffset, &nrecs);
            break;
        case 12 :
        {
        	U16 x2, x3, x4;
        	U32 val;
            
            if ( 	Get695Offset(&addr.basedVar.offsetVal) != GOOD ||
	            	Get695Number(&x2) != GOOD ||
		            Get695Number(&x3) != GOOD ||
		            Get695Number(&x4) != GOOD ||
		            Get695Offset(&addr.basedVar.baseSize) != GOOD ||
		        	Match2Record(IEEE_AS,IEEE_ASN) != GOOD ||
		            ProcessASN(&nindex, &val) != GOOD ) {
	            SyncTo(IEEE_NN, &filePos);
	            continue;
	        }
	        // error basedVar class omit base address
//	        addr.basedVar.offsetVal = val;	
            addr.basedVar.controlNum = (U8)x2;
            addr.basedVar.publicLocal = (U8)x3;
            addr.basedVar.memorySpace = (U8)x4;
            if(!m_IsModExist){
                SymAddVar( (LPSTR)pname,tindex,BASED_VAR_CLASS,
                          NOT_REG,&addr,
                          FALSE,TRUE,&symP);
            }
        	break;
        }

        default:
			// 02/24/94 - Nghia
			// Report any ATN does not support once
            if ( SyncTo(IEEE_NN, &filePos)!=GOOD )
                return FAILURE;
            continue;
        }
    }  	// while NN 
    
    return (GOOD);
}  	// ProcessDbgLocals 

/*****************************************************************************
**
** ProcessDbgLines - Line number block
**
** ondemand - if TRUE, skip over lines (initial load)
**    FALSE for load all, or for module only load (load lines)
** oflag - MCREATE or MOPEN
**    MCREATE = initial load (whether ondemand or not) - MOPEN = load lines
** *nextBlockPos - start position of the line number block, it will be set to
**    the next block for error recovery.
** moduleDesc - module descriptor
**
*****************************************************************************/
int LoaderServer::ProcessDbgLines(U32 *nextBlockPos, U32 *nextBlockSize,
                                BOOL onDemandFlag )
{
//    BOOL resetBlock = FALSE;
    char *sname;
    char *srcname;
//    U16 blockType, cbyte, dummy;
    U16 blockType; //dummy;
    U16 lineno, colno;
    U32 nindex;
    U16 atnType;
    U32 blockPos, blockSize;
    U32 laddr, tindex; //tjunk = 0L;  /* line number type index is bogus */
    long filePos;
    TIMESTAMP_TYPE tsModule;                          
    int nAddFlag;

	// Track file position 
    blockPos = (U32) (m_uBufInFilePos+m_uBufPos);
    srcname == 0;
    nAddFlag = 0;

/*   
// NOTES:  If current position is not a BB5 block - synch up to 
    while (1) {
        if ( MatchRecord(IEEE_BB)!=GOOD ||
            Get695BB(&blockSize, (LPSTR)srcname, &blockType)!=GOOD
            || (blockType != 5) ) {
// Try reset to start of BB5 and retry 
            if ( !resetBlock ) {
                if (*nextBlockSize > 0) {
                    SeekLoadFile(*nextBlockPos, 0);
                    blockPos = (U32) (m_uBufInFilePos+m_uBufPos);
                }
                else {
                    SeekLoadFile(blockPos, 0);
                    blockPos = (U32) (m_uBufInFilePos+m_uBufPos);
                }
                resetBlock = TRUE;
            } else {
// If it is a good block then return GOOD to continue 
                if ( (blockType >= 1) && (blockType <= 11) ) {
// Need to reset to process next block 
                    SeekLoadFile(blockPos, SEEK_SET);             
                    return(GOOD);
                }
                else {
                    m_dwErrorNum = 0x400F;
                    return FAILURE;
                }
            } 
        } 
        else {
// NOTES: Nghia - 08/19/93
// Save the next block position for error recovery

            *nextBlockPos  = blockPos;
            *nextBlockSize = blockSize;
            break; // Continue Processing BB5 block 
        }
    } // end of while 
*/   
	// NOTES:  If current position is not a BB5 block - synch up to 
    if ( MatchRecord(IEEE_BB)!=GOOD ||
            Get695BB(&blockSize, (LPSTR)srcname, &blockType)!=GOOD
            || (blockType != 5) ) {
        m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
        m_bDispOff = 1;
        m_dwOffset = GetFileCurPos();
        return FAILURE;
    } 
    else {
		// NOTES: Nghia - 08/19/93
		// Save the next block position for error recovery
        *nextBlockPos  = blockPos;
        *nextBlockSize = blockSize;
    } 

   	// Load module reference (full file pathname) for the initial load 
    if ( curModDesc && onDemandFlag == FALSE ) {
      	// Load module reference with module descriptor 
        if(!m_IsModExist){
            SymAddModuleReference(curModDesc, (LPSTR)srcname); 
        }
    }
   
    if ( srcname ) delete srcname;
	// ONDEMAND loading, so do not load line number information 
    if ( !onDemandFlag && m_onDemand ) {
        return( SkipOver(blockPos, blockSize, blockType) );
    }
   
	// START LOADING LINE NUMBER INFORMATION 
//    if ( SymAddLinenumStart(curModDesc)!=GOOD ) {
//        m_dwErrorNum = 0x4025 ;
//        return FAILURE;
//    }

	// NOTES: Nghia - According to the IEEE695 Spec. V4.1
	// a BB5 might optionally include timestamp information.
	// So, if it presents then process it.
	
    if ( GOOD != PeekByte(&curByte) ) return FAILURE;
    if ( curByte != IEEE_BB && curByte != IEEE_NN && curByte != IEEE_BE ) {
        Get695Time(&tsModule);
    	if ( GOOD != PeekByte(&curByte) ) return FAILURE;
		// Reset the symbol server timestamp with the new value
		// Used the same module name and descriptor (mname and mdesc).
    }

#ifdef _DUMP_
	recordStartPos = GetFileCurPos();
#endif
	// Process NN record , followed by {ATN/ASN}* 
    if ( curByte == IEEE_NN ) {
        if ( MatchRecord(IEEE_NN) != GOOD ) {
            m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
            m_bDispOff = 1;
            m_dwOffset = GetFileCurPos();
            return FAILURE;
        }
        //sname = 0;
        if ( GOOD != Get695Nrecord(&nindex, (LPSTR)sname) ) {
            m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
            m_bDispOff = 1;
            m_dwOffset = GetFileCurPos();
            return FAILURE;
        }                                          
        if ( sname ) delete sname;
        //sname = 0;               
    }
    while (1) {
        if ( TestKey(VK_ESCAPE) == 1 ) { 
            m_dwErrorNum = ER_LDR_ABORT;	// 0x4010;
            return FAILURE;
        }                  
        if ( (m_window == LOAD_FROM_DIALOG)&&(m_ldrFlags & LDR_STATUS) ) {
            if ( IsLoadCanceled() ) {
                m_dwErrorNum = ER_LDR_ABORT;	// 0x4010;
                return FAILURE;
            }                  
            TestMessage();
        }
	
		// Obtain current file position in case we're skipping over
		// nested BB5 blocks
#ifdef _DUMP_
		recordStartPos = GetFileCurPos();
#endif
        blockPos = (U32) (m_uBufInFilePos+m_uBufPos);
        if ( GOOD != PeekByte(&curByte) ) return FAILURE;
		// Check for any number of #include BB5's and skip over 
        while ( curByte == IEEE_BB ) {
            MatchRecord(IEEE_BB);
//            Get695BB(&blockSize, (LPSTR)srcname, &blockType);
            if ( Get695BB(&blockSize, (LPSTR)srcname, &blockType)!= GOOD 
            		|| blockType != 5) {
                m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
                m_bDispOff = 1;
                m_dwOffset = GetFileCurPos();
                return FAILURE;
            }
            if ( srcname ) delete srcname;
            //srcname = 0;
            if ( SkipOver(blockPos, blockSize, blockType,TRUE)!=GOOD ) {
                m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
                m_bDispOff = 1;
                m_dwOffset = GetFileCurPos();
                return FAILURE;
            }
            blockPos = (U32) (m_uBufInFilePos+m_uBufPos);
            if ( GOOD != PeekByte(&curByte) ) return FAILURE;
        } 	// end of while 
		// nested BB5's (from #include files) don't usually have line records 
		// NN, followed by {ATN/ASN}* 
		// Note that NN may have already been processed above, if there
		// were no nested BB5's
        if ( curByte == IEEE_NN ) {
            MatchRecord(IEEE_NN)    ;
            if ( Get695Nrecord(&nindex, (LPSTR)sname) != GOOD ) {
                SyncTo(IEEE_NN, &filePos);
                continue;
            }
            if ( sname ) delete sname;
            //sname = 0;               
        }
        if ( GOOD != PeekByte(&curByte) ) return FAILURE;
        if ( curByte == IEEE_AT ) 
            Match2Record(IEEE_AT, IEEE_ATN);
        else
            break;
		// Process the ATN record 
        ProcessATN(&nindex, &tindex, &atnType);
        if (atnType == 7) {
            ProcessATN7(&lineno, &colno);
			/* NOTES: Nghia - Check for 2 extra fields of ATN [x3] and [x4] */
/*            if ( GOOD != GetOneByte(&curByte) ) return FAILURE;
            if ( GOOD != UngetOneByte() ) return FAILURE;
            if ( curByte != IEEE_AS ) {
                Get695Number(&dummy);
                Get695Number(&dummy);
            }
*/
        }
        else if ( atnType == 64 ) {
        	// ATN64 is surely existing in BB10
        	U32 typeid;
        	U16 nitems; 
        	if( ProcessATNMisc(atnType,&typeid,0,&nitems)!= GOOD ) {
        		SyncTo(IEEE_NN,&filePos);
        	} 
        	continue;
        }
        else {
            SyncTo(IEEE_NN, &filePos);
            continue;
        }
		// Resynch should probably seek to (stored) end of line no section,
		// and warn user

        if ( Match2Record(IEEE_AS,IEEE_ASN) != GOOD ||
            ProcessASN(&nindex, &laddr) != GOOD ) {
            SyncTo(IEEE_NN, &filePos);
            continue;
        }
        laddr = laddr & 0x0000FFFFL;
        if ( nAddFlag == 0 ) {
            if(!m_IsModExist){
               if ( SymAddLinenumStart(curModDesc)!=GOOD ) {
                    m_dwErrorNum = ER_LDR_SYM_SERVER;	// 0x4025 ;
                    return FAILURE;
                }
            }                 
            nAddFlag = 1;
        }
        if(!m_IsModExist){
            if(m_bLoadToBank&&m_window==LOAD_FROM_SHELL){
               ConvertAddrToBank(laddr);
            }    
            if ( SymAddLinenum(lineno, (U8) colno, laddr)!=GOOD ) {
                m_dwErrorNum = ER_LDR_SYM_SERVER;	// 0x4025;
                return FAILURE;
            }
        }
    }

    if ( nAddFlag&&!m_IsModExist ) 
        SymAddLinenumEnd();

    if ( MatchRecord(IEEE_BE) != GOOD ) {
        m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
        m_bDispOff = 1;
        m_dwOffset = GetFileCurPos();
        return FAILURE;
    }   
    return(GOOD);
}  	// ProcessDbgLines 

/*****************************************************************************
**
**  ProcessDbgAsmBlock
**
** Process BB10 blocks - asm/compiler generated symbols
** BB11 blocks live inside these, as do assembly-generated NN sections.
** Loop over all BB10 blocks clustered together.
**
** hfile      (in)    - file handle.
** blockSize  (in)    - size of block (in bytes on disk)
** moduleName (in)    - name from loadfile
** createAsm  (in)    - whether or not to create asm module
** updateModule (in)  - update the module address range with asm address
**                      range (to support MRI ASM line numbers)
**
*****************************************************************************/
int LoaderServer::ProcessDbgAsmBlock(U32 blockSize, LPSTR& moduleName,
                           BOOL createAsm, BOOL updateModule ) 
{                           
    SYM_DESCRIPTOR moduleDesc;
    char *vers;
    LPSTR moduleNamePtr;
    TIMESTAMP_TYPE ts;
    U16 blockType, sectionType, sectionIndex, toolType;
    U32 moduleAddress, moduleSize, nextBlockPos;
    U32 moffset, toffset;
    LONG filePos, blockPos;
    U32 nindex;
    U16 atnType,  nrecs;
    U32 tindex, nvalue;
    ADD_VAR_ADDR_UNION addr;

	// Note that blocks belonging to a particular module come in the following
	// sequence (MRI C):
	//    BB1   types
	//    BB3   source symbols
	//    BB5   source line numbers
	//    BB10  assembly info
	// Since there can also be assembly modules with no preceding high-level
	// debug info (such as is found in BB3/BB5), we clear the module descriptor
	// passed in after loading the BB10 (its at the end of this chain).

	// Loop over BB10 blocks 
    while (1) {
		// NOTES: 09/29/93 - Nghia
		// BB10 = {$F8}{$0A}{n1}{Id}{Id}{n2}[[]]...
		// Applied MicroSystem 695 converter does not generate {id}{n2}
        if ( TestKey(VK_ESCAPE) == 1 ) {
            m_dwErrorNum = ER_LDR_ABORT;	// 0x4010;
            return(FAILURE);
        } 
        if ( (m_window == LOAD_FROM_DIALOG)&&(m_ldrFlags & LDR_STATUS) ) {
            if ( IsLoadCanceled() ) {
                m_dwErrorNum = ER_LDR_ABORT;	// 0x4010;
                return( -1 );
            }                  
            TestMessage();
        }

        if ( createAsm ) {
            ModuleNodeInit();                       
            start = DEFAULT_START_ADDR;
            end = DEFAULT_END_ADDR;
        }
        if ( GOOD != PeekByte(&curByte) ) {
            m_dwErrorNum = ER_LDR_READ_FILE;	// 0x400F;
            m_bDispOff = 1;
            m_dwOffset = GetFileCurPos();
            return FAILURE;
        }
        // Throw away object file name (0-length string)
        if( Get695Idn(vers) == GOOD ) {
            if ( vers ) delete vers;
            Get695Number(&toolType);  // not used 
            
			// Note: only MRI generates tool version and timestamp.  
   			// Cosmic does not generate either.  Sierra generates tool
   			// version only.  All Loader code should be generic in its
   			// parsing and not be conditionalized for toolchain.
            if( Get695Idn(vers) == GOOD ) {		// tool version (not used) 
                if ( vers ) delete vers;
                Get695Time(&ts);
            }
        }
      
		// Loop over NN records and BB11 blocks within this BB10 
        while (1) {
#ifdef _DUMP_
			recordStartPos = GetFileCurPos();
#endif
			// Switch here: can either find BB11 blocks, or one of the following
			// NN/ATN/ASN
			// NN/ATN/mod misc 55

            if ( GOOD != PeekByte(&curByte) ) {
                m_dwErrorNum = ER_LDR_READ_FILE;	// 0x400F;
                m_bDispOff = 1;
                m_dwOffset = GetFileCurPos();
                return FAILURE;
            }
            if ( curByte != IEEE_BB && curByte != IEEE_NN ) {
                break; // BB11 loop
            }
            if ( curByte == IEEE_NN) {
                MatchRecord(IEEE_NN);
                
/* 				NOTES: Name *may* be a public symbol name.
 				Having it defined here gives a nice correlation between
				low-level assembly blocks and the public symbols that
				are defined within them.  Someday when we have a symbol
				browser we can add support for this.
*/
                Get695Nrecord(&nindex, (LPSTR)vers);
                if ( vers ) delete vers;
                //vers = 0;
                if ( Match2Record(IEEE_AT,IEEE_ATN)!=GOOD ||
                    ProcessATN(&nindex, &tindex, &atnType) != GOOD ) {
                    if ( SyncTo(IEEE_NN, &filePos)!= GOOD )
                        return FAILURE;
                    continue;
                }
                switch( atnType ) {
                case 19 :	// ATN 19 - x1 [x2] ASN
                    Get695Number(&nrecs);

    				// May be global indicator (if not present, indicates
    				// local symbol).
                    if ( GOOD != PeekByte(&curByte) ) {
                        m_dwErrorNum = ER_LDR_READ_FILE;	// 0x400F;
                        m_bDispOff = 1;
                        m_dwOffset = GetFileCurPos();
                        return FAILURE;
                    }
                    if ( curByte == 1 )
                        GetOneByte(&curByte);
    
    				// NOTES: 09/20/93 - Nghia
    				// [x1] = nrecs is not the number of ASN records following
    				// HP generate [x1] = 0, 1, 36,... but there always 1 ASN
    
                    if ( Match2Record(IEEE_AS,IEEE_ASN)!=GOOD ||
                         Get695Offset(&nindex) != GOOD ) {
                        SyncTo(IEEE_NN, &filePos);
                        continue;
                    }
                                           
            		if ( PeekByte(&curByte) != GOOD ) {
                		SyncTo(IEEE_NN, &filePos);
                		break;
            		}
            		if ( curByte == 0xCC ) {
                		if ( GOOD != GetExpression(addr.addr) ) {
                    		SyncTo(IEEE_NN, &filePos);
                    		break;
                		}
            		}
            		else {
                		Get695Offset(&nvalue);
                		addr.addr.segType = SEG_UNTYPED;
                		addr.addr.addr = nvalue & 0x0000FFFFL;
            		}                
                    break;
        		case 64 :		// module misc
        			ProcessATNMisc(atnType,&nvalue,toffset,&nrecs);
            		break;
                default:
                    if ( SyncTo(IEEE_NN, &filePos)!=GOOD ) {
                        m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
                        m_bDispOff = 1;
                        m_dwOffset = GetFileCurPos();
                        return FAILURE;    
                    }    
                    break;
                }
                //continue;
            }
            else if ( curByte == IEEE_BB ) {
                blockPos = (U32) (m_uBufInFilePos+m_uBufPos);
                MatchRecord(IEEE_BB);
				// Throw away string 
                Get695BB(&blockSize, (LPSTR)vers, &blockType);
                if( vers ) delete vers; 
                if (blockType != 11)
                    break; 	// BB11 loop 
               
				// We only care about the code/mixed address region for this
				// asm block, the remainder of asm section types are discarded.
                if ( ProcessDbgAsmSection(&sectionType, &sectionIndex,
                    &moduleAddress, &moduleSize) != GOOD ) {
                    if ( SkipOver(blockPos, blockSize, blockType)
                        != GOOD) return FAILURE;
                    nextBlockPos = (U32) (m_uBufInFilePos+m_uBufPos);
                    continue;
                }   
				// 11/18/94 - Nghia
				// Collect all code/mixed address ranges for the BB10
                if ( (sectionType == 1 || sectionType == 0 && moduleSize ) 
                    && ( createAsm || updateModule ) ) {
					// Make sure module range is 1 byte minimum 
                    moduleSize = (moduleSize > 0) ? moduleSize : 1L;      
               		// Assembly module only 
                    if ( start > moduleAddress ) start = moduleAddress;
                    if ( end < moduleAddress ) end = moduleAddress;
                    moduleAddress += moduleSize-1;
                    if ( start > moduleAddress ) start = moduleAddress;
                    if ( end < moduleAddress ) end = moduleAddress;
                }
            }  	// if BB 
        }  	// while NN/BB11 inside this BB11 
        
        //for load n times
        StripPathString(moduleName, &moduleNamePtr);
        if(IsModuleExist(moduleNamePtr)) m_AsmModExist=1;
        else m_AsmModExist=0;
            
		// NOTES: 09/30/93 - Nghia
		// Only create ASM module if user said so and createAsm is TRUE
        if ( createAsm ) {
            moffset = toffset = 0L;  // unused for asm modules 
            StripPathString(moduleName, &moduleNamePtr);
            m_modNode.codeaddr.segType = ( SEGMENTTYPE ) SEG_CODE;
            m_modNode.codeaddr.startAddr = start;
            m_modNode.codeaddr.endAddr = end;
            if(!m_AsmModExist){
               if(m_bLoadToBank&&m_window==LOAD_FROM_SHELL){
                  ConvertAddrToBank(m_modNode.codeaddr.startAddr);
                  ConvertAddrToBank(m_modNode.codeaddr.endAddr);
                }
                  
               if ( SymAddModuleCreate(moduleNamePtr,
                                    &ts, &m_modNode.codeaddr,
                                    moffset, FALSE,
                                    toffset, &moduleDesc) != GOOD ) {
                   nextBlockPos = (U32) (m_uBufInFilePos+m_uBufPos);
                   continue;
               }
               SymAddModuleClose(FALSE);
           }
        } 
        else if ( updateModule ) { // if createAsm 
			// Update the input moduleDescriptor with the new module
			// address range from the ASM block.
            QUAL_ADDR_RANGE_TYPE qaddr;
            qaddr.startAddr = start;
            qaddr.endAddr = end;
            qaddr.startValid = TRUE;
            qaddr.endValid = TRUE;                      
        
            if ( start > end ) {
                qaddr.startValid = FALSE;
                qaddr.endValid = FALSE;
            }
        
            if ( qaddr.startValid || qaddr.endValid )
            {
                if(!m_AsmModExist){
                   if(m_bLoadToBank&&m_window==LOAD_FROM_SHELL){
                      if ( qaddr.startAddr != DEFAULT_START_ADDR &&
                		   qaddr.endAddr != DEFAULT_END_ADDR ) {
                   	       ConvertAddrToBank(qaddr.startAddr);
                           ConvertAddrToBank(qaddr.endAddr);
                      }
                   }
                   if ( SymAddSymbolSetAddr( &qaddr ) != GOOD ) {
                       m_dwErrorNum = ER_LDR_SYM_SERVER;	// 0x4025;
                       return( FAILURE );
                   }
                }
            }
            updateModule = FALSE;
        }
		// end of this BB10 
        if ( MatchRecord(IEEE_BE) != GOOD ) {
         	// sync to next BB and fall thru 
            UngetOneByte();
            SyncTo(IEEE_BB, &filePos);
// 03/03/94 - Nghia - Introl compiler: BB10 does not have BB11
//            if (strcmpi(toolUseName, TOOL_INTROL) == 0)
//                return err;
            break;
        }
      	// retain current file pos in case of sync 
        blockPos = (U32) (m_uBufInFilePos+m_uBufPos);
        if ( startAddr_ASW[5] ) {
            if ( (U32)blockPos >= startAddr_ASW[5] ) {
                return GOOD;
            }
        }
        if ( MatchRecord(IEEE_BB)!= GOOD ) {
			// thru processing BB10 blocks 
            UngetOneByte();
//            if (strcmpi(toolUseName, TOOL_INTROL) == 0)
//                return err;
            break;
        }
        if ( moduleName ) delete moduleName;
        moduleName = 0;
        Get695BB(&blockSize, moduleName, &blockType);
        if ( blockType != 10 ) {
         	// reset file position to block begin marker 
            SeekLoadFile(blockPos, SEEK_SET);
//            if (strcmpi(toolUseName, TOOL_INTROL) == 0)
//                break; // exit BB10 loop
            return GOOD;
        }
		// Reset createAsm flag for next module 
        createAsm = TRUE;      
    }  	// while BB10 blocks remain 
    return (GOOD);
}  	// ProcessDbgAsmBlock 

/*****************************************************************************
**
**  ProcessDbgAsmSection
**
** psectionType - pointer to section type
** psectionIndex - pointer to section index
** pmoduleAddress - pointer to address for section
** pmoduleSize - size of the block 
**
*****************************************************************************/
int LoaderServer::ProcessDbgAsmSection(U16 *psectionType,
                                     U16 *psectionIndex, U32 *pmoduleAddress,
                                     U32 *pmoduleSize) 
{
    if ( Get695Number(psectionType) != GOOD ||
        Get695Number(psectionIndex) != GOOD ||
        Get695Offset(pmoduleAddress) != GOOD ||
        MatchRecord(IEEE_BE) != GOOD ||
        Get695Offset(pmoduleSize) != GOOD )
        return FAILURE; 
    return GOOD;
}  /* ProcessDbgAsmSection */

void L695OffsetToAddr(U32 lvalue,ADDRESS_TYPE  *addr)
{
    U32 tt;
    U16 tp ;
         
    tt = lvalue;
    tt = tt >> 16;         
    tp = (U16) (tt & 0x000000FFL);
    addr->addr = (U32)( lvalue & 0x0000FFFFL );
    switch ( tp ) {
    case 0xFF :
        addr->segType = ( SEGMENTTYPE ) SEG_CODE ;
        break;
    case 1 :           
    case 0xFE : 
        addr->segType = ( SEGMENTTYPE ) SEG_XDATA ;
        break;
    case 0 :        
        addr->segType = ( SEGMENTTYPE ) SEG_DATA ;
        break;
/*
    case 4 :
        *type = ( SEGMENTTYPE ) SEG_BIT ;
        break;
*/        
    default :
        addr->segType = ( SEGMENTTYPE ) SEG_UNTYPED ;
        break;
    }
}    

/*****************************************************************************
**
** StripPathString
**
** moduleName - the original module name
** newName    - the new module Name
**
*****************************************************************************/
int StripPathString(LPSTR moduleName, LPSTR *newName) 
{
    BOOL done = FALSE;
    int strLen, i;

    *newName = moduleName; /* Assign pointer */
	/* Check if moduleName is NULL */
    if ( (strLen = strlen(moduleName)) >= 0) {
        strLen -= 1; /* String start from 0 index */
        for (i = strLen; i > 0 && !done; i--) {
            switch(*(moduleName+i)) {
            case '.':
                *(moduleName + i) = (char)'\0';  /* Strip the suffix */
                break;
            case '\\':
            case '/':
            case ':':   
                if (i > 0)
                    *newName = (LPSTR)moduleName + (i + 1);
                done = TRUE;
                break;
            }
        }
    }   
    return(GOOD);
}  /* StripPathString */          

int LoaderServer::FindOneSection(U32 num,struct SEC_INFO *& pSec)
{
    pSec = m_pSec;
/*
    if ( m_pCurrentSec ) {
        if ( m_pCurrentSec->sindex <= num ) {
            pSec = m_pCurrentSec;
        }         
    }
*/		// marked for Intermetrics Tools (sindex in descend order )
    while( pSec ) {
        if ( pSec->sindex == num ) break;
        pSec = pSec->next;
    }
    if ( pSec ) return GOOD;
    return FAILURE;
}

/******************************************************************************
**
**  Ldr695SectionPart
**
******************************************************************************/
int LoaderServer::Ldr695SectionPart(void) 
{
   	struct SEC_INFO *psection;

	// Seek to Trailer part of file
    if ( startAddr_ASW[2] == 0L) return GOOD;
   
	// ASW6  --  Trailer Part
    if ( GOOD != SeekLoadFile(startAddr_ASW[2],SEEK_SET) ) {
        m_dwErrorNum = ER_LDR_READ_FILE;	// 0x400F;
        m_bDispOff = 1;
        m_dwOffset = GetFileCurPos();
        return FAILURE;
    }            

#ifdef _DUMP_
	recordStartPos = GetFileCurPos();
#endif
    while ( MatchRecord(IEEE_ST) == GOOD ) {
        psection = new SEC_INFO;
        if ( psection == 0 ) {  
            m_dwErrorNum = ER_LDR_MEMORY_ALLOC;		// 0x4000;
            return FAILURE;
        }
        if ( GetSectionInfo(psection)!= GOOD ) {
            delete psection;
            m_dwErrorNum = ER_LDR_FILE_FORMAT;		// 0x400F;
            m_bDispOff = 1;
            m_dwOffset = GetFileCurPos();
            return FAILURE;
        }
        if ( m_pSec == 0 ) {
            m_pSec = psection;
            m_pCurrentSec = m_pSec;
        }
        else if ( m_pCurrentSec ) {
            while( m_pCurrentSec->next) {
                m_pCurrentSec=m_pCurrentSec->next;
            }
            m_pCurrentSec->next = psection;
            m_pCurrentSec = psection;
        }
#ifdef _DUMP_
		recordStartPos = GetFileCurPos();
#endif
    }  // while 

    return GOOD;
}  /* ProcessSectionPart */

/******************************************************************************
**
**  GetSectionInfo - retrieve section information from loadfile
**
******************************************************************************/
int LoaderServer::GetSectionInfo(SEC_INFO *psection) 
{
    char *name;
    U16 sattr;     /* section attribute (code, ROM data, or data) */
    U32 sindex;    /* section index */
    U32 srecord;   /* other section records */
    U16 stype;     /* section type */
    U16 cbyte;
    U32 svalue;    /* section value (depends on record type) */
/*
	ALGORITHM:
    while (match ($E6) && (numSections < MAX_SECTIONS)) {
    	get sec index
       	get ST (name)
       	get SA (alignment)
       	get ASS (size)
       	get ASL (offset)
       	get ASM (segment type) 
    }
*/
	// NOTES: 04/01/93 - Nghia - Process optional fields.
	// ST record = {$E6}{n1}{l}{Id}[n2][n3][n4]

	// IEEE695 Spec. v4.1, page C-2 - For an absolute file
	// A section part = {ST [SA] ASS ASL} and there must be at most
	// one of the above record for any section index.


    if ( Get695Offset(&sindex) != GOOD ) return FAILURE;
    if ( Get695STrecord(&sattr, &stype) != GOOD )	// Process {l}
    	return FAILURE;
    Get695Idn((LPSTR)name);
    if ( Get695Offset(&srecord)==GOOD ) {		// Process {n2]
        if ( srecord ) {        
            struct SEC_INFO *ttt;
            if ( FindOneSection(srecord,ttt) != GOOD )
                return FAILURE;
            psection->segType = ttt->segType;
        }
		// Strip any byte that is not a SA = 0xE7 or ASS = 0xE2 signature 
        while ( Get695Number(&cbyte) == GOOD );
    }
    //        else return FAILURE;
    switch( stype ) {
    case 1 :  // normal section 
        psection->sindex = sindex;
        psection->str = name;
        psection->type = 1;
        psection->modifier = sattr;
		// IMPORTANT: Get either optional [SA] or {ASS} record
		while ( 1 ) { 
        	if ( Get695Srecord(&srecord, &svalue) != GOOD ) {
        		if ( srecord != -1 ) return FAILURE;
        		else break;
        	}
                        
        	if ( curByte == IEEE_SA ) {
				// svalue is section alignment 
            	psection->align = (U16)svalue;
            }
            else if ( curByte == IEEE_ASL ) {
				// svalue is section base addr 
        		psection->offset = svalue;
        	}
        	else if ( curByte == IEEE_ASS ) {
				// Either case, the svalue is section size - so save it 
        		psection->size = svalue;
        	}
            else if ( curByte == IEEE_ASM ) {
                switch( svalue ) {
                case 0 :
                case 3 :
                case 4 :
                    psection->segType = SEG_DATA;
                    break;
                case 5 :
                    psection->segType = SEG_BIT;
                    break;
                case 1 :
                    psection->segType = SEG_CODE;
                    break;
                case 2 :
                    psection->segType = SEG_XDATA;
                    break;
                default :
                    break;
                }
            }
        }
        break;
    default:
        /* other record types not handled yet */
        return FAILURE;
    }
    return GOOD;
}

int LoaderServer::GetExpression(ADDRESS_TYPE& addr)
{   
    U32 uSec , uOff;
    if ( GetOneByte(&curByte) != GOOD ) return FAILURE;
    if ( curByte != 0xCC ) return FAILURE;
    if ( Get695Offset(&uSec) != GOOD ) return FAILURE;
    if ( Get695Offset(&uOff) != GOOD ) return FAILURE;
    if ( GetOneByte(&curByte) != GOOD ) return FAILURE;
    if ( curByte != 0xA5 ) return FAILURE;
    struct SEC_INFO *ttt;
    if ( FindOneSection(uSec,ttt) != GOOD ) return FAILURE;
    addr.segType = ttt->segType;
    addr.addr = (ttt->offset+uOff) & 0x0000FFFFL;
//    addr.addr = (m_pCurrentSec->offset+uOff) & 0x0000FFFFL;
    return GOOD;    
}

int LoaderServer::GetSegType(U32 secNum, SEGMENTTYPE& type)
{                         
    struct SEC_INFO *ttt;
    if ( FindOneSection(secNum,ttt) != GOOD ) return FAILURE;
    type = ttt->segType;
    return GOOD;    
}

/******************************** E O F ***********************************/

