/* asmalloc.c -- microsoft 80x86 assembler ** ** microsoft (r) macro assembler ** copyright (c) microsoft corp 1986, 1987. all rights reserved ** ** randy nevin ** michael hobbs 7/87 ** 10/90 - Quick conversion to 32 bit by Jeff Spencer ** ** Storage allocation/deallocation ** ** dalloc, dfree ** talloc, tfree ** nearalloc, faralloc, pBCBalloc, freefarbuf */ #include #include "asm86.h" #include "asmfcn.h" /* * dalloc/dfree * * Allocation/deallocation of descriptor nodes. Uses a list of * deallocated descriptors available for allocation. */ /* dscfree list descriptor */ struct dscfree { struct dscfree *strnext; /* next string in list */ UCHAR size; /* allocated size */ UCHAR text[1]; /* text of string */ }; static struct dscfree *dscrfree = (struct dscfree *)NULL; #define nearheap(fp) ((int)(((long)(char far *)&pcoffset) >> 16) == highWord(fp)) /* * dalloc - allocate descriptor from temporary list */ DSCREC * PASCAL CODESIZE dalloc ( ){ register struct dscfree *t; if (!(t = dscrfree)) t = (struct dscfree *)nalloc( sizeof(DSCREC), "dalloc"); else dscrfree = t->strnext; return((DSCREC *)t); } /* * dfree - return descriptor to free list */ VOID PASCAL CODESIZE dfree ( UCHAR *p ){ register struct dscfree *tp; tp = (struct dscfree *)p; tp->strnext = dscrfree; dscrfree = tp; } /* * talloc, tfree * * Allocation\deallocation of memory. * Allocation is made with minimum size of TEMPMAX bytes. * Any allocation request for <= TEMPMAX bytes will be made * by grabbing a block off the free list. Deallocation of these * blocks returns them to the free list. For blocks larger than * TEMPMAX bytes, nalloc() and free() are called. */ #define TEMPMAX 32 static TEXTSTR FAR *tempfree = (TEXTSTR FAR *)NULL; #ifndef M8086 /* * talloc - allocate space from temporary list */ UCHAR * PASCAL talloc( UINT nbytes ){ register TEXTSTR *t; if (nbytes > TEMPMAX) t = (TEXTSTR *) nalloc(nbytes, "talloc"); else if (!(t = tempfree)) t = (TEXTSTR *) nalloc (TEMPMAX, "talloc"); else tempfree = t->strnext; return ((UCHAR *)t); } /* * tfree - return temp allocation to free list */ VOID PASCAL tfree ( UCHAR *ap, UINT nbytes ){ register TEXTSTR *tp; if (nbytes > TEMPMAX) free (ap); else { tp = (TEXTSTR *)ap; tp->strnext = tempfree; tempfree = tp; } } #else /* * talloc - allocate space from temporary list */ UCHAR FAR * PASCAL CODESIZE talloc( USHORT nbytes ){ TEXTSTR FAR *t; if (nbytes > TEMPMAX) t = (TEXTSTR FAR *) falloc(nbytes, "talloc"); else if (!(t = tempfree)) t = (TEXTSTR FAR *) falloc(TEMPMAX, "talloc"); else tempfree = t->strnext; return ((UCHAR FAR *)t); } /* * tfree - return temp allocation to free list */ VOID PASCAL CODESIZE tfree ( UCHAR FAR *ap, UINT nbytes ){ register TEXTSTR FAR *tp; if (nbytes > TEMPMAX) _ffree (ap); else { tp = (TEXTSTR FAR *)ap; tp->strnext = tempfree; tempfree = tp; } } #endif /* NOT M8086 */ #ifndef M8086 /**** nearalloc - normal near memory allocation * * nearalloc (usize, szfunc) * * Entry usize = number of bytes to allocate * szfunc = name of calling routine * Returns Pointer to block if successful * Calls malloc(), memerror() * Note Generates error if malloc unsuccessful * IF NOT M8086, nalloc AND falloc MAP TO THIS FUNCTION */ UCHAR * CODESIZE PASCAL nearalloc( UINT usize, char * szfunc ){ register char * pchT; if (!(pchT = malloc(usize))) memerror(szfunc); return(pchT); } #else /**** nearalloc - normal near memory allocation * * nearalloc (usize) * * Entry usize = number of bytes to allocate * Returns Pointer to block if successful * Calls malloc(), memerror() * Note Generates error if malloc unsuccessful */ UCHAR * CODESIZE PASCAL nearalloc( USHORT usize ){ register char * pchT; if (!(pchT = malloc(usize))) outofmem(); return(pchT); } /**** faralloc - Routine for normal far memory allocation * * faralloc (usize) * * Entry usize = number of bytes to allocate * Returns Pointer to block if successful * Calls _fmalloc(), nearheap(), freefarbuf(), memerror(), _ffree() * Note Should call instead of _fmalloc(), * at least after the first call to pBCBalloc() has been made. * Not called by pBCBalloc. * Generates error if memory full */ UCHAR FAR * CODESIZE PASCAL faralloc( USHORT usize ){ char FAR * fpchT; #ifdef BCBOPT /* need check of _fmalloc 'ing into near heap too */ while ( (!(fpchT = _fmalloc(usize)) || nearheap(fpchT)) && pBCBAvail) { fBuffering = FALSE; /* can't buffer any more */ if (fpchT) _ffree(fpchT); freefarbuf(); } #endif #ifdef FLATMODEL /* If 32 bit small model then use normal malloc */ fpchT = malloc(usize); #else fpchT = _fmalloc(usize); #endif if (!fpchT) outofmem(); return (fpchT); } #ifdef BCBOPT /**** pBCBalloc - allocate a BCB and associated buffer * * pBCBalloc () * * Entry fBuffering must be TRUE * Returns pointer to BCB (connected to buffer if bufalloc() successful) * Calls bufalloc() * Note Returns a BCB even if buffer allocation fails * Returns NULL only after Out-of-memory error */ BCB * FAR PASCAL pBCBalloc( UINT cbBuf ){ register BCB * pBCBT; char FARIO * pfchT; pBCBT = (BCB *) nearalloc(sizeof(BCB)); #ifndef XENIX286 if ((pfchT = _fmalloc(cbBuf)) && nearheap(pfchT)) { _ffree(pfchT); pfchT = NULL; } if (!(pfchT)) #else pfchT = NULL; #endif { fBuffering = FALSE; /* can't buffer anymore */ pBCBT->filepos = 0; } #ifndef XENIX286 else { pFCBCur->cbufCur = cbBuf; pBCBT->pBCBPrev = pBCBAvail; pBCBAvail = pBCBT; } #endif pFCBCur->pbufCur = pBCBT->pbuf = pfchT; pBCBT->pBCBNext = NULL; pBCBT->fInUse = 0; return(pBCBT); } #endif //BCBOPT #ifdef BCBOPT /**** freefarbuf - free a file buffer * * freefarbuf () * * Entry * Returns * Calls _ffree() * Note Frees the last-allocated file buffer */ freefarbuf( ){ while (pBCBAvail && pBCBAvail->fInUse) pBCBAvail = pBCBAvail->pBCBPrev; if (pBCBAvail) { #ifdef XENIX286 free(pBCBAvail->pbuf); #else _ffree(pBCBAvail->pbuf); #endif pBCBAvail->pbuf = NULL; pBCBAvail = pBCBAvail->pBCBPrev; } } #endif //BCBOPT #endif /* M8086 */ #if 0 /* sleazy way to check for valid heap * _mcalls tells how calls to malloc were made so that * a countdown breakpoint can be set for _mcalls iterations */ extern char *_nmalloc(); long _mcalls; UCHAR * malloc ( UINT n ){ register UINT fb; fb = _freect(0); /* walks near heap - usually loops if corrupt */ _mcalls++; return (_nmalloc(n)); } #endif /* 0 */