/* nalloc.c */
/* Memory allocation routines Written By Lawrence Foard */
#include <stdio.h>
#include "nalloc.h"
static BIGBLK blks[MAXBLK];
static int inited = 0;
static void init()
{
int a;
inited = 1;
for (a = 0; a < MAXBLK; a++) {
blks[a].owner = NULL;
blks[a].used = NULL;
blks[a].blk = NULL;
}
}
void na_clear(nalloc)
NALLOC *nalloc;
{
int a;
for (a = 0; a < MAXBLK; a++)
if (nalloc == blks[a].owner) {
blks[a].owner = NULL;
blks[a].used = 0;
}
}
void na_close(nalloc)
NALLOC *nalloc;
{
int a;
/* search block list freeing all owned by nalloc */
for (a = 0; a < MAXBLK; a++)
if (nalloc == blks[a].owner) {
blks[a].owner = NULL;
blks[a].used = 0;
}
free(nalloc);
}
NALLOC *na_open(size)
int size;
{
NALLOC *na = (NALLOC *) malloc(sizeof(NALLOC));
if (!inited)
init();
na->size = size;
na->offset = 0;
na->free = NULL;
na->curblk = 0; /* Note this isn't correct but is checked
* anyways */
return (na);
}
static int get_blk(na)
NALLOC *na;
{
int a;
/* search for a block with no space used */
/* NOTE: owned blocks with no used space are public property!!! */
for (a = 0; a < MAXBLK; a++)
if (!blks[a].used) {
if (!blks[a].blk) {
blks[a].blk = (char *) sbrk(SBSIZE);
#ifdef DEBUG
fprintf(stderr, "new block %d used\n", a * SBSIZE);
#endif
}
blks[a].owner = na;
return (a);
}
return (-1);
}
/* return a pointer to an area containing size bytes (size<SBSIZE) */
char *na_alloc(na, size)
NALLOC *na;
int size;
{
char *p;
/* make sure we still own the current block and that the data */
/* will fit in it if we do */
size += sizeof(int);
if ((blks[na->curblk].owner != na) || (size > (SBSIZE - na->offset))) {
na->curblk = get_blk(na);
na->offset = 0;
}
p = (char *) (&(blks[na->curblk].blk[na->offset]));
/* force p into integer alignment (yuck) */
/* I'm not going to replace & with a division just because some silly */
/* processor may have non power of two byte integers! */
p = (char *) ((((unsigned int) p) + sizeof(int)) & ~(sizeof(int) - 1));
na->offset += size;
blks[na->curblk].used++;
return (p);
}
char *na_ualloc(na, size)
NALLOC *na;
int size;
{
char *p;
/* make sure we still own the current block and that the data */
/* will fit in it if we do */
if ((blks[na->curblk].owner != na) || (size > (SBSIZE - na->offset))) {
na->curblk = get_blk(na);
na->offset = 0;
}
p = (char *) (&(blks[na->curblk].blk[na->offset]));
na->offset += size;
blks[na->curblk].used++;
return (p);
}
/* reduces allocation given to last call by amount size */
void na_giveback(na, size)
NALLOC *na;
int size;
{
na->offset -= size;
}
/* get an item out of nalloc free list */
char *na_get(na)
NALLOC *na;
{
if (na->free) {
/* get next free list pointer */
char *next = (char *) na->free;
na->free = na->free->next;
return (next);
}
return (na_alloc(na, na->size));
}
/* put an item back on the na free list */
void na_free(na, item)
NALLOC *na;
char *item;
{
POINT *tmp = (POINT *) item;
tmp->next = na->free;
na->free = tmp;
}
/* do binary search to find block pointer belongs to */
int findit(ptr)
char *ptr;
{
int b;
/* try linear search,eventually replace with binary */
for (b = 0; b < (MAXBLK - 1); b++)
if (blks[b].blk && (blks[b].blk <= ptr) && ((blks[b].blk + SBSIZE) > ptr))
return (b);
#ifdef DEBUG
fprintf(stderr, "pointer not found\n");
#endif
return (-1);
#ifdef 0
t = MAXBLK;
b = 0;
while (b < (t - 1)) {
m = (b + t) / 2;
/* see if this is it */
if ((blks[m].blk <= ptr) && ((blks[m + 1].blk > ptr) || (blks[m + 1].blk))) {
if ((ptr - blks[m].blk) > SBSIZE) {
fprintf(stderr, "Pointer not in block\n");
report();
return (-1);
}
return (m);
}
if (blks[m].blk && (blks[m].blk < ptr))
b = m;
else
t = m;
}
fprintf(stderr, "Pointer out of range\n");
report();
return (-1);
#endif /* 0 */
}
void na_unalloc(na, data)
NALLOC *na;
char *data;
{
int a;
/*
* data-=sizeof(int); a= *((int*)data);
*/
if (-1 == (a = findit(data))) {
fprintf(stderr, "Can't find pointer\n");
report();
return;
}
if ((a < 0) || (a > MAXBLK)) {
fprintf(stderr, "Attempt to unalloc messed up block\n");
report();
return;
}
if (blks[a].owner != na) {
report();
fprintf(stderr, "Attempt to unalloc unowned block\n");
return;
}
if (blks[a].used <= 0) {
report();
fprintf(stderr, "Attempt to unalloc to many strings\n");
return;
}
blks[a].used--;
/*
* if (findit(data)!=a) fprintf(stderr,"search failed\n");
*/
}
/* routines to deal with big chunks of memory */
char *bigalloc(size)
int size;
{
int a, b;
char *ptr;
#ifdef DEBUG
fprintf(stderr, "bigalloc=%d\n", size);
#endif
/* round size up to nearest block */
size = ((size - 1) / SBSIZE) + 1;
/* assign it block pointers */
for (a = 0; (a < (MAXBLK - size)) && (blks[a].blk); a++) ;
if (a == (MAXBLK - size))
return (NULL);
ptr = (char *) sbrk(SBSIZE * size);
for (b = 0; b < size; b++) {
blks[a + b].owner = (NALLOC *) ptr;
blks[a + b].used = 1;
blks[a + b].blk = ptr + SBSIZE * b;
}
return (ptr);
}
void bigfree(ptr)
char *ptr;
{
int a;
for (a = 0; a < MAXBLK; a++)
if (blks[a].owner == (NALLOC *) ptr) {
blks[a].owner = NULL;
blks[a].used = 0;
}
}
#ifdef BRAIN_DAMAGE
char toupper(c)
char c;
{
return (((c >= 'a') && (c <= 'z')) ? c - 'a' + 'A' : c);
}
void memcpy(dest, source, amt)
char *dest;
char *source;
int amt;
{
while (amt--)
*dest++ = *source++;
}
#endif