/****************************************************************************
**
**  Name:  LTYPE.C
**
**  Description:
**      Type processing routines for IEEE 695 loader.
**
**  Status:  CODED
**
**  $Log:   S:/tbird/mt2_68k/l695/ltype.c_v  $
** 
**    Rev 1.0   13 Feb 1997 08:51:02   gene
** Initial revision.
** 
**    Rev 1.1   14 Jun 1996 08:46:18   kevin
** judy's modification
** 
**    Rev 1.0   07 Sep 1995 10:32:26   gene
** Initial revision.
** 
**    Rev 1.18   18 Jan 1994 16:56:30   nghia
** Revised ldrMangle to have the correct glboal state.
** 
**    Rev 1.17   23 Sep 1993 17:44:06   nghia
** Revised to support forward reference type for TYPEDEF, ARRAY, BITFIELD.
** Cleanup.
** 
**    Rev 1.16   23 Aug 1993 11:10:36   nghia
** Fixed bug for Sierra TYPEDEF1.ABS - invalid index for typedef type index of
** a union type.
** Cleanup.
** 
**    Rev 1.15   13 Aug 1993 13:26:20   nghia
** Fixed PPR 8875 - Allow forward reference type define to be added to the 
** symbol table.
** 
**    Rev 1.14   03 Aug 1993 17:49:22   nghia
** Removed LERR_xxxx to use standard error codes.
** 
**    Rev 1.13   27 Jul 1993 11:20:54   courtney
** Check retcode on array type index (SymGetTypeHeader call), so error
** is reported when forward reference element type is created.
** 
**    Rev 1.12   26 Jul 1993 14:30:24   courtney
** Initialize struct/union member names before entering to symbol table
** (especially affects unnamed bitfields).
** 
**    Rev 1.11   16 Jun 1993 08:28:26   mindy
** Proc types and arrays need to add toffset so they map to the type
** indexes generated for the return type, parameter types and array
** elements.
** 
**    Rev 1.10   06 Jun 1993 21:22:08   courtney
** Demangle struct/union member names before storing to symbol table (C++).
** 
**    Rev 1.9   03 Jun 1993 18:54:48   nghia
** Revised to use new error codes.
** Reported error using only the Warning() and WarningEx().
** 
**    Rev 1.8   12 Apr 1993 16:24:56   nghia
** Major cleanup for coding standard (return RETCODE, function header).
** Updated and revised.
** 
**    Rev 1.7   08 Mar 1993 11:05:28   nghia
** Major cleanup for names and comments.
** 
**    Rev 1.6   21 Oct 1992 16:39:06   courtney
** Cleaned up error reporting to use string resource.
** 
**    Rev 1.5   14 Sep 1992 10:44:24   courtney
** TMalloc has problems when used here (stub out for now).
** 
**    Rev 1.4   07 May 1992 15:48:10   courtney
** Cleanup.
** 
**    Rev 1.3   01 Apr 1992 15:57:24   courtney
** Error check return value on local memory allocation.
** 
**    Rev 1.2   05 Feb 1992 13:22:04   courtney
** Now properly unlock before free.
** 
**    Rev 1.1   09 Jan 1992 16:57:34   courtney
** Fixed bug in array size calculation.
** 
**    Rev 1.0   12 Dec 1991 13:42:26   courtney
** Initial revision.
**
**  $Header:   S:/tbird/mt2_68k/l695/ltype.c_v   1.0   13 Feb 1997 08:51:02   gene  $
**
**  Copyright (C) 1991 Microtek International.  All rights reserved.
**
*****************************************************************************/
                       /****************************
                        *                          *
                        *       INCLUDE FILES      *
                        *                          *
                        ****************************/
#include <limits.h>
#ifndef __LDR__
#include "ldr.h"
#endif
#ifndef _HEAP_
#include "heap.h"
#endif
#ifndef _SYMBLSVR_
#include "symblsvr.h"
#endif
#ifndef __ERR__
#include "err.h"
#endif
#ifndef __LDEBUG__
#include "ldebug.h"
#endif
#ifndef __LMANGLE__
#include "lmangle.h"
#endif

                       /****************************
                        *                          *
                        *     LOCAL DEFINITIONS    *
                        *                          *
                        ****************************/
/* Max index type value */
#define MAX_INDEX_TYPE 0x0FFFFFFFL

                       /****************************
                        *                          *
                        *    EXTERNAL VARIABLES    *
                        *                          *
                        ****************************/
extern U16 ldrDemangle;

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

                       /****************************
                        *                          *
                        *      EXECUTABLE CODE     *
                        *                          *
                        ****************************/
/******************************************************************************
**
**  GetTypePtr - Process Pointer type
**
******************************************************************************/
RETCODE GetTypePtr(HANDLE hfile, U32 tindexParent, U16 stype, U32 toffset) {
   U32 tindex;
   U32 symerr;

   /* Used to finish processing the following symbol types for RT_TY records:
   ** O (16-bit pointer) - obtain target type index
   ** P (32-bit pointer) - "
   */
   if (Get695TIndex(hfile, &tindex, toffset) != GOOD)
      return(ER_SYM_TYPE);
   switch (stype) {
      case T695_SMALL_PTR:
      case T695_LARGE_PTR:
         /* add: pointer type, target type */
         if ((symerr = SymAddTypePointerTypeIndex(tindexParent,
                                                  tindex)) != GOOD) 
            return(ER_SYM_TYPE);
         break;
      default:
         return(ER_UNEXPECTED_TYPE);
   }
   return(GOOD);
}  /* GetTypePtr */

/******************************************************************************
**
**  GetTypeTypedef - Process typedef type
**
******************************************************************************/
RETCODE GetTypeTypedef(HANDLE hfile, U32 tindexParent,
                       TYPE_HEADER_TYPE *parentTypehdr,
                       U32 toffset) {
   U32 baseTypeIndex;
   TYPE_HEADER_TYPE baseTypeHdr;
   CHAR typeName[IEEE_IDNLEN] = "";
   
   /* TypeDef Record: {$F2} {n1} {$CE} {n2} [n3] [n4]..
   ** Where: n3 = typedef index $54 - See Appendix A1 and A2
   ** Following by a {n4} = type index of the underlying type.
   */
   
   /* Get underlying type and its type header */
   if (Get695TIndex(hfile, &baseTypeIndex, toffset) != GOOD)
      return(ER_SYM_TYPE);
   
   /* 08/20/93 - Nghia
   ** Sierra compiler generate baseTypeIndex = 0xFFFFFFFF for
   ** a typedef of union type.
   */
   if (baseTypeIndex >= MAX_INDEX_TYPE) { /* 0x0FFFFFFFL */
      /* Still need to add the typedef to the symbol table */
      parentTypehdr->sizeCalculated = TRUE;
      SymAddTypeHeader(tindexParent, parentTypehdr);
      return(ER_SYM_TYPE);
   }
         
   /* Notes: Nghia 09/15/93 
   ** Forward reference type will be resolved when the type gets accessing.
   ** The defined type does not need to known any information about its
   ** underlying type (or base type) to create the new type.
   */
   baseTypeHdr.typeName = (LPSTR)typeName;
   if (SymGetTypeHeader(baseTypeIndex, &baseTypeHdr) == GOOD) {
      parentTypehdr->sizeInMAUs = baseTypeHdr.sizeInMAUs;
      parentTypehdr->sizeCalculated = TRUE;
   }
   /* Create the new type and
   ** Add the underlying type of typedef type
   */
   if ((SymAddTypeHeader(tindexParent, parentTypehdr) != GOOD) ||
      (SymAddTypeTypeIndex(tindexParent, baseTypeIndex) != GOOD)) {
      return(ER_SYM_TYPE);
   }
   return(GOOD);
}  /* GetTypeTypedef */

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

   /* underlying type is void (built-in type) */
   tindex = T695_VOIDP;
   /* type of typedef, underlying type */
   if (SymAddTypeTypeIndex(tindexParent, tindex) != GOOD) return(ER_SYM_TYPE);
   return (GOOD);
}  /* MapTypeVoid */
/******************************************************************************
**
**  GetTypeProc
**
******************************************************************************/
RETCODE GetTypeProc(HANDLE hfile, U32 tindex, U32 toffset) {
   /* tindex - type index for function */
   U16 frame, level;
   U32 rtntype, attr, pushmask, nargs;
   LOOP_VAR i;
   U32 argtype;
   U32 FAR *parg_typelist;
   LOCALHANDLE htypelist;
   RETCODE err = GOOD;
   CHAR parentName[1] = "";  /* 'fathername' field is not used for C */

   /*
   ** If the ST doesn't need some of this stuff, just
   ** throw it into a 'junk' field and throw it away into the garbage.
   */
   if ((Get695Offset(hfile, &attr) != GOOD) ||
       (Get695Number(hfile, &frame) != GOOD) ||
       (Get695Offset(hfile, &pushmask) != GOOD) ||
       (Get695TIndex(hfile, &rtntype, toffset) != GOOD) ||
       (Get695Offset(hfile, &nargs) != GOOD))
      return(ER_SYM_TYPE);
   
   if((nargs == USHRT_MAX) || (nargs == -1L))  /* unknown nargs */
      nargs = 0;
   if ((htypelist = LocalAlloc(LMEM_MOVEABLE, (WORD)(nargs * sizeof(U32))))
         == NULL) {
      err = ER_NO_MEMORY;
      Warning(err);
   }
   if (!err)
      parg_typelist = (U32 *) LocalLock(htypelist);
   for (i=0; i<nargs; i++) {
      Get695TIndex(hfile, &argtype, toffset);
      if (!err)
         parg_typelist[i] = argtype;
   }
   Get695Number(hfile, &level);
   /* if allocation error, we still need to eat the bytes so we remain
   ** in sync in the loadfile
   */
   if (err != GOOD)
      return(ER_SYM_TYPE);

   /* note: size for function *type* definition has no meaning */
   if (SymAddTypeFunc(tindex, attr, frame, pushmask, rtntype,
                      nargs, level, (LPSTR)parentName) != GOOD) {
      return(ER_SYM_TYPE);
   }
   /* don't add parms if function can't be created */
   for (i = 0; i < nargs; i++) {
      if (SymAddTypeFuncParam(tindex, parg_typelist[i])  != GOOD) {
         err = ER_SYM_TYPE;
         break;
      }
   }
   LocalUnlock(htypelist);
   LocalFree(htypelist);
   return(err);
}  /* GetTypeProc */

/******************************************************************************
**
**  GetTypeProcSimple <Judy 5/8/96>
**  Notes: Procedure without compiler dependencies
******************************************************************************/
RETCODE GetTypeProcSimple(HANDLE hfile, U32 tindex, U32 toffset) {
   /* tindex - type index for function */
   U16 frame, level;
   U32 rtntype, attr, pushmask, nargs;
   LOOP_VAR i;
   U32 argtype;
   U32 FAR *parg_typelist;
   LOCALHANDLE htypelist;
   RETCODE err = GOOD;
   CHAR parentName[1] = "";  /* 'fathername' field is not used for C */

   /*
   ** If the ST doesn't need some of this stuff, just
   ** throw it into a 'junk' field and throw it away into the garbage.
   */
   if ((Get695Offset(hfile, &attr) != GOOD) ||
       (Get695TIndex(hfile, &rtntype, toffset) != GOOD) ||
       (Get695Offset(hfile, &nargs) != GOOD))
      return(ER_SYM_TYPE);
   
       frame=0;
       pushmask=0;
   if((nargs == USHRT_MAX) || (nargs == -1L))  /* unknown nargs */
      nargs = 0;
   if ((htypelist = LocalAlloc(LMEM_MOVEABLE, (WORD)(nargs * sizeof(U32))))
         == NULL) {
      err = ER_NO_MEMORY;
      Warning(err);
   }
   if (!err)
      parg_typelist = (U32 *) LocalLock(htypelist);
   for (i=0; i<nargs; i++) {
      Get695TIndex(hfile, &argtype, toffset);
      if (!err)
         parg_typelist[i] = argtype;
   }
   level=0;
   /* if allocation error, we still need to eat the bytes so we remain
   ** in sync in the loadfile
   */
   if (err != GOOD)
      return(ER_SYM_TYPE);

   /* note: size for function *type* definition has no meaning */
   if (SymAddTypeFunc(tindex, attr, frame, pushmask, rtntype,
                      nargs, level, (LPSTR)parentName) != GOOD) {
      return(ER_SYM_TYPE);
   }
   /* don't add parms if function can't be created */
   for (i = 0; i < nargs; i++) {
      if (SymAddTypeFuncParam(tindex, parg_typelist[i])  != GOOD) {
         err = ER_SYM_TYPE;
         break;
      }
   }
   LocalUnlock(htypelist);
   LocalFree(htypelist);
   return(err);
}  /* GetTypeProcSimple */

/******************************************************************************
**
**  GetTypeSU - Process type structure/union
**  tindexParent - type index for parent
**  stype - type (struct/union) (not used currently)
**  toffset - type fix-up value
**
******************************************************************************/
#pragma argsused /* stype */
RETCODE GetTypeSU(HANDLE hfile, U32 tindexParent, U16 stype, U32 toffset) {
   CHAR mbrName[IEEE_IDNLEN] = ""; /* REQUIRE by SYMBOL SERVER */
   CHAR *pname = "";  /* pointer to demangled name */
   U32 tindex;
   U16 mbrOffset, cbyte;
   TYPE_S_U_STRUCT su;

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

   /* loop over all members of structure (no, we don't know how many) */
   while (1) {
       /* may be unnamed struct/union members which are bitfields */
       if ((Get695Idn(hfile, mbrName) != GOOD) ||      /* member name */
          (Get695TIndex(hfile, &tindex, toffset) != GOOD) || /* member type */
          (Get695Number(hfile, &mbrOffset) != GOOD))   /* member offset */
          return(ER_SYM_TYPE);
       su.typeIndex = tindex;  /* element type */
       su.offset = mbrOffset;

       /* demangle member name before load (C++) */
       if (ldrDemangle)
          CppFixupMember(mbrName, &pname);
       else
          pname = mbrName;  /* pointer assign */

       su.name = (LPSTR)pname;  /* pointer assign */

       if (SymAddTypeStructUnion(tindexParent, &su) != GOOD)
          return(ER_SYM_TYPE);

       Peek695Byte(hfile, &cbyte);
       if (cbyte == RT_NN || cbyte == RT_BE)
           break;
   }
   return (GOOD);
}  /* GetTypeSU */

/******************************************************************************
**
**  GetTypeEnum - Process enum type
**
** tindexParent - type index for parent 
**
******************************************************************************/
RETCODE GetTypeEnum(HANDLE hfile, U32 tindexParent) {
   CHAR mbrName[IEEE_IDNLEN];
   U32 mbrValue;    /* note: our target is a 68K (32-bit int) */
   U16 cbyte;
   RETCODE symerr = GOOD;

   
   /* loop over all members of enum (no, we don't know how many) */
   while (1) {
      /* NOTES: 09/20/93 - Nghia
      ** Enum type might not have any member - file VME14.X by K&S
      */
      Peek695Byte(hfile, &cbyte);
      if (cbyte == RT_NN || cbyte == RT_BE)
        break;
      /* Get member name and member value */
      if ((Get695Idn(hfile, mbrName) != GOOD) ||
         (Get695Offset(hfile, &mbrValue) != GOOD)) {
         return(ER_SYM_TYPE);
      }
      if ((symerr = SymAddTypeEnum(tindexParent, mbrValue, mbrName)) != GOOD) {
         return(ER_SYM_TYPE);
      }
   }
   return (GOOD);
}  /* GetTypeEnum */

/******************************************************************************
**
**  GetTypeArr - Process type array
**
******************************************************************************/
RETCODE GetTypeArr(HANDLE hfile, U32 tindexParent, U32 toffset,
                   TYPE_HEADER_TYPE *parentTypeHdr) {
   TYPE_Z_STRUCT arrayHdrStruct;
   TYPE_HEADER_TYPE elementTypeHdr;
   CHAR typeName[IEEE_IDNLEN] = "";
   
   /* Get element type and boundary */
   if ((Get695TIndex(hfile, &arrayHdrStruct.typeIndex, toffset) != GOOD) ||
       (Get695Offset(hfile, (U32 *)&arrayHdrStruct.highBound) != GOOD))
       return(ER_SYM_TYPE);
   
   /* NOTES: 09/16/93 - Nghia
   ** We don't need the sizeInMAUs of element of array to create its type.
   ** If it's a forward reference type then until the array type is accessed
   ** then the symbol table will calculate the sizeInMAUs of element
   ** and update the sizeInMAUs of the array type. 
   ** This applies to both BUILT-IN and USER-DEFINED types.
   */

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

   return(GOOD);
}  /* GetTypeArr */

/******************************************************************************
**
**  GetTypeBit - Process type bit
**
******************************************************************************/
RETCODE GetTypeBit(HANDLE hfile, U32 tindexParent,
                   TYPE_HEADER_TYPE *parentTypehdr) {
   TYPE_BITFIELD_STRUCT bfHdrStruct;
   U16 cbyte;
   TYPE_HEADER_TYPE baseTypeHdr;
   CHAR typeName[IEEE_IDNLEN] = "";

   /* Get bitfield size and bitfieldsigned */
   if ((Get695Number(hfile, (U16 *)&bfHdrStruct.bitfieldSigned) != GOOD) ||
      (Get695Number(hfile, &bfHdrStruct.size) != GOOD))
      return(ER_SYM_TYPE);
   
   /* The underlying type may not be given - then assume default */
   Peek695Byte(hfile, &cbyte);
   /* Get the base type index */
   if (cbyte != RT_NN && cbyte != RT_BE) {
      if (Get695Offset(hfile, &bfHdrStruct.baseTypeIndex) != GOOD)
         return(ER_SYM_TYPE);
   }
   else
      bfHdrStruct.baseTypeIndex = T695_UNS; /* default is unsigned int */

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

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