home *** CD-ROM | disk | FTP | other *** search
- #include <string.h>
- #include "memalloc.h"
-
- #ifdef __cplusplus
- extern "C" {
- #endif
-
- #define moveleft(d,s,l) memcpy(d,s,l)
- #define moveright(d,s,l) memmove(d,s,l)
- #define mcbsize 16
-
- #ifdef __86__
-
- #include <dos.h>
- #ifdef __TURBOC__
- #include <alloc.h>
- #define memadd(p,i) ((mem_ptr)((char huge*)(p)+(i))+mcbsize)
- #else /*__TURBOC__*/
- #define memadd(p,i) (hugeadd((p),(i))+mcbsize)
- #endif /*__TURBOC__*/
- #define blkmax 0xff00L /* <= 0xff00 ! */
-
- #else /*__86__*/
-
- #include <stdlib.h>
- #define memadd(p,i) ((p)+(i)+mcbsize)
-
- #endif /*__86__*/
-
- #define true 1
- #define false 0
-
- #ifndef __386__
- #define bufsizmax 0xfff0 /* max size of memory buffer */
- #endif /*__386__*/
-
- #define prev(memp) (((memptr)(memp)-1)->m_prev)
- #define next(memp) (((memptr)(memp)-1)->m_next)
- #define size(memp) (((memptr)(memp)-1)->m_size)
- #define datp(memp) (((memptr)(memp)-1)->m_datp)
- #ifdef __86__
- #define used(memp) (*((unsigned short*)&((memptr)(memp)-1)->m_datp+1))
- #else /*__86__*/
- #define used(memp) ((unsigned)(((memptr)(memp)-1)->m_datp))
- #endif /*__86__*/
-
- typedef struct
- {
- mem_ptr m_prev; /* previous memory block */
- mem_ptr m_next; /* next memory block */
- long m_size; /* length of memory block without mcb */
- mem_ptr* m_datp; /* pointer to pointer in user program */
- } memrec; /*16*/
- typedef memrec FAR* memptr;
-
- static long memfree; /* size of free memory */
- static mem_ptr memory; /* memory heap */
- static mem_ptr memend; /* end of memory */
-
- #ifdef __86__
-
- #ifndef __TURBOC__
- static mem_ptr hugeadd(mem_ptr p, long i)
- {
- i+=(unsigned short)p;
- *((unsigned short*)&p+1) += (*((unsigned short*)&i+1)<<12)
- + ((unsigned short)i>>4);
- *(unsigned short*)&p = (unsigned short)i&15;
- return(p);
- }
- #endif /*__TURBOC__*/
-
-
- void hugemoveleft(void FAR* dst, void FAR* src, long len)
- {
- for ( ; len>blkmax; len-=blkmax)
- {
- moveleft((char FAR*)dst,(char FAR*)src,(unsigned)blkmax);
- *((unsigned short*)&dst+1)+=((unsigned short)blkmax>>4);
- *((unsigned short*)&src+1)+=((unsigned short)blkmax>>4);
- }
- moveleft((char FAR*)dst,(char FAR*)src,(unsigned)len);
- }
-
-
- void hugemoveright(void FAR* dst, void FAR* src, long len)
- {
- int n;
-
- for (n=0; len>blkmax; len-=blkmax,n++)
- {
- *((unsigned short*)&dst+1)+=((unsigned short)blkmax>>4);
- *((unsigned short*)&src+1)+=((unsigned short)blkmax>>4);
- }
- moveright((char FAR*)dst,(char FAR*)src,(unsigned)len);
- for ( ; n>0; n--)
- {
- *((unsigned short*)&dst+1)-=((unsigned short)blkmax>>4);
- *((unsigned short*)&src+1)-=((unsigned short)blkmax>>4);
- moveright((char FAR*)dst,(char FAR*)src,(unsigned)blkmax);
- }
- }
-
- #else /*__86__*/
-
- #define hugemoveleft(d,s,l) moveleft(d,s,l)
- #define hugemoveright(d,s,l) moveright(d,s,l)
-
- #endif /*__86__*/
-
-
- /* allocate allmost all of available memory in one block */
- void mem_init(long bufsize)
- {
- mem_ptr bufp; /* beginning of memory */
-
- #ifdef __386__
-
- #ifdef __ZTC__
- #if 0
- memfree=_memmax()-16386; //_memmax() is useless
- if (bufsize!=0 && memfree>bufsize)
- memfree=bufsize;
- bufp=malloc(memfree);
- #else /*0*/
- int i;
- unsigned len;
- void* p[128];
-
- memfree=0;
- if (bufsize!=0)
- {
- bufp=malloc(bufsize);
- if (bufp!=NULL)
- memfree=bufsize;
- }
-
- if (memfree==0)
- {
- /* allocate all available memory */
- len=1<<(8*sizeof(int)-1);
- i=0;
- do
- {
- p[i]=malloc(len-sizeof(int));
- if (p[i]!=NULL)
- {
- memfree+=len;
- i++;
- }
- else
- len>>=1;
- }
- while (i<sizeof(p)/sizeof(*p) && len>=4096);
-
- /* free all pointers */
- for (i--; i>=0; i--)
- free(p[i]);
-
- memfree-=sizeof(int);
-
- /* allocate one big block */
- for (;;)
- {
- bufp=malloc((unsigned)memfree);
- if (bufp!=NULL)
- break;
- memfree-=1024;
- }
- }
- #endif /*0*/
- #endif /*__ZTC__*/
-
- #else /*__386__*/
-
- #ifdef __86__
- memfree=farcoreleft();
- if (bufsize!=0 && memfree>bufsize)
- memfree=bufsize;
- bufp=farmalloc(memfree);
- #else /*__86__*/
- memfree=bufsizmax;
- if (bufsize!=0 && memfree>bufsize)
- memfree=bufsize;
- for (;;)
- {
- bufp=malloc((unsigned)memfree);
- if (bufp!=NULL)
- break;
- memfree-=1024;
- }
- #endif /*__86__*/
-
- #endif /*__386__*/
-
- memory=bufp+mcbsize;
- prev(memory)=NULL;
- next(memory)=NULL;
- size(memory)=memfree-mcbsize;
- datp(memory)=NULL;
- memend=memadd(memory,memfree-mcbsize);
- }
-
-
- /* free all memory */
- void mem_exit(void)
- {
- #ifdef __86__
- farfree(memory-mcbsize);
- #else /*__86__*/
- free(memory-mcbsize);
- #endif /*__86__*/
- }
-
-
- /* exchange used block with free block to the left */
- static void NEAR moveblockleft(mem_ptr memp0)
- {
- long size0;
- mem_ptr memp9; /* prev block */
- mem_ptr memp1; /* next block */
-
- memp9=prev(memp0);
- memp1=next(memp0);
- size0=size(memp0);
- datp(memp9)=datp(memp0);
- *datp(memp9)=memp9;
- hugemoveleft(memp9,memp0,size0);
- memp0=memadd(memp9,size0);
- prev(memp0)=memp9;
- next(memp0)=memp1;
- size(memp0)=size(memp9);
- datp(memp0)=NULL;
- next(memp9)=memp0;
- size(memp9)=size0;
- if (memp1!=NULL)
- prev(memp1)=memp0;
- }
-
-
- /* exchange used block with free block to the right */
- static void NEAR moveblockright(mem_ptr memp0)
- {
- long size0;
- mem_ptr memp1; /* next block */
- mem_ptr memp2;
-
- memp1=next(memp0);
- memp2=next(memp1);
- size0=size(memp0);
- size(memp0)=size(memp1);
- memp1=memadd(memp0,size(memp0));
- hugemoveright(memp1,memp0,size0);
- prev(memp1)=memp0;
- next(memp1)=memp2;
- size(memp1)=size0;
- datp(memp1)=datp(memp0);
- *datp(memp1)=memp1;
- next(memp0)=memp1;
- datp(memp0)=NULL;
- if (memp2!=NULL)
- prev(memp2)=memp1;
- }
-
-
- /* combine a block with the free block to the right */
- static void NEAR combineblock(mem_ptr memp0)
- {
- mem_ptr memp1; /* next block */
- mem_ptr memp2;
-
- memp1=next(memp0);
- memp2=next(memp1);
- next(memp0)=memp2;
- if (memp2!=NULL)
- prev(memp2)=memp0;
- size(memp0)+=size(memp1)+mcbsize;
- if (used(memp0))
- memfree-=size(memp1)+mcbsize;
- }
-
-
- /* split a block */
- static void NEAR splitblock(mem_ptr memp0, long len)
- {
- long size0;
- long size1;
- mem_ptr memp1; /* next block */
- mem_ptr memp2;
-
- size0=size(memp0);
- size1=size0-len-mcbsize;
- if (size1<0)
- return;
- memp2=next(memp0);
- memp1=memadd(memp0,len);
- next(memp0)=memp1;
- size(memp0)=len;
- prev(memp1)=memp0;
- next(memp1)=memp2;
- size(memp1)=size1;
- datp(memp1)=NULL;
- if (memp2!=NULL)
- prev(memp2)=memp1;
- if (used(memp0))
- memfree+=size1+mcbsize;
- }
-
-
- /* free memory */
- void mem_free(mem_ptr* mempp)
- {
- mem_ptr memp;
-
- memp=*mempp;
- if (memp==NULL || datp(memp)!=mempp)
- return;
-
- *mempp=NULL;
- memfree+=size(memp)+mcbsize;
- datp(memp)=NULL;
- if (next(memp)!=NULL && !used(next(memp)))
- combineblock(memp);
- memp=prev(memp);
- if (memp!=NULL && !used(memp))
- combineblock(memp);
- }
-
-
- /* allocate memory block */
- int mem_alloc(mem_ptr* mempp, long n, long sizen)
- {
- int unused;
- long gap;
- long diff;
- long len;
- long len2;
- mem_ptr memp;
- mem_ptr memp1;
- mem_ptr memp2;
-
- sizen=(n*sizen+3)&~3;
-
- if (sizen==0)
- {
- mem_free(mempp);
- return(true);
- }
-
- memp=*mempp;
- if (memp==NULL || datp(memp)!=mempp) /* new allocation */
- {
- /* search largest free block(, stop if large enough) */
- len=-1;
- memp=NULL;
- for (memp1=memory; memp1!=NULL; memp1=next(memp1))
- if (!used(memp1) && size(memp1)>len)
- {
- memp=memp1;
- len=size(memp1);
- }
- if (memp==NULL) /* no free block */
- return(false);
-
- /* if too large split it so there will be gaps */
- gap=((len-sizen)/2-mcbsize)&~3;
- if (gap>=256)
- {
- splitblock(memp,gap);
- memp=next(memp);
- len=size(memp);
- }
-
- /* allocate this block */
- memfree-=len+mcbsize;
- datp(memp)=mempp;
- *datp(memp)=memp;
- }
-
- if (sizen==size(memp))
- return(true);
- if (sizen>size(memp)+memfree)
- return(false);
-
- /* loop is perform at most twice */
- do
- {
- /* block right is free: add it */
- memp1=next(memp);
- if (memp1!=NULL && !used(memp1))
- combineblock(memp);
- if (sizen<=size(memp))
- break;
-
- /* block left is free and large enough: add it */
- memp1=prev(memp);
- if (memp1!=NULL && !used(memp1)
- && sizen<=size(memp)+size(memp1)+mcbsize)
- {
- moveblockleft(memp);
- memp=memp1;
- combineblock(memp);
- if (sizen<=size(memp))
- break;
- }
-
- /* search largest free block */
- len2=-1;
- memp2=NULL;
- for (memp1=memory; memp1!=NULL; memp1=next(memp1))
- if (!used(memp1) && size(memp1)>len2)
- {
- memp2=memp1;
- len2=size(memp1);
- }
-
- if (len2>=sizen)
- {
- /* if too large split it so the will be gaps */
- gap=((len2-sizen)/2-mcbsize)&~3;
- if (gap>=256)
- {
- splitblock(memp2,gap);
- memp2=next(memp2);
- }
-
- /* move the block to the found free block */
- hugemoveleft(memp2,memp,size(memp));
- datp(memp2)=datp(memp);
- *datp(memp2)=memp2;
- datp(memp)=NULL;
- memfree+=size(memp)-size(memp2);
- if (next(memp)!=NULL && !used(next(memp)))
- combineblock(memp);
- memp=prev(memp);
- if (memp!=NULL && !used(memp))
- combineblock(memp);
- memp=memp2;
- break;
- }
-
- memp1=memp;
- diff=sizen-size(memp);
-
- while (diff>0 && next(memp1)!=NULL)
- {
- memp1=next(memp1);
- if (!used(memp1))
- diff-=size(memp1)+mcbsize;
- }
-
- /* move blocks right from current to the right */
- unused=false;
- while (memp1!=memp)
- {
- memp2=prev(memp1);
- if (used(memp1))
- {
- if (unused)
- moveblockright(memp1);
- }
- else
- {
- if (unused)
- combineblock(memp1);
- unused=true;
- }
- memp1=memp2;
- }
-
- while (diff>0 && prev(memp1)!=NULL)
- {
- memp1=prev(memp1);
- if (!used(memp1))
- diff-=size(memp1)+mcbsize;
- }
-
- /* move blocks left from current to the left */
- unused=false;
- while (memp1!=memp)
- {
- memp2=next(memp1);
- if (used(memp1))
- {
- if (unused)
- moveblockleft(memp1);
- }
- else
- {
- if (unused)
- combineblock(prev(memp1));
- unused=true;
- }
- memp1=memp2;
- }
- }
- while (sizen>size(memp));
-
- splitblock(memp,sizen);
-
- return(true);
- }
-
-
- /* return available memory */
- long mem_avail(void)
- {
- return(memfree>mcbsize?memfree-mcbsize:0);
- }
-
-
- /* check memory control blocks, return 0 if ok */
- int mem_check(void)
- {
- mem_ptr memp;
- mem_ptr memp1;
- mem_ptr memp9;
- long memfree1;
- int memi;
-
- memfree1=0;
- memp9=NULL;
- for (memp=memory,memi=0; memp!=NULL; memp=next(memp),memi++)
- {
- if (prev(memp)!=memp9)
- return(1);
- memp1=memadd(memp,size(memp));
- if (next(memp)==NULL)
- {
- if (memp1!=memend)
- return(2);
- }
- else
- {
- if (next(memp)!=memp1)
- return(3);
- }
- if (used(memp))
- {
- if (*datp(memp)!=memp)
- return(4);
- }
- else
- memfree1+=size(memp)+mcbsize;
- memp9=memp;
- }
- if (memfree1!=memfree)
- return(6);
- return(0);
- }
-
- #ifdef __cplusplus
- }
- #endif
-