
/***************************************************************************
**
**    $Header$
**
**    $Log$
** 
****************************************************************************/

/*----------------------------------------------------------------------------
** Name: SYMMEM.cpp
**
** Title: Memory Manager
**
** Purpose:
**  Create and manage the symbol table memory.  Included:
**      creating table
**      adding elements to table
**      growing table
**      closing table
**
** Status: PRELIMINARY
**
** $Log$
** 
** $Header:   D:/EPSLDV1/SRC/LOG/SYMMEM.CPP   1.7.1.0.1.0   11 Nov 1996 12:58:10   ZJRD  $
**
** Copyright (C) 1995 Microtek International.  All rights reserved.
**
**--------------------------------------------------------------------------*/

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

#include "stdafx.h"                      
#include "symmanag.h"

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

//------------------------------------------------------------------------
// Table::InitOrExtendTable
//
// Purpose:
//    Initialize table if tableSize = 0 else
//    extend the table by <expandSize>.
//
// Input parameters:
//    allocFlag:
//       0 if memory does not need to be zeroed upon initialization
//       GMEM_ZEROINIT if memory needs to be zeroed upon initialization
//
// Output parameters: None
//
// Error:
//    Reports ER_SYM_OUT_OF_MEMORY if memory cannot be Alloc'ed or ReAlloc'ed
//------------------------------------------------------------------------
RETCODE Table::InitOrExtendTable(WORD zeroInitFlag) {

   HANDLE tempTableHandle;
   U32 memAvailable;
   U32 trialSize;    // latest incremental size to try

   if (!tableSize) {  // table has not been Alloc'ed yet
      if ((tableHandle = GlobalAlloc(GMEM_MOVEABLE | zeroInitFlag,
                                      initialSize)) == NULL) {
         // not enough memory found; compact then check again

         memAvailable = GlobalCompact(initialSize);
         if (memAvailable < initialSize) {
            return ER_SYM_OUT_OF_MEMORY;
         } else {
            if ((tableHandle = GlobalAlloc(GMEM_MOVEABLE | zeroInitFlag,
                                            initialSize))== NULL)
               return ER_SYM_OUT_OF_MEMORY;
         }
      }
      // memory found; fall thru

      if ((hpTableObject = (HPU8)GlobalLock(tableHandle)) != 0L) {
         //successful initial allocation
         // actual size may be larger than requested size, but we only want
         // the size on an even binary boundary
         tableSize= initialSize;
         return SUCCESS;
      }
   } else {  // table has been previously Alloc'ed; need to ReAlloc
      trialSize = expandSize;

#ifdef DEBUG
      if (expandSize < MIN_EXPAND_SIZE) return ER_EXPAND_SIZE_ERROR;
#endif

	   if ((tempTableHandle = GlobalReAlloc(tableHandle,
                                            (tableSize + trialSize),
                                            GMEM_MOVEABLE | zeroInitFlag))==NULL) {
         // GlobalReAlloc failed; compact and try again
         GlobalCompact(tableSize + trialSize);  // ignore return value
         for (;;)  {
            if ((tempTableHandle =
               GlobalReAlloc(tableHandle,
                             (tableSize + trialSize),
                             GMEM_MOVEABLE | zeroInitFlag)) != 0)
               // get out of loop if the ReAlloc worked
               { break; };

            // reduce requested size in half and try again
            if ((trialSize >>= 1) < 256)
               return ER_SYM_OUT_OF_MEMORY;
         }
      }
      // memory found
      tableHandle = tempTableHandle;    // restore handle

      // restore huge pointer
      if ((hpTableObject = (HPU8)GlobalLock(tableHandle)) != 0L)  {
         //successful lock; update total memory size
         tableSize += trialSize;

         // even though actual size may be larger than requested size,
         // want to maintain binary boundary of memory so that data
         // elements don't cross 64K boundary
         return SUCCESS;
      } else { //GlobalLock failed
         return ER_SYM_OUT_OF_MEMORY;
      }
   }  // end of else part of if (!tableSize)
   return SUCCESS;
};  // end of Table::InitOrExtendTable


//------------------------------------------------------------------------
// Table::ObliterateTable
//
// Purpose: release this table memory with GlobalFree
//------------------------------------------------------------------------
VOID Table::ObliterateTable(VOID) {

   // call the routines to free memory only if the tableHandle is non-zero ;
   if (tableHandle) {
      GlobalUnlock(tableHandle);
      GlobalFree(tableHandle);
   }
   tableHandle = 0;
   tableSize = 0L;
   initialSize = INITIAL_TABLE_SIZE;
   expandSize = MIN_EXPAND_SIZE;
}

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