/*----------------------------------------------------------------------------
** Name: typetbl.cpp
**
** Title: Type Table
**
** Purpose:
**  Create and manage all simple and complex data types
**
** Status: PRELIMINARY
**
** $Log:   S:/tbird/mt2_186/symbol/typetbl.cpv  $
** 
**    Rev 1.2   04 Jun 1998 14:20:12   hera
** 
**    Rev 1.1   18 Apr 1997 09:29:22   Judy
** 
**    Rev 1.1   14 Jan 1997 15:32:22   Judy
** No change.
** 
**    Rev 1.0   14 Jun 1996 16:42:24   Judy
** Initial revision.
** 
**    Rev 1.14   06 Oct 1994 21:46:36   brucea
** Added #define for a constant
** 
**    Rev 1.13   06 Oct 1994 20:53:50   brucea
** Modified TypeTable::InitBasicTypes() to put the #32-#57 pointer types as
**   pointers to their basic type counterparts; i.e. create loaded types for
**   each one.  Each one is a TY_LARGE_PTR and COMPLEX_TYPE_CLASS.
** Other cosmetic changes.
** 
**    Rev 1.12   24 Sep 1993 10:17:46   nghia
** Support forward reference type - Built-in types need to set sizeCalculated
** flag to TRUE.
** 
**    Rev 1.11   23 Mar 1993 17:11:36   courtney
** New allocations to type table which span 8K boundaries should not
** place new objects on rounded boundary (affects typeHdr/type, which 
** should be adjacent), in AllocBytes.
** 
**    Rev 1.10   19 Jul 1992 21:20:42   brucea
** Modified: init size from 0x10000L to 0x2000L
** 
**    Rev 1.9   15 Jun 1992 09:31:06   brucea
** Added: return GOOD to remove compiler warning
** 
**    Rev 1.8   29 Jan 1992 15:15:20   brucea
** Changed the initialization of typeHeader.memberCount to 1 inside
**   TypeTable::InitBasicTypes
** 
**    Rev 1.7   06 Dec 1991 17:00:54   john
** Added member function to free the allocated for the type table.
** 
**    Rev 1.6   21 Nov 1991 16:14:08   john
** maxTypeIndex was one too large
** 
**    Rev 1.5   21 Nov 1991 15:18:36   john
** Fixed the call to max().  The value being returned was not being
** stored.
** 
**    Rev 1.4   20 Nov 1991 09:15:38   john
** Added the code to keep track of the largest type index used so
** far.  This is an aid to the loader during an on demand load
** session.
** 
**    Rev 1.3   12 Nov 1991 10:04:42   brucea
** Changed prototype/function to match TYPE_HEADER_TYPE2 struct
** 
**    Rev 1.2   11 Nov 1991 17:44:32   john
** Changed UpdateSizeInMAUs to hide info
** 
**    Rev 1.1   11 Nov 1991 15:09:54   john
** Added new member functions to operate on info in the type table.
** 
**    Rev 1.0   08 Nov 1991 14:10:48   john
** Initial revision.
**
** $Header:   S:/tbird/mt2_186/symbol/typetbl.cpv   1.2   04 Jun 1998 14:20:12   hera  $
**
** Copyright (C) 1991 Microtek International.  All rights reserved.
**
**--------------------------------------------------------------------------*/

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

#ifndef _INDEXTBL_
#include "indextbl.h"
#endif
#ifndef __MEM_H
#include <mem.h>
#endif
#ifndef _MEMMANAG_
#include "memmanag.h"
#endif
#ifndef _MEMPOOL_
#include "mempool.h"
#endif
#ifndef _SYMBLSVR_
#include "symblsvr.h"
#endif
#ifndef _SYMMGR_
#include "symmgr.h"
#endif
#ifndef _SYMUTIL_
#include "symutil.h"
#endif
#ifndef _TYPES_
#include "types.h"
#endif
#ifndef _TYPETBL_
#include "typetbl.h"
#endif

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


#define TYPETABLE_EXPANSION_SIZE 0x2000L
#define TYPETABLE_INIT_SIZE      0x2000L
#define MAX_TYPE_SIZE 0x10000L

IndexTable typit;
extern MemPool st;
TypeTable tt;  // type table instantiation;

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

//member functions for type table

// constructor ;
TypeTable::TypeTable():Table() {

   availMemOffset = 0L;
   bytesThrownAway = 0;  // initialize member vars

   initialSize = TYPETABLE_INIT_SIZE;
   expandSize  = TYPETABLE_EXPANSION_SIZE;
   maxTypeIndex = 0xFFL;

}


//--------------------------------------------------------------------------
// TypeTable::AllocBytes
//--------------------------------------------------------------------------
RETCODE TypeTable::AllocBytes(U16 size,
                              TABLE_OFFSET& tableDataOffset) {

   RETCODE      retCode;
   U32          memoryLeft;
   U32          copyLength = 0;
   TABLE_OFFSET beginOffset;
   HPU8         srcPtr, destPtr;

   tableDataOffset = 0;    // set to null in case of a memory failure
   if ((memoryLeft = (tableSize-availMemOffset)) < (U32)size) {

      // not enough space or empty table; must get more
      if ((retCode = InitOrExtendTable(0)) != GOOD) {
         return retCode;
      // a non-zero retcode means no memory was found; otherwise fall thru
      } else {   
         // found more memory

         // initialize the first valid offset >= 4.  this will allow
         // uninitialized type headers to be placed at offset 1-3
         // (0 is a bad number because typit.GetOffset believes a type
         // with a value of 0 doesn't exist)
         if (!availMemOffset) {
            destPtr = GetHugeDataPtr(availMemOffset);
            *(U32 *)destPtr = 0L;
            availMemOffset = 4L;
         }

         // jump over any unused bytes to preserve 64K boundary
         // move pointer past boundary of old partition
         // then copy the header to availmemoffset down to new boundary

         if((retCode = typit.GetOffset(typeIndex,beginOffset)) !=GOOD)
            return(retCode);
         // if the beginning offset < 4 it hasn't been initialized to
         // a real value
         if (beginOffset < 4) beginOffset = availMemOffset;
         if( (availMemOffset - beginOffset + size) >= MAX_TYPE_SIZE)
            return(ER_TYPE_TOO_LARGE);
         if (( (availMemOffset + size) & 0xffffL) !=
               ((availMemOffset & 0xffffL) + size)) {
            // the new data being put in will cross a 64k boundary
            // copy the previously inserted data to the new 64k boundary
            copyLength = availMemOffset - beginOffset;
            srcPtr = GetHugeDataPtr(beginOffset);
            destPtr = GetHugeDataPtr(availMemOffset + memoryLeft);
            // the copy can't be >64k because we wouldn't have gotten to
            // this code
            memcpy(destPtr,srcPtr,(U16)copyLength);
         
            // update type index tables pointer to the type_header
            if ((retCode = typit.UpdateOffset(typeIndex,
               availMemOffset + memoryLeft)) != GOOD) 
               return(retCode);
            // only if new 64K region (not 8K region)
            availMemOffset += memoryLeft + copyLength;
            bytesThrownAway += (U16)memoryLeft;
         }
      }
   }  // end of if that checked for enough memory or retrieved more memory

   // set the return pointer to the head of the data
   tableDataOffset = availMemOffset;

   // bump pointer to available memory by size of data 
   availMemOffset += size;

   return(GOOD);
}  // end of TypeTable::AllocBytes


//--------------------------------------------------------------------------
// TypeTable::IncrementMemberCount
//--------------------------------------------------------------------------
RETCODE TypeTable::IncrementMemberCount(VOID) {

   RETCODE            err;
   TYPE_HEADER_TYPE2 HUGE* typeHeader;
   TABLE_OFFSET       typeOffset;
   
   if((err = typit.GetOffset(typeIndex, typeOffset)) != GOOD)
      return(err);
   typeHeader = (TYPE_HEADER_TYPE2 HUGE*)tt.GetHugeDataPtr(typeOffset);
   typeHeader->memberCount++;
   
   return(GOOD);
}  // end of TypeTable::IncrementMemberCount


//--------------------------------------------------------------------------
// TypeTable::InitBasicTypes
//--------------------------------------------------------------------------
RETCODE TypeTable::InitBasicTypes(VOID) {

   RETCODE           err;
   LOOP_VAR          i;
   TYPE_HEADER_TYPE2 typeHeader;

   // initialize all of the basic types
   typeHeader.typeChoice = SIMPLE_TYPE_CLASS;
   // basic types have no members added, therefore set member count to 1
   typeHeader.memberCount = 1;
   // All built-in types have precalculated size of MAU
   typeHeader.sizeCalculated = TRUE;
                    
   for(i = 0; i<BASIC_TYPE_COUNT; i++) {
      // if the name of the basic type is NULL then this is not a valid entry;
      if( lstrlen((LPSTR)basicTypeName[i]) ) {

         // put the type name into the symbol table ;
         if((err = st.PutString((LPSTR)basicTypeName[i],typeHeader.typeName))
            != GOOD) return(err);
         typeHeader.t.simpleType = i;
         typeHeader.sizeInMAUs = basicTypeSize[i];
         typeHeader.recordSize = sizeof(TYPE_HEADER_TYPE2);

         // put the type information into the type table
         if((err = tt.PutHeader((U8 *)&typeHeader,sizeof(TYPE_HEADER_TYPE2),
            i )) != GOOD) return(err);
      }
   }
   // now process #32-#57 of Table A-2, page A-8, the pointer types.
   // Must be added as pointers to #0-#25 basic types.  Size is 4 bytes.
   // The offset from complex to simple is 32.

   typeHeader.memberCount = 0;  // adding type index will bump
   typeHeader.typeChoice = COMPLEX_TYPE_CLASS;
   typeHeader.t.complexType = TY_LARGE_PTR;
   typeHeader.sizeInMAUs = 4L;
   typeHeader.typeName = 0L;  // pointer to null -> no name
   typeHeader.sizeCalculated = TRUE;
   typeHeader.recordSize = sizeof(TYPE_HEADER_TYPE2);

#define POINTERS_TO_BASIC_TYPE_START 32
   for (i=POINTERS_TO_BASIC_TYPE_START; i<58; i++) {
      // put the type information into the type table
      if((err = tt.PutHeader((U8 *)&typeHeader,sizeof(TYPE_HEADER_TYPE2),
                                    i )) != GOOD)
         return(err);
      // update pointer index to point to its simple type; i.e. offset by 32
      if ((err = SymAddTypePointerTypeIndex(i, i-POINTERS_TO_BASIC_TYPE_START))
          != GOOD)
         return err;
   } // end of complex pointer for loop
   return GOOD;
}  // end of TypeTable::InitBasicTypes


//--------------------------------------------------------------------------
// TypeTable::ObliterateTable
//--------------------------------------------------------------------------
VOID TypeTable::ObliterateTable(VOID) {

   Table::ObliterateTable();
   availMemOffset = 0L;
   bytesThrownAway = 0;  // initialize member vars

   initialSize = TYPETABLE_INIT_SIZE;
   expandSize  = TYPETABLE_EXPANSION_SIZE;
   maxTypeIndex = 0xFFL;
}  // end of TypeTable::ObliterateTable


//--------------------------------------------------------------------------
// TypeTable::PutBytes
//--------------------------------------------------------------------------
RETCODE TypeTable::PutBytes(U8 *inputDataPtr,
                            U16 size, 
                            TABLE_OFFSET &offset) {
   RETCODE      retCode;
   HPU8         tempHugePtr;
   TABLE_OFFSET tableDataOffset;

   retCode = AllocBytes(size, tableDataOffset);
   if (retCode != GOOD) return(retCode);  // return if some error

   // tableDataOffset points to head of allocated memory
   // calculate pointer to this data
   tempHugePtr = hpTableObject + tableDataOffset;

   // store the data
   for (; size; size--) {
      *tempHugePtr++ = *inputDataPtr++;
   }
   offset = tableDataOffset;
   return(GOOD);
}  // end of TypeTable::PutBytes


//--------------------------------------------------------------------------
// TypeTable::PutHeader
//--------------------------------------------------------------------------
RETCODE TypeTable::PutHeader(U8 *inputDataPtr,
                             U16 size,
                             TYPE_INDEX index) {

   RETCODE      err;
   TABLE_OFFSET typeOffset = 1L;
   
   typeIndex = index;
   maxTypeIndex = max(typeIndex,maxTypeIndex);
   // put the offset to the type into the type index table
   if((err = typit.AddIndex(index,typeOffset)) != GOOD) 
      return(err);
   if ((err = PutBytes(inputDataPtr, size, typeOffset)) != GOOD)
      return(err);
   return typit.UpdateOffset(index,typeOffset);
}  // end of TypeTable::PutHeader


//--------------------------------------------------------------------------
// TypeTable::UpdateMAUSize
//--------------------------------------------------------------------------
RETCODE TypeTable::UpdateMAUSize(TYPE_INDEX prevIndex) {

   RETCODE            err;
   TYPE_HEADER_TYPE2  HUGE* prevPtr, HUGE* currPtr;
   TABLE_OFFSET       prevOffset, currOffset;

   // whatever type was just added will point back to some previously
   // defined type.  Use the previously defined types MAU size and
   // add it to the MAU size of the type just added to the type table.
   if ((err = typit.GetOffset(prevIndex,prevOffset)) != GOOD)
      return(err);
   prevPtr = (TYPE_HEADER_TYPE2 HUGE*)tt.GetHugeDataPtr(prevOffset);

   // add the previous type MAU size to the current types MAU size
   if ((err = typit.GetOffset(typeIndex,currOffset)) != GOOD)
      return(err);
   currPtr = (TYPE_HEADER_TYPE2 HUGE*)tt.GetHugeDataPtr(prevOffset);
   currPtr->sizeInMAUs += prevPtr->sizeInMAUs;
   return(GOOD);
}  // end of TypeTable::UpdateMAUSize


//--------------------------------------------------------------------------
// TypeTable::UpdateRecordSize
//--------------------------------------------------------------------------
RETCODE TypeTable::UpdateRecordSize(U16 setValue) {

   RETCODE            err;
   TYPE_HEADER_TYPE2  HUGE* typePtr;
   TABLE_OFFSET       typeOffset;

   if ((err = typit.GetOffset(typeIndex,typeOffset)) != GOOD)
      return(err);
   typePtr = (TYPE_HEADER_TYPE2 HUGE*)tt.GetHugeDataPtr(typeOffset);
   typePtr->recordSize += setValue;
   return(GOOD);
}  // end of TypeTable::UpdateRecordSize

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