
/***************************************************************************
**
**    $Header:   D:/EP196/SRC/LOG/SYMSVR/SYMCLI.CPP   1.0   15 Aug 1997 14:04:14   ZJRD  $
**
**    $Log:   D:/EP196/SRC/LOG/SYMSVR/SYMCLI.CPP  $
** 
**    Rev 1.0   15 Aug 1997 14:04:14   ZJRD
** Initial revision.
** 
****************************************************************************/

/****************************************************************************
**
**  Name:  symcli.cpp
**
**  Description:
**     This module parses the info coming from the cli server and then
**     dispatches the appropriate modules.
**
**  Status:  PRELIMINARY
**
**  $Log$
**
**  $Header:   D:/EP196/SRC/LOG/SYMSVR/SYMCLI.CPP   1.0   15 Aug 1997 14:04:14   ZJRD  $
**
**  Copyright (C) 1995 Microtek International.  All rights reserved.
**
*****************************************************************************/

                       /****************************
                        *                          *
                        *       INCLUDE FILES      *
                        *                          *
                        ****************************/
#include "stdafx.h"
#include <stdlib.h>
#include <string.h>

#include "symbase.h"
#include "symwind.h"
#include "symbyadr.h"
#include "symhash.h"
#include "symline.h"
#include "sympool.h"
#include "symord.h"
#include "symblsvr.h"
#include "symerrs.h"
#include "symcli.h"
#include "symclipr.h"
#include "symutil.h"
#include "symadd.h"
#include "symtype.h"
#include "symheap.h"

#include "utilext.h"
#include "symimp.h"
                       /****************************
                        *                          *
                        *    EXTERNAL VARIABLES    *
                        *                          *
                        ****************************/

extern TABLE_OFFSET rootOffset;

extern BaseIndexTable bit;
extern MemPool st;
extern OrdinalTable ot;
extern HashTable ht;
extern TypeTable tt;
extern LinenumTable lt;
extern IndexTable typit;

//----------------------------------------------------------------------------
// Report each symbol type
extern U32 symbolStat[];
extern const S8 *symTypeName[];
extern U8 symTypeMap[];
//extern BOOLEAN createLabelRanges;  // defined in SYMADD.CPP
extern BOOLEAN with0X;  // indicates how to display addresses

                       /****************************
                        *                          *
                        *     LOCAL VARIABLES      *
                        *                          *
                        ****************************/

PRIVATE HANDLE  cliServerHandle;
PRIVATE BOOLEAN sendToFile = FALSE;  // steer output to file or Shell
PRIVATE S16     hFile;  // handle to open file for putting symbol text into
PRIVATE LPSTR   fileNamePtr;  //pointer to open filename

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

RETCODE PRIVATE DisplayModules(SYM_DISPLAY_TYPE displayType);
RETCODE PRIVATE DisplayFunctions(SYM_DESCRIPTOR moduleDescriptor,
                         SYM_DISPLAY_TYPE displayType, U16 indentLevel);
RETCODE PRIVATE DisplayVariables(SYM_DESCRIPTOR symbolDescriptor,
                         SYM_DISPLAY_TYPE displayType, U16 indentLevel);
RETCODE PRIVATE PrintBase(TABLE_OFFSET baseOffset, BOOLEAN *printHeader);

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

#define NESTING_LEVEL  1

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

extern void U16ToStr(U16 ui , char *tt);
extern void U24ToStr(U32 ui , char *tt);
extern void StrToU32(U32& ul , char *tt);

extern int BlockAddrIsFunctionAddr(LPSTR str,ADDRESS_TYPE addr);

//--------------------------------------------------------------------------
// DisplayFunctions
//
// Parameters:
//    symbolDescriptor: desc to function to be displayed
//    displayType: indicates what level of printing is to be done
//    indentLevel: what level of indent nesting for this call
//--------------------------------------------------------------------------
RETCODE PRIVATE DisplayFunctions(SYM_DESCRIPTOR   funcDesc,
                                 SYM_DISPLAY_TYPE displayType,
                                 U16              indentLevel) {
   RETCODE        err;
   SYM_DESCRIPTOR newFuncDesc;
   SYM_TYPE_TYPE  symType;

   if (NULL_SYMBOL != funcDesc) {
      if ((err = SymPrintSymbol(funcDesc,
                                displayType,
                                indentLevel)) != GOOD)
         return err;
      if ((err = DisplayVariables(funcDesc,
                                  displayType,
                                  indentLevel + NESTING_LEVEL)) != GOOD)
         return err;

      // recurse down child pointer
      if ((err = SymGetSymbolChild(funcDesc, &symType, &newFuncDesc))
         != GOOD)
         return err;

      if((err = DisplayFunctions(newFuncDesc, displayType,
                                 indentLevel + NESTING_LEVEL)) != GOOD)
         return err;

      // recurse down sibling pointer
      if ((err = SymGetSymbolSibling(funcDesc, &symType,
                                     &newFuncDesc)) != GOOD)
         return err;
      if((err = DisplayFunctions(newFuncDesc, displayType,
                                 indentLevel)) != GOOD)
         return err;
   }
   return GOOD;
}


//--------------------------------------------------------------------------
// DisplayModules
//
// Description: Sends module information to the CLI for the user.
//
// Input Parameters:
//    moduleDesc: descriptor of module to display
//    displayType: indicates how much to display
//--------------------------------------------------------------------------
RETCODE PRIVATE
DisplayModule(SYM_DESCRIPTOR   moduleDesc,
              SYM_DISPLAY_TYPE displayType) {

   RETCODE        err;
   SYM_DESCRIPTOR funcDesc;
   SYM_TYPE_TYPE  symType;
   BOOLEAN abortFromEsc = FALSE;


   // print out the module info;
   if (GOOD != (err = SymPrintSymbol(moduleDesc, displayType, 0)))
         return err;

   if (displayType != MODULE_DISPLAY) {
      // display all module global vars
      if (GOOD != (err = DisplayVariables(moduleDesc,
                                          displayType,
                                          NESTING_LEVEL)))
         return err;
   }
   // escape when key pressed
    if ( (err = TestKey(VK_ESCAPE)) == 1 ) {
         return( FAILURE );
    }

   // loop through the functions
   if ((err = SymGetSymbolChild(moduleDesc, &symType,
                                &funcDesc)) != GOOD)
      return err;
   if ((NULL_SYMBOL != funcDesc) && (displayType != MODULE_DISPLAY)) {
      if((err = DisplayFunctions(funcDesc,
                                 displayType,
                                 NESTING_LEVEL)) != GOOD)
      return err;
   }
   return GOOD;
}  // end of DisplayModule


//--------------------------------------------------------------------------
// DisplayModules
//
// Description: Sends module symbol information to the CLI for the user.
//
// Input Parameters:
//    displayType: how much of symbol hierarchy to display
//--------------------------------------------------------------------------
RETCODE PRIVATE DisplayModules(SYM_DISPLAY_TYPE displayType) {

   RETCODE        err;
   SYM_DESCRIPTOR moduleDesc;
   SYM_TYPE_TYPE  symType;
   char temp[512];

   // display all module names ;
   if ((err = SymGetModuleListHead(&moduleDesc)) != GOOD)
      return err;

   while (moduleDesc) {              
      if ( GOOD == SymSrcGetModuleName(moduleDesc,temp) && temp[0] != '?' ) {
         if (GOOD != (err = DisplayModule(moduleDesc, displayType)))
            return err;
      }
      if ((err = SymGetSymbolSibling(moduleDesc, &symType,
         &moduleDesc)) != GOOD)
         return err;
   }
   return GOOD;
}  // end of DisplayModules


//--------------------------------------------------------------------------
// DisplayVariables
//--------------------------------------------------------------------------
RETCODE PRIVATE
DisplayVariables(SYM_DESCRIPTOR   symbolDescriptor,
                 SYM_DISPLAY_TYPE displayType,
                 U16              indentLevel) {

   RETCODE        err;
   SYM_DESCRIPTOR currentVarDesc;
   SYM_TYPE_TYPE  symType;
   U16            listCount, i;

   // make sure we are supposed to display variables. ;
   if (displayType == FUNCTION_DISPLAY)
      return GOOD;

   for (i=0; i<4; i++) {

      // cycle through all of the possible lists. ;
      switch (i) {
         case 0:
            symType = SYM_LOCAL_VAR;
            break;
         case 1:
            symType = SYM_LABEL;
            break;
         case 2:
            symType = SYM_CONSTANT;
            break;
         case 3:
            symType = SYM_MISCELLANEOUS;
            break;
      }
      if ((err = SymGetSymbolHeadList(symbolDescriptor, symType,
                                      &currentVarDesc, &listCount)) != GOOD)
         return err;

      // print out all elements of the list. ;
      while (listCount--) {
         if ((err = SymPrintSymbol(currentVarDesc, displayType, indentLevel))
            != GOOD)
            return err;
         if ((err = SymGetSymbolSibling(currentVarDesc, &symType,
                                       &currentVarDesc)) != GOOD)
            return err;
      }
   }
   return GOOD;
}  // DisplayVariables


//--------------------------------------------------------------------------
// DisplayLines
//--------------------------------------------------------------------------
RETCODE PRIVATE DisplayLines(SYM_DISPLAY_TYPE displayType) {

   RETCODE        err;
   SYM_DESCRIPTOR moduleDesc, tmpDesc;
   SYM_TYPE_TYPE  symType;
   U16            indentLevel = 0;

   // get start of module linked list
   if ((err = SymGetModuleListHead(&moduleDesc)) != GOOD)
      return err;

   do {
      // print out the module info;
      if((err = SymPrintSymbol(moduleDesc, displayType, indentLevel))
         != GOOD) return err;

      // display all linenums if they have been loaded; check first
      if (GOOD != (err = SymPrintLines(moduleDesc)))
         return err;

      // get next module
      if ((err = SymGetSymbolSibling(moduleDesc, &symType,
         &tmpDesc)) != GOOD) return err;
      moduleDesc = tmpDesc;
   } while(moduleDesc);

   return GOOD;
}  // end of DisplayLines


//--------------------------------------------------------------------------
// DisplaySortedSymbols
//
// Algorithm:
//    loop from basetbl root to end of linked list
//       loop from beginning of byaddrtable to end
//          SymPrintSymbol
//       }
//    }
//--------------------------------------------------------------------------
RETCODE DisplaySortedSymbols() {

   RETCODE         err;
   SYM_DESCRIPTOR  symDesc;
   TABLE_OFFSET    baseOffset, byAddrTableOffset;
   BaseSymbol     *basePtr;
   ByAddressTable *byAddrTablePtr;
   U32             symbolCount;
   BOOLEAN         printHeader = TRUE;

   baseOffset = bit.GetRootBaseSymbolOffset();
   if (!baseOffset)
      return ER_SYMBOL_NOT_A_MODULE;  // report no symbols loaded

   while (baseOffset) {
      basePtr = (BaseSymbol *)st.GetHugeDataPtr(baseOffset);
      // print base information
      if (GOOD != (err = PrintBase(baseOffset, &printHeader)))
         return err;

      byAddrTableOffset = basePtr->GetByAddressTableOffset();
      byAddrTablePtr = (ByAddressTable *)st.GetHugeDataPtr(byAddrTableOffset);
      // get size of table
      symbolCount = byAddrTablePtr->GetSymbolCount();
      for (U32 i = 0; i < symbolCount; i++)  {
         // get offset of symbol from byadrtbl, then print
         symDesc = byAddrTablePtr->GetOffset(i);
         if (GOOD != (err = SymPrintSymbol(symDesc, MODULE_DISPLAY, 1)))
            return err;
      } // end of for
      baseOffset = basePtr->GetNextBaseOffset();
      // 10/06/94 - Nghia
      // reprint heading for each base
      printHeader = TRUE;
   } // end while (baseOffset)
   return GOOD;
}  // end of DisplaySortedSymbols


//--------------------------------------------------------------------------
// DisplaySymbols
//--------------------------------------------------------------------------
RETCODE 
DisplaySymbols(LPSTR cmdString, int flag) {

   RETCODE          err;
   SYM_DISPLAY_TYPE displayType;
   BOOLEAN          noSymbolsLoaded;
   LPSTR            cmdPtr;
   S8               nullStr[1];
   SYM_DESCRIPTOR   moduleDesc;


   // this is checking for the basic debug PRINT command
   if (GOOD != (err = SymCheckForNoSymbols(&noSymbolsLoaded)))
      return err;
   if (noSymbolsLoaded) {
      return ER_SYMBOL_NOT_A_MODULE;  // reports "no symbols are loaded"
   }
   // clears keyboard of any residual escape key hit
//   err = TskCheckAbort(&abortFromEsc);
//   if(err!=GOOD) return err;
    if ( (err = TestKey(VK_ESCAPE)) == 1 ) {
         return( FAILURE );
    }

   if ( flag == 0 ) {
      cmdPtr = cmdString;
      if (*cmdPtr == '#') {
         cmdPtr++;
      }
      nullStr[0] = '\0';
      if (GOOD != (err = SymGetModuleDesc(cmdPtr,
                                          (LPSTR)nullStr,
                                          &moduleDesc)))
      {
      	  SymShowLine("No such Module!");
          return err;
      }
      return DisplayModule(moduleDesc, PUBLIC_DISPLAY);
   }
   else if ( flag == 1 ) { // _debug
       displayType = DEBUG_DISPLAY;
       if((err = SymPrintSymbols(displayType)) != GOOD)
           return err;
       if((err = SymPrintBases(displayType)) != GOOD)
           return err;

   } else if ( flag == 2  ) { // modules
        displayType = MODULE_DISPLAY;
         // print out all modules ;
        if((err = DisplayModules(displayType)) != GOOD)
            return err;

   } else if ( flag == 3 ) { // functions
        displayType = FUNCTION_DISPLAY;
         // print out all modules, and all functions;
        if((err = DisplayModules(displayType)) != GOOD)
            return err;

   } else if ( flag == 4 ) { // public
        displayType = PUBLIC_DISPLAY;
        // print out everything including publics ;
        err = DisplayModules(displayType);
        if ((GOOD != err) && (ER_SYM_NO_MODULES_LOADED != err))
            return err;
         // print out all of the public variables
        if((err = DisplayVariables(rootOffset, displayType, 0)) != GOOD)
            return err;

    } else if ( flag == 5 ) { // line
        displayType = LINES_DISPLAY;
         // print out module and all lines in module ;
        if((err = DisplayLines(displayType)) != GOOD)
            return err;

    } else if ( flag == 6 ) { // sort
        displayType = LINES_DISPLAY;
         // print out all symbols in sorted order
        if((err = DisplaySortedSymbols()) != GOOD)
            return err;

    } else if ( flag == 7 ) { // _varlife
        displayType = VARLIFE_DISPLAY;
        // print out module and all var with it life-time information
        if ((err = DisplayModules(displayType)) != GOOD)
           return err;
    }
    else {
      // default is to display all symbols except publics
      displayType = USER_DISPLAY;
//      if (GOOD != (err = DisplayModules(PUBLIC_DISPLAY)))
      if (GOOD != (err = DisplayModules( displayType) ))
         return err;
    }
    return GOOD;
}


//--------------------------------------------------------------------------
// PrintBase
//
// For Moto, displays the name and base address of the base.
// For Intel, for real mode, displays the name, USER/SMM, segment number,
//            then base address.
//            For protected mode, displays the name, GDT selector, optional
//            LDT selector if non-zero, then base address.
//--------------------------------------------------------------------------
RETCODE PRIVATE PrintBase(TABLE_OFFSET baseOffset, BOOLEAN* printHeader) {
   S8           bufStr[MAX_SYMNAME_LENGTH];
   LPSTR        bufStrPtr;
   BaseSymbol   HUGE *basePtr;
   U16          len;
 //  U8           n;
 //  SYM_MODE     baseSymMode;

#define SYMCLI_MAX_COLUMN (16)
   basePtr = (BaseSymbol HUGE *)st.GetHugeDataPtr(baseOffset);
   // print the base header first.
   if ((*printHeader) && (basePtr->GetSymMode() == SYM_PROTECTED)) {
      *printHeader = FALSE;
   }

   // print Base name
   sprintf(bufStr , "Base Name : ");
//   bufStr[0] = '\0';
   len = (U16) strlen( bufStr );
   bufStrPtr = bufStr;  // set to beginning of string
//   st.GetString(basePtr->GetBaseNameOffset(), (U8 FAR *)bufStr);
   st.GetString(basePtr->GetBaseNameOffset(), (U8 FAR *)&bufStr[len]);
   // point to null string terminator
//   while (*bufStrPtr != '\0') bufStrPtr++;
//   len = (U16)(bufStrPtr - bufStr);
   SymShowLine( bufStr );
   // output the string
   return ( GOOD );

}  // end of PrintBase

//--------------------------------------------------------------------------
// Count
//
// Displays the number of symbols in the various tables
//--------------------------------------------------------------------------
/*
#pragma argsused
RETCODE WINAPI
Count(LPSTR cmdString, U32 argc, U32 argv[]) {
   RETCODE    err, firstErr;
   S8         str[80];
   U32        count, memSize, tableSize;
   TYPE_INDEX typeIndexMax;
   BOOLEAN    noSymbolsLoaded;

   if (argc != 1)
      return ER_CLI_SYNTAX;
   if (GOOD != (err = SymCheckForNoSymbols(&noSymbolsLoaded)))
      return err;
   if (noSymbolsLoaded) {
      return ER_SYMBOL_NOT_A_MODULE;  // reports "no symbols are loaded"
   }

   // ORDINAL
   count = ot.GetOrdinalCount();
   memSize = ot.GetAvailMemOffset();
   tableSize = ot.GetTableSize();
   sprintf((LPSTR)str, "Ordinal count = %ld  (%ld) [%ld]",
                        count, memSize, tableSize);
   firstErr = SendMessageToCli((LPU8)str);


   // HASH TABLE
   count = ht.GetEntryCount();
   memSize = ht.GetHashTableSize();
   tableSize = ht.GetTableSize();
   sprintf((LPSTR)str, "Global symbol count = %ld (%ld) [%ld]",
                        count, memSize, tableSize);
   err = SendMessageToCli((LPU8)str);
   if (firstErr == GOOD)
      firstErr = err;

   // LINENUMS
   count = lt.GetLinenumCount();
   memSize = lt.GetAvailMemOffset();
   tableSize = lt.GetTableSize();
   sprintf((LPSTR)str, "Line number count = %ld (%ld) [%ld]",
                        count, memSize, tableSize);
   err = SendMessageToCli((LPU8)str);
   if (firstErr == GOOD)
      firstErr = err;

   // TYPES
   err = tt.GetMaxTypeIndex(typeIndexMax);
   memSize = tt.GetAvailMemOffset();
   tableSize = tt.GetTableSize();
   if (firstErr == GOOD)
      firstErr = err;
   sprintf((LPSTR)str, "Type count = %ld (%ld) [%ld]",
                        typeIndexMax, memSize, tableSize);
   err = SendMessageToCli((LPU8)str);
   if (firstErr == GOOD)
      firstErr = err;

   // SYMBOL TABLE SIZE
   memSize = st.GetAvailMemOffset();
   tableSize = st.GetTableSize();
   sprintf((LPSTR)str, "Symbol table size = (%ld) [%ld]",
                        memSize, tableSize);
   firstErr = SendMessageToCli((LPU8)str);


   // BASE TABLE COUNT
   count = bit.BaseGetBaseCount();
   memSize = bit.GetTableSize();
   sprintf((LPSTR)str, "Base count = %ld (%ld)", count, memSize);
   err = SendMessageToCli((LPU8)str);
   if (firstErr == GOOD)
      firstErr = err;

   // SYMBOLS STATISTICS OF EACH SYM_TYPE_TYPE
   U8 symType, nameIndex;
   for (symType = 0; symType < MAX_SYM_TYPE; symType++) {
       nameIndex = symTypeMap[symType];
       if (nameIndex < MAX_SYM_TYPE) {
          sprintf((LPSTR)str, "%12s = %6ld symbols",
                  (LPSTR) symTypeName[nameIndex],
                  symbolStat[symType]);
          err = SendMessageToCli((LPU8)str);
          if (firstErr == GOOD) firstErr = err;
       }
   }

   // BY-ADDRESS TABLE WALK
   {
   TABLE_OFFSET loopPtr;  // pass by reference
   S8           baseName[100];
   U32          entryCount;  // pass by reference
   BOOLEAN      startLoop = TRUE;
   RETCODE      localErr;
      while (TRUE) {
         localErr = ByAddressTableGetNext(startLoop, loopPtr,
                                          (LPSTR)baseName,
                                          entryCount,  // by reference
                                          tableSize);  // by reference
         if (localErr != GOOD)
            break;
         if (0 == strlen(baseName))
            strcat(baseName, "NoNameBase");
         memSize = entryCount * (sizeof(TABLE_OFFSET));
         sprintf((LPSTR)str, "  %s contains %ld symbols (%ld) [%ld]",
                  baseName, entryCount, memSize, tableSize);
         err = SendMessageToCli((LPU8)str);
         if (GOOD == firstErr)
            firstErr = err;
         startLoop = FALSE;
      }
   }
   return firstErr;
}  // end of Count
*/

//--------------------------------------------------------------------------
// NameOf
//
// Converts an address into a symbol and displays it
//    Address can be numeric or "pc" which returns present pc value
//
// Design:
//    convert address text into an address descriptor
//    set up descriptor with symbolic mode on
//    call AdrConvAddressToText
//    output text to CLI
//--------------------------------------------------------------------------
RETCODE EXPORT
NameOf(LPSTR cmdString)  {

//   RETCODE    err, firstErr;
   RETCODE    err;
//   DESCRIPTOR desc;
   LPSTR      lpParam;
//   S8         str[ADDR_BUFF_SZ_SYMBOLIC];
   BOOLEAN    noSymbolsLoaded;
   char       *tt;
   ADDRESS_TYPE   inputAddr;
   MEM_ADDR_CLASS memoryClass;
   SYM_TYPE_TYPE  symbolType;
   U32            offset;
   SYM_DESCRIPTOR outputSymbol;
   SYM_DESCRIPTOR funcDescriptor;
   SYM_DESCRIPTOR moduleDescriptor;
   HANDLE *pHdl;
   U16 linenum; 
   int tFlag , nFlag;
   int nBank;
                    
   nFlag = 0;                 
   if (GOOD != (err = SymCheckForNoSymbols(&noSymbolsLoaded)))
      return err;
   if (noSymbolsLoaded) {
      return ER_SYMBOL_NOT_A_MODULE;  // reports "no symbols are loaded"
   }
                      
   tt = new char[ strlen(cmdString)+1 ] ;
   if ( tt == 0 ) return FAILURE ;
   strcpy( tt , cmdString );                          
   lpParam = tt;

   StrToU32(inputAddr.addr , tt);   
   inputAddr.segType = (SEGMENTTYPE) SEG_CODE;
   switch ( tt[0] ) {
   case 'X' :
   case 'x' :
        inputAddr.segType = (SEGMENTTYPE) SEG_XDATA;
        break;
   case 'I' :
   case 'i' :
        inputAddr.segType = (SEGMENTTYPE) SEG_DATA;
        break;
   case 'R' :
   case 'r' :
        inputAddr.segType = (SEGMENTTYPE) SEG_REGISTER;
        break;
   case 'B' :
   case 'b' :
        inputAddr.segType = (SEGMENTTYPE) SEG_BIT;
        break;
   case 'S' :
   case 's' :
        inputAddr.segType = (SEGMENTTYPE) SEG_SFR;
        break;
   default :
        break;
   }
        
   delete tt;
            
   if ( GOOD != SymMapAddr2Symbol(inputAddr,
                  &memoryClass,
                  &symbolType,
                  &offset,
                  &outputSymbol,
                  &funcDescriptor,
                  &moduleDescriptor) ) {
        return FAILURE ;
   }    
   
   char temp[1024];
   char *temp1, *temp2 ;
   temp1 = temp2 = 0;  
   nBank = (int) ((inputAddr.addr>>16)&0x3);
   switch( inputAddr.segType ) {     
   case SEG_XDATA:
       //sprintf(temp,"      X:");
	   sprintf(temp,"      X%d:",nBank);       
       break;
   case SEG_DATA:
       sprintf(temp,"      I:");
       break;
   case SEG_REGISTER:
       sprintf(temp,"      R:");
       break;
   case SEG_BIT:
       sprintf(temp,"      B:");
       break;
   default:
       sprintf(temp,"      P%d:",nBank);
       break;
   }
   U16ToStr( inputAddr.addr , &temp[9] );
   SymConvertToBank( inputAddr.addr , nBank );
   if ( offset != 0 ) {
        if ( (inputAddr.segType==SEG_CODE) && 
            (0==SymSrcAddr2LinenumStart(nBank,inputAddr.addr ,
                 linenum , moduleDescriptor) ) ) {
            if ( NULL_SYMBOL != moduleDescriptor ) {            
                if ( GOOD != SymGetSymbolName( moduleDescriptor,
                                               &temp1 ) ) 
                    return FAILURE; 
                sprintf(&temp[strlen(temp)],"  #%s#%d",temp1,linenum);
            }   
            if ( *temp != '?' ) {
                SymShowLine( temp );
                nFlag = 1;
            }
        }             
        
        if ( temp1 ) {
            pHdl = (HANDLE *)( temp1 - sizeof(HANDLE) );
            GlobalFree( *pHdl );
        }
        if ( nFlag == 0 ) return FAILURE;
        return GOOD;
    }

    tFlag = 1;    
    if ( GOOD != SymGetSymbolName( outputSymbol ,
                                   &temp1 ) ) 
        return FAILURE; 
    switch( symbolType ) {
    case SYM_MODULE :
    case SYM_GLOBAL_VAR :
        sprintf(&temp[strlen(temp)],"  #%s",temp1);
        break;              
    case SYM_LOCAL_VAR :
        if ( NULL_SYMBOL != moduleDescriptor ) {            
            if ( GOOD != SymGetSymbolName( moduleDescriptor,
                                           &temp2 ) ) 
                return FAILURE; 
            sprintf(&temp[strlen(temp)],"  #%s",temp2);
            if ( temp2 ) {
                pHdl = (HANDLE *)( temp2 - sizeof(HANDLE) );
                GlobalFree( *pHdl );
            }
            temp2 = 0;
            if( NULL_SYMBOL != funcDescriptor ) {
                if ( GOOD != SymGetSymbolName( 
                    funcDescriptor,&temp2 ) ) 
                    return FAILURE; 
                sprintf( &temp[ strlen(temp) ] ,
                    "#%s#%s",temp2,temp1);
            }
            else             
                return FAILURE;
/*
                sprintf( &temp[ strlen(temp) ] ,
                    "#%s",temp1);
*/                    
        }
        else {
            return FAILURE;
/*
            if( NULL_SYMBOL != funcDescriptor ) {
                if ( GOOD != SymGetSymbolName( 
                    funcDescriptor,&temp2 ) ) 
                    return FAILURE; 
                sprintf( &temp[12] ,"  #%s#%s",temp2,temp1);
            }
            else
                sprintf(&temp[12],"  #%s",temp1);
*/                
        }
        break;          
    case SYM_BLOCK :
        if ( *temp1 == '\0' ) {
            if ( NULL_SYMBOL != moduleDescriptor ) {            
                if ( GOOD != SymGetSymbolName( moduleDescriptor,
                                               &temp2 ) ) 
                    return FAILURE; 
                sprintf(&temp[strlen(temp)],"  #%s",temp2);
                if ( temp2 ) {
                    pHdl = (HANDLE *)( temp2 - sizeof(HANDLE) );
                    GlobalFree( *pHdl );
                }
                temp2 = 0;
                if( NULL_SYMBOL != funcDescriptor ) {
                    if ( GOOD != SymGetSymbolName( 
                        funcDescriptor,&temp2 ) ) 
                        return FAILURE; 
                    if (GOOD != BlockAddrIsFunctionAddr(temp2,inputAddr) ) {
//                        return FAILURE;
                        tFlag = 0;
                    }
                    else {
                        sprintf( &temp[ strlen(temp) ] ,"#%s",temp2);
                    }
                }
                else
                    return FAILURE;
            }
            else {
                return FAILURE;
            }
            break;
        }
    default :
        if ( NULL_SYMBOL != moduleDescriptor ) {            
            if ( GOOD != SymGetSymbolName( moduleDescriptor,
                                           &temp2 ) ) 
                return FAILURE; 
            sprintf(&temp[strlen(temp)],"  #%s#%s",temp2,temp1);
        }
        else {
            sprintf(&temp[strlen(temp)],"  #%s",temp1);
        }
        break;
    }
    
    if (tFlag) {
        if ( *temp != '?' ) {
            SymShowLine( temp );
            nFlag = 1;
        }
    }          

    if ( temp1 ) {
        pHdl = (HANDLE *)( temp1 - sizeof(HANDLE) );
        GlobalFree( *pHdl );
    }
    temp1 = 0;
    if ( (inputAddr.segType==SEG_CODE) && 
        (0==SymSrcAddr2LinenumStart(nBank,inputAddr.addr ,
             linenum , moduleDescriptor) ) ) {
        if ( NULL_SYMBOL != moduleDescriptor ) {            
            if ( GOOD != SymGetSymbolName( moduleDescriptor,
                                           &temp1 ) ) 
                return FAILURE; 
            sprintf(&temp[strlen(temp)],"  #%s#%d",temp1,linenum);
        }
        SymShowLine( temp );
        nFlag = 1;
    }             
    
    if ( temp1 ) {
        pHdl = (HANDLE *)( temp1 - sizeof(HANDLE) );
        GlobalFree( *pHdl );
    }
    if ( temp2 ) {
        pHdl = (HANDLE *)( temp2 - sizeof(HANDLE) );
        GlobalFree( *pHdl );
    }
    if ( nFlag == 0 ) return FAILURE;
   return GOOD;
} // end of NameOf

//--------------------------------------------------------------------------
// AddressOf
//
// Converts a symbol path and name into an address; uses #mod#func#var
//   naming convention
//--------------------------------------------------------------------------
RETCODE EXPORT
AddressOf(LPSTR cmdString)  {

   RETCODE           err;
   ADDR_RANGE_TYPE   addrRange;
   SYM_DESCRIPTOR    symDesc = 0L;
   LINENUM_TYPE      actualLinenum;
   COLUMN_RANGE_TYPE actualColumnRange;
   LPSTR             lpParam;
   S8                str[512];
   BOOLEAN           noSymbolsLoaded;
   char *tt ;               
   int i,j;

   if (GOOD != (err = SymCheckForNoSymbols(&noSymbolsLoaded)))
      return err;
   if (noSymbolsLoaded) {
      return ER_SYMBOL_NOT_A_MODULE;  // reports "no symbols are loaded"
   }

//   lpParam = &(cmdString[(U16)argv[1]]);
//   while (isspace((S16)*lpParam)) {  // skip over spaces; requires int 
//      lpParam++;
//   }       
    tt = new char[ strlen( cmdString ) + 1 ];
    if ( tt == 0 ) return (-1);
    strcpy( tt , cmdString );
   lpParam = tt;
//   lpParam = cmdString;
   err = SymGetAddrFromName(lpParam,
                            SYM_UNKNOWN_ADDR,
                            &symDesc,
                            &addrRange,
                            &actualLinenum,
                            &actualColumnRange);
    delete tt;                            
//   NOTES: 09/22/93 - Nghia
//   Filter out ER_NO_LINENUMS_ADDED to support ASM module which does not
//   have any line number infomation, but still has a valid address range
//   if ((err != GOOD) && (err != ER_NO_LINENUMS_ADDED) &&

//   if ((err != GOOD) && (err != ER_ADR_END_ADDR_TOO_SMALL))
//      return err;    // addrDesc not alloc'ed when error occurs

    if ((err != GOOD) && (err != ER_ADR_END_ADDR_TOO_SMALL)) {
        tt = new char[ strlen( cmdString ) + 2 ];
        if ( tt == 0 ) return (-1);           
        strcpy( tt, cmdString );
        i = strlen(cmdString);
        j = i;
        while( j ) {
            if ( tt[j-1] == '#') {
                for(int ii=i;ii>=j;ii--) {
                    tt[ii+1] = tt[ii];
                }
                tt[j] = '_';
                tt[i+1] = '\0';
                lpParam = tt;
                err = SymGetAddrFromName(lpParam,
                                    SYM_UNKNOWN_ADDR,
                                    &symDesc,
                                    &addrRange,
                                    &actualLinenum,
                                    &actualColumnRange);
                delete tt;                            
                if ((err != GOOD) && (err != ER_ADR_END_ADDR_TOO_SMALL))
                    return err; // addrDesc not alloc'ed when error occurs
                break;
            }
            j--;
        }
        if ( j == 0 ) return (err);
    }


   if (actualLinenum == 0) { // indicates not a linenum lookup
      int i;
      i = sprintf(str , "      %s " , cmdString);
      err = SymConvSymAddrToText(symDesc, &str[i]);
      // NOTES: 09/21/93 - Nghia
      // Only destroy addrDesc if it's valid
   } else {
      int i;
      i = sprintf(str , "      %s P%d:%lX-%lX" , cmdString , 
               	(int)(((addrRange.startAddr>>16)&0x03)),
	                addrRange.startAddr&0x0FFFFL , addrRange.endAddr&0x0FFFFL );
      }

   SymShowLine( str );
    return GOOD;
//   return( err );

} // end of AddressOf

//--------------------------------------------------------------------------
// DisplayTypes
//
// Displays all the types loaded.
//--------------------------------------------------------------------------
RETCODE DisplayTypes(int flag) {
   S8                     str[80];
   S8                     typeName[MAX_SYMNAME_LENGTH];
   U32                    memSize, tableSize;
   TYPE_INDEX             typeIndexMax, typeIndex;
   TYPE_INDEX             startIndex, endIndex;
   BOOLEAN                noSymbolsLoaded, outputTotal;
   RETCODE                err = GOOD;
   TYPE_HEADER_TYPE2 HUGE *typeHdr;
   TYPE_HEADER_TYPE       typeHeader;
   TABLE_OFFSET           offset;

   if (GOOD != (err = SymCheckForNoSymbols(&noSymbolsLoaded)))
      return err;
   if (noSymbolsLoaded) {
      return ER_SYMBOL_NOT_A_MODULE;  // reports "no symbols are loaded"
   }
   // clears keyboard of any residual escape key hit
//   if ((err = TskCheckAbort(&abortFromEsc)) != GOOD)
//      return err;
    if ( (err = TestKey(VK_ESCAPE)) == 1 ) {
         return( FAILURE );
    }

   // TYPES TABLE INFORMATION
   err       = tt.GetMaxTypeIndex(typeIndexMax);
   memSize   = tt.GetAvailMemOffset();
   tableSize = tt.GetTableSize();
   // Set default endIndex = maxTypeIndex
   startIndex = 0L;
   endIndex = typeIndexMax;
   outputTotal = TRUE;

   if ( flag ) {
      endIndex = 255L;  // Actual last built-in type is 57
   }
   else {
      startIndex = 256L;
   }

   if (outputTotal) {
      sprintf((LPSTR)str,
           "Max Type Index = %ld, MemSize = (%ld) TableSize = [%ld]",
           typeIndexMax, memSize, tableSize);
      SymShowLine( str );
   }
   typeHeader.typeName = (LPSTR) typeName;

   // Loop over all type and print the type out
   for (typeIndex = startIndex; typeIndex <= endIndex; typeIndex++) {
      // Use SymGetTypeHeader() to resolve any indirect reference type
      if ((err = SymGetTypeHeader(typeIndex, &typeHeader)) == GOOD) {
         sprintf((LPSTR)str,
         "-- TYPE INDEX: %ld (%#04X) --------------------------------------",
                 typeIndex, typeIndex);
         SymShowLine( str );
         // Get more information about the type
         if ((err = typit.GetOffset(typeIndex, offset)) != GOOD)
            return(err);
         typeHdr = (TYPE_HEADER_TYPE2 HUGE *)tt.GetHugeDataPtr(offset);

         switch (typeHeader.typeChoice) {
            case SIMPLE_TYPE_CLASS:
               sprintf((LPSTR)str,
                       "Name = %s, Type Value = %#04X, SizeInMAUs = %ld",
                       (LPSTR)typeHeader.typeName,
                       (U8)typeHeader.t.simpleType,
                       (U32)typeHeader.sizeInMAUs);
               SymShowLine( str );
               sprintf((LPSTR)str,
                       "Member = %d, Record size = %ld bytes",
                       (U16)typeHdr->memberCount,
                       (U32)typeHdr->recordSize);
               SymShowLine( str );
               break;

            case COMPLEX_TYPE_CLASS:
               sprintf((LPSTR)str,
                       "Name = %s, Type Value = %#04X, SizeInMAUs = %ld",
                       (LPSTR)typeHeader.typeName,
                       (COMPLEX_TYPE)typeHeader.t.complexType,
                       (U32)typeHeader.sizeInMAUs);
               SymShowLine( str );
               sprintf((LPSTR)str,
                       "Member = %d, Record size = %ld bytes",
                       (U16)typeHdr->memberCount,
                       (U32)typeHdr->recordSize);
               SymShowLine( str );
               // Get information about the complex type
               switch(typeHeader.t.complexType) {
                  case TY_UNKNOWN :       // = 0x21  !
                     sprintf((LPSTR) str, "-- TY_UNKNOWN");
                     break;
                  case TY_ENUM_PASCAL :   // = 0x45  E
                     sprintf((LPSTR) str, "-- TY_ENUM_PASCAL");
                     break;
                  case TY_GENERAL :       // = 0x47  G
                     sprintf((LPSTR) str, "-- TY_GENERAL");
                     break;
                  case TY_ENUM_C:         // = 0x4E,  // N
                     sprintf((LPSTR) str, "-- TY_ENUM_C");
                     break;
                  case TY_SMALL_PTR :     // = 0x4F,  // O
                  {
                     TYPE_INDEX baseTypeIndex;
                     if (SymGetTypePointerTypeIndex(typeIndex, &baseTypeIndex)
                         == GOOD) {
                        sprintf((LPSTR)str,"BASE TYPE INDEX = %ld",
                                (TYPE_INDEX)baseTypeIndex);
                        SymShowLine( str );
                     }
                     sprintf((LPSTR) str, "-- TY_SMALL_PTR");
                     break;
                  }

                  case TY_OMF51_PTR :     // = 0x4F,  // O
                  {
                     TYPE_OMF51_PTR_STRUCT ptrStruct;
                     if (SymGetTypePointer51(typeIndex, &ptrStruct)
                         == GOOD) {
                        sprintf((LPSTR)str,"BASE TYPE INDEX = %ld",
                                (TYPE_INDEX)ptrStruct.typeIndex);
                        SymShowLine( str );
                     }
                     sprintf((LPSTR) str, "-- TY_OMF51_PTR");
                     break;
                  }

                  case TY_LARGE_PTR :     // = 0x50,  // P
                  {
                     TYPE_INDEX baseTypeIndex;
                     if (SymGetTypePointerTypeIndex(typeIndex, &baseTypeIndex)
                         == GOOD) {
                        sprintf((LPSTR)str,"BASE TYPE INDEX = %ld",
                                (TYPE_INDEX)baseTypeIndex);
                        SymShowLine( str );
                     }
                     sprintf((LPSTR) str, "-- TY_LARGE_PTR");
                     break;
                  }

                  case TY_16_16_PTR :     // = 0x00,
                  {
                     TYPE_INDEX baseTypeIndex;
                     if (SymGetTypePointerTypeIndex(typeIndex, &baseTypeIndex)
                         == GOOD) {
                        sprintf((LPSTR)str,"BASE TYPE INDEX = %ld",
                                (TYPE_INDEX)baseTypeIndex);
                        SymShowLine( str );
                     }
                     sprintf((LPSTR) str, "-- TY_16_16_PTR");
                     break;
                  }

                  case TY_16_32_PTR :     // = 0x01,
                  {
                     TYPE_INDEX baseTypeIndex;
                     if (SymGetTypePointerTypeIndex(typeIndex, &baseTypeIndex)
                         == GOOD) {
                        sprintf((LPSTR)str,"BASE TYPE INDEX = %ld",
                                (TYPE_INDEX)baseTypeIndex);
                        SymShowLine( str );
                     }
                     sprintf((LPSTR) str, "-- TY_16_32_PTR");
                     break;
                  }

                  case TY_RANGE :         // = 0x52,  // R
                     sprintf((LPSTR) str, "-- TY_RANGE");
                     break;
                  case TY_STRUCT :        // = 0x53,  // S
                     sprintf((LPSTR) str, "-- TY_STRUCT");
                     break;
                  case TY_TYPE :          // = 0x54,  // T
                  {
                     TYPE_INDEX baseTypeIndex;
                     if (SymGetTypeTypeIndex(typeIndex, &baseTypeIndex)
                         == GOOD) {
                        sprintf((LPSTR)str,"BASE TYPE INDEX = %ld",
                                (TYPE_INDEX)baseTypeIndex);
                        SymShowLine( str );
                     }
                     sprintf((LPSTR) str, "-- TY_TYPE");
                     break;
                  }
                  case TY_UNION :         // = 0x55,  // U
                     sprintf((LPSTR) str, "-- TY_UNION");
                     break;
                  case TY_VOID :          // = 0x56,  // V
                     sprintf((LPSTR) str, "-- TY_VOID");
                     break;
                  case TY_FUNC_NODEP :    // = 0x58,  // X
                     sprintf((LPSTR) str, "-- TY_FUNC_NODEP");
                     break;
                  case TY_C_ARRAY :       // = 0x5A,  // Z
                  {
                     TYPE_Z_STRUCT arrStruct;
                     if (SymGetTypeCArray(typeIndex, &arrStruct) == GOOD) {
                        if (arrStruct.highBound < 0)
                           sprintf((LPSTR)str,
                                   "external");
                        else
                           sprintf((LPSTR)str,
                                   "HighBound = %ld",
                                   (S32)arrStruct.highBound);
                        SymShowLine( str );
                        sprintf((LPSTR)str,"BASE TYPE INDEX = %ld",
                                (TYPE_INDEX)arrStruct.typeIndex);
                        SymShowLine( str );
                     }
                     sprintf((LPSTR) str, "-- TY_C_ARRAY");
                     break;
                  }

                  case TY_OMF51_ARRAY :       // = 0x5A,  // Z
                  {
                     TYPE_OMF51_ARRAY_STRUCT arrStruct;
                     if (SymGetTypeArray51(typeIndex, &arrStruct) == GOOD) {
                        if (arrStruct.dim == 0)
                           sprintf((LPSTR)str,
                                   "external");
                        else
                           sprintf((LPSTR)str,
                                   "Dimension = %u",
                                   arrStruct.dim);
                        SymShowLine( str );
                        sprintf((LPSTR)str,"BASE TYPE INDEX = %ld",
                                (TYPE_INDEX)arrStruct.typeIndex);
                        SymShowLine( str );
                     }
                     sprintf((LPSTR) str, "-- TY_OMF51_ARRAY");
                     break;
                  }

                  case TY_BITFIELD :      // = 0x67,  // g
                  {
                     TYPE_BITFIELD_STRUCT bfStruct;
                     if (SymGetTypeBitfield(typeIndex, &bfStruct) == GOOD) {
                        sprintf((LPSTR) str,
                          "bitfieldSigned = %d, sizeInBits = %d",
                          (U8)bfStruct.bitfieldSigned,
                          (U16)bfStruct.size);
                        SymShowLine( str );
                        sprintf((LPSTR)str,"BASE TYPE INDEX = %ld",
                                (TYPE_INDEX)bfStruct.baseTypeIndex);
                        SymShowLine( str );
                     }
                     sprintf((LPSTR) str, "-- TY_BITFIELD");
                     break;
                  }
                  case TY_FUNC_DEP :      // = 0x78,  // x
                     sprintf((LPSTR) str, "-- TY_FUNC_DEP");
                     break;
                  default :
                     sprintf((LPSTR)str, "Not supported type");
                     break;
               }
               SymShowLine( str );
               break;

            default :
               sprintf((LPSTR)str, "Unknown");
               SymShowLine( str );

         } // end of switch
      }
      // escape when key pressed
//      if ((TskCheckAbort(&abortFromEsc) != GOOD) || abortFromEsc)
//         return ER_ABORT_FROM_ESC;
        if ( (err = TestKey(VK_ESCAPE)) == 1 ) {
             return( FAILURE );
        }
   }
   return(err);
}

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