394 lines
6.6 KiB
C
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 */
|