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