summaryrefslogblamecommitdiffstats
path: root/private/sdktools/masm/asmalloc.c
blob: b4d1f69f167f72da8b9493be004574760005a327 (plain) (tree)








































































































































































































































































































































































































                                                                                 
/* 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 */