windows-nt/Source/XPSP1/NT/sdktools/masm/asmalloc.c
2020-09-26 16:20:57 +08:00

394 lines
6.6 KiB
C

/* 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 <stdio.h>
#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 */