/*----------------------------------------------------------------------------
** Name: symutil.cpp
**
** Title: symbol utilities
**
** Purpose:
**  Utility code for symbol table; any routines that are used by a number of
**     symbol functions that warrant being placed in one central module.
**
** Status: PRELIMINARY | 
**
** $Log:   S:/tbird/mt2_68k/symbol/symutil.cpv  $
** 
**    Rev 1.0   13 Feb 1997 09:06:28   gene
** Initial revision.
** 
**    Rev 1.0   07 Sep 1995 11:16:56   gene
** Initial revision.
** 
**    Rev 1.29   18 Mar 1994 10:53:44   marilyn
** Fixed bug dealing with mixing address mode and address type in a
** couple of switch statements.
** 
**    Rev 1.28   28 Feb 1994 16:25:18   marilyn
** Removed references to ADDR_LOGICAL.
** 
**    Rev 1.27   18 Jan 1994 17:08:16   nghia
** Fixed bug: General Instrument - DC2.ABS and BWM loadfile.
** When on demand loading for large file, the symbol table loose pointer value
** upon table expanding demanded.  Re-dereference the offset to get the 
** correct pointer value.
** 
**    Rev 1.26   24 Sep 1993 10:31:56   nghia
** Filter out ER_NO_LINENUMS_ADDED for UtilLoadOnDemand() to set data module
** to SYMBOLS_LOADED.
** 
**    Rev 1.25   14 Jul 1993 12:02:24   nghia
** Call LdrLoadModuleByDesc() to do ondemand loading.
** 
**    Rev 1.24   18 Dec 1992 18:13:46   brucea
** Added: SymCalcSymbolOffset
** 
**    Rev 1.23   14 Sep 1992 17:51:08   brucea
** Took out: EVENT_SYMBOL_DELETED event notify from SymRemoveSymbols
** 
**    Rev 1.22   08 Sep 1992 13:06:06   brucea
** Added: events.h include
** 
**    Rev 1.21   28 Aug 1992 10:47:30   brucea
** Fixed bug: UtilIsValidSymDescriptor now checks for valid symDesc before
**    moving on to next part of check
** 
**    Rev 1.20   10 Aug 1992 09:13:24   brucea
** Adde: & 0xF to access to typeindex.symType in UtilOnDemandLoad
** 
** 
**    Rev 1.19   06 Aug 1992 15:24:52   brucea
** Cleanup
** 
**    Rev 1.18   06 Aug 1992 10:12:22   brucea
** Changed access to .typeIndex.symType to use &0xF
** 
**    Rev 1.17   15 Jun 1992 09:30:28   brucea
** Removed: break after return (it was redundant)
** 
**    Rev 1.16   01 Apr 1992 23:38:20   brucea
** Fixed: compiler warnings
** 
**    Rev 1.15   14 Feb 1992 15:17:24   brucea
** Added: setting of modPtr->fileOffset once the on-demand symbols have been
**    loaded
** 
**    Rev 1.14   04 Feb 1992 16:12:10   brucea
** Improved and fixed UtilIsValidSymDescriptor; added check for NULL_SYMBOL,
**    changed |= to &= so FALSE is propagated for each test.
** 
**    Rev 1.13   10 Jan 1992 19:21:32   brucea
** Added #include "enlib.h" to support event notification
** 
**    Rev 1.12   10 Jan 1992 16:16:18   brucea
** Added event notification when symbols are deleted
** Changed array 256 to MAX_SYMNAME_LENGTH
** 
**    Rev 1.11   02 Jan 1992 11:59:28   john
** Added code for comparing two timestamps
** 
**    Rev 1.10   18 Dec 1991 10:39:14   john
** Renamed LdrLoad695_Module to match new name in ldrsvr.h
** 
**    Rev 1.9   16 Dec 1991 16:24:56   brucea
** Added #include "ldrsvr.h" and removed explicit prototype
** Removed last 3 parameters from LdrLoad695_Module call
** 
**    Rev 1.8   13 Dec 1991 14:13:48   brucea
** Added call to LdrLoad695_Module and other changes inside UtilOnDemandLoad
** Added UtilIsValidSymDescriptor
** 
**    Rev 1.7   12 Dec 1991 14:11:56   john
** Seperated the code to remove the tables to allow only the tables to be
** removed when the DLL is removed.
** 
**    Rev 1.6   11 Dec 1991 17:09:26   brucea
** Added UtilGetAddrFromSymDesc, UtilGetOffsetFromAddrDesc,
**    UtilGetOffsetFromAddrDesc, UtilSetAddrOffset, UtilSetEndAddrOffset
** Modified UtilOnDemandLoad with commented code to call loader for on-demand
** 
**    Rev 1.5   09 Dec 1991 14:44:14   john
** Needed prototypes for InitSymTable
** 
**    Rev 1.4   09 Dec 1991 14:40:20   john
** Added a function to remove all the symbols from the symbol table.
** 
**    Rev 1.3   05 Dec 1991 14:45:04   brucea
** Fixed end address code error in UtilSetAddrParams
** 
**    Rev 1.2   02 Dec 1991 18:04:40   john
** Added call to support on demand loading
** 
**    Rev 1.1   29 Nov 1991 20:06:40   brucea
** Added #includes for: addr.h, symbolsvr.h, symget.h
** Added function UtilSetAddrParams
** 
**    Rev 1.0   18 Nov 1991 20:26:22   brucea
** Initial revision.
** 
** $Header:   S:/tbird/mt2_68k/symbol/symutil.cpv   1.0   13 Feb 1997 09:06:28   gene  $
**
** Copyright (C) 1991 Microtek International.  All rights reserved.
**
**--------------------------------------------------------------------------*/

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

#ifndef _ADDR_
#include "addr.h"
#endif

#ifndef _BASETBL_
#include "basetbl.h"
#endif

#ifndef _BYADRBL_
#include "byadrtbl.h"
#endif

#ifndef _HASHTBL_
#include "hashtbl.h"
#endif

#ifndef _INDEXTBL_
#include "indextbl.h"
#endif

#ifndef _LDRSVR_
#include "ldrsvr.h"
#endif

#ifndef _LINENUM_
#include "linenum.h"
#endif

#ifndef _MEMPOOL_
#include "mempool.h"
#endif

#ifndef _ORDTBL_
#include "ordtbl.h"
#endif

#ifndef _SYMADD_
#include "symadd.h"
#endif

#ifndef _SYMBLSVR_
#include "symblsvr.h"
#endif

#ifndef _SYMGET_
#include "symget.h"
#endif

#ifndef _SYMMGR_
#include "symmgr.h"
#endif

#ifndef _SYMUTIL_
#include "symutil.h"
#endif

#ifndef _TYPETBL_
#include "typetbl.h"
#endif

                       /****************************
                        *                          *
                        *        DEFINITIONS       *
                        *                          *
                        ****************************/

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

// holds filename containing symbols to load
extern U8 loadFilename[MAX_SYMNAME_LENGTH];


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

//------------------------------------------------------------------------
//                  SYMBOL UTILITIES
//------------------------------------------------------------------------

//------------------------------------------------------------------------
// SymRemoveSymbols
//
// Purpose:
//    Removes all symbols from the symbol table.
//
// Input parameters:
//
// Output parameters:
//
//------------------------------------------------------------------------
RETCODE EXPORT SymRemoveSymbols(VOID) {

   RETCODE err;

   // remove all dynamically allocated memory ;
   if ((err = UtilDeleteTables()) != GOOD) return(err);
   
   // re-initialize all the tables ;
   if((err = InitSymTable()) != GOOD) return(err);
   if((err = tt.InitBasicTypes()) != GOOD) return(err);

   return(GOOD);
}  // SymRemoveSymbols


//------------------------------------------------------------------------
// SymCalcSymbolOffset
//
// Description:
//    Given a symbol descriptor and address, calculate the offset from
//    the beginning of that symbol to the input address.  If the input
//    address is less than the start of the symbol range, return a value
//    of 0.
//
// Input parameters:
//    symDesc: symbol descriptor to address to be compared
//    inputAddrDesc: address to be compared with symbol's start address
//
//    NOTE: none of the descriptors are destroyed; this is the job of
//    the caller.  Also, none of the contents of the descriptors are
//    modified.
//
// Output parameter:
//    symbolOffset: simple offset (U32) from start to requested addr
//------------------------------------------------------------------------
RETCODE EXPORT
SymCalcSymbolOffset(DESCRIPTOR symDesc,
                    DESCRIPTOR inputAddrDesc,
                    U32 FAR   *symbolOffset) {

   DESCRIPTOR   symAddrDesc = 0L;
   DESCRIPTOR   resultAddrDesc = 0L;
   ADDR_COMPARE result;
   RETCODE      err, firstErr = GOOD;
   U32          tempOffset;

   *symbolOffset = 0L;   // default value
   // get address of symbol; compare input address to symbol address
   if (GOOD != (err = AdrCreateAddress(&symAddrDesc)))
      return err;
   if (GOOD != (err = SymGetSymbolAddress(symDesc,
                                          symAddrDesc)))
      goto CLEANUP;
   // compare input address (inputAddrDesc) with symbol start address
   if (GOOD != (err = AdrCompareAddresses(inputAddrDesc,
                                          symAddrDesc,
                                          &result)))
      goto CLEANUP;

   if (FIRST_ADDR_GREATER == result) {
      // must subtract starting address from input address and return
      // the offset difference.
      if (GOOD != (err = AdrGetAddrOffset(symAddrDesc,
                                          &tempOffset)))
         goto CLEANUP;
      // do not want to change symbol passed in; so much duplicate
      if (GOOD != (err = AdrDuplicateAddress(inputAddrDesc,
                                             &resultAddrDesc)))
         goto CLEANUP;
      if (GOOD != (err = AdrSubtractFromAddress(resultAddrDesc,
                                                tempOffset)))
         goto CLEANUP;   // modifies resultAddrDesc

      if (GOOD !=
         (err = AdrGetAddrOffset(resultAddrDesc, symbolOffset)))
         goto CLEANUP;   // put result into symbolOffset
   }
CLEANUP:
   firstErr = err;
   if (0L != symAddrDesc) {
      err = AdrDestroyAddress(symAddrDesc);
      if (GOOD == firstErr)
         firstErr = err;
   }
   if (0L != resultAddrDesc) {
      err = AdrDestroyAddress(resultAddrDesc);
      if (GOOD == firstErr)
         firstErr = err;
   }
   return firstErr;
}  /* end of SymCalcSymbolOffset */
         

//------------------------------------------------------------------------
// UtilCmpTimestamp
//------------------------------------------------------------------------
S16 UtilCmpTimestamp(TIMESTAMP_TYPE *time1, TIMESTAMP_TYPE *time2) {
   S16 diff;
   
   if ((diff = time1->year - time2->year) != 0) return (diff);
   if ((diff = time1->month - time2->month) != 0) return (diff);
   if ((diff = time1->day - time2->day) != 0) return (diff);
   if ((diff = time1->hour - time2->hour) != 0) return (diff);
   if ((diff = time1->minute - time2->minute) != 0) return (diff);
   if ((diff = time1->second - time2->second) != 0) return (diff);

   return (0);
}

//------------------------------------------------------------------------
// UtilDeleteTables
//------------------------------------------------------------------------
RETCODE UtilDeleteTables(VOID) {

   // remove the base index table and all the by-address tables associated
   // with bit.  This call does both
   bit.ObliterateTable();
   
   // remove the storage for global name hash table;
   ht.ObliterateTable();
   
   // remove all line number info. ;
   lt.ObliterateTable();
   
   // remove info on what order symbols were loaded. ;
   ot.ObliterateTable();
   
   // remove all the memory for all type info. ;
   tt.ObliterateTable();
   
   // remove the index table for all the types just removed. ;
   typit.ObliterateTable();
   
   // remove all the memory for all symbols.  this is done last since it ;
   // holds information potentially stored in all the other tables. ;
   st.ObliterateTable();

   return(GOOD);
}

//--------------------------------------------------------------------------
//  UtilGetAddrFromSymDesc
//
//  Description:
//    Returns the base address of <symDesc>
//     
//  Parameters:
//    input:
//       symDesc: offset to a symbol
//    output:
//       baseAddr: the base address being returned
//--------------------------------------------------------------------------
RETCODE
UtilGetAddrFromSymDesc(SYM_DESCRIPTOR symDesc,
                       BASE_ADDRESS *baseAddr) {
   
   RETCODE    retCode;
   COMMON_SYMBOL_HEADER *symPtr;

   symPtr=(COMMON_SYMBOL_HEADER *)st.GetHugeDataPtr(symDesc);
   retCode = SymGetBaseAddress(symPtr -> typeIndex.baseIndex,
                               baseAddr);
   return retCode;
}  // end of UtilGetAddrFromSymDesc


//------------------------------------------------------------------------
// UtilIsValidSymDescriptor
//
// Purpose:
//    Checks for validity of the passed symbol descriptor; i.e. that the
//       symbol descriptor is not outside the bounds of st
//    Checks that symbolNameOffset, symParentOffset, and symSiblingOffset
//       are also within the st bounds
//
// Input parameters:
//    symDesc: st table offset to be tested against size of table
//
// Output parameters:  returns FALSE if not valid, TRUE if valid
//------------------------------------------------------------------------
BOOLEAN UtilIsValidSymDescriptor(SYM_DESCRIPTOR symDesc) {

   BOOLEAN bool;
   COMMON_SYMBOL_HEADER *symPtr;

   if (symDesc == NULL_SYMBOL)
      return FALSE;
   bool = st.IsValidTableOffset(symDesc);
   if (bool) {
      symPtr = (COMMON_SYMBOL_HEADER *)st.GetHugeDataPtr(symDesc);
      bool &= st.IsValidTableOffset(symPtr->symbolNameOffset);
      bool &= st.IsValidTableOffset(symPtr->symParentOffset);
      bool &= st.IsValidTableOffset(symPtr->symSiblingOffset);
   }
   return bool;
   } // end of UtilIsValidSymDescriptor


//------------------------------------------------------------------------
// UtilGetOffsetFromAddrDesc
//
// Purpose:
//    Convert an abstract address into an offset value for local address
//    lookup.  If type is logical, subtracts the base address from the
//    requested address and returns the result.  If virtual, simply returns
//    the abstract offset.
//
// Input parameters:
//    symbolDesc: any legitimate symbol -> must have base index and base addr
//    addrDesc: abstract requested address
//
// Output parameters:
//    offsetAddr: final offset address used for looking up a symbol
//
// Errors:
//    returns error if the abstract address is virtual and the
//       selector/segment is larger than the allowed base index
//------------------------------------------------------------------------
RETCODE
UtilGetOffsetFromAddrDesc(SYM_DESCRIPTOR   symbolDesc,
                          DESCRIPTOR       addrDesc,
                          OFFSET_ADDR_TYPE *offsetAddr)  {

   RETCODE          retCode;
   BASE_ADDRESS     baseAddr;
   ADDR_TYPE        addrType;
   U32              ldt;            // holds ldt selector

   // get address type and handle appropriately
   if (SUCCESS != (retCode = AdrGetAddrType(addrDesc, &addrType)))
      return retCode;
   // get offset (is logical before base address subtracted)
   if (SUCCESS != (retCode = AdrGetAddrOffset(addrDesc, offsetAddr)))
      return retCode;

//@@@!!! does ADDR_SEGSEL_TYPE have to be checked here first???
   switch (addrType) {
      case ADDR_VIRTUAL:
         // check for valid selector
         // get address selector
         if (SUCCESS != (retCode = AdrGetLdtSelector(addrDesc, &ldt)))
            return retCode;

         // check for ldt out of bounds of allowed base index
         if (ldt > MAX_BASE_INDEX_SIZE)
            return ER_INDEX_OUT_OF_BOUNDS;

         // have already gotten offset
         break;

      case ADDR_LINEAR:
         // code type is logical or linear; must extract base address
         // from module symbol, then subtract it from the requested logical
         // address
         if (SUCCESS != (retCode =
             UtilGetAddrFromSymDesc(symbolDesc, &baseAddr)))
            return retCode;
         *offsetAddr -= baseAddr;
         break;

      default:
         return ER_ADDR_TYPE_NOT_ACCEPTED;
      }  //end of switch
   return SUCCESS;
   } // end of UtilGetOffsetFromAdrDesc


//------------------------------------------------------------------------
// UtilSetAddrOffset
//
// Purpose:
//    Convert an offset value back into an abstract address.
//    If type is logical, adds the base address into the passed address and
//    returns the result.  If virtual, simply places the offset into the
//    the abstract address.
//
// Input parameters:
//    symbolDesc: any legitimate symbol -> must have base index and base addr
//    offsetAddr: offset address value to be put into abstract address
//
// Output parameters:
//    addrDesc: abstract address to be filled in
//
// Errors:
//    returns error if the abstract address is virtual and the
//       selector/segment is larger than the allowed base index
//------------------------------------------------------------------------
RETCODE
UtilSetAddrOffset(SYM_DESCRIPTOR   symbolDesc,
                  OFFSET_ADDR_TYPE offsetAddr,
                  DESCRIPTOR       addrDesc)  {

   RETCODE          retCode;
   BASE_ADDRESS     baseAddr;
   ADDR_TYPE        addrType;
   U32              ldt;            // holds ldt selector

   // get address type and handle appropriately
   if (SUCCESS != (retCode = AdrGetAddrType(addrDesc, &addrType)))
      return retCode;

//@@@!!! does ADDR_SEGSEL_TYPE have to be checked here first???
   switch (addrType) {
      case ADDR_VIRTUAL:
         // check for valid selector
         // get address selector
         if (SUCCESS != (retCode = AdrGetLdtSelector(addrDesc, &ldt)))
            return retCode;

         // check for ldt out of bounds of allowed base index
         if (ldt > MAX_BASE_INDEX_SIZE)
            return ER_INDEX_OUT_OF_BOUNDS;

         break;

      case ADDR_LINEAR:
         // code type is logical or linear; must extract base address
         // from module symbol, then subtract it from the requested logical
         // address
         if (SUCCESS != (retCode =
             UtilGetAddrFromSymDesc(symbolDesc, &baseAddr)))
            return retCode;
         offsetAddr += baseAddr;
         break;

      default:
         return ER_ADDR_TYPE_NOT_ACCEPTED;
      }  //end of switch

   return AdrSetAddrOffset(addrDesc, offsetAddr);
   } // end of UtilSetAddrOffset


//------------------------------------------------------------------------
// UtilSetEndAddrOffset
//
// Purpose:
//    Convert an offset value back into the end abstract address.
//    If type is logical, adds the base address into the passed address and
//    returns the result.  If virtual, simply places the end offset into the
//    the abstract end address.
//    NOTE: this routine assumes that UtilSetAddrOffset has been called first
//    and has checked for selector validity.
//
// Input parameters:
//    symbolDesc: any legitimate symbol -> must have base index and base addr
//    endOffsetAddr: offset address value to be put into abstract address
//
// Output parameters:
//    addrDesc: abstract address to be filled in
//
// Errors:
//------------------------------------------------------------------------
RETCODE
UtilSetEndAddrOffset(SYM_DESCRIPTOR   symbolDesc,
                     OFFSET_ADDR_TYPE endOffsetAddr,
                     DESCRIPTOR       addrDesc)  {

   RETCODE          retCode;
   BASE_ADDRESS     baseAddr;
   ADDR_TYPE        addrType;

   // get address type and handle appropriately
   if (SUCCESS != (retCode = AdrGetAddrType(addrDesc, &addrType)))
      return retCode;

//@@@!!! does ADDR_SEGSEL_TYPE have to be checked here first???
   switch (addrType) {
      case ADDR_VIRTUAL:
         break;

      case ADDR_LINEAR:
         // code type is logical or linear; must extract base address
         // from module symbol, then subtract it from the requested logical
         // address
         if (SUCCESS != (retCode =
             UtilGetAddrFromSymDesc(symbolDesc, &baseAddr)))
            return retCode;
         endOffsetAddr += baseAddr;
         break;

      default:
         return ER_ADDR_TYPE_NOT_ACCEPTED;
      }  //end of switch

   return AdrSetEndAddrOffset(addrDesc, endOffsetAddr);
   } // end of UtilSetEndAddrOffset


//------------------------------------------------------------------------
// UtilOnDemandLoad
//------------------------------------------------------------------------
RETCODE UtilOnDemandLoad(SYM_DESCRIPTOR inputSymbol) {

   RETCODE         err;
   COMMON_SYMBOL_HEADER *headPtr;
   SYM_TYPE_MODULE *modPtr;
   SYM_DESCRIPTOR  currentOffset, tmpOffset;
   SYM_TYPE_TYPE   symType;
   U8              modName[MAX_SYMNAME_LENGTH];
   U8              tmpSymType;

   headPtr = (COMMON_SYMBOL_HEADER *) st.GetHugeDataPtr(inputSymbol);
   tmpSymType = (headPtr->typeIndex.symType) & 0xF;
   if (!((tmpSymType == SYM_MODULE)  ||
         (tmpSymType == SYM_FUNCTION)||
         (tmpSymType == SYM_BLOCK))) {
      return(ER_SYMBOL_NOT_A_FUNCTION);
   }

   // find the module descriptor from the inputSymbol descriptor. ;
   // the input symbol is a func/block/module descriptor. ;
   currentOffset = inputSymbol;
   while (((headPtr->typeIndex.symType) & 0xF) != SYM_MODULE) {
      // search the symbols parent list until the module descriptor ;
      // is found.  Then check to see if the module symbols have been ;
      // loaded. ;
      if ((err = SymGetSymbolParent(currentOffset, &symType, 
         &tmpOffset)) != GOOD) return(err);
      headPtr = (COMMON_SYMBOL_HEADER *) st.GetHugeDataPtr(tmpOffset);
      currentOffset = tmpOffset;
   }
   modPtr = (SYM_TYPE_MODULE *) headPtr;
   if (modPtr->fileOffset != SYMBOLS_LOADED) {
      // Get the module name to do loading - currentOffset == symDesc
      if (SUCCESS != (err = SymAddGetModuleName(currentOffset,
                                                (LPSTR)modName)))
         return err;
      // Call loader to load symbols and set flag when done
      if ((err = LdrLoadModuleByDesc((LPSTR)loadFilename, (LPSTR)modName,
            currentOffset)) != GOOD) {
         // NOTES: 09/22/93 - Nghia
         // Filter out err if module does not contain line number information
         if ((err == ER_NO_LINENUMS_ADDED) ||
             (err == ER_NO_LINEBLK_IN_MODULE)) {
            // Notes: 01/18/94 - Nghia
            // Retrieve the headPtr again, in cases the table is expanded
            // which trashed the headPtr.  STRANGE PROBLEM with
            // Windows ReAlloc() function.
            headPtr = (COMMON_SYMBOL_HEADER *)
                      st.GetHugeDataPtr(currentOffset);
            if (((headPtr->typeIndex.symType) & 0xF) == SYM_MODULE) {
               modPtr = (SYM_TYPE_MODULE *) headPtr;            
               // indicate that the module does not have line information
               // so set flag to indicate that it's loaded
               modPtr->fileOffset = SYMBOLS_LOADED;
            }
         }
         // return err to avoid unwanted processing 
         // Caller need not to report the filter errors  
         return err;
         
      } else
         // Notes: 01/18/94 - Nghia
         // Retrieve the headPtr again, in cases the table is expanded
         // which trashed the headPtr.  STRANGE PROBLEM with
         // Windows ReAlloc() function.
         headPtr = (COMMON_SYMBOL_HEADER *)
                   st.GetHugeDataPtr(currentOffset);
         modPtr = (SYM_TYPE_MODULE *) headPtr;
         // Make sure that it is a module
         if (((headPtr->typeIndex.symType) & 0xF) != SYM_MODULE)
            return ER_SYMBOL_NOT_A_MODULE;
         // indicate that the rest of module symbols have been loaded
         modPtr->fileOffset = SYMBOLS_LOADED;
   }
   return(GOOD);
}
         
//------------------------------------------------------------------------
// UtilSetAddrParams
//
// Purpose:
//    Enters the address or addresses into a address object
//
// Input parameters:
//    baseIndex: symbol table base index which equates to Intel selector
//               or segment
//    offsetAddr: symbol offset address
//    offsetAddrEnd: end address of symbol: makes up the address range
//                   0 ==> no end address; any other value means there is
//    desc: descriptor for access to address object; it is equivalent to
//          a pointer
//
// Output parameters:
//    desc: modifies the address object
//------------------------------------------------------------------------
RETCODE
UtilSetAddrParams(BASE_INDEX       baseIndex,
                  OFFSET_ADDR_TYPE offsetAddr,
                  OFFSET_ADDR_TYPE offsetAddrEnd,
                  DESCRIPTOR       desc)  {

   ADDR_TYPE addrType;
   RETCODE   retCode;
   BASE_ADDRESS baseAddr;

   if (SUCCESS != (retCode = AdrGetAddrType(desc, &addrType)))
      return retCode;
   switch (addrType)  {
      case ADDR_LINEAR:

         // enter the start and end addresses
         if (SUCCESS != (retCode = SymGetBaseAddress(baseIndex, &baseAddr)))
               return retCode;
         if (SUCCESS !=
            (retCode = AdrSetAddrOffset(desc, baseAddr + offsetAddr)))
            return retCode;
         if (0L != offsetAddrEnd)  {
            if (SUCCESS != (retCode =
                AdrSetEndAddrOffset(desc, baseAddr + offsetAddrEnd)))
               return retCode;
            }
         break;

      case ADDR_VIRTUAL:

         // set the selector and offset values
         if (SUCCESS != (retCode =
             AdrSetAddrSegmentSelector(desc, ADDR_USE_VALUE, (U32)baseIndex)))
             return retCode;
         if (SUCCESS != (retCode = AdrSetAddrOffset(desc, offsetAddr)))
            return retCode;
         if (0L != offsetAddrEnd)  {
            if (SUCCESS != (retCode = AdrSetEndAddrOffset(desc, offsetAddrEnd)))
               return retCode;
            }
         break;

      case ADDR_PHYSICAL:
      // cannot accept a physical address request; must be in logical, linear,
      // or virtual form.  The caller must convert these back to physical
      // after type is returned
         return ER_ADDR_TYPE_NOT_ACCEPTED;

      } // end of switch
   return SUCCESS;
   }  // end of SetAddrParams

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