/****************************************************************************
**
**  Name:  TYPE.CPP
**
**  Description:
**      routines for type processing
**
**  Status:  CODED
**
**  $Log:   S:/tbird/mt2_186/omf86/type.cpv  $
** 
**    Rev 1.3   19 Jun 1997 17:11:38   Judy
** Support Paradigm locate extended version which accept register variables.
** 
**    Rev 1.2   18 Jun 1997 14:53:30   Judy
** 
**    Rev 1.1   18 Apr 1997 09:29:46   Judy
** 
**    Rev 1.0   26 Feb 1997 11:40:38   Judy
** Initial revision.
** 
**    Rev 1.3   11 Oct 1996 16:21:16   hera
** Fix ProcessTypeScalar() for High C
** 
**    Rev 1.3   11 Oct 1996 16:19:04   hera
** Fix ProcessTypeScalar function for High C
** 
**    Rev 1.2   25 Sep 1996 10:10:56   hera
** 
**    Rev 1.1   24 Sep 1996 17:36:46   matt
** remove the warning message of invalid type index
** 
**    Rev 1.23   07 Apr 1995 09:36:18   nghia
** Fixed bug in chaining hash node for LIST TYPDEF records.
** <X>HashTail pointer must point to the last hash node of <X>HashBuf.
** Added comments to clarify how on earth the <X>ListBuf and the <X>HashBuf
** are related.
** 
**    Rev 1.22   29 Mar 1995 17:35:24   nghia
** Added type index in error report invalid type signature.
** 
**    Rev 1.21   10 Mar 1995 13:59:00   nghia
** Fixed PPR 10083 10088 10095 - Revised OMF86 loader to support BC/PDM
** Rewritten processTypeList() to handle all OMF86 LIST types.
** Added CreateListBuffer() and FreeListBuffer() to allocate/deallocate list
** buffers genericly.
** Added GetNumber() to handle all OMF86 numbers format.
** Rewritten processTypeEnum to handle OMF86 enum type correctly.
** Rewritten processTypeUnion to handle OMF86 BC/MS union type.
** 
**    Rev 1.20   14 Feb 1995 17:39:26   nghia
** Fixed PPR 10075 for PV 2.4 - Incorrectly compute the union members offset.
** Fixed byg Joyce.
**
**    Rev 1.19   21 Nov 1994 02:11:30   nghia
** Put Changes in for Joyce.  Added check for SHORT$NOPOP and LONG$NOPOP type
** signature for PROC type - {proc} {nil} {type} {SHORT$NOPOP/LONG$NOPOP}
** 
**    Rev 1.18   25 Oct 1994 14:38:18   joyce
** Modify ProcessTypeProcedure() to support PARADIGM Locater.
**
**    Rev 1.17   13 Oct 1994 10:45:56   joyce
** Add one more condition in converting typeIndex to the number > 0x8000:
** typeindex needs to be close to 0x8000; let's say 0x7f00.
**
**    Rev 1.16   11 Oct 1994 09:58:06   joyce
** 1. Add the type as TY_VOID if the type processing failed.
** 2. Add LABEL type as BI_VOID(return void type).
**
**    Rev 1.15   26 Sep 1994 13:41:30   joyce
** 1. Add TFree checkings.
**
**    Rev 1.14   20 Sep 1994 11:54:34   joyce
** Add ProcessTypeVar() to handle register variable types.
**
**    Rev 1.13   14 Sep 1994 10:45:36   joyce
** Use complex type TY_VOID instead of BI_VOID to build void type.
**
**    Rev 1.12   07 Sep 1994 12:48:00   joyce
** 1. Modify ProcessTypeSU() to accept lists in different orders.
** 2. Modify ProcessTypeScalar() to ignore the rest of the string after "name"
**    if it's not a enum.
**
**    Rev 1.11   06 Sep 1994 10:00:52   joyce
** Add structure member offset checking.
** Fix the highbound of Array.
**
**    Rev 1.10   23 Aug 1994 14:24:36   joyce
** 1. Change the algorithm of handling types.
** 2. Fix the bug of array high bound.
** 3. Use hash table to store LIST records.
** 4. Handle types greater than 32767.
** 5. Add ProcessTypeEnum() and ProcessTypeBitField.
**
**    Rev 1.9   03 Aug 1994 13:25:32   steve
** Joyce's changes for 386 build 11
**
**    Rev 1.8   25 Jul 1994 12:41:22   steve
** Joyce's omf changes for 386 build 9
**
**    Rev 1.7   14 Jul 1994 15:23:18   steve
** More changes for 386 build 8 from Joyce
**
**    Rev 1.4   17 Jun 1994 15:14:04   joyce
** Add retcode checking for LdrWarning() so if user cancelled the load, it would
** cleanup and return.
**
**    Rev 1.3   16 Jun 1994 13:35:16   joyce
** Use LdrWarning() to replace Warning() and remove err.h from the include list.
**
**    Rev 1.2   02 Jun 1994 18:41:48   joyce
** Mark PRIVATE instead of STATIC for local functions to meet the code
** convention.
**
**    Rev 1.1   25 May 1994 16:06:34   joyce
** Free TypeMap and TypeOffset at InitializeTypeInfo() to ensure the memory
** is cleaned up before each load/reload.
**
**    Rev 1.0   24 May 1994 14:48:40   joyce
** Initial revision.
**
**  $Header:   S:/tbird/mt2_186/omf86/type.cpv   1.3   19 Jun 1997 17:11:38   Judy  $
**
**  Copyright (C) 1994 Microtek International.  All rights reserved.
**
*****************************************************************************/

                       /****************************
                        *                          *
                        *       INCLUDE FILES      *
                        *                          *
                        ****************************/
#ifndef __STDIO_H
#include <stdio.h>
#endif

#ifndef _BASEWIND_
#include "basewind.h"
#endif

#include <mem.h>
#include <string.h>

#ifndef _HEAP_
#include "heap.h"
#endif

#ifndef _LMANGLE_
#include "lmangle.h"
#endif

#ifndef _HOSTERRS_
#include "hosterrs.h"
#endif

#ifndef _INIUTIL_
#include "iniutil.h"
#endif

#ifndef __OMF86LDR__
#include "omf86ldr.h"
#endif

#ifndef __BASE__
#include "base.h"
#endif

#ifndef __TYPE__
#include "type.h"
#endif

                       /****************************
                        *                          *
                        *     LOCAL DEFINITIONS    *
                        *                          *
                        ****************************/
STATIC BOOLEAN ExpandSmallPtr=FALSE;
TYPE_INDEX TypeIndex;
OMF86_TYPE prevProcessedType;
TYPE_INDEX firstListTypeIndex;
STATIC TYPE_LIST_BUF *IndexListBuf, *NameListBuf, *ValueListBuf,
                     *IndexListTail, *NameListTail, *ValueListTail;
STATIC HASH_BUF *IndexHashBuf, *NameHashBuf, *ValueHashBuf,
                *IndexHashTail, *NameHashTail, *ValueHashTail;
STATIC U32 NameListCnt, IndexListCnt, ValueListCnt;
STATIC TypeWarned=FALSE;
const CHAR *UnknownTypeName = "TypeUnknown\0";
CHAR typeIdStr[MAX_STRING_SIZE] = "";
                       /****************************
                        *                          *
                        *    EXTERNAL VARIABLES    *
                        *                          *
			****************************/
extern int ExtOmf;
                       /****************************
                        *                          *
                        *     LOCAL PROTOTYPES     *
                        *                          *
                        ****************************/
PRIVATE RETCODE GetTypeIndexesFromList(HANDLE, TYPE_INDEX, U32, TYPE_INDEX **);
PRIVATE RETCODE GetNamesFromList(HANDLE, TYPE_INDEX, U32, CHAR **);
PRIVATE RETCODE GetListRecord(HANDLE, LIST_TYPE, TYPE_INDEX, U8 **, U16 *);
//PRIVATE S16 GetSignedInteger(U8 *typeRec, U16 *i);
PRIVATE U32 GetValue(U8 *typeRec, U16 *i); //Hera 4/9/97
PRIVATE TYPE_INDEX GetSubTypeIndex(TYPE_INDEX, U8 *, U16 *);
PRIVATE U32 GetTypeLength(U8 *, U16 *);
PRIVATE U32 GetNumber(U8 *, U16 *);
PRIVATE RETCODE GetTypeName(U8 *, U16 *, CHAR *);
PRIVATE RETCODE GetTYPDEF(HANDLE, U32, U16 *, U8 **);
PRIVATE RETCODE GetSmallPtrOption(VOID);
PRIVATE RETCODE ProcessSymbolType(HANDLE, U32, TYPE_INDEX, U16, U8 *);
PRIVATE RETCODE ProcessTypeArray(TYPE_PARAM FAR *para);
PRIVATE RETCODE ProcessTypeBitField(TYPE_PARAM FAR *para, U32 len);
PRIVATE RETCODE ProcessTypeEnum(TYPE_PARAM FAR *para);
PRIVATE RETCODE ProcessTypeList(TYPE_PARAM FAR *para);
PRIVATE RETCODE ProcessTypePointer(TYPE_PARAM FAR *para, U32 len);
PRIVATE RETCODE ProcessTypeProcedure(TYPE_PARAM FAR *para);
PRIVATE RETCODE ProcessTypeRegVar(TYPE_PARAM FAR *para);
PRIVATE RETCODE ProcessTypeScalar(TYPE_PARAM FAR *para);
PRIVATE RETCODE ProcessTypeSU(TYPE_PARAM FAR *para);
PRIVATE RETCODE ProcessTypeTypeIndex(TYPE_PARAM FAR *para);
PRIVATE RETCODE ProcessTypeUnion(TYPE_PARAM FAR *para);
PRIVATE RETCODE ProcessTypeVoid(TYPE_PARAM FAR *para);

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

/******************************************************************************
**
**  ProcessTYPDEF
**
**  Note:  The OMF86 supports up to 32767 types, currently if the types
**         exceed this limit, the corresponding symbols might resolve to
**         incorrect types.
**
**  Here are the theories about handling this case :
**
**  Adding types(implemented in GetSubTypeIndex) :
**  . for simple types(eg. scalar), it will have no problem since the type
**    index = TypeIndex(type count) + 0x100.
**  . for complex types(ie. types refer to other types), eg. if a
**    type refers to the type index (0x80)(0x05), we don't know
**    whether this index is 0x5 or 0x8005.
**
**    Let's make some assumptions:
**    1. Types and thier subtypes should not be too distant from one
**       another except some basic types, such as 0x01(null).
**
**    2. Base types are usually one-byte.
**
**    3. If the type is very close to 0x8000(how about >= 0x7f00) and
**       the distance of a 2-byte subtype from its parent type exceeds
**       certain value(how about MAX_TYPE_INDEX/2(0x4000)?), we assume the
**       subType is an index larger than 0x8000.
**
**    So the algorithm is :
**       if ((subTypeIndex is 2-byte) && (parentType >= 0x7f00) &&
**           (|subTypeIndex - parentType| > MAX_TYPE_INDEX/2))
**          subTypeIndex += MAX_TYPE_INDEX;
**
**  Adding symbols(implemented in GetTypeIndex) :
**    The type index of a symbol is implemented as following:
**
**    if ((typeIndex is 2-byte) && (more than 32767 types) &&
**        (SymGetTypeHeader(typeIndex, &targetTypes) != GOOD))
**       typeIndex += MAX_TYPE_INDEX;
**
******************************************************************************/
RETCODE ProcessTYPDEF(OMF86_FUNC_PARA *funcPara) {
RETCODE err= GOOD;
U8 *typeDescriptor=NULL;
U16 leafCnt = 0;

   if (IsLoadSymbol(funcPara->flags) && (funcPara->oFlag == MCREATE)) {
      //Hera 5/16/97
      if (TypeWarned && ExtOmf != 1)
	 return GOOD;
      else
         ++TypeIndex;
      if ((TypeIndex > MAX_TYPE_INDEX) && !TypeWarned) {
         sprintf(typeIdStr, "%0X", TypeIndex);
         if ((err=LdrWarning(ER_OMF86_TYPES_TOO_LARGE,
                             (LPSTR)typeIdStr, NULL, NULL))
                 != GOOD)
            return(err);
         TypeWarned = TRUE;
      }
      if ((err = GetTYPDEF(funcPara->hFile, funcPara->endLoc, &leafCnt,
                           &typeDescriptor)) != GOOD) {
         if (typeDescriptor) TFree((LPSTR)typeDescriptor);
         return(err);
      }
      err = ProcessSymbolType(funcPara->hFile, funcPara->flags, TypeIndex,
                              leafCnt, typeDescriptor);
      if (typeDescriptor) TFree((LPSTR)typeDescriptor);
      if (err != GOOD) {
         sprintf(typeIdStr, "%0X", TypeIndex);
         if ((err == ER_LDR_ABORT) || (err=LdrWarning(err,
               (LPSTR)typeIdStr, NULL, NULL)) != GOOD)
            return(err);
         else {
            // NOTES: 05/07/95 - Nghia
            // <funcPara> needs to have a flag indicate whether the current
            // type has been created with the Symbol server yet, this to
            // avoid calling ProcessTypeVoid() with a TypeIndex already
            // created. 
            TYPE_PARAM typePara;
            TYPE_HEADER_TYPE typeHdrInfo;

            typeHdrInfo.typeChoice = COMPLEX_TYPE_CLASS;
            typePara.typeIdx = TypeIndex + TYPE_OFFSET;
            typePara.typeHdrInfo = &typeHdrInfo;
            err = ProcessTypeVoid((TYPE_PARAM FAR *)&typePara);
         }
      }
   }
   return(err);
}  /* ProcessTYPDEF */

/***************************************************************************
**
**  Name: GetTYPDEF
**
****************************************************************************/
PRIVATE RETCODE GetTYPDEF(HANDLE hFile, U32 endLoc, U16 *leafCnt,
                          U8 **typeDescriptor) {
RETCODE err=GOOD;
CHAR typeDefName[NAME_LEN];
U8 dummy;

  /* Name is for Link86 use only, so it's always '\0' */
  if ((err=GetName(hFile, &dummy, typeDefName)) != GOOD)
     return(err);
  /* Get EN field(Easy or Nice flags); it's useless for us */
  if ((err=OMFGetBytes(hFile, &dummy, sizeof(dummy))) != GOOD)
     return(err);
  *leafCnt = (U16)(endLoc - CurrentLocation());
  if (*leafCnt < 1)
     return(ER_OMF86_BAD_TYPE_SIGNATURE);
  if ((*typeDescriptor = (U8 *)TMalloc((U32)*leafCnt)) == NULL)
     return(ERR_BAD_MEMORY);
  if ((err=OMFGetBytes(hFile, *typeDescriptor, *leafCnt)) != GOOD) {
     if (*typeDescriptor) TFree((LPSTR)*typeDescriptor);
     *typeDescriptor = NULL;
  }
  return(err);
} /* GetTYPDEF */

/******************************************************************************
**
**  GetTypeIndex
**
******************************************************************************/
RETCODE GetTypeIndex(HANDLE hFile, TYPE_INDEX *type) {
RETCODE err;
U8 c;

   if ((err = OMFGetBytes(hFile, &c, sizeof(c))) != GOOD)
      return(err);
   *type = c;
   //Hera 6/16/97 for extend Omf
   if (ExtOmf == 1) {
      if (*type == 0) {
         if ((err = OMFGetBytes(hFile, &c, sizeof(c))) != GOOD)
	    return(err);
         *type = c;
      }
      else {
	 TYPE_INDEX newType;
	 *type = c << 8;
	 if ((err=OMFGetBytes(hFile, &c, sizeof(c))) != GOOD)
            return(err);
         *type += c;
	 newType = *type + MAX_TYPE_INDEX + 1L;
         if ((TypeIndex > MAX_TYPE_INDEX) && (newType <= TypeIndex)) {
            CHAR typeName[NAME_LEN+1]="";
            TYPE_HEADER_TYPE targetTypeHdr;

            targetTypeHdr.typeName = (LPSTR)typeName;
            if (SymGetTypeHeader(*type+TYPE_OFFSET, &targetTypeHdr) != GOOD)
               *type = newType;
	 }
      }
   }
   else {
      if (LARGE_INDEX(c)) {    /* Two-byte index? */
	 TYPE_INDEX newType;

         *type = (c&0x7F) << 8;
         if ((err=OMFGetBytes(hFile, &c, sizeof(c))) != GOOD)
            return(err);
         *type += c;
         newType = *type + MAX_TYPE_INDEX + 1L;
         if ((TypeIndex > MAX_TYPE_INDEX) && (newType <= TypeIndex)) {
            CHAR typeName[NAME_LEN+1]="";
            TYPE_HEADER_TYPE targetTypeHdr;

            targetTypeHdr.typeName = (LPSTR)typeName;
            if (SymGetTypeHeader(*type+TYPE_OFFSET, &targetTypeHdr) != GOOD)
               *type = newType;
         }
      }
   }
   if (*type > TypeIndex)
      return(ER_TYPE_IDXS_DONT_MATCH);
   *type += TYPE_OFFSET;
   return(GOOD);
} /* GetTypeIndex */

/***************************************************************************
**
**  InitializeTypeInfo
**
****************************************************************************/
RETCODE InitializeTypeInfo(VOID) {
   TypeIndex = firstListTypeIndex = 0L;
   prevProcessedType = OMF86_UNKNOWN_TYPE;
   IndexListBuf  = NameListBuf  = ValueListBuf  = NULL;
   IndexListTail = NameListTail = ValueListTail = NULL;
   IndexHashBuf  = NameHashBuf  = ValueHashBuf  = NULL;
   IndexHashTail = NameHashTail = ValueHashTail = NULL;
   NameListCnt = IndexListCnt = ValueListCnt = 0L;
   TypeWarned = FALSE;
   return(GetSmallPtrOption());
}  /* InitializeTypeInfo */

/***************************************************************************
**
**  Name: CreateListBuffer
**
****************************************************************************/
RETCODE CreateListBuffer(TYPE_LIST_BUF **listBufPtr, HASH_BUF **hashBufPtr) {

   if (!*listBufPtr) {
      if ((*listBufPtr = (TYPE_LIST_BUF *)TMalloc(sizeof(TYPE_LIST_BUF)))
          == NULL) return(ER_NO_MEMORY);
      memset(*listBufPtr, NULL, sizeof(TYPE_LIST_BUF));
   }
   if (!*hashBufPtr) {
      if ((*hashBufPtr = (HASH_BUF *)TMalloc(sizeof(HASH_BUF)))
          == NULL) return(ER_NO_MEMORY);
      memset(*hashBufPtr, NULL, sizeof(HASH_BUF));
   }
   return GOOD;
} /* CreateListBuffer */

/***************************************************************************
**
**  Name: FreeListBuffer
**
****************************************************************************/
RETCODE FreeListBuffer(LIST_TYPE listType) {
TYPE_LIST_BUF *tmpPtr, *tmpPtrNext;
HASH_BUF *hashPtr, *tmpHashNext;
RETCODE err;

   switch(listType) {
      case INDEX_LIST:
         tmpPtr = IndexListBuf;
         hashPtr = IndexHashBuf;
         IndexListBuf = IndexListTail = NULL;
         IndexHashBuf = IndexHashTail = NULL;
         IndexListCnt = 0L;
         break;
      case NAME_LIST:
         tmpPtr = NameListBuf;
         hashPtr = NameHashBuf;
         NameListBuf = NameListTail = NULL;
         NameHashBuf = NameHashTail = NULL;
         NameListCnt = 0L;
         break;
      case VALUE_LIST:
         tmpPtr = ValueListBuf;
         hashPtr = ValueHashBuf;
         ValueListBuf = ValueListTail = NULL;
         ValueHashBuf = ValueHashTail = NULL;
         ValueListCnt = 0L;
         break;
      default:
         // Invalid list type
         if ((err=LdrWarning(ER_BAD_FREE, NULL, NULL, NULL)) != GOOD)
            return(err);
   } // switch

   // free the lists
   while (tmpPtr != NULL) {
      tmpPtrNext = tmpPtr->next;
      if ((TFree((LPSTR)tmpPtr) != GOOD) &&
          ((err=LdrWarning(ER_BAD_FREE, NULL, NULL, NULL)) != GOOD))
         return(err);
      tmpPtr = tmpPtrNext;
   }
   while (hashPtr != NULL) {
      tmpHashNext = hashPtr->next;
      if ((TFree((LPSTR)hashPtr) != GOOD) &&
          ((err=LdrWarning(ER_BAD_FREE, NULL, NULL, NULL))  != GOOD))
         return(err);
      hashPtr = tmpHashNext;
   }
   return(GOOD);
}  /* FreeListBuffer */

/**************************************************************************
**
** ProcessSymbolType
**
**************************************************************************/
PRIVATE RETCODE ProcessSymbolType(HANDLE hFile, U32 flags,
                                  TYPE_INDEX typeIdx,
                                  U16 recLen, U8 *typeRec) {
OMF86_TYPE type;
TYPE_PARAM typePara;
TYPE_HEADER_TYPE typeHdrInfo;
RETCODE err=GOOD;
CHAR typeName[NAME_LEN+1] = "";

   typePara.i = 0;
   typePara.typeRec = typeRec;
   typePara.typeHdrInfo = &typeHdrInfo;
   typePara.recLen = recLen;
   typePara.typeIdx = typeIdx + TYPE_OFFSET;
   typePara.hFile = hFile;
   typePara.flags = flags;
// while (typePara.i < recLen) {
      type = (OMF86_TYPE)typeRec[(typePara.i)++];
      typeHdrInfo.typeChoice = COMPLEX_TYPE_CLASS;
      typeHdrInfo.sizeInMAUs    = 0L;  /* default MAU size for all types */
      typeHdrInfo.typeName = (LPSTR)typeName;
      typeHdrInfo.sizeCalculated = FALSE;
      switch(type) {
         case OMF86_REGISTER:  /* 0x40 */
            if ((err=ProcessTypeRegVar((TYPE_PARAM FAR *)&typePara)) != GOOD)
               return(err);
            break;
	 case OMF86_LABEL:     /* 0x71 */

	    //**Hera 09/17/96**/
	    typeHdrInfo.t.complexType  = TY_FUNC_NODEP;
	    //**Hera**/

            if (((err=SymAddTypeHeader(typePara.typeIdx,
                                       &typeHdrInfo)) != GOOD) ||
                 (err=SymAddTypeTypeIndex(typePara.typeIdx, BI_VOID)) != GOOD)
               return(err);
            return(GOOD);
         case OMF86_PROCEDURE: /* 0x74 */
            if ((err=ProcessTypeProcedure((TYPE_PARAM FAR *)&typePara))
                != GOOD) return(err);
            break;
         case OMF86_SELECTOR:  /* 0x62 */
         case OMF86_CONST:     /* 0x6F */
         case OMF86_PARAMETER: /* 0x75 */
         case OMF86_POINTER:   /* 0x7A */
            if ((err=ProcessTypeTypeIndex((TYPE_PARAM FAR *)&typePara))
                != GOOD) return(err);
            break;
         case OMF86_ARRAY:     /* 0x77 */
            if ((err=ProcessTypeArray((TYPE_PARAM FAR *)&typePara)) != GOOD)
               return(err);
            break;
         case OMF86_STRUCTURE: /* 0x79 */
            if ((err=ProcessTypeSU((TYPE_PARAM FAR *)&typePara)) != GOOD)
               return(err);
            break;
         case OMF86_SCALAR:    /* 0x7B */
            if ((err=ProcessTypeScalar((TYPE_PARAM FAR *)&typePara)) != GOOD)
               return(err);
            break;
         case OMF86_LIST:      /* 0x7F */
            // Save the first OMF86_LIST type index 
            if (prevProcessedType != type) {
               // <TypeIndex> is global type index without offset
               // When process a OMF86_STRUCTURE (aka Union) type,
               // this <firstListTypeIndex> will be reset back to 0.
               firstListTypeIndex = TypeIndex;
            }
            if ((err=ProcessTypeList((TYPE_PARAM FAR *)&typePara)) != GOOD)
               return(err);
            break;
         case LEAF_NIL:        /* 0x80 */
            if ((err=ProcessTypeVoid((TYPE_PARAM FAR *)&typePara)) != GOOD)
               return(err);
            break;
         default :
            break;
      }
// }
   
   // NOTES: 03/09/95 - Nghia
   // Save the processed type to record the first list type in a group
   // of list type which will be used in processing a union type.
   prevProcessedType = type;
   
   return(err);
}  /* ProcessSymbolType */

/******************************************************************************
**
**  GetSmallPtrOption
**
**  Description:
**     Get the ExpandSmallPtr option(ON/OFF) from MP186.INI file.
**
******************************************************************************/
PRIVATE RETCODE GetSmallPtrOption(VOID) {
CHAR smallPtrOption[NAME_LEN];

   ExpandSmallPtr = FALSE;

   /* Retrieve the ExpandSmallPtr option from MP186.INI for OMF86 Loader */
   if ((IniGetString((LPSTR) TOOL_CHAIN,  (LPSTR) EXPAND_SMALL_PTR,
                     PWRVIEWS_INI_DEFAULT, (LPSTR)smallPtrOption) == GOOD) &&
        (strcmpi(smallPtrOption, SP_ON) == 0))
      ExpandSmallPtr = TRUE;

   return GOOD;
}

/***************************************************************************
**
**  GetSubTypeIndex
**
****************************************************************************/
PRIVATE TYPE_INDEX GetSubTypeIndex(TYPE_INDEX parentType,
                                   U8 *typeStr, U16 *i) {
U16 j;
TYPE_INDEX typeIndex;

  j = (U16)typeStr[(*i)++];
  if (ExtOmf==1) {
    if (j == 0) //Hera 6/13/97 
       typeIndex = (U16)typeStr[(*i)++];
    else {
       U32 typeOffset=0L;

       typeIndex = (j << 8) + typeStr[(*i)++];
       typeOffset = (parentType > typeIndex) ? (parentType - typeIndex) :
                  (typeIndex - parentType);
       if ((parentType > (MAX_TYPE_INDEX - 0x100)) &&
                                          (typeOffset > MAX_TYPE_INDEX/2))
       typeIndex += MAX_TYPE_INDEX + 1L;
    }
  }
  else {
     if (LARGE_INDEX(j)) {
	U32 typeOffset=0L;

        typeIndex = ((j&0x7F) << 8) + typeStr[(*i)++];
        typeOffset = (parentType > typeIndex) ? (parentType - typeIndex) :
                     (typeIndex - parentType);
        if ((parentType > (MAX_TYPE_INDEX - 0x100)) &&
            (typeOffset > MAX_TYPE_INDEX/2))
	   typeIndex += MAX_TYPE_INDEX + 1L;
     }
     else typeIndex = j;
  }
  return(typeIndex);
}  /* GetSubTypeIndex */

/***************************************************************************
**
**  GetTypeLength
**
****************************************************************************/
PRIVATE U32 GetTypeLength( U8 *typeRec, U16 *i ) {
U32 len= 0L;
U8 leaf;
U16 index;

   index = *i;
   leaf = typeRec[index++];
   switch (leaf) {
      case LEAF_U16:   // 0x81
          len = typeRec[index];
          len += (U32)(((U16)typeRec[index+1]) << 8);
          index += 2;
          break;
      case LEAF_U24:   // 0x84
          len = typeRec[index+2];
          len = (U32)(len << 8) + typeRec[index+1];
          len = (U32)(len << 8) + typeRec[index];
          index += 3;
          break;
      default:
          len = (U32)leaf;
          break;
   }
   *i = index;
   return(len);
}  /* GetTypeLength */

/***************************************************************************
**
**  GetValue --Hera 4/9/97
**
****************************************************************************/

PRIVATE U32 GetValue(U8 *typeRec, U16 *i) {
U32 len = 0;
U8 leaf;
U16 index;

   index = *i;
   leaf = typeRec[index++];
   switch(leaf) {
      case LEAF_S8:   // 0x86
          len = (U32)typeRec[index];
          index++;
          break;
      case LEAF_S16:   // 0x87
      case LEAF_U16:   // 0x81
          len = typeRec[index+1];
          len = (U32)((U16)(len << 8) + typeRec[index]);
          index += 2;
	  break;
      case LEAF_U24:   //0x84
	  len = typeRec[index+2];
	  len = (U32)((U16)(len << 8) + typeRec[index+1]);
	  len = (len << 8) + typeRec[index];
          index += 3;
	  break;
      case LEAF_S32: // 0x88
	  len = typeRec[index+3];
	  len = (U32)((U16)(len << 8) + typeRec[index+2]);
	  len = (U32)((len << 8) + typeRec[index+1]);
	  len = (len << 8) + typeRec[index];
	  index += 4;
	  break;
      default:
          len = (U32)leaf;
          break;
   }
   *i = index;
   return(len);
}
/***************************************************************************
**
**  GetSignedInteger
**
****************************************************************************/
/*PRIVATE S16 GetSignedInteger(U8 *typeRec, U16 *i) {
S16 len= 0;
U8 leaf;
U16 index;

   index = *i;
   leaf = typeRec[index++];
   switch (leaf) {
      case LEAF_S8:   // 0x86
          len = typeRec[index];
          index++;
          break;
      case LEAF_S16:   // 0x87
          len = typeRec[index+1];
          len = (S16)((U16)(len << 8) + typeRec[index]);
          index += 2;
          break;
      default:
          len = (S16)leaf;
          break;
   }
   *i = index;
   return(len);
}*/  /* GetSignedInteger */

/***************************************************************************
**
**  GetNumber
**
****************************************************************************/
PRIVATE U32 GetNumber(U8 *typeRec, U16 *i ) {
U32 len= 0L;
U8 leaf;
U16 index;

   index = *i;
   leaf = typeRec[index++];
   // Value between 0 and 128 is a single byte integer number
   if (leaf <= LEAF_NIL) {
      *i = index;
      return(leaf);
   }
   
   switch (leaf) {
      case LEAF_U16:   // 0x81 - Value: 2 bytes (0 to 64K-1)
          len = typeRec[index];
          len += (U32)(((U16)typeRec[index+1]) << 8);
          index += 2;
          break;
      case LEAF_U24:   // 0x84 - Value: 3 bytes (0 to 16M-1)
          len = typeRec[index+2];
          len = (U32)(len << 8) + typeRec[index+1];
          len = (U32)(len << 8) + typeRec[index];
          index += 3;
          break;
      case LEAF_S8:   // 0x86 - Value: 1 byte (-127 to +127)
          len = typeRec[index];
          index++;
          break;
      case LEAF_S16:   // 0x87 - Value: 2 bytes (-32K to +32K)
          len = typeRec[index+1];
          len = (S16)((U16)(len << 8) + typeRec[index]);
          index += 2;
          break;
      case LEAF_S32:   // 0x88 - Value: 4 bytes signed integer
          len = typeRec[index+3];
          len = (U32)(len << 8) + typeRec[index+2];
          len = (U32)(len << 8) + typeRec[index+1];          
          len = (U32)(len << 8) + typeRec[index];
          index += 4;
          break;
      default:
          len = (U32)leaf;
          index += 4;
          break;
   }
   // Update the index
   *i = index;
   return(len);
}  /* GetNumber */

/***************************************************************************
**
**  Name: GetListRecord
**
****************************************************************************/
PRIVATE RETCODE GetListRecord(HANDLE hFile,
                              LIST_TYPE getListType,
                              TYPE_INDEX listType,
                              U8 **listRecord, U16 *leafCnt) {
RETCODE err=GOOD;
TYPE_LIST_BUF *tmpPtr = NULL;
HASH_BUF *hashPtr = NULL;
U32 filePos=0L, oldPos;
OMF86_REC_HEADER recHdr;
U32 endLoc;

  // Select the list to get the requested <listType>
  switch(getListType) {
     case INDEX_LIST:
        tmpPtr = IndexListTail; break;
     case NAME_LIST:
        tmpPtr = NameListTail; break;
     case VALUE_LIST:
        tmpPtr = ValueListTail; break;
  }
  
  // There are list holding the type information.
  // Use them for checking the requested list type.
  if (tmpPtr != NULL) {
     if (tmpPtr->typeDefIndex == listType)
        filePos = tmpPtr->filePtr;
     else if (tmpPtr->typeDefIndex > listType) {
        TYPE_LIST_BUF *oldPtr;
        tmpPtr = oldPtr = NULL;

        // Select the hash list to get the requested <listType>
        switch(getListType) {
           case INDEX_LIST:
              hashPtr = IndexHashBuf; break;
           case NAME_LIST:
              hashPtr = NameHashBuf; break;
           case VALUE_LIST:
              hashPtr = ValueHashBuf; break;
        }
        // search the hash list for start location
        while (hashPtr != NULL) {
           if (hashPtr->typeDefIndex == listType) {
              filePos = hashPtr->listPtr->filePtr;
              break;
           }
           else if (hashPtr->typeDefIndex > listType) {
              tmpPtr = oldPtr;
              break;
           }
           // save the previous hash node to go back
           oldPtr = hashPtr->listPtr;
           hashPtr = hashPtr->next;
        }
        if (!filePos) {
           U16 cnt=0;
           // set the start location to search the list
           if (!tmpPtr) tmpPtr = oldPtr;
           while ((tmpPtr != NULL) && (cnt < LIST_INDEX_OFFSET)) {
              if (tmpPtr->typeDefIndex == listType) {
                 filePos = tmpPtr->filePtr;
                 break;
              }
              cnt++;
              tmpPtr = tmpPtr->next;
           }
        }
     }
  }
  oldPos = CurrentLocation();
  if (filePos > 0L) {
     if (SeekFile( hFile, filePos, SEEK_SET ) == -1L)
        return(ER_BAD_SEEK);
     if ((err=OMFGetBytes(hFile, (U8 *)&recHdr, sizeof(recHdr))) != GOOD)
        goto GET_LIST_END;
     endLoc = CurrentLocation() + recHdr.len;
  }
  else {
     TYPE_INDEX typeDefCnt = TypeIndex;  // The global current TypeIndex
     
     // Move forward to the requested type
     if (listType < typeDefCnt)
        listType += (MAX_TYPE_INDEX+1L); // for types larger than 0x7FFF
     if ((err=Flush(hFile, CurrentLocation()+1L)) != GOOD) // skip checksum
        goto GET_LIST_END;
     while (1) {
        if ((err=OMFGetBytes(hFile, (U8 *)&recHdr, sizeof(recHdr))) != GOOD)
           goto GET_LIST_END;
        endLoc = CurrentLocation() + recHdr.len;
        if (++typeDefCnt == listType)
           break;
        if ((err=Flush(hFile, endLoc)) != GOOD)
           goto GET_LIST_END;
     }
  }
  if (recHdr.type != TYPDEF) {
     err = ER_OMF86_BAD_TYPE_SIGNATURE;
     goto GET_LIST_END;
  }
  
  // Get the LIST record 
  err = GetTYPDEF(hFile, endLoc-1L, leafCnt, listRecord);

GET_LIST_END:
   // Reset the file position to its old location
   if (SeekFile(hFile, oldPos, SEEK_SET ) == -1L) 
      return (err == GOOD) ? ER_BAD_SEEK : err;
   return(err);
} /* GetListRecord */

/***************************************************************************
**
**  Name: GetTypeIndexesFromList
**
****************************************************************************/
PRIVATE RETCODE GetTypeIndexesFromList(HANDLE hFile,
                                       TYPE_INDEX listType,
                                       U32 itemCnt,
                                       TYPE_INDEX **typeIdxList) {
RETCODE err=GOOD;
U8 *listRecord = NULL;
U16 leafCnt=0, i=0;
LOOP_VAR j;
U32 len;
TYPE_INDEX *idxPtr;

  if ((err=GetListRecord(hFile, INDEX_LIST, listType, &listRecord, &leafCnt))
         != GOOD)  goto GET_INDEX_END;
  if ((listRecord == NULL) || (listRecord[i++] != OMF86_LIST)) {
     err = ER_BAD_SEEK;
     goto GET_INDEX_END;
  }
  len = itemCnt*sizeof(TYPE_INDEX);
  if ((*typeIdxList = (TYPE_INDEX *)TMalloc(len)) == NULL) {
     err = ERR_BAD_MEMORY;
     goto GET_INDEX_END;
  }
  idxPtr = *typeIdxList;
  for (j=0; j < itemCnt; j++) {
     if (listRecord[i++] != LEAF_INDEX) {
        err = ER_OMF86_BAD_TYPE_SIGNATURE;
        goto GET_INDEX_END;
     }
     idxPtr[j] = GetSubTypeIndex(listType, listRecord, &i) + TYPE_OFFSET;
     while (!listRecord[i]) i++;
  }
  if (i < leafCnt)
     err = ER_OMF86_BAD_TYPE_SIGNATURE;
  
GET_INDEX_END:
  if (listRecord) TFree((LPSTR)listRecord);
  return(err);
}

/***************************************************************************
**
**  Name: GetNamesFromList
**
****************************************************************************/
PRIVATE RETCODE GetNamesFromList(HANDLE hFile, TYPE_INDEX listType,
                                 U32 itemCnt, CHAR **nameList) {
RETCODE err=GOOD;
U8 *listRecord = NULL;
U16 leafCnt=0, i=0;
LOOP_VAR j;
U32 len;
CHAR *namePtr;

  if ((err=GetListRecord(hFile, NAME_LIST, listType, &listRecord, &leafCnt))
         != GOOD)
     goto GET_NAME_END;
  if ((listRecord == NULL) || (listRecord[i++] != OMF86_LIST)) {
     err = ER_BAD_SEEK;
     goto GET_NAME_END;
  }
  len = itemCnt * NAME_LEN;
  if ((*nameList = (CHAR *)TMalloc(len)) == NULL) {
     err = ERR_BAD_MEMORY;
     goto GET_NAME_END;
  }
  namePtr = *nameList;
  for (j=0; j < itemCnt; j++) {
     if (listRecord[i++] != LEAF_STRING) {
        err = ER_OMF86_BAD_TYPE_SIGNATURE;
        goto GET_NAME_END;
     }
     if ((err= GetTypeName(listRecord, &i, namePtr)) != GOOD)
        goto GET_NAME_END;
     namePtr = (CHAR *)((U32)namePtr+NAME_LEN);
     while (!listRecord[i]) i++;
  }
  if (i < leafCnt)
     err = ER_OMF86_BAD_TYPE_SIGNATURE;
  
GET_NAME_END:
  if (listRecord) TFree((LPSTR)listRecord);
  return(err);
}

/***************************************************************************
**
**  Name: GetTypeName
**
****************************************************************************/
PRIVATE RETCODE GetTypeName( U8 *typeStr, U16 *i, CHAR *name ) {
U16 len; 
U32 j;

   j = GetTypeLength( typeStr, i);
   len = (U16)(j > NAME_LEN ? NAME_LEN : j);
   strncpy( name, (CHAR *)&typeStr[*i], len );
   name[len] = '\0';
   *i += (U16)j;
   return(GOOD);
}  /* GetTypeName */

/***************************************************************************
**
**  Name: ProcessTypeProcedure
**
****************************************************************************/
PRIVATE RETCODE ProcessTypeProcedure(TYPE_PARAM FAR *para) {
U8 c;
U32 attribute;
TYPE_INDEX targetType, listType, *typeIdxList = NULL;
LOOP_VAR j;
CHAR typeName[NAME_LEN+1]="";
RETCODE err = GOOD;
U32 numParam=0;

   if (para->typeRec[para->i++] != LEAF_NIL)
      return(ER_OMF86_BAD_TYPE_SIGNATURE);
   if ((c = para->typeRec[para->i++]) == LEAF_INDEX)
      targetType = GetSubTypeIndex(para->typeIdx, para->typeRec, &(para->i))
                   + TYPE_OFFSET;
   else if (c == LEAF_NIL)
      targetType = BI_VOID;
   else return(ER_OMF86_BAD_TYPE_SIGNATURE);     
   if (((attribute = para->typeRec[para->i++]) != OMF86_LONG_NOPOP) &&
        (attribute != OMF86_SHORT_NOPOP) &&
        (attribute != OMF86_LONG) && (attribute != OMF86_SHORT))
      return(ER_OMF86_BAD_TYPE_SIGNATURE);
   if (para->i < para->recLen)
      numParam = GetTypeLength(para->typeRec,&(para->i));
   /* attribute : 0 : NEAR_16, 1:FAR_16 */
   if (attribute < OMF86_LONG)          /* Phar Lap and LL86 */
      attribute -= OMF86_SHORT_NOPOP;
   else attribute = OMF86_SHORT - attribute;    /* BCTOPROM */
   if ((para->i < para->recLen) && (numParam > 0)) {
      if(para->typeRec[para->i] != LEAF_NIL) { //Hera 4/1/97
      if (para->typeRec[para->i++] != LEAF_INDEX)
         return(ER_OMF86_BAD_TYPE_SIGNATURE);

      listType = GetSubTypeIndex(para->typeIdx, para->typeRec, &(para->i));
      if ((err = GetTypeIndexesFromList(para->hFile, listType, numParam,
                                        &typeIdxList)) != GOOD)
	 goto TYPE_FUNC_END;
      }
   }
   para->typeHdrInfo->t.complexType = TY_FUNC_DEP;
   para->typeHdrInfo->sizeCalculated = TRUE; //size for function doesn't matter
   if (((err=SymAddTypeHeader(para->typeIdx, para->typeHdrInfo)) != GOOD) ||
       (err=SymAddTypeFunc(para->typeIdx, attribute, 0, 0, targetType,
                           (U8)numParam, 0, (LPSTR)typeName)) != GOOD)
      goto TYPE_FUNC_END;
   for (j=0; (j < numParam) && typeIdxList; j++) {
      if ((err=SymAddTypeFuncParam(para->typeIdx, typeIdxList[j])) != GOOD)
         goto TYPE_FUNC_END;
   }
TYPE_FUNC_END:
   if (typeIdxList) TFree((LPSTR)typeIdxList);
   para->i = para->recLen;
   return(err);
}  /* ProcessTypeProcedure */

/***************************************************************************
**
**  Name: ProcessTypeArray
**
**  ARRAY(0x77) (length) @btype
**
**  example :
**  [0017] TYPDEF (8EH)
**         00 00 77 48 83 1F
**         // 0x117 load as TY_C_ARRAY,  sizeMAUs = 6;
**         // element type 0x11F
**
**  Note that highbound might not be available in the loader
**
****************************************************************************/
PRIVATE RETCODE ProcessTypeArray(TYPE_PARAM FAR *para) {
U32 len;
RETCODE err;
TYPE_Z_STRUCT arrayHdrStruct;
CHAR typeName[NAME_LEN+1]="";
TYPE_HEADER_TYPE targetTypeHdr;

   len = GetTypeLength(para->typeRec, &(para->i));
   if (para->typeRec[para->i++] != LEAF_INDEX)
      return(ER_OMF86_BAD_TYPE_SIGNATURE);
   para->typeHdrInfo->sizeInMAUs = len/MAU_BITS;
   arrayHdrStruct.typeIndex = GetSubTypeIndex(para->typeIdx,
                              para->typeRec, &(para->i)) + TYPE_OFFSET;
   /* Get the highbound of the target type */
   targetTypeHdr.typeName = (LPSTR)typeName;
   if ((SymGetTypeHeader(arrayHdrStruct.typeIndex, &targetTypeHdr) == GOOD)
       && (targetTypeHdr.sizeInMAUs > 0)) {
      arrayHdrStruct.highBound = para->typeHdrInfo->sizeInMAUs /
                                 targetTypeHdr.sizeInMAUs - 1;
      para->typeHdrInfo->sizeCalculated = TRUE;
   }
   else arrayHdrStruct.highBound = 0;
   /* Add a new type header for the type and
   ** Add information about its basetype and its boundary
   */
   para->typeHdrInfo->t.complexType = TY_C_ARRAY;
   if (((err=SymAddTypeHeader(para->typeIdx, para->typeHdrInfo)) != GOOD) ||
       ((err=SymAddTypeCArray(para->typeIdx, &arrayHdrStruct)) != GOOD))
      return(err);
   return(GOOD);
}  /* ProcessTypeArray */

/***************************************************************************
**
**  Name: ProcessTypeSU
**
****************************************************************************/
PRIVATE RETCODE ProcessTypeSU(TYPE_PARAM FAR *para) {
RETCODE err = GOOD;
U32 itemCnt;
LOOP_VAR k;
TYPE_INDEX listType;
TYPE_S_U_STRUCT su;
CHAR *nameList = NULL, *namePtr;
TYPE_INDEX *typeIdxList = NULL;
CHAR typeName[NAME_LEN+1];
BOOLEAN offsetValid=TRUE;
U16 *mbrOffsets = NULL, offset=0;
U32 len;

   // Get type MAU and itemCnt
   para->typeHdrInfo->sizeInMAUs =
      GetTypeLength(para->typeRec,&(para->i)) / MAU_BITS;
   itemCnt = GetTypeLength(para->typeRec, &(para->i));
   if (!itemCnt)  /* Union */
      return(ProcessTypeUnion(para));
   /* Process Structure */
   for (k=0; k<2; k++) { /* Get Lists */
      if (para->typeRec[para->i++] != LEAF_INDEX) {
         err=ER_OMF86_BAD_TYPE_SIGNATURE;
         goto TYPE_SU_END;
      }
      listType = GetSubTypeIndex(para->typeIdx, para->typeRec, &(para->i));

      if (typeIdxList == NULL) {
         if ((err = GetTypeIndexesFromList(para->hFile, listType, itemCnt,
                                           &typeIdxList)) != GOOD) {
            if (typeIdxList) TFree((LPSTR)typeIdxList);
            typeIdxList = NULL;
         }
         else continue;
      }
      if (nameList == NULL) {
         if ((err = GetNamesFromList(para->hFile, listType,
                                     itemCnt, &nameList)) != GOOD) {
            if (nameList) TFree((LPSTR)nameList);
            nameList = NULL;
         }
         else continue;
      }
   }
   if ((typeIdxList == NULL) || (nameList == NULL)) {
      err=ER_OMF86_BAD_TYPE_SIGNATURE;
      goto TYPE_SU_END;
   }
   /* Calculate the members' offset */
   len = itemCnt*sizeof(U16);
   if ((mbrOffsets = (U16 *)TMalloc(len)) == NULL)
      goto TYPE_SU_END;
   memset(mbrOffsets, NULL, (U16)len);
   k = 0;
   offset = 0;
   while (offsetValid && (k < itemCnt)) {
     TYPE_HEADER_TYPE targetTypeHdr;

      mbrOffsets[k] = offset;
      targetTypeHdr.typeName = (LPSTR)typeName;
      if (typeIdxList[k] > para->typeIdx)
         offsetValid = FALSE;
      else if (SymGetTypeHeader(typeIdxList[k], &targetTypeHdr) != GOOD)
         offsetValid = FALSE;
      else if (!targetTypeHdr.sizeCalculated)
         offsetValid = FALSE;
      else {
         // 08/04/95 - Typecast to U16 to fix compiler warning
         offset += (U16)targetTypeHdr.sizeInMAUs;
      }
      k++;
   }
   if (offsetValid)
      para->typeHdrInfo->sizeCalculated = TRUE;

   if (para->i >= para->recLen)  /* PL/M type */
      *typeName = NULL;
   else {                        /* C type */
      if (para->typeRec[para->i++] != LEAF_STRING) {
         err=ER_OMF86_BAD_TYPE_SIGNATURE;
         goto TYPE_SU_END;
      }
      if ((err=GetTypeName(para->typeRec, &(para->i), (CHAR *)typeName)) != GOOD)
         goto TYPE_SU_END;
   }
   para->typeHdrInfo->t.complexType = TY_STRUCT ;
   para->typeHdrInfo->typeName = (LPSTR)typeName;
   if ((err=SymAddTypeHeader(para->typeIdx, para->typeHdrInfo)) != GOOD)
      return(err);
   namePtr = nameList;
   for (k=0; k < itemCnt; k++) {
      CHAR *pname="";
      su.typeIndex = typeIdxList[k];
      if ((*namePtr != '\0') && IsDeMangle(para->flags))
         LdrCppFixupMember((LPSTR)namePtr, (LPSTR *)&pname);
      else if (namePtr != NULL)
         pname = namePtr;
      else {
         err=ER_OMF86_BAD_TYPE_SIGNATURE;
         goto TYPE_SU_END;
      }
      su.name = (LPSTR)pname;
      su.offset = mbrOffsets[k];
      if ((err=SymAddTypeStructUnion(para->typeIdx, &su)) != GOOD)
         goto TYPE_SU_END;
      namePtr = (CHAR *)((U32)namePtr+NAME_LEN);
   }
TYPE_SU_END:
   if (typeIdxList) TFree((LPSTR)typeIdxList);
   if (nameList) TFree((LPSTR)nameList);
   if (mbrOffsets) TFree((LPSTR)mbrOffsets);
   return(err);
}  /* ProcessTypeSU */

/***************************************************************************
**
**  Name: ProcessTypeUnion
**
**  STRUCTURE(0x79) length 0 NIL(0x80) NIL(0x80) nameTag UNPACKED(0x66) -->
**  count NIL NIL -->
**  1 @tlist1 @nlist1 --> 
**  1 @tlist2 @nlist2 -->
**     .........
**  1 @tlistn @nlistn -->
**
**  NOTES: 03/08/95 - Nghia
**  Supports BC and MSVC Union type, which has a different format.  
** 
**     1 @tlist1 @nlist1 -->  
**     1 @tlist2 @nlist2 -->  
**     .........
**     1 @tlistn @nlistn -->
**  STRUCTURE(0x79) length 0 NIL(0x80) NIL(0x80) nameTag UNPACKED(0x66) -->
**     0 0 NIL(0x80) NIL(0x80)
**
**  {Notes: the members' lists usually appear before the union type, but
**  it also possible to appear after the union type as well. For BC, we
**  assume that the list is appears before the type.}
**
**  example:
**   
**      TYPDEF   51: 
**      00 00 7F 83 03                                     .....
**      7F: -list- 83: Typdef #3
**      TYPDEF   52: 
**      00 00 7F 82 02 49 30                               .....I0
**      7F: -list- 82: "I0"
**      TYPDEF   53: 
**      00 00 7F 83 3A                                     ....:
**      7F: -list- 83: Typdef #58
**      TYPDEF   54: 
**      00 00 7F 82 02 49 31                               .....I1
**      7F: -list- 82: "I1"
**      TYPDEF   55: 
**      00 00 7F 83 3C                                     ....<
**      7F: -list- 83: Typdef #60
**      TYPDEF   56: 
**      00 00 7F 82 06 50 55 6E  69 6F 6E                  .....PUn|ion
**      7F: -list- 82: "PUnion"
**      TYPDEF   57: 
**      00 00 79 50 00 80 80 82  06 41 55 6E 54 61 67 66   ..yP....|.AUnTagf
**      00 00 80 80                                        ....
**      79: -structure-, Length=80 bit(s) = 10 byte(s), 0 elements
**      80: -null-
**      80: -null-
**      82: "AUnTag"
**      66: -unpacked-
**       0: Length=0 bit(s) = 0 byte(s)
**       0: Length=0 bit(s) = 0 byte(s)
**      80: -null-
**      80: -null-
**
****************************************************************************/
PRIVATE RETCODE ProcessTypeUnion(TYPE_PARAM FAR *para) {
RETCODE err;
LOOP_VAR j;
CHAR typeName[NAME_LEN+1];
U32 itemCnt;
TYPE_S_U_STRUCT su;

   // Process bytes: <LEAF_NIL-0x80> <LEAF_NIL-0x80> <nameTag-0x82"..."> 
   if (para->typeRec[para->i++] != LEAF_NIL ||  
       para->typeRec[para->i++] != LEAF_NIL ||  
       para->typeRec[para->i++] != LEAF_STRING) 
      return(ER_OMF86_BAD_TYPE_SIGNATURE);
   if ((err=GetTypeName(para->typeRec, &(para->i), typeName)) != GOOD)
      return(err);
   // Process byte: <UNPACKED-0x66>
   if (para->typeRec[para->i++] != OMF86_UNPACKED) 
      return(ER_OMF86_BAD_TYPE_SIGNATURE);
   
   // NOTES: 03/08/95 - Nghia
   // There are two different formats to process.  Use (<count> == 0)
   // as an indicator to process the record differently.
   // Metaware: <count> <LEAF_NIL-0x80> <LEAF_NIL-0x80> 
   // BC/MS:    <0> <0> <LEAF_NIL-0x80> <LEAF_NIL-0x80>
   itemCnt = GetTypeLength(para->typeRec, &(para->i));
   while (!para->typeRec[para->i]) para->i++;
   if ((para->typeRec[para->i++] != LEAF_NIL) ||
       (para->typeRec[para->i++] != LEAF_NIL))
      return(ER_OMF86_BAD_TYPE_SIGNATURE);
   
   para->typeHdrInfo->t.complexType = TY_UNION;
   para->typeHdrInfo->typeName = (LPSTR)typeName;
   
   // Load the UNION header information
   if ((err=SymAddTypeHeader(para->typeIdx, para->typeHdrInfo)) != GOOD)
      return(err);
   
   // All union member are offset at 0L
   su.offset=0;
   CHAR *nameList = NULL;
   TYPE_INDEX *typeIdxList = NULL;
   TYPE_INDEX listType;
   CHAR *pname="";
   BOOLEAN memberLoaded = FALSE;
   TYPE_INDEX parentType = para->typeIdx - TYPE_OFFSET;
   
   // NOTES: For BC/MS tool chains, the member's type index and name lists
   // can appear before/after the Union type itself.
   // IMPORTANT: Only handle lists appeared before the union type for now.
   if (!itemCnt) {
      if (!IndexListCnt) {
         // The union members list are appeared after the Union type itself
         // NOT IMPLEMENTED:
         goto MEMBER_LOAD_ERR;
      }
      
      // Use the saved firstListTypeIndex if available, else backup in the
      // list to look for the members' list types
      if (!firstListTypeIndex) {
         // Backup thru the IndexListBuf until error occurs, which
         // indicates that we just pass over the 1st member type index
         // Start at the unionType index - 2. Need to offset the TYPE_OFFSET
         listType = parentType - 2;
         while ((listType > 0) &&
                (GetTypeIndexesFromList(para->hFile, listType, 1L,
                                        &typeIdxList) == GOOD)) {
            // Order of list types = [1 @typelist1 @namelist1....]
            // Index List is offset by 2 from the union type index.
            TFree((LPSTR) typeIdxList);
            listType -= 2;
         }
         // Restore to the last known good list type index
         listType += 2;         
      } else {
         listType = firstListTypeIndex;
         firstListTypeIndex = 0L;  // reset for the next first list index
      }
      
      // Loop through the all type index and name lists to add union members.
      // Go forward until listType = unionType.
      while ((listType < parentType) && (err == GOOD)) {
         // Rely on the GetTypeIndexesFromList() to handle extracting
         // the 1 type index in the IndexListBuf.  If error occurs
         // then we are done
         if (((err = GetTypeIndexesFromList(para->hFile, listType++, 1L,
                                           &typeIdxList)) != GOOD) ||
             ((err = GetNamesFromList(para->hFile, listType++, 1L,
                                     &nameList)) != GOOD)) {
            if (typeIdxList) TFree((LPSTR)typeIdxList);
            if (nameList) TFree((LPSTR)nameList);
            // This means we are done which the members. Exit
            err = GOOD;
            break;  // exit do-while
         }
         // Setup the union member type information
         if ((*nameList != '\0') && IsDeMangle(para->flags)) {
            LdrCppFixupMember((LPSTR)nameList, (LPSTR *)&pname);
         } else if (nameList != NULL) {
            pname = nameList;
         } else {
            err=ER_OMF86_BAD_TYPE_SIGNATURE;
            goto TYPE_UNION_LOOP_END1;
         }
         // Load the Union member
         su.typeIndex = typeIdxList[0];
         su.name = (LPSTR)pname;
         err = SymAddTypeStructUnion(para->typeIdx, &su);
         memberLoaded = TRUE;
TYPE_UNION_LOOP_END1:
         // Free the allocated memory
         if (typeIdxList) { TFree((LPSTR)typeIdxList); typeIdxList = NULL; }
         if (nameList) { TFree((LPSTR)nameList); nameList = NULL; }
      } // while
      
      if (!memberLoaded) {
MEMBER_LOAD_ERR:         
         // Make sure that union has a member 
         su.typeIndex = TY_VOID;
         su.name = (LPSTR)UnknownTypeName;
         SymAddTypeStructUnion(para->typeIdx, &su);
         return ER_OMF86_BAD_TYPE_SIGNATURE;
      }
   } else {
      // NOTES: For Metaware HC toolchain
      // Union type had number of members
      for (j=0; (j < itemCnt) && (err == GOOD); j++)  {
         while (!para->typeRec[para->i]) para->i++;
         if (para->typeRec[para->i++] != 0x01)
            return(ER_OMF86_BAD_TYPE_SIGNATURE);
         while (!para->typeRec[para->i]) para->i++;
         if (para->typeRec[para->i++] != LEAF_INDEX)
            return(ER_OMF86_BAD_TYPE_SIGNATURE);
         listType = GetSubTypeIndex(para->typeIdx, para->typeRec, &(para->i));
         if ((err = GetTypeIndexesFromList(para->hFile, listType, 1L,
                                           &typeIdxList)) != GOOD)
            goto TYPE_UNION_LOOP_END2;
         while (!para->typeRec[para->i]) para->i++;
         if (para->typeRec[para->i++] != LEAF_INDEX) {
            err=ER_OMF86_BAD_TYPE_SIGNATURE;
            goto TYPE_UNION_LOOP_END2;
         }
         listType = GetSubTypeIndex(para->typeIdx, para->typeRec, &(para->i));
         if ((err = GetNamesFromList(para->hFile, listType, 1L,
                                     &nameList)) != GOOD)
            goto TYPE_UNION_LOOP_END2;
         su.typeIndex = typeIdxList[0];
         if ((*nameList != '\0') && IsDeMangle(para->flags))
            LdrCppFixupMember((LPSTR)nameList, (LPSTR *)&pname);
         else if (nameList != NULL)
            pname = nameList;
         else {
            err=ER_OMF86_BAD_TYPE_SIGNATURE;
            goto TYPE_UNION_LOOP_END2;
         }
         // Load the Union member
         su.name = (LPSTR)pname;
         err = SymAddTypeStructUnion(para->typeIdx, &su);
TYPE_UNION_LOOP_END2:
         // Free the alocated memory
         if (typeIdxList) { TFree((LPSTR)typeIdxList); typeIdxList = NULL; }
         if (nameList) { TFree((LPSTR)nameList); nameList = NULL; }
      } // for
   } // else
   
   return(err);
}  /* ProcessTypeUnion */

/***************************************************************************
**
**  Name: ProcessTypeTypeIndex
**
**  CONST(0x6F)      @type
**  PARAMETER(0x75)  @type
**  POINTER(0x7A)    @type
**  POINTER(0x7A)               // PL/M
**  SELECTOR(0x62)              // PL/M
**
**
**  eg.1 :
**  [0020] TYPDEF (8EH)
**         00 00 7A 83 1A
**         // 0x120 load as TY_TYPE, sizeMAUs = 0 of type 0x11A
**  eg.2 :
**  [004A] TYPDEF (8EH)
**         00 00 75 83 05
**         // 0x14A load as TY_TYPE, sizeMAUs = 0 of type 0x105
**  eg.3 :
**  [0050] TYPDEF (8EH)
**         00 00 7A
**         // 0x150 load as TY_VOID
**
****************************************************************************/
PRIVATE RETCODE ProcessTypeTypeIndex(TYPE_PARAM FAR *para)
{
RETCODE err;
TYPE_INDEX targetType;
TYPE_HEADER_TYPE baseTypeHdr;
CHAR typeName[NAME_LEN+1] = "";

   if (para->i >= para->recLen) { /* PL/M POINTER and SELECTOR */
      strcpy(typeName, "void");
      para->typeHdrInfo->typeName = (LPSTR)typeName;
      para->typeHdrInfo->sizeCalculated = TRUE;
      para->typeHdrInfo->t.complexType = TY_VOID;
      return(SymAddTypeHeader(para->typeIdx, para->typeHdrInfo));
   }
   if (para->typeRec[para->i++] != LEAF_INDEX)
      return(ER_OMF86_BAD_TYPE_SIGNATURE);
   targetType = GetSubTypeIndex(para->typeIdx, para->typeRec, &(para->i)) +
                TYPE_OFFSET;
   baseTypeHdr.typeName = (LPSTR)typeName;
   if (SymGetTypeHeader(targetType, &baseTypeHdr) == GOOD) {
      para->typeHdrInfo->sizeInMAUs = baseTypeHdr.sizeInMAUs;
      if (typeName[0] != '\0')
         para->typeHdrInfo->sizeCalculated = TRUE;
   }
   para->typeHdrInfo->t.complexType  = TY_TYPE;
   if (((err=SymAddTypeHeader(para->typeIdx, para->typeHdrInfo)) != GOOD) ||
       (err=SymAddTypeTypeIndex(para->typeIdx, targetType)) != GOOD)
      return(err);
   return(GOOD);
}  /* ProcessTypeTypeIndex */

/***************************************************************************
**
**  Name: ProcessTypeScalar
**
**  . Scalar : SCALAR [0x7B] (length) (SGNINT/UNSINT/REAL)
**         2 : BI_S8_SCHAR    3 : BI_U8_UCHAR
**         4 : BI_S16_SINT    5 : BI_U16_UNIT
**         6 : BI_S32_SLONG   7 : BI_U32_ULONG
**         8 : BI_S64_SLONG   9 : BI_U64_ULONG
**        10 : BI_F32        11 : BI_F64
**        12 : BI_F_EXTEND   13 : BI_F128
**        25 : BI_F64_BCD (length is 48 for Borland C++)
**
**  . Pointer    : SCALAR [0x7B] (length) @pointer
**
**  . Bit field  : SCALAR [0x7B] (length) (SGNINT/UNSINT) name INTEGER
**
**  . Enumerated : SCALAR [0x7B] 16 (SGNINT/UNSINT) tagname @name @values members
**                 SCALAR [0x7B]  8 (SGNINT) tagname @name lbnd ubnd (Metaware)
**
****************************************************************************/
PRIVATE RETCODE ProcessTypeScalar(TYPE_PARAM FAR *para) {
U32 len;
TYPE_INDEX  buildInType;
RETCODE err;
LOOP_VAR k;
U8 c;
STATIC U16 realLen[] = { 32, 64, 80, 128};
CHAR typeName[NAME_LEN+1] = "";
STATIC BUILT_IN_TYPE scalarType[]={ BI_U8_UCHAR, BI_U16_UINT, BI_U32_ULONG,
                                    BI_UNKNOWN,  BI_U64_ULONG };

   len = GetTypeLength(para->typeRec, &(para->i));
   if ((len == 0L) || (len % MAU_BITS))
      return(ProcessTypeBitField(para, len));
   if (((c = para->typeRec[para->i++]) >= OMF86_UNSINT) &&
        (c <= OMF86_REAL) && (len >= LEN_MINSCALAR) &&
        (len <= LEN_MAXSCALAR)) {
      if (c != OMF86_REAL) {
         if (para->i < para->recLen) {
            if (para->typeRec[para->i++] != LEAF_STRING)
               return(ER_OMF86_BAD_TYPE_SIGNATURE);
            if ((err=GetTypeName(para->typeRec, &(para->i), typeName)) != GOOD)
               return(err);
	    para->typeHdrInfo->typeName = (LPSTR)typeName;

	    if(para->typeRec[para->i] == LEAF_INDEX) //**Hera 10/4/96**//
               if ((para->i < para->recLen) &&
                  ((len == LEN_SHORT) ||(len == LEN_MINSCALAR)) &&
                  ((c==OMF86_SGNINT) || (c==OMF86_UNSINT)))
		    return(ProcessTypeEnum(para));
         }
         if (len > LEN_MAXINTEGER)
            return(ER_OMF86_BAD_TYPE_SIGNATURE);
         /* buildInType is one of the followings :   */
         /* 2 : BI_S8_SCHAR    3 : BI_U8_UCHAR       */
         /* 4 : BI_S16_SINT    5 : BI_U16_UNIT       */
         /* 6 : BI_S32_SLONG   7 : BI_U32_ULONG      */
         /* 8 : BI_S64_SLONG   9 : BI_U64_ULONG      */
         buildInType = (TYPE_INDEX)(OMF86_UNSINT +
                                    scalarType[(U16)len/LEN_SHORT] - c);
      }
      else { /* floating point types */
         BOOLEAN found = FALSE;

         if (len < LEN_MIN_REAL)
            return(ER_OMF86_BAD_TYPE_SIGNATURE);
         if (len == 0x30) { // BCD type for Borland C++
            buildInType = BI_F64_BCD;
            found = TRUE;
         }
         else {
            for (k=0; k < sizeof(realLen)/sizeof(U16); k++) {
               if (realLen[k] == len) {
                  /* buildInType is one of the followings :   */
                  /* 10 : BI_F32       11 : BI_F64            */
                  /* 12 : BI_F_EXTEND  13 : BI_F128           */
                  buildInType = BI_F32 + k;
                  found = TRUE;
               }
            } /* for */
         }
         if (!found)
            return(ER_OMF86_BAD_TYPE_SIGNATURE);
      }
      para->typeHdrInfo->sizeInMAUs = len/MAU_BITS;
      para->typeHdrInfo->t.complexType = TY_TYPE;
      if (((err=SymAddTypeHeader(para->typeIdx, para->typeHdrInfo)) != GOOD) ||
           (err=SymAddTypeTypeIndex(para->typeIdx, buildInType)) != GOOD)
         return(err);
   }
   else if (c == LEAF_INDEX) { /* pointer types */
      if ((err=ProcessTypePointer(para, len)) != GOOD)
         return(err);
   }
   else if(c == OMF86_CONST) return(GOOD); //Hera 4/1/97
   else return(ER_OMF86_BAD_TYPE_SIGNATURE);
   return(GOOD);
}  /* ProcessTypeScalar */

/***************************************************************************
**
**  Name: ProcessTypeList
**
**  LIST(0x7F) leafNodes...
**             (3 types: index = 0x83, string = 0x82, value = 0x87)
**  
**  NOTES: 
**     Store the list type information (type and file position)
**     into global list(s) for later accessing.
**     [From Nghia]
**     Each list type: index, name, or value is chained together with
**     its <X>ListBuff.  The <X>ListTail is the tail of the <X>ListBuff.
**     For each LIST_INDEX_OFFSET:128 nodes, there will be a hash node,
**     which chained to the <X>HashBuff and pointed to the <X>list node.
**     The hash list is used in searching the list type.
**
****************************************************************************/
PRIVATE RETCODE ProcessTypeList(TYPE_PARAM FAR *para) {
RETCODE err = GOOD;
LIST_TYPE listType;
TYPE_LIST_BUF *tmpPtr = NULL, *tmpListTail=NULL;
HASH_BUF *hashPtr=NULL, *tmpIndexTail=NULL;
U32 listCnt=0L;
    
   // Get the type of list type
   listType = (LIST_TYPE)para->typeRec[para->i++];
   switch(listType) {
      case INDEX_LIST: // LEAF_INDEX - 0x83
         if (!IndexListBuf || !IndexHashBuf) {
            if ((err = CreateListBuffer(&IndexListBuf,&IndexHashBuf))!= GOOD) {
               FreeListBuffer(listType);
               return err;
            }
            tmpPtr = IndexListTail = IndexListBuf;
            hashPtr = IndexHashTail = IndexHashBuf;
         }
         tmpListTail = IndexListTail;
         tmpIndexTail = IndexHashTail;
         listCnt = IndexListCnt;
         break;

      case NAME_LIST: // LEAF_STRING - 0x82
         if (!NameListBuf || !NameHashBuf) {
            if ((err = CreateListBuffer(&NameListBuf, &NameHashBuf)) != GOOD) {
               FreeListBuffer(listType);
               return err;
            } 
            tmpPtr = NameListTail = NameListBuf;
            hashPtr = NameHashTail = NameHashBuf;
         }
         tmpListTail = NameListTail;
         tmpIndexTail = NameHashTail;
         listCnt = NameListCnt;
	 break;

      default: //Hera 4/10/97
         if (listType > LEAF_S32)
            return(ER_OMF86_BAD_TYPE_SIGNATURE);
         else {
            if (!ValueListBuf || !ValueHashBuf) {
               if ((err = CreateListBuffer(&ValueListBuf,&ValueHashBuf)) != GOOD){
                  FreeListBuffer(listType);
                  return err;
               }
               tmpPtr = ValueListTail = ValueListBuf;
               hashPtr = ValueHashTail = ValueHashBuf;
            }
            tmpListTail = ValueListTail;
            tmpIndexTail = ValueHashTail;
            listCnt = ValueListCnt;
         }
	 break;
     /* case VALUE_LIST: // LEAF_S16 - 0x87
         if (!ValueListBuf || !ValueHashBuf) {
            if ((err = CreateListBuffer(&ValueListBuf,&ValueHashBuf)) != GOOD){
               FreeListBuffer(listType);
               return err;
            }
            tmpPtr = ValueListTail = ValueListBuf;
            hashPtr = ValueHashTail = ValueHashBuf;
         }
         tmpListTail = ValueListTail;
         tmpIndexTail = ValueHashTail;
         listCnt = ValueListCnt;
         break;
       
      default:
         // Bad list type
         if (para->i > para->recLen) return(GOOD);
         return(ER_OMF86_BAD_TYPE_SIGNATURE);*/
   } // switch

   // 03/08/95 - Nghia
   // Allocate new node of LIST_TYPE and connect to its lists.
   // The following code genericly handles all three types of list.
   if (!tmpPtr) {
      // Check for index list tail_pointer first to avoid
      // allocate memory for the tmpPtr.
      if (tmpListTail == NULL) {
         FreeListBuffer(listType);
         return(ER_OMF86_BAD_TYPE_SIGNATURE);
      }
      if ((tmpPtr=(TYPE_LIST_BUF *)TMalloc(sizeof(TYPE_LIST_BUF))) == NULL) {
         FreeListBuffer(listType);
         return(ER_NO_MEMORY);
      }
      memset(tmpPtr, NULL, sizeof(TYPE_LIST_BUF));
      tmpListTail->next = tmpPtr;
   }
   // Store the list type information for later accessing
   // TYPE_LIST_BUF: tmpPtr->(typeIndex, filePtr)
   tmpPtr->typeDefIndex = TypeIndex;  // global TypeIndex (without offset)
   tmpPtr->filePtr = CurrentLocation() -
                     para->recLen - sizeof(OMF86_REC_HEADER) - 2;
   
   // Create a hash index for every LIST_INDEX_OFFSET
   if (!hashPtr && (listCnt > 0L) && !(listCnt % LIST_INDEX_OFFSET)) {
      // Check for hash list tail_pointer first to avoid
      // allocate memory for the hashPtr.
      if (tmpIndexTail == NULL) {
         FreeListBuffer(listType);
         return(ER_OMF86_BAD_TYPE_SIGNATURE);
      }
      if ((hashPtr=(HASH_BUF *)TMalloc(sizeof(HASH_BUF))) == NULL) {
         FreeListBuffer(listType);
         return(ER_NO_MEMORY);
      }
      memset(hashPtr, NULL, sizeof(HASH_BUF));
      //chain the hash node to the list
      tmpIndexTail->next = hashPtr;
   }
   
   if (hashPtr) {
      hashPtr->typeDefIndex = TypeIndex;
      hashPtr->listPtr      = tmpPtr;
   }
   
   // Set the list tail_pointer to the new node and
   // update the tail of hash list
   switch(listType) {
      case INDEX_LIST:
         IndexListTail = tmpPtr;
         if (hashPtr)
            IndexHashTail = hashPtr; 
         IndexListCnt++;
         break;
      case NAME_LIST:
         NameListTail = tmpPtr;
         if (hashPtr)
            NameHashTail = hashPtr;
         NameListCnt++;
	 break;
      default: //Hera 4/10/97
         ValueListTail = tmpPtr;
         if (hashPtr)
            ValueHashTail = hashPtr;
         ValueListCnt++;
	 break;
      /*case VALUE_LIST:
         ValueListTail = tmpPtr;
         if (hashPtr)
            ValueHashTail = hashPtr;
         ValueListCnt++;
         break;*/
   } // switch
   
   // done saving the list for later processing
   para->i = para->recLen;

   return(err);
}  /* ProcessTypeList */

/***************************************************************************
**
**  Name: ProcessTypePointer
**
**  Pointer types have the form :
**  SCALAR   length  @pointer
**  POINTER  @type
**
**  example :
**  [0019] TYPDEF (8EH)
**         00 00 7B 20 83 20
**         // 0x119 load as pointer type, sizeMAUs = 4 and
**         // typeHdrInfo.t.complexType = TY_16_16_PTR, with the pointed-to
**         // type 0x120.
**
**  [0020] TYPDEF (8EH)
**         00 00 7A 83 1A
**         // 0x120 load as TY_TYPE, sizeMAUs = 0 of type 0x11A
**
****************************************************************************/
PRIVATE RETCODE ProcessTypePointer(TYPE_PARAM FAR *para, U32 len) {
TYPE_INDEX targetType;
RETCODE err;

   targetType = GetSubTypeIndex(para->typeIdx, para->typeRec, &(para->i)) +
                TYPE_OFFSET;
   if (len == BITS_16_16)
      para->typeHdrInfo->t.complexType = TY_16_16_PTR;
   else if (len == BITS_OFFSET) {
      if (!ExpandSmallPtr)
         para->typeHdrInfo->t.complexType = TY_SMALL_PTR;
      else {
         para->typeHdrInfo->t.complexType = TY_16_16_PTR;
         len = BITS_16_16;
      }
   }
   else return(ER_OMF86_BAD_TYPE_SIGNATURE);
   para->typeHdrInfo->sizeInMAUs = len/MAU_BITS;
   para->typeHdrInfo->sizeCalculated = TRUE;
   if (((err=SymAddTypeHeader(para->typeIdx, para->typeHdrInfo)) != GOOD) ||
       (err=SymAddTypePointerTypeIndex(para->typeIdx, targetType)) != GOOD)
      return(err);
   return(GOOD);
}  /* ProcessTypePointer */

/***************************************************************************
**
**  Name: ProcessTypeVoid
**
****************************************************************************/
PRIVATE RETCODE ProcessTypeVoid(TYPE_PARAM FAR *para) {
CHAR typeName[NAME_LEN+1] = "void";

   para->typeHdrInfo->t.complexType = TY_VOID;
   para->typeHdrInfo->sizeInMAUs = 1;
   para->typeHdrInfo->sizeCalculated = TRUE;
   para->typeHdrInfo->typeName = (LPSTR)typeName;
   return(SymAddTypeHeader(para->typeIdx, para->typeHdrInfo));
}  /* ProcessTypeVoid */

/***************************************************************************
**
**  Name: ProcessTypeEnum
**
**  SCALAR(0x7B) 16 SGNINT tagname @name @values members
**
**  example:
**
**  [0084] TYPDEF (8EH)
**         00 00 7B 10 7D 82 03 44 41 59 83 80 83 86 00 86 06
**         // 0x184 load as TY_ENUM_C type, sizeMAUs = 2
**         // type name = DAY, @name [0083] memberValue = 0 - 6.
**  [0083] TYPDEF (8EH)
**         00 00 7F 82 08 73 61 74 75 72 64 61 79 82 06 73   *.....saturday..s*
**         75 6E 64 61 79 82 06 6D 6F 6E 64 61 79 82 07 74   *unday..monday..t*
**         75 65 73 64 61 79 82 09 77 65 64 6E 65 73 64 61   *uesday..wednesda*
**         79 82 07 74 68 75 72 64 61 79 82 06 66 72 69 64   *y..thurday..frid*
**         61 79                                             *ay*
**
**  NOTES: 08/03/95 - Nghia
**     BC and MSVC tool chains supports.
**     When Enumerate type members had values other than the default,
**     There will be a Numeric List following the Name List to describe
**     the user defined enumerate member values.
**
**  example:
**
**  [020F] TYPDEF (8EH) 
**      00 00 7F 82 05 70 65 6E 6E 79 82 06 6E 69 63 6B   .....pen|ny..nick
**      6C 65 82 04 64 69 6D 65 82 06 64 6F 6C 6C 61 72   le..dime|..dollar
**      7F: -list- 82: "penny" 82: "nickle" 82: "dime"
**      82: "dollar"
**  [0210] TYPDEF (8EH) 
**      00 00 7F 87 01 00 87 05 00 87 0A 00 87 64 00      ........|.....d.
**      7F: -list- 87: 1 bits 87: 5 bits 87: 10 bits
**      87: 100 bits.
**  [0211] TYPDEF (8EH) 
**      00 00 7B 10 7D 82 06 4D 6F 6E 65 79 73 83 82 0F   ..{.}..M|oneys...
**      01 64                                              .d
**      7B: -scalar-
**      10: Length=16 bit(s) = 2 byte(s)
**      7D: -signed integer-
**      82: "Moneys"
**      83: Typdef #20F
**       1: lowLimit
**      64: upperLimit
**
**  NOTES : 03/27/96 - Joyce
**  Metaware High C : size - signed char, and the rest is same as BC and MSVC
**  SCALAR [0x7B]  8 (SGNINT) tagname @name lbnd ubnd (Metaware)
**
******************************************************************************/
PRIVATE RETCODE ProcessTypeEnum(TYPE_PARAM FAR *para) {
RETCODE err = GOOD;
TYPE_INDEX listType;
U16 i = 0, j = 0;
S16 min, max ,mbrTemp;//, mbrValue;
U32 mbrValue;
U16 nameListLen = 0, valueListLen = 0;
CHAR nameStr[NAME_LEN+1] = "";
U8 *nameList = NULL, *valueList = NULL;
BOOLEAN useDefaultValue = FALSE;

   if (para->typeRec[para->i++] != LEAF_INDEX)
      return(ER_OMF86_BAD_TYPE_SIGNATURE);

   listType = GetSubTypeIndex(para->typeIdx, para->typeRec, &(para->i));
   min = (S16)GetNumber(para->typeRec, &(para->i));
   max = (S16)GetNumber(para->typeRec, &(para->i));
   
   // NOTES: 03/08/95 - Nghia
   // min and max are the value of the first and last enumerate members.
   // Which do not represent the number of members.
   //
   // Get the enum member names list 
   if ((err = GetListRecord(para->hFile, NAME_LIST, listType,
                            &nameList, &nameListLen)) != GOOD)
      goto TYPE_ENUM_END;
   if ((nameList == NULL) || (nameList[i++] != OMF86_LIST)) {
     err = ER_OMF86_BAD_TYPE_SIGNATURE;
     goto TYPE_ENUM_END;
   }
   // Get the member value list. MIGHT NOT EXIST
   // NOTES: It might be the next index type from the name index type.
   if (((err = GetListRecord(para->hFile, VALUE_LIST, listType+1,
                            &valueList, &valueListLen)) != GOOD) ||
       (valueList == NULL) || (valueList[j++] != OMF86_LIST)) {
      // There is no value list, use the default value from <min> to <max>
      useDefaultValue = TRUE;
      if (valueList) {
         TFree((LPSTR)valueList); valueList = NULL;
      }
   }
   // Load the ENUM header type information
   para->typeHdrInfo->t.complexType = TY_ENUM_C;
   para->typeHdrInfo->sizeInMAUs = 2; // default to <signed int> type
   para->typeHdrInfo->sizeCalculated = TRUE;
   if ((err = SymAddTypeHeader(para->typeIdx, para->typeHdrInfo)) != GOOD)
      goto TYPE_ENUM_END;
   
   if (useDefaultValue) //mbrValue = min;
      mbrTemp = min-1;
   // Load all member in the nameList[]
   while (i < nameListLen) {
      // check the nameList[] for LEAF_STRING
      if (nameList[i++] != LEAF_STRING) {
         err = ER_OMF86_BAD_TYPE_SIGNATURE;
         break; // to TYPE_ENUM_END;
      }
      // Get the member name - <i> is updated by GetTypeName().
      if ((err = GetTypeName(nameList, &i, nameStr)) != GOOD)
         break; // to TYPE_ENUM_END;
      // skip over <nil> name
      while ((!nameList[i]) && (i < nameListLen))  
         i++;

      // Get the member value - <j> is updated by GetSignedInteger()
      if ((!useDefaultValue) && (j < valueListLen)) 
	 //mbrValue = GetSignedInteger(valueList, &j);
         mbrValue = GetValue(valueList, &j);//Hera 4/9/97
      else {
         // Increment the member value by 1, guard against the max value
	 //mbrValue += ((mbrValue < max) ? 1 : 0);
	 mbrTemp += ((mbrTemp < max) ? 1 : 0);
	 mbrValue = (U32)mbrTemp;
      }
      
      // Load the ENUM member
      if ((err = SymAddTypeEnum(para->typeIdx, mbrValue, nameStr)) != GOOD)
         break; // TYPE_ENUM_END;
   }
   
TYPE_ENUM_END:
   // Clean up the allocated list records
   if (nameList) TFree((LPSTR)nameList);
   if (valueList) TFree((LPSTR)valueList);
   return(err);
}  /* ProcessTypeEnum */

/***************************************************************************
**
**  Name: ProcessTypeBitField
**
****************************************************************************/
PRIVATE RETCODE ProcessTypeBitField(TYPE_PARAM FAR *para, U32 len) {
TYPE_BITFIELD_STRUCT bfHdrStruct;
TYPE_HEADER_TYPE baseTypeHdr;
CHAR typeName[NAME_LEN+1] = "";
U8 c;

   if (((c = para->typeRec[para->i++]) != OMF86_UNSINT) && (c != OMF86_SGNINT))
      return(ER_OMF86_BAD_TYPE_SIGNATURE);
   bfHdrStruct.bitfieldSigned = c - OMF86_UNSINT;
   bfHdrStruct.size = (U16)len;
   bfHdrStruct.baseTypeIndex = BI_STACK_U; /* default unsigned */
   baseTypeHdr.typeName = (LPSTR)typeName;
   if (SymGetTypeHeader(bfHdrStruct.baseTypeIndex, &baseTypeHdr) == GOOD) {
      para->typeHdrInfo->sizeInMAUs = baseTypeHdr.sizeInMAUs;
      para->typeHdrInfo->sizeCalculated = TRUE;
   }
   para->typeHdrInfo->t.complexType = TY_BITFIELD;
   /* Add a new type header for the type and its underlying info */
   if ((SymAddTypeHeader(para->typeIdx, para->typeHdrInfo) != GOOD) ||
       (SymAddTypeBitfield(para->typeIdx, &bfHdrStruct) != GOOD))
      return(ER_SYM_TYPE);
   return(GOOD);
}  /* ProcessTypeBitField */

/***************************************************************************
**
**  Name: ProcessTypeRegVar
**
****************************************************************************/
PRIVATE RETCODE ProcessTypeRegVar(TYPE_PARAM FAR *para) {
U32 regNum;
TYPE_INDEX baseType;
CHAR typeName[NAME_LEN+1];
RETCODE err;
U16 regIndex;

   if (((regNum = GetTypeLength(para->typeRec, &(para->i))) >=
        MAX_REGISTER_SUPPORTED) || (para->typeRec[para->i++] != LEAF_INDEX)) {
      return(ER_OMF86_BAD_TYPE_SIGNATURE);
   }
   if ((err=GetRegID((U16)regNum, &regIndex)) != GOOD)
      return(err);
   baseType = GetSubTypeIndex(para->typeIdx, para->typeRec, &(para->i))
              + TYPE_OFFSET;
   if ((err=GetTypeName(para->typeRec, &(para->i), typeName)) != GOOD)
      return(err);
   para->typeHdrInfo->t.complexType = TY_REGISTER;
   para->typeHdrInfo->typeName = (LPSTR)typeName;
   if (((err=SymAddTypeHeader(para->typeIdx, para->typeHdrInfo)) != GOOD) ||
       ((err=SymAddTypeRegVar(para->typeIdx, regIndex, baseType)) != GOOD))
      return(err);
   return(GOOD);
}

/**************************************************************************
**
** ProcessRegVarExt
**
** Note: The function will be used to support Paradigm locate extended ver.
**       which accept register variables.
**************************************************************************/
RETCODE ProcessRegVarExt(HANDLE hFile, U32 flags) {
RETCODE err=GOOD;
CHAR typeName[NAME_LEN+1] = "";
TYPE_INDEX baseType;
U16 regIndex;
U8 len, regNum;
SYM_DESCRIPTOR symP;
U32 symOffset;
TYPE_HEADER_TYPE  typeHdrInfo;


   if (TypeWarned && ExtOmf != 1)
      return GOOD;
   else
      ++TypeIndex;
   if ((TypeIndex > MAX_TYPE_INDEX) && !TypeWarned) {
      sprintf(typeIdStr, "%0X", TypeIndex);
      if ((err=LdrWarning(ER_OMF86_TYPES_TOO_LARGE,
                          (LPSTR)typeIdStr, NULL, NULL))
              != GOOD)
         return(err);
      TypeWarned = TRUE;
   }
   if ((err=GetName(hFile, &len, typeName)) != GOOD)
      return(err);
   if ((err=GetIndex(hFile, &regIndex)) != GOOD)
      return(err);
   if ((err=GetTypeIndex(hFile, &baseType)) != GOOD)
      return(err);
   if ((err=OMFGetByte(hFile, &regNum)) != GOOD)
      return(err);
   if ((err=GetRegID((U16)regNum, &regIndex)) != GOOD)
      return(err);

   symOffset=(U32)regIndex;
   if ((err = SymAddVar(typeName,
                       0,
                       baseType,
                       AUTO_VAR_CLASS,
                       LIVING_REG,
                       (ADD_VAR_ADDR_UNION *)&symOffset,
                       FALSE, /* not constant */
                       TRUE,  /* address is valid */
                       &symP)) != GOOD) {
     return(err);
   }
   typeHdrInfo.t.complexType = TY_REGISTER;
   typeHdrInfo.typeName = (LPSTR)typeName;
   if (((err=SymAddTypeHeader(TypeIndex+TYPE_OFFSET,&typeHdrInfo)) != GOOD) ||
       ((err=SymAddTypeRegVar(TypeIndex+TYPE_OFFSET,regIndex, baseType)) != GOOD))
      return(err);
   return(err);
}  /* ProcessRegVarExt */

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