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

/*----------------------------------------------------------------------------
** Name: SYMTYPE.CPP
**
** Title: Type Table
**
** Purpose:
**  Create and manage all simple and complex data types
**
** Status: PRELIMINARY
**
** $Log$
** 
** $Header:   D:/EP196/SRC/LOG/SYMSVR/SYMTYPE.CPP   1.0   15 Aug 1997 14:04:16   ZJRD  $
**
** Copyright (C) 1995 Microtek International.  All rights reserved.
**
**--------------------------------------------------------------------------*/

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

#include "stdafx.h"                      
#include <memory.h>
#include "symindex.h"
#include "symmanag.h"
#include "sympool.h"
#include "symblsvr.h"
#include "symmgr.h"
#include "symutil.h"
#include "symtypes.h"
#include "symtype.h"

                       /****************************
                        *                          *
                        *        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 *typeHeader;
   TABLE_OFFSET       typeOffset;
   
   if((err = typit.GetOffset(typeIndex, typeOffset)) != GOOD)
      return(err);
   typeHeader = (TYPE_HEADER_TYPE2 *)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 = (SIMPLE_TYPE)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 *prevPtr, *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 *)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 *)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 *typePtr;
   TABLE_OFFSET       typeOffset;

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

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