.ad 8
.bm 8
.fm 4
.bt $Copyright by   Software AG, 1993$$Page %$
.tm 12
.hm 6
.hs 3
.tt 1 $NME$Project Distributed Database System$vos57c$
.tt 2 $$$
.tt 3 $R.Roedling$commmon alloc$1997-06-16$
***********************************************************
.nf


    ========== licence begin LGPL
    Copyright (C) 2002 SAP AG

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    ========== licence end

.fo
.nf
.spc
Module  : common_alloc
=========
.sp
Purpose :
.CM *-END-* purpose -------------------------------------
.sp
.cp 3
Define  :

.CM *-END-* define --------------------------------------
.sp;.cp 3
Use     :

.CM *-END-* use -----------------------------------------
.sp;.cp 3
Synonym :

.CM *-END-* synonym -------------------------------------
.sp;.cp 3
Author  : M. Oezgen
.sp
.cp 3
Created : 16.02.92
.sp
.cp 3
Version :
.sp
.cp 3
Release :  6.2 	 Date : 1997-06-16
.br
.sp
***********************************************************
.sp
.cp 10
.fo
.oc _/1
Specification:

.CM *-END-* specification -------------------------------
.sp 2
***********************************************************
.sp
.cp 10
.fo
.oc _/1
Description:

.CM *-END-* description ---------------------------------
.sp 2
***********************************************************
.sp
.cp 10
.nf
.oc _/1
Structure:

.CM *-END-* structure -----------------------------------
.sp 2
**********************************************************
.sp
.cp 10
.nf
.oc _/1
.CM -lll-
Code    :
/*PRETTY*/


//
//  INCLUDE FILES
//


//
//  DEFINES
//

#define MOD__  "VOS57C : "
#define MF__   MOD__"UNDEFINED"

//
//  MACROS
//
#if defined(_WIN32)
 #define MK_PA(f)                (*lp##f)

 #define LOAD_FUNC(f)            ((lp##f = sql57c_load_func(#f)) == NULL) ? \
                                   -1 : NO_ERROR
 #define CALL_FUNC(fdll, forg,p) (( lp##fdll == NULL ) ? ##forg##p : lp##fdll##p)
#endif


//
//  LOCAL TYPE AND STRUCT DEFINITIONS
//
#if defined(_WIN32)
 typedef HANDLE              POOLTYP;
#else
 typedef PVOID               POOLTYP;
#endif

#if ALIGNMENT_VALUE < 4
 #define INFOAREA_SIZE       sizeof(ULONG)
#else
 #define INFOAREA_SIZE       ALIGNMENT_VALUE
#endif

#define COMP_NAME_LEN        30
#define COMP_NAME_FORMAT     "%30.30s"
//
// EXTERNAL VARIABLES
//


//
//  EXPORTED VARIABLES
//


//
// LOCAL VARIABLES
//
static POOLTYP    pvAllocPool   = NULL;

#if defined(_WIN32)
 static HINSTANCE  hinstDLL      = NULL;

 static HANDLE MK_PA (HeapCreateP)  ( DWORD  flOptions,
                                      DWORD  dwInitialSize,
                                      DWORD  dwMaximumSize );
 static LPVOID MK_PA (HeapAllocP)   ( HANDLE hHeap,
                                      DWORD  dwFlags,
                                      DWORD  dwBytes );
 static BOOL MK_PA   (HeapFreeP)    ( HANDLE hHeap,
                                      DWORD  dwFlags,
                                      LPVOID lpMem );
 static BOOL MK_PA   (HeapDestroyP) ( HANDLE hHeap );
#endif

//
// LOCAL FUNCTION PROTOTYPES
//
#if defined(_WIN32)
 static ULONG sql57c_load_functions (  VOID );
 static VOID* sql57c_load_func      (  PSZ  pszFuncName );
#endif

#if defined (DEBUG_MEM_ALLOC)
 static VOID sql57_compress_path ( PSZ    pszCompPathName,
                                   PSZ    pszPathName,
                                   ULONG  ulCompPathLen );
#endif


//
// ========================== GLOBAL FUNCTIONS ================================
//


APIRET  sql57c_malloc   ( ULONG   ulLine,
                          PSZ     pszModuleName,
                          PPVOID  ppvMemBlock,
                          ULONG   ulSize )
  {
  #undef  MF__
  #define MF__ MOD__"sql57c_malloc"

  static BOOL     fMessOutputPending = FALSE;
  APIRET          rc                 = NO_ERROR;
  ULONG           ulInfoAreaSize;
  #if defined (DEBUG_MEM_ALLOC)
   CHAR           szCompModName[COMP_NAME_LEN + 1];
  #endif


  DBGIN;

  DBG3  (( MF__, "Memory size requested: %ld", ulSize ));

  if ( !pvAllocPool )
    {
    #if defined(_WIN32)
     if ( hinstDLL  == NULL )
       sql57c_load_functions ();

     pvAllocPool = CALL_FUNC( HeapCreateP, HeapCreate,(0, 1, 0));

     if  (pvAllocPool == NULL)
       rc = ERROR_NOT_ENOUGH_MEMORY;
    #else
      rc = DosAllocMem (&pvAllocPool, MAX_ALLOC_POOL_SIZE,
                        PAG_READ | PAG_WRITE);
    #endif

    if ( rc != NO_ERROR )
      {
      // --- message output might produce additional allocation errors
      if ( !fMessOutputPending )
        {
        fMessOutputPending = TRUE;
        DBG1  (( MF__, "No more memory" ));
        MSGCD (( ERR_ALLOC_MEMORY, rc   ));
        fMessOutputPending = FALSE;
        }

      pvAllocPool     = NULL;
      *ppvMemBlock    = NULL;

      DBGOUT;
      return ( rc );
      }

    #if !defined(_WIN32)
     rc = DosSubSetMem ( pvAllocPool, DOSSUB_INIT | DOSSUB_SPARSE_OBJ,
                         MAX_ALLOC_POOL_SIZE );
     if ( rc != NO_ERROR )
       {
       // --- message output might produce additional allocation errors
       if ( !fMessOutputPending )
         {
         fMessOutputPending = TRUE;
         DBG1  (( MF__, "No more memory" ));
         MSGCD (( IERR_CANT_SUBSET_MEMORY, rc ));
         fMessOutputPending = FALSE;
         }

       DosFreeMem ( pvAllocPool );

       pvAllocPool   = NULL;
       *ppvMemBlock  = NULL;

       DBGOUT;
       return ( rc );
       }
    #endif
    }

  ulInfoAreaSize = ALIGN ( sizeof(ULONG), ALIGNMENT_VALUE );
  ulSize        += ulInfoAreaSize;

  if ( ulSize < ulInfoAreaSize )  // - overrun error
     rc = ERROR_NOT_ENOUGH_MEMORY;
  else
    {
    #if defined(_WIN32)
     *ppvMemBlock = CALL_FUNC( HeapAllocP, HeapAlloc,
                               (pvAllocPool, HEAP_ZERO_MEMORY, ulSize));

     if ( *ppvMemBlock == NULL )
       rc = ERROR_NOT_ENOUGH_MEMORY;
    #else
     rc  = DosSubAllocMem  ( pvAllocPool, ppvMemBlock, ulSize );
    #endif
    }

  if ( rc != NO_ERROR )
    {
    // --- message output might produce additional allocation errors
    if ( !fMessOutputPending )
      {
      fMessOutputPending = TRUE;
      DBG1  (( MF__, "No more memory" ));
      MSGCD (( ERR_CANT_ALLOC_HEAP_MEMORY, rc ));
      fMessOutputPending = FALSE;
      }

    *ppvMemBlock  = NULL;

    DBGOUT;
    return ( rc );
    }

  **( ULONG** ) ppvMemBlock  = ulSize;
  *( char** ) ppvMemBlock   += ulInfoAreaSize;

  #if defined (DEBUG_MEM_ALLOC)
   sql57_compress_path ( szCompModName, pszModuleName, COMP_NAME_LEN );

   MSGD(( 19999,INFO_TYPE, "ALLOC   ",
          "'%4d':'"COMP_NAME_FORMAT"' - 0x%08x, size: %d",
          ulLine, szCompModName, *ppvMemBlock, ulSize ));
  #endif


  DBGOUT;
  return ( rc );
  }


/*------------------------------*/


APIRET  sql57c_free ( ULONG   ulLine,
                      PSZ     pszModuleName,
                      PVOID   pvMemBlock )
  {
  #undef  MF__
  #define MF__ MOD__"sql57c_free"

  APIRET          rc       = NO_ERROR;
  ULONG           ulSize   = 0;
  ULONG           ulInfoAreaSize;
  #if defined (DEBUG_MEM_ALLOC)
   CHAR           szCompModName[COMP_NAME_LEN + 1];
  #endif


  DBGIN;

  if (( pvMemBlock ) && ( pvAllocPool ))
    {
    ulInfoAreaSize = ALIGN ( sizeof(ULONG), ALIGNMENT_VALUE );
    pvMemBlock     = (char*) pvMemBlock - ulInfoAreaSize;
    ulSize         = *(ULONG*) pvMemBlock;

    #if defined (DEBUG_MEM_ALLOC)
     sql57_compress_path ( szCompModName, pszModuleName, COMP_NAME_LEN );

     MSGD(( 19999,INFO_TYPE, "FREE    ",
            "'%4d':'"COMP_NAME_FORMAT"' - 0x%08x, size: %d",
            ulLine, szCompModName,
            (char*)pvMemBlock + ulInfoAreaSize, ulSize));
    #endif



    #if defined(_WIN32)
     if ( !CALL_FUNC( HeapFreeP, HeapFree,(pvAllocPool, 0, pvMemBlock)) )
       rc = ERROR_INVALID_BLOCK;
    #else
     rc = DosSubFreeMem ( pvAllocPool, pvMemBlock, ulSize );
    #endif
    }
  else
    {
    rc = ERROR_INVALID_BLOCK;

    #if defined (DEBUG_MEM_ALLOC)
     sql57_compress_path ( szCompModName, pszModuleName, COMP_NAME_LEN );

     MSGD(( 19999,INFO_TYPE, "FREE    ",
            "'%4d':'"COMP_NAME_FORMAT"' - NULL",
            ulLine, szCompModName ));
    #endif
    }

  if ( rc != NO_ERROR)
    {
    DBG1  (( MF__, "Can not free memory" ));
    MSGD (( IERR_CANT_FREE_HEAP_MEMORY, rc ));
    }


  DBGOUT;

  return ( rc );
  }

/*------------------------------*/

APIRET  sql57c_realloc  ( ULONG   ulLine,
                          PSZ     pszModuleName,
                          PPVOID  ppvMemBlock,
                          ULONG   ulSize )
  {
  #undef  MF__
  #define MF__ MOD__"sql57c_realloc"

  PVOID           pvOldMemBlock     = *ppvMemBlock ;
  APIRET          rc                 = NO_ERROR;

  DBGIN;

  DBG3  (( MF__, "Memory size requested: %ld", ulSize ));
  rc = sql57c_malloc ( ulLine, pszModuleName, ppvMemBlock, ulSize );

  if ( rc == NO_ERROR )
    {
    ULONG           ulOldSize,
                    ulInfoAreaSize = ALIGN ( sizeof(ULONG), ALIGNMENT_VALUE );
    pvOldMemBlock  = ( char* ) pvOldMemBlock - ulInfoAreaSize;
    ulOldSize      = *( ULONG* ) pvOldMemBlock;
    memcpy ( (char *) *ppvMemBlock, (char *) pvOldMemBlock, ulOldSize ) ;

    rc = sql57c_free ( ulLine, pszModuleName,
                       ( char* ) pvOldMemBlock + ulInfoAreaSize);
    }

  DBGOUT;

  return ( rc );
  }

/*------------------------------*/

VOID sql57c_heap_destroy ( VOID )
  {
  #undef  MF__
  #define MF__ MOD__"sql57c_heap_destroy"

  if ( pvAllocPool )
    {
    #if defined(_WIN32)
     CALL_FUNC( HeapDestroyP, HeapDestroy,( pvAllocPool ));
     pvAllocPool = NULL;
    #endif
    }

  DBGOUT;

  return;
  }


//
// ========================== LOCAL FUNCTIONS =================================
//

#if defined(_WIN32)
 static ULONG sql57c_load_functions(  VOID )
   {
   #undef  MF__
   #define MF__ MOD__"sql57c_load_functions"
   LONG             rc         = NO_ERROR;
   static BOOL      fFirstTime = FALSE;

   DBGIN;

   if ( !fFirstTime )
     {
     rc = LOAD_FUNC( HeapCreateP );

     if (rc == NO_ERROR ) rc = LOAD_FUNC( HeapAllocP );
     if (rc == NO_ERROR ) rc = LOAD_FUNC( HeapFreeP );
     if (rc == NO_ERROR ) rc = LOAD_FUNC( HeapDestroyP );

     if ( rc != NO_ERROR )
       {
       lpHeapCreateP  =  NULL;
       lpHeapAllocP   =  NULL;
       lpHeapFreeP    =  NULL;
       lpHeapDestroyP =  NULL;

       FreeLibrary( hinstDLL);
       hinstDLL = NULL;
       }
     fFirstTime = TRUE;
     }

   DBGOUT;
   return ( rc );
   }

/*------------------------------*/

 static VOID* sql57c_load_func(  PSZ  pszFuncName )
   {
   #undef  MF__
   #define MF__ MOD__"sql57c_load_func"
   static PSZ       pszDLL;
   HINSTANCE        hinst = NULL;
   LONG             rc    = NO_ERROR;
   FARPROC          pFunc;

   DBGIN;

   if ( hinstDLL == NULL )
     {
     hinst = LoadLibrary( "adamema.dll" );

     if ( hinst == NULL )
       {
       DBGOUT;
       return ( NULL );
       }

     hinstDLL = hinst;
     }

   pFunc = GetProcAddress( hinstDLL, pszFuncName);

   DBGOUT;
   return ( pFunc );
   }
#endif

/*------------------------------*/

#if defined (DEBUG_MEM_ALLOC)
 static VOID sql57_compress_path ( PSZ    pszCompPathName,
                                   PSZ    pszPathName,
                                   ULONG  ulCompPathLen )
   {
   #undef  MF__
   #define MF__ MOD__"sql57_compress_path"
   LONG           lPathLen;
   LONG           lSplitPos;
   LONG           lRest;

   DBGPAS;

   if ( ulCompPathLen < 4 )
     {
     pszCompPathName[0] = '\0';
     return;
     }

   lPathLen = strlen ( pszPathName );

   if ( lPathLen > (INT)ulCompPathLen )
     {
     lSplitPos = (ulCompPathLen / 2) - 2;
     lRest     = ulCompPathLen - lSplitPos - 4;

     strncpy ( pszCompPathName, pszPathName, lSplitPos );
     pszCompPathName [ lSplitPos ] = '\0';
     strcat ( pszCompPathName, "...." );
     strcat ( pszCompPathName, pszPathName + lPathLen - lRest );
     }
   else
     strcpy ( pszCompPathName, pszPathName );

   return;
   }
#endif

//
// =============================== END ========================================
//
.CM *-END-* code ----------------------------------------
.SP 2
***********************************************************
.PA
