1366 lines
		
	
	
		
			36 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			1366 lines
		
	
	
		
			36 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
| /* m4memory.c   (c)Copyright Sequiter Software Inc., 1988-1996.  All rights reserved. */
 | |
| 
 | |
| #ifdef S4OS2
 | |
|    #ifdef __DLL__
 | |
|       #define  INCL_DOSMEMMGR
 | |
|    #endif
 | |
| #endif
 | |
| #include "d4all.h"
 | |
| 
 | |
| #ifdef S4VB_DOS
 | |
|    #include "malloc.h"
 | |
| #endif
 | |
| 
 | |
| #ifdef __TURBOC__
 | |
|    #pragma hdrstop
 | |
| #endif
 | |
| 
 | |
| #ifdef S4OS2
 | |
|    #ifdef __DLL__
 | |
|       #include <bsememf.h>
 | |
|    #endif
 | |
| #endif
 | |
| 
 | |
| #ifdef S4SERVER
 | |
|    /* for 32 bit servers, allow more than 10000 memory allocations... */
 | |
|    #ifndef S4WIN32
 | |
|       #ifdef S4WINTEL
 | |
|          #ifndef S4OS2
 | |
|             #define MEM4MAX_POINTERS 10000
 | |
|          #endif
 | |
|       #endif
 | |
|    #endif
 | |
|    #ifndef MEM4MAX_POINTERS
 | |
|       #define MEM4MAX_POINTERS 100000
 | |
|    #endif
 | |
| #else
 | |
|    #define MEM4MAX_POINTERS 10000
 | |
| #endif
 | |
| 
 | |
| #define mem4numTypes 10
 | |
| 
 | |
| #ifdef S4MEM_PRINT
 | |
|    #ifdef S4WINDOWS
 | |
|       #ifdef S4TESTING
 | |
|          #include "t4test.h"
 | |
|       #endif
 | |
|    #endif
 | |
|    int v4print = 0 ; /* if v4print == 0 then stdout, else stdprn, no output if -1 */
 | |
|    /* use globals to hold the current file name and line number */
 | |
|    const char *m4fileName = 0 ;
 | |
|    int m4lineNo = 0 ;
 | |
|    #ifdef S4WINDOWS
 | |
|       int  S4FUNCTION code4memFileName( void )
 | |
|       {
 | |
|          return m4lineNo ;
 | |
|       }
 | |
| 
 | |
|       const char *S4FUNCTION code4memFileNo( void )
 | |
|       {
 | |
|          return m4fileName ;
 | |
|       }
 | |
| 
 | |
|       void S4FUNCTION code4memLineNoSet( int val )
 | |
|       {
 | |
|          m4lineNo = val ;
 | |
|       }
 | |
| 
 | |
|       void S4FUNCTION code4memFileNameSet( const char *ptr )
 | |
|       {
 | |
|          m4fileName = ptr ;
 | |
|       }
 | |
|    #endif
 | |
| #endif
 | |
| 
 | |
| typedef struct
 | |
| {
 | |
|    LINK4  link ;
 | |
|    MEM4  types[mem4numTypes] ;
 | |
| } MEMORY4GROUP ;
 | |
| 
 | |
| #ifdef S4WIN32
 | |
|    #ifdef S4SEMAPHORE
 | |
|       /* multi-thread support */
 | |
|       CRITICAL_SECTION critical4memory, critical4expression ;
 | |
|    #endif
 | |
| #endif
 | |
| 
 | |
| #ifndef S4CBPP
 | |
|    static LIST4  avail = { 0, 0, 0 } ;   /* A list of available MEM4 entries */
 | |
|    static LIST4  used = { 0, 0, 0 } ;   /* A list of used MEM4 entries */
 | |
|    static LIST4  groups = { 0, 0, 0 } ; /* A list of Allocated MEM4 groups */
 | |
| #else
 | |
|    /* initialization with class and union structures */
 | |
|    static LIST4  avail  = { {0}, 0, {0} } ;   /* A list of available MEM4 entries */
 | |
|    static LIST4  used   = { {0}, {0}, {0} } ;   /* A list of used MEM4 entries */
 | |
|    static LIST4  groups = { {0}, 0, {0} } ;   /* A list of Allocated MEM4 groups */
 | |
| #endif
 | |
| #ifdef S4SEMAPHORE
 | |
|    #ifdef S4WIN32
 | |
|       static int memoryInitialized = 0 ;
 | |
|    #endif
 | |
| #endif
 | |
| 
 | |
| #ifdef S4SEMAPHORE
 | |
| #ifdef S4WIN32
 | |
| int mem4start( CODE4 *c4 )
 | |
| {
 | |
|    if ( memoryInitialized == 0 )
 | |
|       return -1 ;
 | |
| 
 | |
|    EnterCriticalSection( &critical4memory ) ;
 | |
| 
 | |
|    return 0 ;
 | |
| }
 | |
| 
 | |
| void mem4stop( CODE4 *c4 )
 | |
| {
 | |
|    if ( memoryInitialized == 0 )
 | |
|       return ;
 | |
| 
 | |
|    LeaveCriticalSection( &critical4memory ) ;
 | |
| }
 | |
| #else
 | |
| static int mem4start( CODE4 *c4 )
 | |
| {
 | |
|    APIRET rc ;
 | |
| 
 | |
|    #ifdef E4ANALYZE
 | |
|       if ( c4 == 0 )
 | |
|          return error4( c4, e4info, "OS/2 Semaphore Failure" ) ;
 | |
|    #endif
 | |
| 
 | |
|    rc = DosRequestMutexSem( c4->hmtxMem, -1 ) ;
 | |
|    if ( rc != 0 )
 | |
|       return error4( c4, e4info, "OS/2 Semaphore Failure" ) ;
 | |
|    return 0 ;
 | |
| }
 | |
| 
 | |
| static void mem4stop( CODE4 *c4 )
 | |
| {
 | |
|    #ifdef E4ANALYZE
 | |
|       if ( c4 == 0 )
 | |
|       {
 | |
|          error4( c4, e4info, "OS/2 Semaphore Failure" ) ;
 | |
|          return ;
 | |
|       }
 | |
|    #endif
 | |
| 
 | |
|    DosReleaseMutexSem( c4->hmtxMem ) ;
 | |
| }
 | |
| #endif /* S4WIN32 */
 | |
| #endif /* S4SEMAPHORE */
 | |
| 
 | |
| #ifdef E4MISC
 | |
| 
 | |
| static char **mem4testPointers ;
 | |
| static int mem4numPointer = -1 ;
 | |
| static int mem4numUsed = 0 ;
 | |
| 
 | |
| #ifdef S4DATA_ALIGN
 | |
|    #define mem4extraChars 12
 | |
| #else
 | |
|    #define mem4extraChars 10
 | |
| #endif
 | |
| #define mem4extraTot (mem4extraChars*2 + sizeof(unsigned))
 | |
| #define mem4checkChar 0x55
 | |
| 
 | |
| #define MEM4INC 500
 | |
| 
 | |
| /* Returns the pointer to be returned; is passed the pointer allocated by malloc ... */
 | |
| static char *mem4fixPointer( char *startPtr, unsigned largeLen )
 | |
| {
 | |
|    char *returnPtr ;
 | |
|    unsigned pos ;
 | |
| 
 | |
|    memset( startPtr, mem4checkChar, mem4extraChars ) ;
 | |
|    returnPtr = startPtr + mem4extraChars ;
 | |
| 
 | |
|    memcpy( returnPtr, (void *)&largeLen, sizeof(largeLen) ) ;
 | |
|    pos = largeLen - mem4extraChars ;
 | |
|    memset( startPtr+ pos, mem4checkChar, mem4extraChars ) ;
 | |
| 
 | |
|    return returnPtr + sizeof(unsigned) ;
 | |
| }
 | |
| 
 | |
| /* Returns the pointer allocated by malloc; */
 | |
| /* passed by pointer returned by 'mem4fixPointer' */
 | |
| static char *mem4checkPointer( char *returnPtr, int clear )
 | |
| {
 | |
|    unsigned *largeLenPtr ;
 | |
|    char *mallocPtr, *testPtr ;
 | |
|    int i, j ;
 | |
| 
 | |
|    largeLenPtr = (unsigned *)(returnPtr - sizeof(unsigned)) ;
 | |
|    mallocPtr = returnPtr - sizeof(unsigned) - mem4extraChars ;
 | |
| 
 | |
|    for ( j = 0; j < 2; j++ )
 | |
|    {
 | |
|       if (j == 0)
 | |
|          testPtr = mallocPtr ;
 | |
|       else
 | |
|          testPtr = mallocPtr + *largeLenPtr - mem4extraChars ;
 | |
| 
 | |
|       for ( i = 0 ; i < mem4extraChars ; i++ )
 | |
|          if ( testPtr[i] != mem4checkChar )
 | |
|          {
 | |
|             #ifdef S4MEM_PRINT
 | |
|                if ( v4print != -1 )
 | |
|                {
 | |
|                   #ifdef S4WINDOWS
 | |
|                      #ifdef S4TESTING
 | |
|                         d4displayStr( mem4displayPtr, "corrupt memory: ", 1 ) ;
 | |
|                         d4displayPtr( mem4displayPtr, mallocPtr- sizeof(unsigned) - mem4extraChars, 0 ) ;
 | |
|                      #endif
 | |
|                   #else
 | |
|                      if ( v4print )
 | |
|                         fprintf( stdprn, "\r\ncorrupt memory: %p", mallocPtr- sizeof(unsigned) - mem4extraChars ) ;
 | |
|                      else
 | |
|                         printf( "\r\ncorrupt memory: %p", mallocPtr- sizeof(unsigned) - mem4extraChars ) ;
 | |
|                   #endif
 | |
|                }
 | |
|             #endif
 | |
|             error4( 0, e4result, E85901 ) ;
 | |
|             return 0 ;
 | |
|          }
 | |
|    }
 | |
|    if ( clear == 1 ) /* null the memory to potentially detect re-use, including clearing check chars */
 | |
|       memset( mallocPtr, 0, *largeLenPtr ) ;
 | |
|    return mallocPtr ;
 | |
| }
 | |
| 
 | |
| static int mem4pushPointer( char *ptr )
 | |
| {
 | |
|    #ifdef S4WINDOWS
 | |
|       HANDLE handle, *hPtr, *oldHPtr ;
 | |
|       hPtr = (HANDLE *)0 ;
 | |
|    #endif
 | |
| 
 | |
|    if ( mem4numPointer < 0 )
 | |
|    {
 | |
|       #ifdef S4WINDOWS
 | |
|          #ifdef __DLL__
 | |
|             handle = GlobalAlloc( GMEM_MOVEABLE | GMEM_DDESHARE | GMEM_ZEROINIT, (DWORD) sizeof(char *) * MEM4INC + sizeof(HANDLE) ) ;
 | |
|          #else
 | |
|             handle = GlobalAlloc( GMEM_MOVEABLE | GMEM_ZEROINIT, (DWORD) sizeof(char *) * MEM4INC + sizeof(HANDLE) ) ;
 | |
|          #endif
 | |
| 
 | |
|          if ( handle == (HANDLE) 0 )
 | |
|             return error4( 0, e4memory, E95901 ) ;
 | |
| 
 | |
|          hPtr = (HANDLE *)GlobalLock( handle ) ;
 | |
|          *hPtr++ = handle ;
 | |
|          mem4testPointers = (char **)hPtr ;
 | |
|       #else
 | |
|          mem4testPointers = (char **)malloc( sizeof(char *) * MEM4INC ) ;
 | |
|       #endif
 | |
|       mem4numPointer = MEM4INC ;
 | |
|    }
 | |
|    if ( mem4numPointer == mem4numUsed )
 | |
|    {
 | |
|       mem4numPointer += MEM4INC ;
 | |
|       if ( mem4numPointer > MEM4MAX_POINTERS )
 | |
|          return error4( 0, e4result, E95901 ) ;
 | |
| 
 | |
|       #ifdef S4WINDOWS
 | |
|          oldHPtr = (HANDLE *)(mem4testPointers) ;
 | |
|          oldHPtr-- ;  /* get the actual handle */
 | |
| 
 | |
|          #ifdef __DLL__
 | |
|             handle = GlobalReAlloc( *oldHPtr, (DWORD)sizeof(char *) * mem4numPointer + sizeof( HANDLE ), GMEM_MOVEABLE ) ;
 | |
|          #else
 | |
|             handle = GlobalReAlloc( *oldHPtr, (DWORD)sizeof(char *) * mem4numPointer + sizeof( HANDLE ), GMEM_MOVEABLE ) ;
 | |
|          #endif
 | |
| 
 | |
|          if ( handle == (HANDLE) 0 )
 | |
|             return error4( 0, e4memory, E95901 ) ;
 | |
| 
 | |
|          hPtr = (HANDLE *)GlobalLock( handle ) ;
 | |
|          *hPtr++ = handle ;
 | |
|          mem4testPointers = (char **)hPtr ;
 | |
|       #else
 | |
|          mem4testPointers = (char **)realloc( (void *)mem4testPointers, sizeof(char *)*mem4numPointer ) ;
 | |
|       #endif
 | |
|    }
 | |
| 
 | |
|    if ( mem4testPointers == 0 )
 | |
|       return error4( 0, e4memory, E95901 ) ;
 | |
| 
 | |
|    mem4testPointers[mem4numUsed++] = ptr ;
 | |
| 
 | |
|    return 0 ;
 | |
| }
 | |
| 
 | |
| static int mem4popPointer( char *ptr )
 | |
| {
 | |
|    int i ;
 | |
| 
 | |
|    if ( mem4testPointers == 0 )   /* failure in allocating tracking memory, so allow shutdown */
 | |
|    {
 | |
|       mem4numUsed-- ;
 | |
|       return 0 ;
 | |
|    }
 | |
| 
 | |
|    for ( i = mem4numUsed - 1 ; i >= 0 ; i-- )
 | |
|       if ( mem4testPointers[i] == ptr )
 | |
|       {
 | |
|          /* This 'memmove' may create compile warning */
 | |
|          c4memmove( mem4testPointers+i, mem4testPointers+i+1, (size_t) (sizeof(char *) * (mem4numUsed-i-1))) ;
 | |
|          mem4numUsed-- ;
 | |
|          return 0 ;
 | |
|       }
 | |
| 
 | |
|    return error4( 0, e4result, E95902 ) ;
 | |
| }
 | |
| 
 | |
| int S4FUNCTION mem4checkMemory()
 | |
| {
 | |
|    int i ;
 | |
|    char *ptr ;
 | |
| 
 | |
|    if ( code4numCodeBase() == 0 )
 | |
|       return 0 ;
 | |
| 
 | |
|    #ifdef S4SEMAPHORE
 | |
|       mem4start( 0 ) ;
 | |
|    #endif
 | |
| 
 | |
|    for ( i = 0; i < mem4numUsed; i++ )
 | |
|    {
 | |
|       ptr = mem4checkPointer( mem4testPointers[i], 0 ) ;
 | |
|       if ( ptr == 0 )
 | |
|          return error4( 0, e4result, E95903 ) ;
 | |
|    }
 | |
| 
 | |
|    #ifdef S4SEMAPHORE
 | |
|       mem4stop( 0 ) ;
 | |
|    #endif
 | |
| 
 | |
|    return 0 ;
 | |
| }
 | |
| 
 | |
| int S4FUNCTION mem4freeCheck( const int maxLeft )
 | |
| {
 | |
|    #ifdef S4MEM_PRINT
 | |
|       int i ;
 | |
|       if ( v4print != -1 )
 | |
|       {
 | |
|          #ifdef S4WINDOWS
 | |
|             #ifdef S4TESTING
 | |
|                for ( i = 0; i < mem4numUsed; i++ )
 | |
|                {
 | |
|                   d4displayStr( mem4displayPtr, "mem4freeCheck: ", 1 ) ;
 | |
|                   d4displayPtr( mem4displayPtr, mem4testPointers[i], 0 ) ;
 | |
|                }
 | |
|             #endif
 | |
|          #else
 | |
|             if ( v4print )
 | |
|                for ( i = 0; i < mem4numUsed; i++ )
 | |
|                   fprintf( stdprn, "\r\nmem4freeCheck: %p", mem4testPointers[i] ) ;
 | |
|             else
 | |
|                for ( i = 0; i < mem4numUsed; i++ )
 | |
|                   printf( "\r\nmem4freeCheck: %p", mem4testPointers[i] ) ;
 | |
|          #endif
 | |
|       }
 | |
|    #endif
 | |
| 
 | |
|    if ( mem4numUsed > maxLeft )
 | |
|       return error4( 0, e4result, 95904 ) ;
 | |
| 
 | |
|    return ( mem4numUsed ) ;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| void *S4FUNCTION mem4allocDefault( MEM4 *memoryType )
 | |
| {
 | |
|    #ifdef E4PARM_HIGH
 | |
|       if ( memoryType == 0 )
 | |
|       {
 | |
|          error4( 0, e4parm_null, E95905 ) ;
 | |
|          return 0 ;
 | |
|       }
 | |
|    #endif
 | |
| 
 | |
|    return mem4alloc2Default( memoryType, 0 ) ;
 | |
| }
 | |
| 
 | |
| static Y4CHUNK *mem4allocChunkDefault( MEM4 *typePtr )
 | |
| {
 | |
|    Y4CHUNK *chunkPtr ;
 | |
|    int  nAllocate, i ;
 | |
|    char *ptr ;
 | |
|    long allocSize ;
 | |
| 
 | |
|    nAllocate = typePtr->unitExpand ;
 | |
|    if ( l4last( &typePtr->chunks ) == 0 )
 | |
|       nAllocate = typePtr->unitStart ;
 | |
| 
 | |
|    for ( ;; )
 | |
|    {
 | |
|       allocSize = (long)sizeof( LINK4 ) + (long)nAllocate * typePtr->unitSize ;
 | |
|       if ( allocSize < UINT_MAX )
 | |
|          break ;
 | |
|       if ( nAllocate <= 1 )
 | |
|          return 0 ;
 | |
|       nAllocate = nAllocate / 2 ;
 | |
|    }
 | |
| 
 | |
|    #ifdef S4DOS    /* no memory sharing under DOS, so can use a CODE4 for limited memory */
 | |
|       chunkPtr = (Y4CHUNK *)u4allocFreeDefault( typePtr->codeBase, allocSize ) ;
 | |
|    #else
 | |
|       chunkPtr = (Y4CHUNK *)u4alloc( allocSize ) ;
 | |
|    #endif
 | |
|    if ( chunkPtr == 0 )
 | |
|       return 0 ;
 | |
|    ptr = (char *)&chunkPtr->data ;
 | |
|    for ( i = 0 ; i < nAllocate ; i++ )
 | |
|       l4add( &typePtr->pieces, (LINK4 *)( ptr + i * typePtr->unitSize ) ) ;
 | |
| 
 | |
|    return  chunkPtr ;
 | |
| }
 | |
| 
 | |
| static void *mem4allocLow( MEM4 *memoryType )
 | |
| {
 | |
|    LINK4 *nextPiece ;
 | |
|    Y4CHUNK *newChunk ;
 | |
|    #ifdef E4MISC
 | |
|       char *ptr ;
 | |
|    #endif
 | |
|    #ifdef S4OS2_SEMAPHORE
 | |
|       #ifdef __DLL__
 | |
|          ULONG flags ;
 | |
|       #endif
 | |
|    #endif
 | |
| 
 | |
|    if ( memoryType == 0 )
 | |
|       return 0 ;
 | |
|    nextPiece = (LINK4 *)l4pop( &memoryType->pieces ) ;
 | |
| 
 | |
|    if ( nextPiece != 0 )
 | |
|    {
 | |
|       #ifdef S4SEMAPHORE
 | |
|          #ifdef S4OS2
 | |
|             #ifdef __DLL__
 | |
|                /* get access to the memory */
 | |
|                flags = PAG_WRITE | PAG_READ  ;
 | |
|                if ( DosGetSharedMem( nextPiece, flags ) != 0 )
 | |
|                   return 0 ;
 | |
|             #endif
 | |
|          #endif
 | |
|       #endif
 | |
|       #ifdef E4MISC
 | |
|          memoryType->nUsed++ ;
 | |
|          ptr = mem4fixPointer( (char *)nextPiece, memoryType->unitSize ) ;
 | |
| 
 | |
|          if ( mem4pushPointer( ptr ) == e4memory )
 | |
|          {
 | |
|             memoryType->nUsed-- ;
 | |
|             l4add( &memoryType->pieces, nextPiece ) ;
 | |
|             return 0 ;
 | |
|          }
 | |
| 
 | |
|          #ifdef S4MEM_PRINT
 | |
|             if ( v4print != -1 )
 | |
|             {
 | |
|                #ifdef S4WINDOWS
 | |
|                   #ifdef S4TESTING
 | |
|                      {
 | |
|                         d4displayStr( mem4displayPtr, "  Y4ALLOC:  ", 1 ) ;
 | |
|                         d4displayPtr( mem4displayPtr, ptr, 0 ) ;
 | |
|                         d4displayStr( mem4displayPtr, "  file:  ", 0 ) ;
 | |
|                         d4displayStr( mem4displayPtr, m4fileName, 0 ) ;
 | |
|                         d4displayStr( mem4displayPtr, "  line:  ", 0 ) ;
 | |
|                         d4displayNum( mem4displayPtr, m4lineNo, 0 ) ;
 | |
|                      }
 | |
|                   #endif
 | |
|                #else
 | |
|                   if ( v4print )
 | |
|                      fprintf( stdprn, "\r\n  Y4ALLOC:  %lx  file:  %s  line:  %12d", ptr, m4fileName, m4lineNo ) ;
 | |
|                   else
 | |
|                      printf( "\r\n  Y4ALLOC:  %lx  file:  %s  line:  %12d", ptr, m4fileName, m4lineNo  ) ;
 | |
|                #endif
 | |
|             }
 | |
|          #endif
 | |
| 
 | |
|          return (void *)ptr ;
 | |
|       #else
 | |
|          return nextPiece ;
 | |
|       #endif
 | |
|    }
 | |
| 
 | |
|    if ( (newChunk = mem4allocChunkDefault( memoryType )) == 0 )
 | |
|       return 0 ;
 | |
|    l4add( &memoryType->chunks, &newChunk->link ) ;
 | |
| 
 | |
|    memoryType->nUsed++ ;
 | |
|    #ifdef E4MISC
 | |
|       ptr = mem4fixPointer( (char *)l4pop(&memoryType->pieces),
 | |
|                             memoryType->unitSize ) ;
 | |
|       #ifdef S4MEM_PRINT
 | |
|          if ( v4print != -1 )
 | |
|          {
 | |
|             #ifdef S4WINDOWS
 | |
|                #ifdef S4TESTING
 | |
|                   {
 | |
|                      d4displayStr( mem4displayPtr, "  Y4ALLOC:  ", 1 ) ;
 | |
|                      d4displayPtr( mem4displayPtr, ptr, 0 ) ;
 | |
|                      d4displayStr( mem4displayPtr, "  file:  ", 0 ) ;
 | |
|                      d4displayStr( mem4displayPtr, m4fileName, 0 ) ;
 | |
|                      d4displayStr( mem4displayPtr, "  line:  ", 0 ) ;
 | |
|                      d4displayNum( mem4displayPtr, m4lineNo, 0 ) ;
 | |
|                   }
 | |
|                #endif
 | |
|             #else
 | |
|                if ( v4print )
 | |
|                   fprintf( stdprn, "\r\n  Y4ALLOC:  %lx  file:  %s  line:  %12d", ptr, m4fileName, m4lineNo ) ;
 | |
|                else
 | |
|                   printf( "\r\n  Y4ALLOC:  %lx  file:  %s  line:  %12d", ptr, m4fileName, m4lineNo  ) ;
 | |
|             #endif
 | |
|          }
 | |
|       #endif
 | |
| 
 | |
|       mem4pushPointer( ptr ) ;
 | |
|       return (void *)ptr ;
 | |
|    #else
 | |
|       return l4pop( &memoryType->pieces ) ;
 | |
|    #endif
 | |
| }
 | |
| 
 | |
| void *S4FUNCTION mem4alloc2Default( MEM4 *memoryType, CODE4 *c4 )
 | |
| {
 | |
|    void *ptr ;
 | |
| 
 | |
|    if ( code4numCodeBase() == 0 )
 | |
|       return 0 ;
 | |
| 
 | |
|    if ( c4 )
 | |
|       if ( error4code( c4 ) < 0 )
 | |
|          return 0 ;
 | |
| 
 | |
|    #ifdef S4SEMAPHORE
 | |
|       mem4start( c4 ) ;
 | |
|    #endif
 | |
| 
 | |
|    ptr = mem4allocLow( memoryType ) ;
 | |
| 
 | |
|    #ifdef S4SEMAPHORE
 | |
|       #ifdef S4WIN32
 | |
|          mem4stop( c4 ) ;
 | |
|       #else
 | |
|          mem4stop( memoryType->codeBase ) ;
 | |
|       #endif
 | |
|    #endif
 | |
| 
 | |
|    if ( ptr == 0 )
 | |
|    {
 | |
|       if ( c4 )
 | |
|          error4set( c4, e4memory ) ;
 | |
|       return 0 ;
 | |
|    }
 | |
|    #ifdef E4MISC
 | |
|       memset( ptr, 0, memoryType->unitSize - mem4extraTot ) ;
 | |
|    #else
 | |
|       memset( ptr, 0, memoryType->unitSize ) ;
 | |
|    #endif
 | |
|    return ptr ;
 | |
| }
 | |
| 
 | |
| MEM4 *S4FUNCTION mem4createDefault( CODE4 *c4, int start, const unsigned int uSize, int expand, const int isTemp )
 | |
| {
 | |
|    MEM4 *onType ;
 | |
|    unsigned int unitSize ;
 | |
|    #ifdef S4SEMAPHORE
 | |
|       #ifdef S4OS2
 | |
|          #ifdef __DLL__
 | |
|             ULONG flags ;
 | |
|          #endif
 | |
|       #endif
 | |
|    #endif
 | |
| 
 | |
|    #ifdef E4PARM_HIGH
 | |
|       /* c4 == 0 is allowable */
 | |
|       if (  start < 1 || expand < 1 )
 | |
|       {
 | |
|          error4( c4, e4parm, E95906 ) ;
 | |
|          return 0 ;
 | |
|       }
 | |
|    #endif
 | |
| 
 | |
|    if ( code4numCodeBase() == 0 )
 | |
|       return 0 ;
 | |
| 
 | |
|    if ( uSize < sizeof( LINK4 ) )   /* ensure enough so that we can keep track of the memory */
 | |
|       unitSize = sizeof( LINK4 ) ;
 | |
|    else
 | |
|       unitSize = uSize ;
 | |
| 
 | |
|    #ifdef E4MISC
 | |
|       unitSize += 2 * mem4extraChars + sizeof( unsigned ) ;
 | |
|    #endif
 | |
| 
 | |
|    if ( c4 )
 | |
|       if ( error4code( c4 ) < 0 )
 | |
|          return 0 ;
 | |
| 
 | |
|    #ifdef S4SEMAPHORE
 | |
|       mem4start( c4 ) ;
 | |
|    #endif
 | |
| 
 | |
|    if ( !isTemp )
 | |
|       for( onType = 0 ;; )
 | |
|       {
 | |
|          onType = (MEM4 *)l4next( &used, onType ) ;
 | |
|          if ( onType == 0 )
 | |
|             break ;
 | |
| 
 | |
|          #ifdef S4SEMAPHORE
 | |
|             #ifdef S4OS2
 | |
|                #ifdef __DLL__
 | |
|                   /* get access to the memory */
 | |
|                   flags = PAG_WRITE | PAG_READ  ;
 | |
|                   if ( DosGetSharedMem( onType, flags ) != 0 )
 | |
|                      return 0 ;
 | |
|                #endif
 | |
|             #endif
 | |
|          #endif
 | |
| 
 | |
|          #ifdef S4DOS    /* no memory sharing under DOS, so can use a CODE4 for limited memory */
 | |
|             if ( onType->codeBase == c4 || onType->codeBase == 0 )
 | |
|          #endif
 | |
|          if ( onType->unitSize == unitSize && onType->nRepeat > 0 )
 | |
|          {
 | |
|             /* Match */
 | |
|             if ( start > onType->unitStart )
 | |
|                onType->unitStart = start ;
 | |
|             if ( expand > onType->unitExpand)
 | |
|                onType->unitExpand = expand ;
 | |
|             onType->nRepeat++ ;
 | |
|             #ifdef S4SEMAPHORE
 | |
|                mem4stop( c4 ) ;
 | |
|             #endif
 | |
|             #ifdef S4DOS
 | |
|                if ( onType->codeBase == 0 )  /* set to avoid code4initUndo() errors */
 | |
|                   onType->codeBase = c4 ;
 | |
|             #endif
 | |
|             return onType ;
 | |
|          }
 | |
|       }
 | |
| 
 | |
|    /* Allocate memory for another MEM4 */
 | |
| 
 | |
|    onType = (MEM4 *)l4last( &avail ) ;
 | |
|    if ( onType == 0 )
 | |
|    {
 | |
|       MEMORY4GROUP *group ;
 | |
|       int i ;
 | |
| 
 | |
|       #ifdef S4MEM_PRINT
 | |
|          char *nullPtr = 0 ;
 | |
| 
 | |
|          if ( v4print != -1 )
 | |
|          {
 | |
|             #ifdef S4WINDOWS
 | |
|                #ifdef S4TESTING
 | |
|                   {
 | |
|                      d4displayStr( mem4displayPtr, "  MEM4:  ", 1 ) ;
 | |
|                      d4displayPtr( mem4displayPtr, nullPtr, 0 ) ;
 | |
|                      d4displayStr( mem4displayPtr, "  file:  ", 0 ) ;
 | |
|                      d4displayStr( mem4displayPtr, "ignoreNextLine", 0 ) ;
 | |
|                      d4displayStr( mem4displayPtr, "  line:  ", 0 ) ;
 | |
|                      d4displayNum( mem4displayPtr, 0, 0 ) ;
 | |
|                      d4displayStr( mem4displayPtr, "  num bytes:  ", 0 ) ;
 | |
|                      d4displayNum( mem4displayPtr, 0, 0 ) ;
 | |
|                   }
 | |
|                #endif
 | |
|             #else
 | |
|                if ( v4print )
 | |
|                   fprintf( stdprn, "\r\n  MEM4:  %lx  file:  ignoreNextLine  line:  %12d  num bytes:  %12d", nullPtr, 0, 0 ) ;
 | |
|                else
 | |
|                   printf("\r\n  MEM4:  %lx  file:  ignoreNextLine  line:  %12d  num bytes:  %12d", nullPtr, 0, 0 ) ;
 | |
|             #endif
 | |
|          }
 | |
|       #endif
 | |
| 
 | |
|       group = (MEMORY4GROUP *)u4allocFreeDefault( c4, (long)sizeof( MEMORY4GROUP ) ) ;
 | |
|       if ( group == 0 )
 | |
|       {
 | |
|          if ( c4 )
 | |
|             error4set( c4, e4memory ) ;
 | |
|          #ifdef S4SEMAPHORE
 | |
|             mem4stop( c4 ) ;
 | |
|          #endif
 | |
|          return 0 ;
 | |
|       }
 | |
| 
 | |
|       for ( i = 0 ; i < mem4numTypes ; i++ )
 | |
|          l4add( &avail, group->types + i ) ;
 | |
|       onType = (MEM4 *)l4last( &avail ) ;
 | |
|       l4add( &groups, group ) ;
 | |
|    }
 | |
| 
 | |
|    l4remove( &avail, onType ) ;
 | |
|    memset( (void *)onType, 0, sizeof( MEM4 ) ) ;
 | |
|    l4add( &used, onType ) ;
 | |
| 
 | |
|    onType->unitStart = start ;
 | |
|    onType->unitSize = unitSize ;
 | |
|    onType->unitExpand= expand ;
 | |
|    onType->nRepeat = 1 ;
 | |
|    onType->nUsed = 0 ;
 | |
|    if ( isTemp )
 | |
|       onType->nRepeat = -1 ;
 | |
| 
 | |
|    #ifdef S4SEMAPHORE
 | |
|       mem4stop( c4 ) ;
 | |
|    #endif
 | |
| 
 | |
|    #ifdef S4MEM_PRINT
 | |
|       if ( v4print != -1 )
 | |
|       {
 | |
|          #ifdef S4WINDOWS
 | |
|             #ifdef S4TESTING
 | |
|                {
 | |
|                   d4displayStr( mem4displayPtr, "  MEM4:     ", 1 ) ;
 | |
|                   d4displayPtr( mem4displayPtr, onType, 0 ) ;
 | |
|                   d4displayStr( mem4displayPtr, "  file:  ", 0 ) ;
 | |
|                   d4displayStr( mem4displayPtr, m4fileName, 0 ) ;
 | |
|                   d4displayStr( mem4displayPtr, "  line:  ", 0 ) ;
 | |
|                   d4displayNum( mem4displayPtr, m4lineNo, 0 ) ;
 | |
|                }
 | |
|             #endif
 | |
|          #else
 | |
|             if ( v4print )
 | |
|                fprintf( stdprn, "\r\n  MEM4:     %lx  file:  %s  line:  %12d", onType, m4fileName, m4lineNo ) ;
 | |
|             else
 | |
|                printf( "\r\n  MEM4:     %lx  file:  %s  line:  %12d", onType, m4fileName, m4lineNo ) ;
 | |
|          #endif
 | |
|       }
 | |
|    #endif
 | |
| 
 | |
|    #ifdef S4DOS    /* no memory sharing under DOS, so can use a CODE4 for limited memory */
 | |
|       onType->codeBase = c4 ;
 | |
|    #endif
 | |
|    return onType ;
 | |
| }
 | |
| 
 | |
| void *S4FUNCTION mem4createAllocDefault( CODE4 *c4, MEM4 **typePtrPtr, int start, const unsigned int unitSize, int expand, const int isTemp)
 | |
| {
 | |
|    if ( *typePtrPtr == 0 )
 | |
|    {
 | |
|       *typePtrPtr = mem4createDefault( c4, start, unitSize, expand, isTemp ) ;
 | |
|       if ( *typePtrPtr == 0 )
 | |
|          return 0 ;
 | |
|    }
 | |
| 
 | |
|    return mem4alloc2Default( *typePtrPtr, c4 ) ;
 | |
| }
 | |
| 
 | |
| int S4FUNCTION mem4freeDefault( MEM4 *memoryType, void *freePtr )
 | |
| {
 | |
|    #ifdef E4MISC
 | |
|       int rc ;
 | |
|       LINK4 *holdPtr ;
 | |
|    #endif
 | |
| 
 | |
|    if ( freePtr == 0 )  /* as documented */
 | |
|       return 0 ;
 | |
| 
 | |
|    if ( memoryType == 0 )
 | |
|       return error4( 0, e4parm_null, E95907 ) ;
 | |
| 
 | |
|    if ( code4numCodeBase() == 0 )
 | |
|       return 0 ;
 | |
| 
 | |
|    #ifdef S4SEMAPHORE
 | |
|       mem4start( 0 ) ;
 | |
|    #endif
 | |
| 
 | |
|    memoryType->nUsed-- ;
 | |
|    #ifdef E4MISC
 | |
|       if ( memoryType->nUsed < 0 )
 | |
|       {
 | |
|          #ifdef S4SEMAPHORE
 | |
|             mem4stop( 0 ) ;
 | |
|          #endif
 | |
|          return error4( 0, e4result, E95907 ) ;
 | |
|       }
 | |
| 
 | |
|       rc = mem4popPointer( (char *)freePtr ) ;
 | |
|       holdPtr = (LINK4 *)mem4checkPointer( (char *)freePtr, 0 ) ;
 | |
|       if ( holdPtr != 0 )
 | |
|       {
 | |
|          l4add( &memoryType->pieces, holdPtr ) ;
 | |
|          #ifdef S4MEM_PRINT
 | |
|             if ( v4print != -1 )
 | |
|             {
 | |
|                #ifdef S4WINDOWS
 | |
|                   #ifdef S4TESTING
 | |
|                      {
 | |
|                         d4displayStr( mem4displayPtr, "  Y4FREE:   ", 1 ) ;
 | |
|                         d4displayPtr( mem4displayPtr, freePtr, 0 ) ;
 | |
|                         d4displayStr( mem4displayPtr, "  file:  ", 0 ) ;
 | |
|                         d4displayStr( mem4displayPtr, m4fileName, 0 ) ;
 | |
|                         d4displayStr( mem4displayPtr, "  line:  ", 0 ) ;
 | |
|                         d4displayNum( mem4displayPtr, m4lineNo, 0 ) ;
 | |
|                      }
 | |
|                   #endif
 | |
|                #else
 | |
|                   if ( v4print )
 | |
|                      fprintf(stdprn, "\r\n  Y4FREE:   %lx  file:  %s  line:  %12d", freePtr, m4fileName, m4lineNo ) ;
 | |
|                   else
 | |
|                      printf( "\r\n  Y4FREE:   %lx  file:  %s  line:  %12d", freePtr, m4fileName, m4lineNo ) ;
 | |
|                #endif
 | |
|             }
 | |
|          #endif
 | |
|       }
 | |
| 
 | |
|       memset( ((char *)freePtr), 0, memoryType->unitSize - 2 * mem4extraChars - sizeof( unsigned ) ) ;
 | |
|       #ifdef S4SEMAPHORE
 | |
|          mem4stop( 0 ) ;
 | |
|       #endif
 | |
|       return rc ;
 | |
|    #else
 | |
|       l4add( &memoryType->pieces, (LINK4 *)freePtr ) ;
 | |
|       #ifdef S4SEMAPHORE
 | |
|          mem4stop( 0 ) ;
 | |
|       #endif
 | |
|       return 0 ;
 | |
|    #endif
 | |
| }
 | |
| 
 | |
| void S4FUNCTION mem4release( MEM4 *memoryType )
 | |
| {
 | |
|    void *ptr ;
 | |
| 
 | |
|    if ( memoryType == 0 )
 | |
|       return ;
 | |
| 
 | |
|    if ( code4numCodeBase() == 0 )
 | |
|       return ;
 | |
| 
 | |
|    #ifdef S4SEMAPHORE
 | |
|       mem4start( 0 ) ;
 | |
|    #endif
 | |
| 
 | |
|    memoryType->nRepeat-- ;
 | |
|    if ( memoryType->nRepeat <= 0 )
 | |
|    {
 | |
|       for(;;)
 | |
|       {
 | |
|          ptr = l4pop( &memoryType->chunks) ;
 | |
|          if ( ptr == 0 )
 | |
|             break ;
 | |
|          u4freeDefault( ptr ) ;
 | |
|       }
 | |
| 
 | |
|       l4remove( &used, memoryType ) ;
 | |
|       l4add( &avail, memoryType ) ;
 | |
| 
 | |
|       #ifdef S4MEM_PRINT
 | |
|          if ( v4print != -1 )
 | |
|          {
 | |
|             #ifdef S4WINDOWS
 | |
|                #ifdef S4TESTING
 | |
|                   {
 | |
|                      d4displayStr( mem4displayPtr, "  Y4RELEASE:  ", 1 ) ;
 | |
|                      d4displayPtr( mem4displayPtr, memoryType, 0 ) ;
 | |
|                   }
 | |
|                #endif
 | |
|             #else
 | |
|                if ( v4print )
 | |
|                   fprintf( stdprn, "\r\n  Y4RELEASE:  %lx", memoryType ) ;
 | |
|                else
 | |
|                   printf( "\r\n  Y4RELEASE:  %lx", memoryType ) ;
 | |
|             #endif
 | |
|          }
 | |
|       #endif
 | |
|    }
 | |
| 
 | |
|    #ifdef S4SEMAPHORE
 | |
|       mem4stop( 0 ) ;
 | |
|    #endif
 | |
| }
 | |
| 
 | |
| #ifdef S4TESTING
 | |
|    int s4allocOff = 0 ;
 | |
| #endif
 | |
| 
 | |
| #ifdef S4MAX
 | |
|    static long mem4maxMemory = 16384 ;
 | |
|    static long mem4allocated = 0L ;
 | |
| 
 | |
|    long u4allocated( void )
 | |
|    {
 | |
|       return mem4allocated ;
 | |
|    }
 | |
| 
 | |
|    long u4max( void )
 | |
|    {
 | |
|       return mem4maxMemory ;
 | |
|    }
 | |
| #endif
 | |
| 
 | |
| void *S4FUNCTION u4allocDefault( long n )
 | |
| {
 | |
|    size_t s ;
 | |
|    char *ptr ;
 | |
|    #ifdef S4SEMAPHORE
 | |
|       #ifdef S4OS2
 | |
|          #ifdef __DLL__
 | |
|             ULONG    flags;
 | |
|             APIRET   rc;
 | |
|          #endif
 | |
|       #endif
 | |
|    #endif
 | |
|    #ifdef S4WINDOWS
 | |
|       HANDLE  handle, *hPtr ;
 | |
|    #endif
 | |
| 
 | |
|    #ifdef S4TESTING
 | |
|       if ( s4allocOff == 1 )   /* for testing, emulate out of memory conditions */
 | |
|          return 0 ;
 | |
|    #endif
 | |
| 
 | |
|    #ifdef E4PARM_HIGH
 | |
|       if ( n == 0L )
 | |
|       {
 | |
|          error4( 0, e4parm, E85903 ) ;
 | |
|          return 0 ;
 | |
|       }
 | |
|       #ifdef E4MISC
 | |
|          n += mem4extraChars*2 + sizeof(unsigned) ;
 | |
|       #endif
 | |
|    #endif
 | |
| 
 | |
|    #ifdef S4MAX
 | |
|       n += sizeof( long ) ;   /* room for length */
 | |
|       if ( mem4allocated + n > mem4maxMemory )
 | |
|          return 0 ;
 | |
|    #endif
 | |
| 
 | |
|    s = (size_t) n ;
 | |
|    if ( n > (long) s )
 | |
|       return 0 ;
 | |
| 
 | |
|    #ifdef S4WINDOWS
 | |
|       #ifdef __DLL__
 | |
|          handle = GlobalAlloc( GMEM_MOVEABLE | GMEM_DDESHARE | GMEM_ZEROINIT, (DWORD) s+ sizeof(HANDLE) ) ;
 | |
|       #else
 | |
|          handle = GlobalAlloc( GMEM_MOVEABLE | GMEM_ZEROINIT, (DWORD) s+ sizeof(HANDLE) ) ;
 | |
|       #endif
 | |
| 
 | |
|       if ( handle == (HANDLE)0 )
 | |
|          return 0 ;
 | |
| 
 | |
|       hPtr = (HANDLE *)GlobalLock( handle ) ;
 | |
|       *hPtr++ = handle ;
 | |
|       ptr = (char *)hPtr ;
 | |
|    #else
 | |
|       #ifdef __DLL__
 | |
|          #ifdef S4OS2_SEMAPHORE
 | |
|             flags = PAG_WRITE | PAG_READ | OBJ_GETTABLE ;
 | |
|             rc = DosAllocSharedMem( (void *)&ptr, 0, s, flags ) ;
 | |
| 
 | |
|             if (rc != 0)
 | |
|                return 0 ;
 | |
|             flags = PAG_WRITE | PAG_READ ;
 | |
|             rc = DosGetSharedMem( ptr, flags ) ;
 | |
|             if ( rc != 0 )
 | |
|                return 0 ;
 | |
|          #else
 | |
|             ptr = (char *)malloc( s ) ;
 | |
| 
 | |
|             if ( ptr == 0 )
 | |
|                return 0 ;
 | |
| 
 | |
|             #ifndef S4PASCAL_WIN
 | |
|                memset( ptr, 0, s ) ;
 | |
|             #endif
 | |
|          #endif
 | |
|       #else
 | |
|          ptr = (char *)malloc( s ) ;
 | |
| 
 | |
|          if ( ptr == 0 )
 | |
|             return 0 ;
 | |
| 
 | |
|                               /* Borland malloc of 64K (or close to) will */
 | |
|          #ifdef __TURBOC__    /* result in corruption of segment memory due */
 | |
|             if ( (ptr+s-1 <= ptr) && (s > 1 ))    /* to wrap-around problems  */
 | |
|             {
 | |
|                free( ptr ) ;
 | |
|                return 0 ;
 | |
|             }
 | |
|          #endif
 | |
| 
 | |
|          #ifndef S4PASCAL_WIN
 | |
|             memset( ptr, 0, s ) ;
 | |
|          #endif
 | |
|       #endif
 | |
|    #endif
 | |
| 
 | |
|    #ifdef S4MEM_PRINT
 | |
|       if ( v4print != -1 )
 | |
|       {
 | |
|          #ifdef S4WINDOWS
 | |
|             #ifdef S4TESTING
 | |
|                {
 | |
|                   d4displayStr( mem4displayPtr, "  U4ALLOC:  ", 1 ) ;
 | |
|                   d4displayPtr( mem4displayPtr, ptr, 0 ) ;
 | |
|                   d4displayStr( mem4displayPtr, "  file:  ", 0 ) ;
 | |
|                   d4displayStr( mem4displayPtr, m4fileName, 0 ) ;
 | |
|                   d4displayStr( mem4displayPtr, "  line:  ", 0 ) ;
 | |
|                   d4displayNum( mem4displayPtr, m4lineNo, 0 ) ;
 | |
|                   d4displayStr( mem4displayPtr, "  num bytes:  ", 0 ) ;
 | |
|                   d4displayNum( mem4displayPtr, n, 0 ) ;
 | |
|                }
 | |
|             #endif
 | |
|          #else
 | |
|             if ( v4print )
 | |
|                fprintf( stdprn, "\r\n  U4ALLOC:  %lx  file:  %s  line:  %12d  num bytes:  %12ld", ptr, m4fileName, m4lineNo, n ) ;
 | |
|             else
 | |
|                printf("\r\n  U4ALLOC:  %lx  file:  %s  line:  %12d  num bytes:  %12ld", ptr, m4fileName, m4lineNo, n ) ;
 | |
|          #endif
 | |
|       }
 | |
|    #endif
 | |
| 
 | |
|    #ifdef E4MISC
 | |
|       #ifdef S4SEMAPHORE
 | |
|          mem4start( 0 ) ;
 | |
|       #endif
 | |
|       ptr = mem4fixPointer( ptr, s ) ;
 | |
|       mem4pushPointer( ptr ) ;
 | |
|       memset( ptr, 0, s-mem4extraChars*2 - sizeof(unsigned) ) ;
 | |
|       #ifdef S4SEMAPHORE
 | |
|          mem4stop( 0 ) ;
 | |
|       #endif
 | |
|    #endif
 | |
| 
 | |
|    #ifdef S4MAX
 | |
|       #ifdef S4SEMAPHORE
 | |
|          mem4start( 0 ) ;
 | |
|       #endif
 | |
|       mem4allocated += n ;
 | |
|       #ifdef S4SEMAPHORE
 | |
|          mem4stop( 0 ) ;
 | |
|       #endif
 | |
|       *((long *)ptr) = n ;
 | |
|       ptr += sizeof( long ) ;
 | |
|    #endif
 | |
| 
 | |
|    return (void *)ptr ;
 | |
| }
 | |
| 
 | |
| void S4FUNCTION u4freeFixedDefault( FIXED4MEM fixedMem )
 | |
| {
 | |
|    #ifdef S4USE_LOW_MEMORY
 | |
|       if ( ( GetWinFlags() & WF_ENHANCED ) == WF_ENHANCED )
 | |
|          GlobalPageUnlock( (HGLOBAL)s4protected( fixedMem ) ) ;
 | |
|       GlobalDosFree( (HGLOBAL)s4protected( fixedMem ) ) ;
 | |
|    #else
 | |
|       u4freeDefault( fixedMem ) ;
 | |
|    #endif
 | |
| }
 | |
| 
 | |
| /* u4alloc_fixed() allocates fixed memory blocks in the lower 1 MEG of ram.
 | |
|    It is used for allocating memory that is to be used with DOS interrupts.
 | |
| */
 | |
| FIXED4MEM S4FUNCTION u4allocFixedDefault( CODE4 *c4, long n )
 | |
| {
 | |
|    #ifdef S4USE_LOW_MEMORY
 | |
|       size_t s ;
 | |
|       FIXED4MEM fixedMem ;
 | |
| 
 | |
|       memset( &fixedMem, 0, sizeof( FIXED4MEM ) ) ;
 | |
| 
 | |
|       #ifdef E4PARM_LOW
 | |
|          if ( c4 == 0 )
 | |
|          {
 | |
|             error4( 0, e4parm_null, E95908 ) ;
 | |
|             return fixedMem ;
 | |
|          }
 | |
| 
 | |
|          if ( n == 0L )
 | |
|          {
 | |
|             error4( c4, e4parm, E85903 ) ;
 | |
|             return fixedMem ;
 | |
|          }
 | |
|          n += mem4extraChars*2 + sizeof(unsigned) ;
 | |
|       #endif
 | |
| 
 | |
|       s = (size_t)n ;
 | |
|       if ( n > (long)s )
 | |
|          return fixedMem ;
 | |
| 
 | |
|       #ifdef __DLL__
 | |
|          fixedMem.block = GlobalDosAlloc( (DWORD)s + sizeof(HANDLE) ) ;
 | |
|       #else
 | |
|          fixedMem.block = GlobalDosAlloc( (DWORD)s + sizeof(HANDLE) ) ;
 | |
|       #endif
 | |
| 
 | |
|       if ( fixedMem.block == 0 )
 | |
|          return fixedMem ;
 | |
| 
 | |
|       if ( ( GetWinFlags() & WF_ENHANCED ) == WF_ENHANCED )
 | |
|          GlobalPageLock( (HGLOBAL)s4protected( fixedMem ) ) ;
 | |
| 
 | |
|       memset( (void *)s4protected( fixedMem ), 0, (size_t)n ) ;
 | |
|       return fixedMem ;
 | |
|    #else
 | |
|       return u4allocFreeDefault( c4, n ) ;
 | |
|    #endif
 | |
| }
 | |
| 
 | |
| void *S4FUNCTION u4allocErDefault( CODE4 *c4, long n )
 | |
| {
 | |
|    void *ptr = (void *)u4allocFreeDefault( c4, n ) ;
 | |
|    if ( ptr == 0 && c4 )
 | |
|       error4( c4, e4memory, E95909 ) ;
 | |
| 
 | |
|    return ptr ;
 | |
| }
 | |
| 
 | |
| int S4FUNCTION u4freeDefault( void *ptr )
 | |
| {
 | |
|    int rc ;
 | |
|    #ifdef S4WINDOWS
 | |
|       HANDLE  hand ;
 | |
|    #endif
 | |
| 
 | |
|    #ifdef S4MAX
 | |
|       long amount ;
 | |
|    #endif
 | |
| 
 | |
|    rc = 0 ;
 | |
| 
 | |
|    if ( code4numCodeBase() == 0 )
 | |
|       return 0 ;
 | |
| 
 | |
|    if ( ptr == 0 )
 | |
|       return 0 ;
 | |
| 
 | |
|    #ifdef S4MAX
 | |
|       ptr = ((char *)ptr) - sizeof( long ) ;
 | |
|       amount = *((long *)ptr) ;
 | |
|       #ifdef S4SEMAPHORE
 | |
|          mem4start( 0 ) ;
 | |
|       #endif
 | |
|       mem4allocated -= amount ;
 | |
|       #ifdef S4SEMAPHORE
 | |
|          mem4stop( 0 ) ;
 | |
|       #endif
 | |
|    #endif
 | |
| 
 | |
|    #ifdef S4WINDOWS
 | |
|       #ifdef E4MISC
 | |
|          rc = mem4popPointer( (char *)ptr ) ;
 | |
|          ptr = mem4checkPointer( (char *)ptr, 1 ) ;
 | |
|          if ( (char *)ptr == 0 )  /* error during mem check */
 | |
|             return -1 ;
 | |
|          hand = ((HANDLE *)(char *)ptr)[-1] ;
 | |
|       #else
 | |
|          hand = ((HANDLE *)ptr)[-1] ;
 | |
|       #endif
 | |
| 
 | |
|       #ifdef S4MEM_PRINT
 | |
|          if ( v4print != -1 )
 | |
|          {
 | |
|             #ifdef S4WINDOWS
 | |
|                #ifdef S4TESTING
 | |
|                   d4displayStr( mem4displayPtr, "  U4FREE:   ", 1 ) ;
 | |
|                   d4displayPtr( mem4displayPtr, ptr, 0 ) ;
 | |
|                   d4displayStr( mem4displayPtr, "  file:  ", 0 ) ;
 | |
|                   d4displayStr( mem4displayPtr, m4fileName, 0 ) ;
 | |
|                   d4displayStr( mem4displayPtr, "  line:  ", 0 ) ;
 | |
|                   d4displayNum( mem4displayPtr, m4lineNo, 0 ) ;
 | |
|                #endif
 | |
|             #endif
 | |
|          }
 | |
|       #endif
 | |
|       GlobalUnlock( hand ) ;
 | |
|       hand = GlobalFree( hand ) ;
 | |
| 
 | |
|       if ( hand != (HANDLE) 0 )
 | |
|          return error4( 0, e4memory, E95910 ) ;
 | |
|    #else
 | |
|       #ifdef E4MISC
 | |
|          #ifdef S4SEMAPHORE
 | |
|             mem4start( 0 ) ;
 | |
|          #endif
 | |
|          rc = mem4popPointer( (char *)ptr ) ;
 | |
|          ptr = mem4checkPointer( (char *)ptr, 1 ) ;
 | |
|          #ifdef S4SEMAPHORE
 | |
|             mem4stop( 0 ) ;
 | |
|          #endif
 | |
| 
 | |
|          #ifdef S4MEM_PRINT
 | |
|             if ( v4print != -1 )
 | |
|             {
 | |
|                #ifdef S4WINDOWS
 | |
|                   #ifdef S4TESTING
 | |
|                      {
 | |
|                         d4displayStr( mem4displayPtr, "  U4FREE:  ", 1 ) ;
 | |
|                         d4displayPtr( mem4displayPtr, ptr, 0 ) ;
 | |
|                         d4displayStr( mem4displayPtr, "  file:  ", 0 ) ;
 | |
|                         d4displayStr( mem4displayPtr, m4fileName, 0 ) ;
 | |
|                         d4displayStr( mem4displayPtr, "  line:  ", 0 ) ;
 | |
|                         d4displayNum( mem4displayPtr, m4lineNo, 0 ) ;
 | |
|                      }
 | |
|                   #endif
 | |
|                #else
 | |
|                   if ( v4print )
 | |
|                      fprintf( stdprn, "\r\n  U4FREE:  %lx  file:  %s  line:  %12d", ptr, m4fileName, m4lineNo  ) ;
 | |
|                   else
 | |
|                      printf( "\r\n U4FREE:  %lx  file:  %s  line:  %12d", ptr, m4fileName, m4lineNo  );
 | |
|                #endif
 | |
|             }
 | |
|          #endif
 | |
| 
 | |
|          free( ptr ) ;
 | |
|       #else
 | |
|          #ifdef S4MEM_PRINT
 | |
|             if ( v4print != -1 )
 | |
|             {
 | |
|                #ifdef S4WINDOWS
 | |
|                   #ifdef S4TESTING
 | |
|                      {
 | |
|                         d4displayStr( mem4displayPtr, "  U4FREE:  ", 1 ) ;
 | |
|                         d4displayPtr( mem4displayPtr, ptr, 0 ) ;
 | |
|                         d4displayStr( mem4displayPtr, "  file:  ", 0 ) ;
 | |
|                         d4displayStr( mem4displayPtr, m4fileName, 0 ) ;
 | |
|                         d4displayStr( mem4displayPtr, "  line:  ", 0 ) ;
 | |
|                         d4displayNum( mem4displayPtr, m4lineNo, 0 ) ;
 | |
|                      }
 | |
|                   #endif
 | |
|                #else
 | |
|                   if ( v4print )
 | |
|                      fprintf( stdprn, "\r\n  U4FREE:  %lx  file:  %s  line:  %12d", ptr, m4fileName, m4lineNo  ) ;
 | |
|                   else
 | |
|                      printf( "\r\n  U4FREE:  %lx  file:  %s  line:  %12d", ptr, m4fileName, m4lineNo  );
 | |
|                #endif
 | |
|             }
 | |
|          #endif
 | |
| 
 | |
|          free( ptr ) ;
 | |
|       #endif
 | |
|    #endif
 | |
| 
 | |
|    return rc ;
 | |
| }
 | |
| 
 | |
| int mem4reset( void )
 | |
| {
 | |
|    MEM4 *onType ;
 | |
|    LINK4 *onChunk, *onGroup ;
 | |
|    #ifdef S4WINDOWS
 | |
|       #ifdef E4MISC
 | |
|          HANDLE hand ;
 | |
|       #endif
 | |
|    #endif
 | |
|    #ifdef S4LOCK_CHECK
 | |
|       return error4( 0, e4result, E85904 ) ;
 | |
|    #endif
 | |
| 
 | |
|    for( onType = 0 ;; )
 | |
|    {
 | |
|       onType = (MEM4 *)l4next(&used,onType) ;
 | |
|       if ( onType == 0 )
 | |
|          break ;
 | |
|       do
 | |
|       {
 | |
|          onChunk = (LINK4 *)l4pop( &onType->chunks) ;
 | |
|          u4freeDefault( onChunk ) ;  /* free of 0 still succeeds */
 | |
|       } while ( onChunk ) ;
 | |
|    }
 | |
| 
 | |
|    for( ;; )
 | |
|    {
 | |
|       onGroup = (LINK4 *)l4pop( &groups ) ;
 | |
|       if ( onGroup == 0 )
 | |
|          break ;
 | |
|       u4freeDefault( onGroup ) ;
 | |
|    }
 | |
| 
 | |
|    #ifdef E4MISC
 | |
|       if ( mem4numPointer > 0 )
 | |
|       {
 | |
|          #ifdef S4WINDOWS
 | |
|             hand = ((HANDLE *)mem4testPointers)[-1] ;
 | |
| 
 | |
|             GlobalUnlock( hand ) ;
 | |
|             hand = GlobalFree( hand ) ;
 | |
| 
 | |
|             if ( hand != (HANDLE)0 )
 | |
|                return error4( 0, e4memory, E95911 ) ;
 | |
|          #else
 | |
|             #ifdef S4MEM_PRINT
 | |
|                if ( v4print != -1 )
 | |
|                {
 | |
|                   #ifdef S4WINDOWS
 | |
|                      #ifdef S4TESTING
 | |
|                         {
 | |
|                            d4displayStr( mem4displayPtr, "  MEM4RESET:  ", 1 ) ;
 | |
|                            d4displayPtr( mem4displayPtr, mem4testPointers, 0 ) ;
 | |
|                      #endif
 | |
|                   #else
 | |
|                      if ( v4print )
 | |
|                         fprintf( stdprn, "\r\n  MEM4RESET:  %lx", mem4testPointers ) ;
 | |
|                      else
 | |
|                         printf( "\r\n  MEM4RESET:  %lx", mem4testPointers );
 | |
|                   #endif
 | |
|                }
 | |
|             #endif
 | |
| 
 | |
|             free( (void *)mem4testPointers ) ;
 | |
|          #endif
 | |
| 
 | |
|          mem4testPointers = 0 ;
 | |
|          mem4numPointer = -1 ;
 | |
|          mem4numUsed = 0 ;
 | |
|       }
 | |
|    #endif
 | |
| 
 | |
|    mem4init() ;
 | |
| 
 | |
|    #ifdef S4SEMAPHORE
 | |
|       #ifdef S4WIN32
 | |
|          DeleteCriticalSection( &critical4memory ) ;
 | |
|          DeleteCriticalSection( &critical4expression ) ;
 | |
|       #endif
 | |
|    #endif
 | |
| 
 | |
|    #ifdef S4SEMAPHORE
 | |
|       #ifdef S4WIN32
 | |
|          memoryInitialized = 0 ;
 | |
|       #endif
 | |
|    #endif
 | |
| 
 | |
|    return 0 ;
 | |
| }
 | |
| 
 | |
| void mem4init( void )
 | |
| {
 | |
|    if ( code4numCodeBase() != 0 )
 | |
|       return ;
 | |
| 
 | |
|    #ifdef S4SEMAPHORE
 | |
|       #ifdef S4WIN32
 | |
|          memoryInitialized = 1 ;
 | |
|       #endif
 | |
|    #endif
 | |
| 
 | |
|    #ifdef S4SEMAPHORE
 | |
|       #ifdef S4WIN32
 | |
|          InitializeCriticalSection( &critical4memory ) ;
 | |
|          InitializeCriticalSection( &critical4expression ) ;
 | |
|       #endif
 | |
|       mem4start( 0 ) ;
 | |
|    #endif
 | |
|    memset( (void *)&avail, 0, sizeof( avail ) ) ;
 | |
|    memset( (void *)&used, 0, sizeof( used ) ) ;
 | |
|    memset( (void *)&groups, 0, sizeof( groups ) ) ;
 | |
|    #ifdef S4SEMAPHORE
 | |
|       mem4stop( 0 ) ;
 | |
|    #endif
 | |
| }
 | |
| 
 |