
/***************************************************************************
**
**    $Header:   D:/EPSLDV1/SRC/LOG/SYMCLIPR.CPP   1.8   20 Jun 1996 09:25:22   ZJRD  $
**
**    $Log:   D:/EPSLDV1/SRC/LOG/SYMCLIPR.CPP  $
** 
**    Rev 1.8   20 Jun 1996 09:25:22   ZJRD
** EasyPack/SLD Version 1.20a
** 
**    Rev 1.6   10 Jun 1996 10:20:00   ZJRD
** EasyPack/SLD Version 1.20
** 
**    Rev 1.4   29 May 1996 09:29:22   ZJRD
** EasyPack/SLD Version 1.95
** 
**    Rev 1.3   16 May 1996 09:06:40   ZJRD
** No change.
** 
**    Rev 1.2   10 May 1996 09:11:18   ZJRD
** No change.
** 
**    Rev 1.1   02 May 1996 10:23:10   ZJRD
** EasyPack/SLD Version 1.92
** 
**    Rev 1.31   18 Apr 1996 13:03:04   Shirley
** No change.
** 
**    Rev 1.30   12 Apr 1996 10:37:06   Shirley
** EasyPack/SLD Version 1.90
** 
**    Rev 1.28   15 Feb 1996 08:50:06   Shirley
** No change.
** 
**    Rev 1.27   12 Feb 1996 14:02:32   Shirley
** No change.
** 
**    Rev 1.26   06 Feb 1996 15:27:48   Shirley
** No change.
** 
**    Rev 1.25   06 Feb 1996 13:43:24   Shirley
** No change.
** 
**    Rev 1.24   01 Feb 1996 10:16:18   Shirley
** No change.
** 
**    Rev 1.23   26 Jan 1996 09:13:10   Shirley
** No change.
** 
**    Rev 1.22   25 Jan 1996 13:13:48   Shirley
** No change.
** 
**    Rev 1.21   24 Jan 1996 10:39:34   Shirley
** No change.
** 
**    Rev 1.20   23 Jan 1996 11:29:18   Shirley
** No change.
** 
**    Rev 1.19   18 Jan 1996 10:14:10   Shirley
** No change.
** 
**    Rev 1.18   15 Jan 1996 16:11:02   Shirley
** No change.
** 
**    Rev 1.17   04 Jan 1996 11:10:20   Shirley
** No change.
** 
**    Rev 1.16   30 Nov 1995 09:13:42   Shirley
** No change.
** 
**    Rev 1.15   28 Nov 1995 15:33:42   Shirley
** No change.
** 
**    Rev 1.14   21 Nov 1995 11:21:02   Shirley
** No change.
** 
**    Rev 1.13   13 Nov 1995 09:24:20   Shirley
** No change.
** 
**    Rev 1.12   12 Nov 1995 11:32:28   Shirley
** No change.
** 
**    Rev 1.11   08 Nov 1995 16:30:52   Shirley
** No change.
** 
**    Rev 1.10   08 Nov 1995 12:45:30   Shirley
** No change.
** 
**    Rev 1.9   02 Nov 1995 10:07:40   Shirley
** No change.
** 
**    Rev 1.8   27 Oct 1995 16:50:52   Shirley
** No change.
** 
**    Rev 1.7   27 Oct 1995 13:47:16   Shirley
** No change.
** 
**    Rev 1.6   25 Oct 1995 14:31:30   Shirley
** EasyPack/SLD Version 0.1f
** 
**    Rev 1.5   18 Oct 1995 14:49:04   Shirley
** EasyPack/SLD Version 0.1e
** 
**    Rev 1.4   13 Oct 1995 13:22:28   Shirley
** EasyPack/SLD Version 0.1d
** 
**    Rev 1.3   29 Sep 1995 09:49:28   Shirley
** No change.
** 
**    Rev 1.2   20 Sep 1995 10:57:02   Shirley
** No change.
** 
**    Rev 1.1   15 Sep 1995 09:49:42   Shirley
** No change.
** 
**    Rev 1.0   07 Sep 1995 09:53:32   Shirley
** Initial revision.
**
****************************************************************************/

/****************************************************************************
**
**  Name:  symclipr.cpp
**
**  Description:
**     This is a set of routines to print out symbols in the symbol table 
**     in the order in which they were entered.  All these routines send
**     messages to the cli.
**
**  Status:  PRELIMINARY
**
**  $Log$
** 
**  $Header:   D:/EPSLDV1/SRC/LOG/SYMCLIPR.CPP   1.8   20 Jun 1996 09:25:22   ZJRD  $
**
**  Copyright (C) 1995 Microtek International.  All rights reserved.
**
*****************************************************************************/

                       /****************************
                        *                          *
                        *       INCLUDE FILES      *
                        *                          *
                        ****************************/
#include "stdafx.h"
#include "uicom.h"

#include "basewind.h"
#include "basetbl.h"
#include "byadrtbl.h"
#include "indextbl.h"
#include "heap.h"
#include "linenum.h"
#include "mempool.h"
#include "ordtbl.h"
#include <string.h>
#include "symcli.h"
#include "symmgr.h"
#include "symblsvr.h"
#include "symclipr.h"
#include "symutil.h"
                       /****************************
                        *                          *
                        *     LOCAL DEFINITIONS    *
                        *                          *
                        ****************************/

PRIVATE S8 globalStr[MAX_SYMNAME_LENGTH * 2];
PRIVATE COMMON_SYMBOL_HEADER HUGE *rootPtr;

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

extern LinenumTable lt;
extern BaseIndexTable bit; // base index table ;
extern OrdinalTable ot;    // ordinal table ;
extern MemPool st;   // symbol table ;
extern TABLE_OFFSET rootOffset;
extern BOOLEAN      with0X;  // how to display addrs for proc family

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

RETCODE PRIVATE FillInAddress(SYM_DESCRIPTOR symbol);
RETCODE PRIVATE GetDestinationOfPtr(TYPE_INDEX typeIndex, LPSTR returnName);
RETCODE PRIVATE GetDestinationOfOmf51Ptr(TYPE_INDEX typeIndex, LPSTR returnName);
VOID    PRIVATE FillInDetailedType(SYM_DESCRIPTOR symbol);
RETCODE PRIVATE FillInTypeAndName(SYM_DESCRIPTOR symbol, U8 nesting);
RETCODE PRIVATE GetSymbolPrintLine(SYM_DESCRIPTOR   symbol,
  //                                 SYM_DISPLAY_TYPE displayType,
                                   U16              nesting);
VOID PRIVATE SpaceToColumn(U16 column);

RETCODE PRIVATE PrintBlockHeader(HPU8 symPtr, SYM_DISPLAY_TYPE displayType);
RETCODE PRIVATE PrintCommonHeader(HPU8 symPtr, SYM_DISPLAY_TYPE displayType);
RETCODE PRIVATE PrintFunction(HPU8 symPtr, SYM_DISPLAY_TYPE displayType);
RETCODE PRIVATE PrintModule(HPU8 symPtr, SYM_DISPLAY_TYPE displayType);
RETCODE PRIVATE PrintSymbolAddress(HPU8 symPtr);
RETCODE PRIVATE PrintVariable(TABLE_OFFSET inputSymbol, HPU8 symPtr,
                              SYM_DISPLAY_TYPE displayType);

                       /****************************
                        *                          *
                        *      EXECUTABLE CODE     *
                        *                          *
                        ****************************/
extern void ShowLine(char *);
RETCODE SymGetFuncReturnTypeIndex(SYM_DESCRIPTOR inputSymbol,
                          TYPE_INDEX FAR *returnType); 

//--------------------------------------------------------------------------
// PrintBlock
//--------------------------------------------------------------------------
RETCODE PRIVATE PrintBlock(HPU8 symPtr, SYM_DISPLAY_TYPE displayType) {

   RETCODE err;

   // print the information common to all block/function/module symbols ;
   if ((err = PrintBlockHeader(symPtr, displayType)) != GOOD) return(err);

   return(GOOD);

}

#define NAME_COLUMN          14
#define DETAILED_TYPE_COLUMN 30
#define ADDRESS_COLUMN       55


//--------------------------------------------------------------------------
// SymConvSymAddrToText
//
// Design:
//    Calculates symbol address and returns it in string alloc'ed by caller
//    Fixed addresses:
//       Displays fixed address as xxx-yyy where xxx is the start address and
//       yyy is the end address; then displays the range as [rrr].
//       Start and end addresses are is hex, the range is in decimal
//    Stack-based addresses:
//       Displays as a single signed decimal number followed by [sss] size.
//
// Input Parameter:
//    symbol: symbol being printed
//
// Output Parameter:
//    str: alloc'ed by caller using size SYMCLIPR_ADDR_TEXT_WIDTH
//--------------------------------------------------------------------------
RETCODE SymConvSymAddrToText(SYM_DESCRIPTOR symbol, LPSTR str)  {

   RETCODE          err;
   HPU8             symPtr;
   U32              startAddr, tmpAddrSize;
   S8               tmpStr[SYMCLIPR_ADDR_TEXT_WIDTH];
   TYPE_HEADER_TYPE typeHeader;
   SYM_TYPE_VARIABLE *varPtr;
   LPSTR            strPtr;
   int             n;

   strPtr = str;  // set string pointer at beginning of passed-in string
   tmpStr[0] = '\0';  // init string
   str[0] = '\0';  // init string

   symPtr = st.GetHugeDataPtr(symbol);
   varPtr = (SYM_TYPE_VARIABLE *)symPtr;
   
   switch (((COMMON_SYMBOL_HEADER HUGE *)symPtr)->typeIndex.symType & 0xF) {
      case SYM_LOCAL_VAR:
      case SYM_GLOBAL_VAR:
      case SYM_USER_DEFINED_VAR:
      case SYM_PUBLIC_VAR:
         if (varPtr->registerClass != NOT_REG) {
            // if reg, get size from type info
            typeHeader.typeName = tmpStr;
            if ((err = SymGetTypeHeader(varPtr->typeIndex, &typeHeader))
                != GOOD) return err;
            n = sprintf(strPtr, "[%ld]", (U32)typeHeader.sizeInMAUs);
            strPtr += n;
            break; /* out of the switch statement */
         }

         if (AUTO_VAR_CLASS == varPtr->storageClass) {
             switch( ((COMMON_SYMBOL_HEADER *)symPtr)->typeIndex.baseIndex ) {
             case 0 :
                n = sprintf(strPtr , " U:");
                break;
             case 1 :
                n = sprintf(strPtr , " P:");
                break;
             case 2 :
                n = sprintf(strPtr , " I:");
                break;
             case 3 :
                n = sprintf(strPtr , " X:");
                break;
             case 4 :
                n = sprintf(strPtr , " B:");
                break;
             case 5 :
                n = sprintf(strPtr , " R:");
                break;
             case 6 :
                n = sprintf(strPtr , " C:");
                break;
             default :
                n = 0;
                break;
             }
             strPtr += n;
            startAddr = varPtr->symHeader.beginAddrInfo.autoVarOffset;
            n = sprintf(strPtr, "%+d", startAddr);
            strPtr += n;
            // insert auto size
            n = sprintf(strPtr," [%ld]",varPtr->symHeader.endAddrInfo.varSize);
            strPtr += n;
            break; /* out of the switch statement */
         }
 
      // PURPOSELY FALLING THROUGH HERE
      default:    // fixed address cases
         // get the logical address
//         if((err = UtilSetAddrParams(
//            ((COMMON_SYMBOL_HEADER *)symPtr)->typeIndex.baseIndex,
//            ((COMMON_SYMBOL_HEADER *)symPtr)->beginAddrInfo.startAddr,
//            ((COMMON_SYMBOL_HEADER *)symPtr)->endAddrInfo.endAddr,
//            startAddrDesc)) != GOOD) {
            // 05/04/93 - Nghia - Handle Invalid adddress cases
            // symbol didn't have a valid address; print "unknown address"
//            n = sprintf(strPtr, "unknown address");
//            strPtr += n;
//            break; /* out of the switch statement */
//         }
        if ( ((COMMON_SYMBOL_HEADER *)symPtr)->beginAddrInfo.startAddr >
            ((COMMON_SYMBOL_HEADER *)symPtr)->endAddrInfo.endAddr )
            tmpAddrSize = 0;
         if (0L == tmpAddrSize) {
            // symbol didn't have a valid address; print "external"
            int ii = ((COMMON_SYMBOL_HEADER HUGE *)symPtr)->typeIndex.symType & 0xF;
            if ( (ii != SYM_MODULE)||(ii != SYM_FUNCTION) ) { 
                n = sprintf(strPtr, "external ");
                strPtr += n;
            }
         }
         
         switch( ((COMMON_SYMBOL_HEADER *)symPtr)->typeIndex.baseIndex ) {
         case 0 :
            n = sprintf(strPtr , " U:");
            break;
         case 1 :
            n = sprintf(strPtr , " P:");
            break;
         case 2 :
            n = sprintf(strPtr , " I:");
            break;
         case 3 :
            n = sprintf(strPtr , " X:");
            break;
         case 4 :
            n = sprintf(strPtr , " B:");
            break;
         case 5 :
            n = sprintf(strPtr , " R:");
            break;
         case 6 :
            n = sprintf(strPtr , " C:");
            break;
         default :
            n = 0;
            break;
         }
         if ( ((COMMON_SYMBOL_HEADER *)symPtr)->beginAddrInfo.startAddr
           <= ((COMMON_SYMBOL_HEADER *)symPtr)->endAddrInfo.endAddr ) {
            strPtr += n;
            n= sprintf(strPtr, "%lX-%lX",
               ((COMMON_SYMBOL_HEADER *)symPtr)->beginAddrInfo.startAddr,
               ((COMMON_SYMBOL_HEADER *)symPtr)->endAddrInfo.endAddr );
            strPtr += n;
            tmpAddrSize =
                ((COMMON_SYMBOL_HEADER *)symPtr)->endAddrInfo.endAddr -
                   ((COMMON_SYMBOL_HEADER *)symPtr)->beginAddrInfo.startAddr+1;
            sprintf(strPtr," [%lu]",tmpAddrSize);
         }
         else {
            sprintf(strPtr, "unknown address");
         }
         break;
   } // end of switch
   return GOOD;
}  // end of SymConvSymAddrToText

//--------------------------------------------------------------------------
// FillInAddress
//
// Design:
//    Gets symbol address and inserts it into globalStr
//
// Input Parameter:
//    symbol: symbol being printed
//--------------------------------------------------------------------------
RETCODE PRIVATE FillInAddress(SYM_DESCRIPTOR symbol)  {

   RETCODE          err;
   S8               tmpStr[SYMCLIPR_ADDR_TEXT_WIDTH];

   SpaceToColumn(ADDRESS_COLUMN);

   // tmpStr is modified by call
   if ((err = SymConvSymAddrToText(symbol, tmpStr)) != GOOD)
      return err;
   strcat(globalStr, tmpStr);
   return GOOD;
}  // end of FillInAddress


PRIVATE const S8 *complexTypeNames[] = {
   "16:16 ptr",
   "16:32 ptr",            
   "array", // old is "C array",
   "generic ptr",
   "unknown",
   "pascal enum",
   "general",
   "enum",
   "pointer", // for MCS51 only "small ptr",
   "ptr",
   "range",
   "struct",
   "typedef",
   "union",
   "void",
   "function",
   "C array",
   "bit field",
   "function",
   "not valid complex"  // only displayed if stored complex value is invalid
};

PRIVATE U8 complexTypeNamesMap[] = {    // can't be const because writing to
   0x00,                                // last entry
   0x01,     
   0x10,    
   0x11,
   0x21,
   0x45,
   0x47,
   0x4E,
   0x4F,
   0x50,
   0x52,
   0x53,
   0x54,
   0x55,
   0x56,
   0x58,
   0x5A,
   0x67,
   0x78,
   0x00  // filler to place complex type value for match if no others match
};

U8 varStorageClass[][9] = {
   "Local ",
   "Static ",
   "Global ",
   "Based ",
   "Public "
};

//--------------------------------------------------------------------------
// GetDestinationOfPtr 
//
// Design:
//    Given a pointer type index, return text of what it points to
//    It may point to another complex in which case, return complex name
//
// Input Parameter:
//    typeIndex: index of type pointer points to
//    returnName: string pointer of where to put:
//          "to <type name>"
//--------------------------------------------------------------------------
RETCODE PRIVATE
GetDestinationOfPtr(TYPE_INDEX typeIndex, LPSTR returnName)  {

   TYPE_INDEX       ptrToTypeIndex;
   RETCODE          err;
   TYPE_HEADER_TYPE ptrToTypeHeader;
   LPSTR            strPtr;
   int              n;

   // get type of what pointer points to
   if ((err = SymGetTypePointerTypeIndex(typeIndex, &ptrToTypeIndex)) != GOOD) {
      n = sprintf(strPtr, " < unknown pointer > ");
      strPtr += n;
      return err;
   }
   strPtr = returnName;  // set char pointer to start of return string buffer
   n = sprintf(strPtr, "to ");
   strPtr += n;
   // get info on dest of ptr
   // must supply data structure with string memory to be filled in
   ptrToTypeHeader.typeName = strPtr;  // point to after "to "
   if ((err = SymGetTypeHeader(ptrToTypeIndex, &ptrToTypeHeader)) != GOOD) {
      n = sprintf(strPtr, "unknown type");
      strPtr += n;
      return err;
   }
   
   if (ptrToTypeHeader.typeChoice == COMPLEX_TYPE_CLASS)  {
      // match complex type number to constant index table; extract
      //   index for complexTypeNames string table
            
      complexTypeNamesMap[sizeof(complexTypeNamesMap) - 1] =
         (U8)ptrToTypeHeader.t.complexType;
      // scan array for match
      for (U8 i=0; i < sizeof(complexTypeNamesMap); i++) {
         if ((U8)ptrToTypeHeader.t.complexType == complexTypeNamesMap[i])
            break;
      };
      // 08/15/94 - Nghia
      // Report the actual pointer base type name if there is one 
      if (*(ptrToTypeHeader.typeName) != '\0')
         strcpy(strPtr, ptrToTypeHeader.typeName);
      else   
         strcpy(strPtr, complexTypeNames[i]);
   }
   return GOOD;
}  // end of GetDestinationOfPtr


//--------------------------------------------------------------------------
// GetDestinationOfOmf51Ptr 
//
// Design:
//    Given a pointer type index, return text of what it points to
//    It may point to another complex in which case, return complex name
//
// Input Parameter:
//    typeIndex: index of type pointer points to
//    returnName: string pointer of where to put:
//          "to <type name>"
//--------------------------------------------------------------------------
RETCODE PRIVATE
GetDestinationOfOmf51Ptr(TYPE_INDEX typeIndex, LPSTR returnName)  {

   TYPE_OMF51_PTR_STRUCT omf51Ptr ;
   TYPE_INDEX       ptrToTypeIndex;
   RETCODE          err;
   TYPE_HEADER_TYPE ptrToTypeHeader;
   LPSTR            strPtr;
   int              n;

   // get type of what pointer points to
//   if ((err = SymGetTypePointerTypeIndex(typeIndex, &ptrToTypeIndex)) != GOOD)
//      return err;
   if ((err = SymGetTypePointer51(typeIndex, &omf51Ptr)) != GOOD) {
      n = sprintf(strPtr, " < unknown pointer > ");
      strPtr += n;
      return err;                                                  
   }   
   ptrToTypeIndex = omf51Ptr.typeIndex ;   
      
   strPtr = returnName;  // set char pointer to start of return string buffer
   n = sprintf(strPtr, "to ");
   strPtr += n;
   // get info on dest of ptr
   // must supply data structure with string memory to be filled in
   ptrToTypeHeader.typeName = strPtr;  // point to after "to "
   if ((err = SymGetTypeHeader(ptrToTypeIndex, &ptrToTypeHeader)) != GOOD) {
      n = sprintf(strPtr, "unknown type");
      strPtr += n;
      return err;                                                           
   }   

   if (ptrToTypeHeader.typeChoice == COMPLEX_TYPE_CLASS)  {
      // match complex type number to constant index table; extract
      //   index for complexTypeNames string table
            
      complexTypeNamesMap[sizeof(complexTypeNamesMap) - 1] =
         (U8)ptrToTypeHeader.t.complexType;
      // scan array for match
      for (U8 i=0; i < sizeof(complexTypeNamesMap); i++) {
         if ((U8)ptrToTypeHeader.t.complexType == complexTypeNamesMap[i])
            break;
      };
      // 08/15/94 - Nghia
      // Report the actual pointer base type name if there is one 
      if (*(ptrToTypeHeader.typeName) != '\0')
         strcpy(strPtr, ptrToTypeHeader.typeName);
      else   
         strcpy(strPtr, complexTypeNames[i]);
   }
   return GOOD;
}  // end of GetDestinationOfPtr


//--------------------------------------------------------------------------
// FillInDetailedType
//--------------------------------------------------------------------------
VOID FillInDetailedType(SYM_DESCRIPTOR symbol)  {

   HPU8             symPtr;
   LINENUM_TYPE     firstLinenum;
   LINENUM_TYPE     lastLinenum;
   S8               tmpStr[MAX_SYMNAME_LENGTH]; // used for type names
   TYPE_HEADER_TYPE typeHeader;
   TYPE_INDEX       typeIndex;
   REG_INDEX        regIndex;
   S8               regName[40];
   RETCODE          err;
   LPSTR            strPtr;
   int              n;

   SpaceToColumn(DETAILED_TYPE_COLUMN);
   tmpStr[0] = '\0';  // init string

   strPtr = globalStr;  // set pointer to beginning of string
   while (*++strPtr != '\0');  // point to null string terminator
   symPtr = (HPU8)st.GetHugeDataPtr(symbol);

   // get symbol type index
   switch (((COMMON_SYMBOL_HEADER *)symPtr)->typeIndex.symType & 0xF) {
      case SYM_MODULE:  // display linenum range
         if (SUCCESS ==
               (lt.GetLinenumFirstLast(symbol, firstLinenum, lastLinenum))) {
            n = sprintf( strPtr , "Lines ");
            strPtr += n;
            n = sprintf(strPtr, "%u-%u", firstLinenum, lastLinenum);
            strPtr += n;
            }
         break;

      case SYM_FUNCTION:   // display local/global and return type
         if (((SYM_TYPE_FUNCTION *)symPtr)->funcClass == FUNC_GLOBAL)  {
            n = sprintf(strPtr, "Global returning ");
         } else {                                   
            n = sprintf(strPtr, "Local returning ");
         }              
         strPtr += n;
         // insert the return type name
         // assign the string pointer in typeHeader to the local string
         typeHeader.typeName = tmpStr;

         U32 attribute;
         U8  frameType;
         U32 pushMask;
         U8  argCount;
         U8  level;
         U8  fatherName[MAX_SYMNAME_LENGTH];
         TYPE_INDEX returnIndexType;
         
         if (GOOD == SymGetFuncType(symbol,
                                    &attribute,
                                    &frameType,
                                    &pushMask,
                                    &typeHeader,  // contains tmpStr ptr
                                    &argCount,
                                    &level,
                                    (LPSTR)fatherName)) {
            // tmpStr filled in with simple name or null
            if (typeHeader.typeChoice == COMPLEX_TYPE_CLASS)  {
               // add complex name
               // match complex type number to constant index table; extract
               //   index for complexTypeNames string table
            
               complexTypeNamesMap[sizeof(complexTypeNamesMap) - 1] =
                  (U8)typeHeader.t.complexType;
               // scan array for match
               for (U8 i=0; i < sizeof(complexTypeNamesMap); i++) {
                  if ((U8)typeHeader.t.complexType == complexTypeNamesMap[i])
                     break;
               };
               // Only fill in the type name map for non-typedef types
               // and non-X86 family.
               if (typeHeader.t.complexType != TY_TYPE) {
                   n = sprintf(strPtr, complexTypeNames[i]);
                   strPtr += n;
                   *strPtr = ' ';
                   strPtr++;
               }

               // if type is ptr, add text indicating what it points to
               // tmpStr freed up here inside if stmt
               if ((typeHeader.t.complexType == TY_SMALL_PTR) ||   // small ptr
                   (typeHeader.t.complexType == TY_LARGE_PTR) ||   // large ptr
                   (typeHeader.t.complexType == TY_16_16_PTR) ||   // 16:16 ptr
                   (typeHeader.t.complexType == TY_16_32_PTR)) {   // 16:32 ptr
                  // although a kludge, the SymGetFuncType does not return
                  // the return type INDEX, it only fills out the values
                  // of the type; therefore, must use following function...
                  if (GOOD != (err = 
                     SymGetFuncReturnTypeIndex(symbol,
                                               &returnIndexType)))
//                  if (GOOD !=
//                     (err = GetDestinationOfPtr(returnIndexType,
//                                                tmpStr)))
//                     goto CLEANUP;
                    GetDestinationOfPtr(returnIndexType,tmpStr);
                  // tmpStr has " to <type name>"
               }
            }
            // just fall through for all simple types
         } else { 
            // SymGetFunctype() failed to retrieve the function return type.
            strcpy(tmpStr, "unknown");
         }
         // 08/16/94 - Nghia
         // Handle both complex and simple return type
         n += sprintf( strPtr , tmpStr );
         strPtr += n;
//         strPtr = stpcpy(strPtr, tmpStr);  
         break;

      case SYM_GLOBAL_VAR:
      case SYM_LOCAL_VAR:
      case SYM_USER_DEFINED_VAR:
      case SYM_PUBLIC_VAR:   // display built-in type or general complex type
         // insert basic variable type
         if (NOT_REG == ((SYM_TYPE_VARIABLE *)symPtr)->registerClass) {
            // insert non-register typename
            n = sprintf(strPtr,
                (S8 FAR *)varStorageClass[((SYM_TYPE_VARIABLE *)symPtr)->
                storageClass]);
            strPtr += n;
         } else {      
            n = sprintf(strPtr, "Reg ");
            strPtr += n;
            // insert register name
            regIndex =
               ((COMMON_SYMBOL_HEADER *)symPtr)->beginAddrInfo.registerIndex;

//            err = CpuFindRegisterName(regIndex, regName);
            err = 1;
            if (err) {  // print out reg number if no matching name
               n = sprintf(strPtr, "%02u ", regIndex);
               strPtr += n;
            } else {    // insert register name
               n = sprintf( strPtr , regName ); 
               strPtr += n;
               n = sprintf( strPtr , " " ); 
               strPtr += n;
            }
         }
         // insert the type name even if a built-in
         typeHeader.typeName = tmpStr;  // give routine string memory
         typeIndex = ((SYM_TYPE_VARIABLE *)symPtr)->typeIndex;

         // get the type header info of the type
         if (GOOD != (err = SymGetTypeHeader(typeIndex, &typeHeader))) 
            goto CLEANUP;
            
         // if the type is complex, insert complex type name first
         if (typeHeader.typeChoice == COMPLEX_TYPE_CLASS)  {
            // add complex name
            // match complex type number to constant index table; extract
            //   index for complexTypeNames string table            
            if (tmpStr[0] != '\0') {  // if text in string, copy typedef name
               n = sprintf( strPtr , tmpStr );  
               strPtr += n;
               n = sprintf( strPtr , " " );
               strPtr += n;
            }
            complexTypeNamesMap[sizeof(complexTypeNamesMap) - 1] =
               (U8)typeHeader.t.complexType;
            // scan array for match
            for (U8 i=0; i < sizeof(complexTypeNamesMap); i++) {
               if ((U8)typeHeader.t.complexType == complexTypeNamesMap[i])
                  break;
            };

            // Only fill in the type name map for non-typedef types
            // and non-X86 family
            if (typeHeader.t.complexType != TY_TYPE) {
               n = sprintf( strPtr , complexTypeNames[i]);
               strPtr += n;
               *strPtr = ' ';
               strPtr++;
            }
            
            // 08/15/94 - Nghia
            // Get the base type to print out with the complex type.
            switch(typeHeader.t.complexType) {
               case TY_C_ARRAY :
               {
                  TYPE_Z_STRUCT arrStruct;
                  TYPE_HEADER_TYPE baseTypeHeader;
                  // use the parent type name buffer even if a built-in
                  // give routine string memory
                  baseTypeHeader.typeName = tmpStr;                    
                  n = sprintf(strPtr, "of ");
                  strPtr += n;
                  if ((SymGetTypeCArray(typeIndex, &arrStruct) != GOOD) ||
                      (SymGetTypeHeader((TYPE_INDEX)arrStruct.typeIndex,
                       &baseTypeHeader) != GOOD)) 
                     goto CLEANUP; 
                     
                  if ( tmpStr[0] == '\0' ) {   
                    complexTypeNamesMap[sizeof(complexTypeNamesMap) - 1] =
                        (U8)baseTypeHeader.t.complexType;
                    // scan array for match
                    for (i=0; i < sizeof(complexTypeNamesMap); i++) {
                        if ((U8)baseTypeHeader.t.complexType == 
                            complexTypeNamesMap[i])
                            break;
                    }       
                    sprintf( tmpStr , complexTypeNames[i]);
                  }
                  break;
               }

               case TY_OMF51_ARRAY :
               {
                  TYPE_OMF51_ARRAY_STRUCT arrStruct;
                  TYPE_HEADER_TYPE baseTypeHeader;
                  // use the parent type name buffer even if a built-in
                  // give routine string memory
                  baseTypeHeader.typeName = tmpStr;                    
                  n = sprintf(strPtr, "of ");
                  strPtr += n;
                  if ((SymGetTypeArray51(typeIndex, &arrStruct) != GOOD) ||
                      (SymGetTypeHeader((TYPE_INDEX)arrStruct.typeIndex,
                       &baseTypeHeader) != GOOD)) 
                     goto CLEANUP; 
                     
                  if ( tmpStr[0] == '\0' ) {   
                    complexTypeNamesMap[sizeof(complexTypeNamesMap) - 1] =
                        (U8)baseTypeHeader.t.complexType;
                    // scan array for match
                    for (i=0; i < sizeof(complexTypeNamesMap); i++) {
                        if ((U8)baseTypeHeader.t.complexType == 
                            complexTypeNamesMap[i])
                            break;
                    }       
                    sprintf( tmpStr , complexTypeNames[i]);
                  }
                  break;
               }

               case TY_TYPE :
                  // For OMF load format, there is no "typedef" types
                  // Clear the duplicated 
                  *tmpStr = '\0';                  
                  break;

               case TY_SMALL_PTR : // small ptr
               case TY_LARGE_PTR : // large ptr
               case TY_16_16_PTR : // 16:16 ptr
               case TY_16_32_PTR : // 16:32 ptr  
//                  if (GOOD != (err = GetDestinationOfPtr(typeIndex, tmpStr)))
//                     goto CLEANUP;
                  GetDestinationOfPtr(typeIndex, tmpStr);
                  break;

               case TY_OMF51_PTR : // generic ptr
//                  if (GOOD != (err = GetDestinationOfOmf51Ptr(typeIndex, tmpStr)))
//                     goto CLEANUP;
                  GetDestinationOfOmf51Ptr(typeIndex, tmpStr);
                  break;

               default :
                  *tmpStr = '\0';
            }            
         }
         // Handle both simple and complex type
         // concatenate the type name to the output string
         n = sprintf( strPtr , tmpStr );
         strPtr += n;
//         strPtr = stpcpy(strPtr, tmpStr); 
         break;

      default: ; // insert nothing
   } // end of switch
   return;

CLEANUP:
//   ErrDisplayError(err, CHECK_MODE);
   return;
}  // end of FillInDetailedType


//--------------------------------------------------------------------------
// SymbolDetailedType
//--------------------------------------------------------------------------
int SymbolDetailedType(SYM_DESCRIPTOR symbol , char * str)  {

    HPU8             symPtr;
    S8               tmpStr[256]; // used for type names
    TYPE_HEADER_TYPE typeHeader;
    TYPE_INDEX       typeIndex;
    REG_INDEX        regIndex;
    S8               regName[40];
    RETCODE          err;
    LPSTR            strPtr;
    int              n;

    tmpStr[0] = '\0';  // init string

    strPtr = str;  // set pointer to beginning of string
    symPtr = (HPU8)st.GetHugeDataPtr(symbol);

    // get symbol type index
    switch (((COMMON_SYMBOL_HEADER *)symPtr)->typeIndex.symType & 0xF) {
    case SYM_MODULE:  // display linenum range
    case SYM_FUNCTION:   // display local/global and return type
        return FAILURE;
        break;

    case SYM_GLOBAL_VAR:
    case SYM_LOCAL_VAR:
    case SYM_USER_DEFINED_VAR:
    case SYM_PUBLIC_VAR:   // display built-in type or general complex type
         // insert basic variable type
        if (NOT_REG == ((SYM_TYPE_VARIABLE *)symPtr)->registerClass) {
            // insert non-register typename
            n = sprintf(strPtr,
                (S8 FAR *)varStorageClass[((SYM_TYPE_VARIABLE *)symPtr)->
                storageClass]);
            strPtr += n;
        } else {      
            n = sprintf(strPtr, "Reg ");
            strPtr += n;
            // insert register name
            regIndex =
               ((COMMON_SYMBOL_HEADER *)symPtr)->beginAddrInfo.registerIndex;

//            err = CpuFindRegisterName(regIndex, regName);
            err = 1;
            if (err) {  // print out reg number if no matching name
               n = sprintf(strPtr, "%02u ", regIndex);
               strPtr += n;
            } else {    // insert register name
               n = sprintf( strPtr , regName ); 
               strPtr += n;
               n = sprintf( strPtr , " " ); 
               strPtr += n;
            }
        }
         // insert the type name even if a built-in
        typeHeader.typeName = tmpStr;  // give routine string memory
        typeIndex = ((SYM_TYPE_VARIABLE *)symPtr)->typeIndex;

         // get the type header info of the type
        if (GOOD != (err = SymGetTypeHeader(typeIndex, &typeHeader))) 
            return FAILURE;
            
         // if the type is complex, insert complex type name first
        if (typeHeader.typeChoice == COMPLEX_TYPE_CLASS)  {
            // add complex name
            // match complex type number to constant index table; extract
            //   index for complexTypeNames string table            
            if (tmpStr[0] != '\0') {  // if text in string, copy typedef name
                n = sprintf( strPtr , tmpStr ); 
                strPtr += n;
                n = sprintf( strPtr , " " );
                strPtr += n;
            }
            complexTypeNamesMap[sizeof(complexTypeNamesMap) - 1] =
                (U8)typeHeader.t.complexType;
            // scan array for match
            for (U8 i=0; i < sizeof(complexTypeNamesMap); i++) {
                if ((U8)typeHeader.t.complexType == complexTypeNamesMap[i])
                    break;
            };

            // Only fill in the type name map for non-typedef types
            // and non-X86 family
            if (typeHeader.t.complexType != TY_TYPE) {
                n = sprintf( strPtr , complexTypeNames[i]);
                strPtr += n;
                *strPtr = ' ';
                strPtr++;
            }
            
            // 08/15/94 - Nghia
            // Get the base type to print out with the complex type.
            switch(typeHeader.t.complexType) {
            case TY_C_ARRAY :
            {
                TYPE_Z_STRUCT arrStruct;
                TYPE_HEADER_TYPE baseTypeHeader;
                // use the parent type name buffer even if a built-in
                // give routine string memory
                baseTypeHeader.typeName = tmpStr;                    
                n = sprintf(strPtr, "of ");
                strPtr += n;
                if ((SymGetTypeCArray(typeIndex, &arrStruct) != GOOD) ||
                    (SymGetTypeHeader((TYPE_INDEX)arrStruct.typeIndex,
                     &baseTypeHeader) != GOOD)) 
                    return FAILURE;
                  if ( tmpStr[0] == '\0' ) {   
                    complexTypeNamesMap[sizeof(complexTypeNamesMap) - 1] =
                        (U8)baseTypeHeader.t.complexType;
                    // scan array for match
                    for (i=0; i < sizeof(complexTypeNamesMap); i++) {
                        if ((U8)baseTypeHeader.t.complexType == 
                            complexTypeNamesMap[i])
                            break;
                    }       
                    sprintf( tmpStr , complexTypeNames[i]);
                  }
                break;
            }

            case TY_OMF51_ARRAY :
            {
                TYPE_OMF51_ARRAY_STRUCT arrStruct;
                TYPE_HEADER_TYPE baseTypeHeader;
                // use the parent type name buffer even if a built-in
                // give routine string memory
                baseTypeHeader.typeName = tmpStr;                    
                n = sprintf(strPtr, "of ");
                strPtr += n;
                if ((SymGetTypeArray51(typeIndex, &arrStruct) != GOOD) ||
                    (SymGetTypeHeader((TYPE_INDEX)arrStruct.typeIndex,
                     &baseTypeHeader) != GOOD)) 
                    return FAILURE;
                  if ( tmpStr[0] == '\0' ) {   
                    complexTypeNamesMap[sizeof(complexTypeNamesMap) - 1] =
                        (U8)baseTypeHeader.t.complexType;
                    // scan array for match
                    for (i=0; i < sizeof(complexTypeNamesMap); i++) {
                        if ((U8)baseTypeHeader.t.complexType == 
                            complexTypeNamesMap[i])
                            break;
                    }       
                    sprintf( tmpStr , complexTypeNames[i]);
                  }
                break;
            }

            case TY_TYPE :
                // For OMF load format, there is no "typedef" types
                // Clear the duplicated 
                *tmpStr = '\0';                  
                break;

            case TY_SMALL_PTR : // small ptr
            case TY_LARGE_PTR : // large ptr
            case TY_16_16_PTR : // 16:16 ptr
            case TY_16_32_PTR : // 16:32 ptr  
                if (GOOD != (err = GetDestinationOfPtr(typeIndex, tmpStr)))
                    return FAILURE;
                break;

            case TY_OMF51_PTR : // generic ptr
                if (GOOD != (err = GetDestinationOfOmf51Ptr(typeIndex, tmpStr)))
                    return FAILURE; 
                break;

            default :
                *tmpStr = '\0';
            }            
        }
        // Handle both simple and complex type
        // concatenate the type name to the output string
        n = sprintf( strPtr , tmpStr );
        strPtr += n;
//         strPtr = stpcpy(strPtr, tmpStr); 
        break;

    default: ; // insert nothing
        return FAILURE;
   } // end of switch
   return GOOD;

}  // end of FillInDetailedType


//--------------------------------------------------------------------------
// BuildDetailedType
//--------------------------------------------------------------------------
int BuildDetailedType(TYPE_INDEX typeIndex, char *str)  {

//  HPU8             symPtr;
    S8               tmpStr[256]; // used for type names
    TYPE_HEADER_TYPE typeHeader;
//  TYPE_INDEX       typeIndex;
//  REG_INDEX        regIndex;
//  S8               regName[40];
    RETCODE          err;
    LPSTR            strPtr;
    int              n;

    tmpStr[0] = '\0';  // init string

    // insert the type name even if a built-in
    typeHeader.typeName = tmpStr;  // give routine string memory
    strPtr = str;

    // get the type header info of the type
    if (GOOD != (err = SymGetTypeHeader(typeIndex, &typeHeader))) 
        return FAILURE;
            
   // if the type is complex, insert complex type name first
    if (typeHeader.typeChoice == COMPLEX_TYPE_CLASS)  {
            // add complex name
            // match complex type number to constant index table; extract
            //   index for complexTypeNames string table            
        if (tmpStr[0] != '\0') {  // if text in string, copy typedef name
            n = sprintf( strPtr , tmpStr ); 
            strPtr += n;
            n = sprintf( strPtr , " " );
            strPtr += n;
        }
        complexTypeNamesMap[sizeof(complexTypeNamesMap) - 1] =
            (U8)typeHeader.t.complexType;
            // scan array for match
        for (U8 i=0; i < sizeof(complexTypeNamesMap); i++) {
            if ((U8)typeHeader.t.complexType == complexTypeNamesMap[i])
                break;
        };

        // Only fill in the type name map for non-typedef types
        // and non-X86 family
        if (typeHeader.t.complexType != TY_TYPE) {
            n = sprintf( strPtr , complexTypeNames[i]);
            strPtr += n;
            *strPtr = ' ';
            strPtr++;
        }
            
        // 08/15/94 - Nghia
        // Get the base type to print out with the complex type.
        switch(typeHeader.t.complexType) {
        case TY_C_ARRAY :
        {
            TYPE_Z_STRUCT arrStruct;
            TYPE_HEADER_TYPE baseTypeHeader;
            // use the parent type name buffer even if a built-in
            // give routine string memory
            baseTypeHeader.typeName = tmpStr;                    
            n = sprintf(strPtr, "of ");
            strPtr += n;
            if ((SymGetTypeCArray(typeIndex, &arrStruct) != GOOD) ||
                (SymGetTypeHeader((TYPE_INDEX)arrStruct.typeIndex,
                 &baseTypeHeader) != GOOD)) 
                return FAILURE;
            if ( tmpStr[0] == '\0' ) {   
                complexTypeNamesMap[sizeof(complexTypeNamesMap) - 1] =
                    (U8)baseTypeHeader.t.complexType;
                // scan array for match
                for (i=0; i < sizeof(complexTypeNamesMap); i++) {
                    if ((U8)baseTypeHeader.t.complexType == 
                        complexTypeNamesMap[i])
                        break;
                }       
                sprintf( tmpStr , complexTypeNames[i]);
            }
            break;
        }

        case TY_OMF51_ARRAY :
        {
            TYPE_OMF51_ARRAY_STRUCT arrStruct;
            TYPE_HEADER_TYPE baseTypeHeader;
            // use the parent type name buffer even if a built-in
            // give routine string memory
            baseTypeHeader.typeName = tmpStr;                    
            n = sprintf(strPtr, "of ");
            strPtr += n;
            if ((SymGetTypeArray51(typeIndex, &arrStruct) != GOOD) ||
                (SymGetTypeHeader((TYPE_INDEX)arrStruct.typeIndex,
                 &baseTypeHeader) != GOOD)) 
                return FAILURE;
            if ( tmpStr[0] == '\0' ) {   
                complexTypeNamesMap[sizeof(complexTypeNamesMap) - 1] =
                (U8)baseTypeHeader.t.complexType;
                // scan array for match
                for (i=0; i < sizeof(complexTypeNamesMap); i++) {
                    if ((U8)baseTypeHeader.t.complexType == 
                        complexTypeNamesMap[i])
                        break;
                }       
                sprintf( tmpStr , complexTypeNames[i]);
            }
            break;
        }

        case TY_TYPE :
            // For OMF load format, there is no "typedef" types
            // Clear the duplicated 
            *tmpStr = '\0';                  
            break;

        case TY_SMALL_PTR : // small ptr
        case TY_LARGE_PTR : // large ptr
        case TY_16_16_PTR : // 16:16 ptr
        case TY_16_32_PTR : // 16:32 ptr  
            if (GOOD != (err = GetDestinationOfPtr(typeIndex, tmpStr)))
                return FAILURE;
            break;

        case TY_OMF51_PTR : // generic ptr
            if (GOOD != (err = GetDestinationOfOmf51Ptr(typeIndex, tmpStr)))
                return FAILURE;
            break;

        default :
            *tmpStr = '\0';
        }            
    }
    // Handle both simple and complex type
    // concatenate the type name to the output string
    n = sprintf( strPtr , tmpStr );
    strPtr += n;
//         strPtr = stpcpy(strPtr, tmpStr); 

   return GOOD;
}  // end of FillInDetailedType


// Text table definition
#define MAX_SYM_TYPE_NAMES 11
const S8 *symTypeName[MAX_SYM_TYPE_NAMES] = {
   "MODULE",
   "FUNCTION",
   "BLOCK",
   "VARIABLE",
   "LABEL",
   "CONSTANT",
   "USER VAR",
   "USER LABEL",
   "PUBLIC VAR",
   "PUBLIC LABEL",
   "PUBLIC"
};

// The values in this array map the SYM_TYPE_TYPE enum entries (which start at
// 0) to the string array <symTypeName> above.  A value of 0xFF means there is
// no string name for that symbol type
U8 symTypeMap[MAX_SYM_TYPE] = {
   0xFF, //SYM_ROOT
   0,    //SYM_MODULE
   1,    //SYM_FUNCTION
   2,    //SYM_BLOCK
   3,    //SYM_GLOBAL_VAR
   3,    //SYM_LOCAL_VAR
   4,    //SYM_LABEL
   5,    //SYM_CONSTANT
   0xFF, //SYM_TYPE
   6,    //SYM_USER_DEFINED_VAR
   7,    //SYM_USER_DEFINED_LABEL
   8,    //SYM_PUBLIC_VAR
   9,    //SYM_PUBLIC_LABEL
   10,   //SYM_PUBLIC_UNKNOWN
   0xFF, //SYM_MISCELLANEOUS
   0xFF  //SYM_UNDEFINED
};


//--------------------------------------------------------------------------
// FillInTypeAndName
//--------------------------------------------------------------------------
RETCODE PRIVATE FillInTypeAndName(SYM_DESCRIPTOR symbol, U8 nesting)  {

   COMMON_SYMBOL_HEADER HUGE *symPtr;
   S8 name[MAX_SYMNAME_LENGTH];
   U8 symTypeMapIndex;
   RETCODE retCode;

   globalStr[0] = '\0';   // init string
   SpaceToColumn((U16)(min(nesting, 6) * 2));
   symPtr = (COMMON_SYMBOL_HEADER HUGE *)st.GetHugeDataPtr(symbol);

   // get symbol type index; map to string index; if index > number of entries
   // in the string table, return; otherwise copy string into char array
   if ((symTypeMapIndex = symTypeMap[(symPtr->typeIndex.symType) & 0xF]) >
      MAX_SYM_TYPE_NAMES)
      return ER_STRING_LENGTH_ZERO;
   // map symbol type to symbol type name string
   strcat(globalStr, symTypeName[symTypeMapIndex]);
   SpaceToColumn(NAME_COLUMN);

   // install name
   if (((symPtr->typeIndex.symType) & 0xF) == SYM_MODULE) {
      if ((retCode = SymAddGetModuleName(symbol, name)) != SUCCESS)
         return retCode;
   }
   else {
      st.GetString(symPtr->symbolNameOffset, (LPU8)name);
   }
   strcat(globalStr, name);
   return GOOD;   
}  // end of FillInTypeAndName


//--------------------------------------------------------------------------
// GetSymbolPrintLine
//--------------------------------------------------------------------------
RETCODE PRIVATE
GetSymbolPrintLine(SYM_DESCRIPTOR   symbol,
//                   SYM_DISPLAY_TYPE displayType,
                   U16              nesting)  {

   RETCODE err;

   if ((err = FillInTypeAndName(symbol, (U8)nesting)) != GOOD)
      return err;
   FillInDetailedType(symbol);
   if ((err = FillInAddress(symbol)) != GOOD)
      return err;
   return GOOD;
} // end of GetSymbolPrintLine


//--------------------------------------------------------------------------
// SpaceToColumn
//
// Design:
//    fills spaces up to but not including requested column (column 1 = first
//    character, i.e. string[0])
//    If requested column is less than or equal to the position of the null
//    termination, then insert one space and put the null character one
//    location after its present position.
//
// Input Parameter:
//    column:
//       indicates what column to insert spaces to; i.e. if the value is 10,
//       spaces should be inserted through column 9, where column 1 is the
//       first character field.
//--------------------------------------------------------------------------
VOID SpaceToColumn(U16 column) {

   U16 len;

   if (column == 0) return;      // no request for space padding
   len = (U16)strlen(globalStr);
   if (column <= len) {
      column = len + 1;   // fill in one additional space, then null terminate
   }
/* as defined, sizeof(globalStr) is always larger than a U8 (256 * 2) */
// if (column > sizeof(globalStr))
//    return;              // don't fill if request is beyond size of string

   for (; len < column; globalStr[len++] = ' ');

   globalStr[len] = '\0'; // add null termination
   
}  // end of SpaceToColumn


//--------------------------------------------------------------------------
// PrintBlockHeader
//--------------------------------------------------------------------------
RETCODE PRIVATE PrintBlockHeader(HPU8 symPtr, SYM_DISPLAY_TYPE displayType) {

   COMMON_BLOCK_HEADER *blkPtr;

   // Don't print any of the block info if this is a user symbol display ;
   if (displayType == DEBUG_DISPLAY) {
      blkPtr=(COMMON_BLOCK_HEADER *)symPtr;
      sprintf((LPSTR)globalStr,"Child Descriptor:  %8lX",blkPtr->child);
      ShowLine( globalStr );
      sprintf((LPSTR)globalStr,"Variable List Descriptor:  %8lX   "
          "Label List Descriptor:  %8lX", blkPtr->list.varListOffset, 
          blkPtr->list.labelListOffset);
      ShowLine( globalStr );
      sprintf((LPSTR)globalStr,"Constant List Descriptor:  %8lX   "
         "Misc. List Descriptor:  %8lX", blkPtr->list.constListOffset,
         blkPtr->list.miscListOffset);
      ShowLine( globalStr );
   }
   return(GOOD);

}

//--------------------------------------------------------------------------
// PrintCommonHeader
//--------------------------------------------------------------------------
RETCODE PRIVATE PrintCommonHeader(HPU8 symPtr, SYM_DISPLAY_TYPE displayType) {

   RETCODE err;
   COMMON_SYMBOL_HEADER *headPtr;
   U8 name[MAX_SYMNAME_LENGTH];
   U8 *namePtr;

   headPtr=(COMMON_SYMBOL_HEADER *)symPtr;

   // get the name of the symbol ;
   if ( (headPtr->symbolNameOffset == NULL_SYMBOL) && 
      (displayType == DEBUG_DISPLAY)) {
      sprintf((LPSTR) globalStr, "Unnamed symbol");
      ShowLine( globalStr );
   } else {
      if (headPtr->symbolNameOffset) {
         st.GetString(headPtr->symbolNameOffset,(LPU8)name);
         if (headPtr->typeIndex.symType == SYM_MODULE) {
            // move the pointer past the extra two characters prepended to ;
            // module names to make them unique. ;
            namePtr = name + 2;
         } else {
            namePtr = name;
         }
         sprintf((LPSTR)globalStr,"Name:  %s",(LPSTR)namePtr);
         ShowLine( globalStr );
      }
   }
   
   if ((err = PrintSymbolAddress(symPtr)) != GOOD)
      return(err);
   
   if (displayType == DEBUG_DISPLAY) {
      sprintf((LPSTR)globalStr,"Type:    %4d   Base Index:      %d",
         ((headPtr->typeIndex.symType) & 0xF), headPtr->typeIndex.baseIndex);
      ShowLine( globalStr );
      sprintf((LPSTR)globalStr,"Parent Descriptor:  %8lX   "
         "Sibling Descriptor:  %8lX", headPtr->symParentOffset,
         headPtr->symSiblingOffset);
      ShowLine( globalStr );
      sprintf((LPSTR)globalStr,"Ordinal Value:  %8lX",headPtr->ordinalVal);
      ShowLine( globalStr );
   }
   return(GOOD);
}

//--------------------------------------------------------------------------
// PrintFunction
//--------------------------------------------------------------------------
RETCODE PRIVATE PrintFunction(HPU8 symPtr, SYM_DISPLAY_TYPE displayType) {
   
   RETCODE err;
   SYM_TYPE_FUNCTION *funcPtr;

   // print the information common to all block/function/module symbols ;
   if ((err = PrintBlockHeader(symPtr, displayType)) != GOOD) return(err);
   
   if (displayType == DEBUG_DISPLAY) {
      // print the information specific to modules ;
      funcPtr=(SYM_TYPE_FUNCTION *)symPtr;
   
      sprintf((LPSTR)globalStr,"Function Class:  %4x",funcPtr->funcClass);
      ShowLine( globalStr );
   
      sprintf((LPSTR)globalStr,"Stack Space:  %8lX  Type Index:  %8lX",
         funcPtr->stackSpace,funcPtr->typeIndex);
      ShowLine( globalStr );
   }
   return(GOOD);
}

//--------------------------------------------------------------------------
// PrintModule
//--------------------------------------------------------------------------
RETCODE PRIVATE PrintModule(HPU8 symPtr, SYM_DISPLAY_TYPE displayType) {
   
   RETCODE err;
   SYM_TYPE_MODULE *modPtr;
   U8 name[MAX_SYMNAME_LENGTH];

   // print the information common to all block/function/module symbols ;
   if ((err = PrintBlockHeader(symPtr, displayType)) != GOOD) return(err);

   if (displayType == DEBUG_DISPLAY) {
      // print the information specific to modules ;
      modPtr=(SYM_TYPE_MODULE *)symPtr;
      
      sprintf((LPSTR)globalStr,"Line Number Offset Start:  %8lX",
         modPtr->linenumOffsetStart);
      ShowLine( globalStr );

      sprintf((LPSTR)globalStr,"Line Number Offset End:  %8lX",
         modPtr->linenumOffsetEnd);
      ShowLine( globalStr );
   }
   
   // get the source file name ;
   st.GetString(modPtr->srcFilenameOffset, (LPU8)name);
   
   sprintf((LPSTR)globalStr,"Filename: %s",(LPSTR)name);
   ShowLine( globalStr );

   if (displayType == DEBUG_DISPLAY) {
      sprintf((LPSTR)globalStr,"%#02d-%#02d-%#04d", modPtr->timestamp.day,
         modPtr->timestamp.month, modPtr->timestamp.year);
      ShowLine( globalStr );
   
      sprintf((LPSTR)globalStr,"%#02d:%#02d:%#02d", modPtr->timestamp.hour,
         modPtr->timestamp.minute, modPtr->timestamp.second);
      ShowLine( globalStr );
   }
   return(GOOD);
}

//--------------------------------------------------------------------------
// PrintSymbolAddress
//--------------------------------------------------------------------------
RETCODE PRIVATE
PrintSymbolAddress(HPU8 symPtr) {

   RETCODE              err = GOOD, err1 = GOOD;
   COMMON_SYMBOL_HEADER *headPtr;
   S8                   *tmpPtr = globalStr;
   int                  n;
   
   headPtr = (COMMON_SYMBOL_HEADER *)symPtr;
   switch (headPtr->typeIndex.symType & 0xF) {
      case SYM_LOCAL_VAR:
      case SYM_GLOBAL_VAR:
      case SYM_PUBLIC_VAR:
      case SYM_FUNCTION:
      case SYM_MODULE:
      case SYM_LABEL:
      case SYM_PUBLIC_LABEL:
      case SYM_PUBLIC_UNKNOWN:
         n = sprintf((LPSTR) globalStr, "    Start Address: ");
         tmpPtr += n;
         switch( headPtr->typeIndex.baseIndex ) {
         case 0 :
            n = sprintf(tmpPtr , " U:");
            break;
         case 1 :
            n = sprintf(tmpPtr , " P:");
            break;
         case 2 :
            n = sprintf(tmpPtr , " I:");
            break;
         case 3 :
            n = sprintf(tmpPtr , " X:");
            break;
         case 4 :
            n = sprintf(tmpPtr , " B:");
            break;
         case 5 :
            n = sprintf(tmpPtr , " R:");
            break;
         case 6 :
            n = sprintf(tmpPtr , " C:");
            break;
         default :
            n = 0;
            break;
         }
         tmpPtr += n;
         n= sprintf(tmpPtr, "%lX-%lX",
            headPtr->beginAddrInfo.startAddr,
            headPtr->endAddrInfo.endAddr );
         tmpPtr += n;
//         tmpAddrSize = headPtr->endAddrInfo.endAddr -
//                headPtr->beginAddrInfo.startAddr+1 ;
//         sprintf(tmpPtr," [%lu]",tmpAddrSize);
//         ShowLine( globalStr );

         break;
     default :
         break;
   } /* end of switch */
   return((err != GOOD ? err : err1));
}

//--------------------------------------------------------------------------
// SymPrintBases
//--------------------------------------------------------------------------
RETCODE SymPrintBases(SYM_DISPLAY_TYPE displayType) {

   BaseSymbol HUGE *base;
   ByAddressTable HUGE *byAddrTablePtr;
   U8 name[MAX_SYMNAME_LENGTH];
   TABLE_OFFSET baseOffset, byAddrBaseOffset;
   
   // get the offset of the first base ;
   if((baseOffset = bit.GetRootBaseSymbolOffset()) == NULL_SYMBOL)
      return ER_INDEX_NOT_IN_TABLE;

   do {    
      // get a pointer to the base ;
      base = (BaseSymbol HUGE *)st.GetHugeDataPtr(baseOffset);

      // print out the BASES info ;
      st.GetString(base->GetBaseNameOffset(), (LPU8)name);
      strcpy(globalStr,"-----------------------------------------------------------------");
      ShowLine( globalStr );

      // print base name
      sprintf((LPSTR)globalStr, "Name:  %s", (LPSTR)name);
      ShowLine( globalStr );

      // print base address and the next base offset
      sprintf((LPSTR)globalStr,"Base Address:  %8lX", base->GetBaseAddress());
      ShowLine( globalStr );

      if (displayType == DEBUG_DISPLAY) {
         // print address min and max ;
         sprintf((LPSTR)globalStr,"Address Min: %8lX   Address Max: %8lX",
            base->GetAddressMin(), base->GetAddressMax());
         ShowLine( globalStr );

         // print by-address table offset and number of entries ;
         byAddrBaseOffset = base->GetByAddressTableOffset();
         byAddrTablePtr = 
            (ByAddressTable HUGE *)st.GetHugeDataPtr(byAddrBaseOffset);
         sprintf((LPSTR)globalStr,
                  "Address Count:  %8lX   Address Table:  %8lX",
                  byAddrTablePtr->GetSymbolCount(), byAddrBaseOffset);
         ShowLine( globalStr );
         sprintf((LPSTR)globalStr,"Next Base Offset:  %8lX", 
            base->GetNextBaseOffset());
         ShowLine( globalStr );
      }

      // print the base type and table dirty status
      strcpy(globalStr, "Base Type:  ");
      switch (base->GetBaseType()) {
         case BASE_UNKNOWN:   strcat(globalStr, "UNKNOWN BASE"); break;
         case BASE_CODE:      strcat(globalStr, "CODE BASE");  break;
         case BASE_DATA:      strcat(globalStr, "DATA BASE");  break;
         case BASE_CODE_DATA: strcat(globalStr, "CODE_DATA BASE");  break;
         default:             strcat(globalStr, "ERROR");
      }

      if(displayType == DEBUG_DISPLAY) {
         strcpy(globalStr, "Table Dirty:  ");
         if (base->GetAddrTableDirty())
            strcat(globalStr, "TRUE\n\0");
         else strcat(globalStr, "FALSE\n\0");
         ShowLine( globalStr );
      }

      // go to next base object
      baseOffset=base->GetNextBaseOffset();
   } while(baseOffset);
   return(GOOD);
}


//--------------------------------------------------------------------------
// SymPrintSymbol
//--------------------------------------------------------------------------
RETCODE EXPORT
SymPrintSymbol(TABLE_OFFSET symbol, 
               SYM_DISPLAY_TYPE displayType,
               U16 indentLevel) {

   RETCODE err;
   HPU8    symPtr;

   if ((displayType != DEBUG_DISPLAY) &&
       (displayType != VARLIFE_DISPLAY)) {
      if (GOOD != (err = GetSymbolPrintLine(symbol, indentLevel)))
         return err;
      ShowLine( globalStr );

      // abort key was or is pressed
//      err = TskCheckAbort(&abortFromEsc);
//      if ((err != GOOD) || abortFromEsc) {
//         return ER_ABORT_FROM_ESC;
//      }
       // escape when key pressed
        if ( (err = TestKey(VK_ESCAPE)) == 1 ) {
             return( FAILURE );
        }
      return GOOD;
   }

   // fall thru and display the debug lines
   // get a ptr to that symbol and print out the common info ;
   symPtr=st.GetHugeDataPtr(symbol);

   // Display Register variable information
   if (displayType == VARLIFE_DISPLAY) { 
      if (GOOD != (err = GetSymbolPrintLine(symbol, indentLevel)))
         return err;
      ShowLine( globalStr );
       switch(((COMMON_SYMBOL_HEADER *)symPtr)->typeIndex.symType & 0xF) {
          case SYM_LOCAL_VAR:
          case SYM_GLOBAL_VAR:
          case SYM_PUBLIC_VAR:
             return(PrintVariable(symbol, symPtr, displayType));
       }
       return(GOOD);
   } 
         
   // find out what type the symbol is and then print the specific info ;
   switch (((COMMON_SYMBOL_HEADER *)symPtr)->typeIndex.symType & 0xF) {
      case SYM_ROOT:
      case SYM_MODULE:
         if ((err = PrintCommonHeader(symPtr, displayType)) != GOOD) break;
         err = PrintModule(symPtr, displayType);
         break;
      case SYM_FUNCTION:
         if ((err = PrintCommonHeader(symPtr, displayType)) != GOOD) break;
         err = PrintFunction(symPtr, displayType);
         break;
      case SYM_BLOCK:
         if ((err = PrintCommonHeader(symPtr, displayType)) != GOOD) break;
         err = PrintBlock(symPtr, displayType);
         break;
      case SYM_LABEL:
      case SYM_PUBLIC_LABEL:
      case SYM_PUBLIC_UNKNOWN:
         err = PrintCommonHeader(symPtr, displayType);
         break;
      case SYM_LOCAL_VAR:
      case SYM_GLOBAL_VAR:
      case SYM_PUBLIC_VAR:
         err = PrintCommonHeader(symPtr, displayType);
         err = PrintVariable(symbol, symPtr, displayType);
         break;
      default:
         err = ER_SYMBOL_NOT_FOUND;
   }

     // escape when key pressed
     if ( (err = TestKey(VK_ESCAPE)) == 1 ) {
           return( FAILURE );
     }

   return(err);
}

//--------------------------------------------------------------------------
// SymPrintSymbols
//--------------------------------------------------------------------------
RETCODE EXPORT
SymPrintSymbols(SYM_DISPLAY_TYPE displayType) {

   RETCODE err;
   U32 i,maxEntries;
   TABLE_OFFSET varOffset;
   COMMON_SYMBOL_HEADER HUGE *symPtr;

   // get a pointer to the root symbol ;
   rootPtr = (COMMON_SYMBOL_HEADER HUGE *)st.GetHugeDataPtr(rootOffset);
   
   maxEntries=ot.GetOrdinalCount();
   for(i=0;i<maxEntries;i++) {
      // get the offset into the symbol table of the nth symbol ;
      if((err=ot.GetOffset(i,varOffset))!=GOOD) return(err);

      // print the symbol when DEBUGGING or when it has a valid name. ;
      symPtr = (COMMON_SYMBOL_HEADER HUGE *)st.GetHugeDataPtr(varOffset);
      if ( ((symPtr->symbolNameOffset) && 
         (symPtr->symbolNameOffset != rootPtr->symbolNameOffset)) || 
         (displayType == DEBUG_DISPLAY)) {
         // print the symbol ;
         strcpy(globalStr,"-----------------------------------"
                     "-----------------------------------");
         ShowLine( globalStr );
         err = SymPrintSymbol(varOffset, displayType, 0);
         if ((err != GOOD) && (err != ER_SYMBOL_NOT_FOUND))
            return(err);
         // this routine can take a LONG TIME.  So yield to other ;
         // applications every time through the loop. ;
//         Yield();
      }
   }
   return(GOOD);
}

//--------------------------------------------------------------------------
// SymPrintLines - prints all linenums for input module;
//--------------------------------------------------------------------------
RETCODE
SymPrintLines(SYM_DESCRIPTOR moduleDesc) {

   RETCODE            err;
   LINENUM_DESCRIPTOR linenumIndex, nextLinenumIndex;
   OFFSET_ADDR_TYPE   linenumAddr;
   LINENUM_TYPE       linenum;
   COLUMN_TYPE        column;
   U16                linenumCount;

   // get starting index to walk linenum table
   err = lt.GetLinenumFirstIndex(moduleDesc, &linenumIndex);
   if (err) {
      if (ER_NO_LINENUMS_ADDED == err) {
         sprintf(globalStr, "   No line numbers loaded");
         ShowLine( globalStr );
         return GOOD;  // let caller continue with other modules
      } else {
         return err;
      }
   }
   linenumCount = 1;
   // Create a temp address descriptor

   do {
      if ((err = lt.GetRawLinenumByIndex(moduleDesc, linenumIndex,
            &linenumAddr, &linenum, &column, &nextLinenumIndex)) != GOOD) {
         if (err == ER_LINENUM_INDEX_TOO_LARGE)
            err = GOOD; // No error report.
         break; // out of do_while
      }
      //------------------
      // display linenum
      //------------------
      // convert address to string
      sprintf(globalStr, "%5u: Line#%-5u Col#%-3hu  P:%lX",
               linenumCount, linenum, column, linenumAddr);
      ShowLine( globalStr );

      // set up for next iteration
      linenumIndex = nextLinenumIndex;
      linenumCount++;

     // escape when key pressed
     if ( (err = TestKey(VK_ESCAPE)) == 1 ) {
           return( FAILURE );
     }

   } while (TRUE);

   return( GOOD );
}  // end of SymPrintLines

      
//--------------------------------------------------------------------------
// PrintVariable
//--------------------------------------------------------------------------
RETCODE PRIVATE PrintVariable(TABLE_OFFSET inputSymbol,
                              HPU8 symPtr, SYM_DISPLAY_TYPE displayType) {
   
   SYM_TYPE_VARIABLE *varPtr;

   // print the information specific to variables ;
   varPtr=(SYM_TYPE_VARIABLE *)symPtr;

   if (displayType == DEBUG_DISPLAY ) {
      sprintf((LPSTR)globalStr,"Variable Type:  %8lX    isConstant: %1d"
              "    isValidAddr: %1d",
              varPtr->typeIndex,
              varPtr->isConstant,
              varPtr->isValidAddr);
      ShowLine( globalStr );

      sprintf((LPSTR)globalStr,"Storage Class:  %8X  Register Class:  %8X",
                               varPtr->storageClass,
                               varPtr->registerClass);
      ShowLine( globalStr );
   }

   if ((displayType == VARLIFE_DISPLAY) &&
          ((varPtr->registerClass) != NOT_REG)) {
      // Define some locals
      TABLE_OFFSET lifetimeOffset, currentOffset;
      SYM_LIFETIME_START_INFO HUGE *lifetimeStartPtr;
      SYM_LIFETIME_INFO HUGE    *lifetimePtr;

      switch (varPtr->registerClass) {
         case LOCKED_REG:
            /* Locked registers are living until first DEATH record
            ** occurs telling of the DEATH of the register.
            */
            lifetimeOffset = inputSymbol +
                          sizeof(SYM_TYPE_VARIABLE) + 
                          sizeof(AUTO_VAR_OFFSET);
            sprintf((LPSTR)globalStr,"    Locked Register");
            break;

         case LIVING_REG:
            /* ATN2 - living registers are LIVE until BIRTH record occurs
            ** indicating where register starts DEAD/ALIVE.
            */
            lifetimeOffset = inputSymbol + sizeof(SYM_TYPE_VARIABLE);
            sprintf((LPSTR)globalStr,"    Living Register");
            break;
         case SHADOW_REG:
         default:
            return(ER_REGISTER_CLASS_UNKNOWN);
      }
      // print common message
      ShowLine( globalStr );
      
      // Get pointer to first lifetime data.  If value is NULL_SYMBOL, there
      // is no lifetime data; return LIVE.
      lifetimeStartPtr = (SYM_LIFETIME_START_INFO HUGE *)
                                     st.GetHugeDataPtr(lifetimeOffset);
      if ((currentOffset = lifetimeStartPtr->firstEntry) == NULL) {
         sprintf((LPSTR)globalStr,"    No lifetime Info existed.");
         ShowLine( globalStr );
         return( GOOD );
      }
      // The while loop compares print out the life information
      // addresses in the lifetime linked list and the variable living
      // state.
      while (currentOffset != NULL_SYMBOL) {
         lifetimePtr = (SYM_LIFETIME_INFO HUGE *)
                                   st.GetHugeDataPtr(currentOffset);
         if ((lifetimePtr->lifetimeInfo.lifetimeClass) == LIVE)
            sprintf((LPSTR)globalStr,"    Local Offset: 0x%lX - LIVE",
                    lifetimePtr->lifetimeInfo.lifetimeAddr);
         else
            sprintf((LPSTR)globalStr,"    Local Offset: 0x%lX - DEAD",
                    lifetimePtr->lifetimeInfo.lifetimeAddr);
          ShowLine( globalStr );
         // Next lifetimeInfo - follow linked list
         currentOffset = lifetimePtr->nextLifetimeInfo;  
      }
   }
   return(GOOD);
}


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