/* 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 #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 ) ; } 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 }