muse1.7b4/
muse1.7b4/config/
muse1.7b4/doc/
muse1.7b4/run/
muse1.7b4/run/db/
muse1.7b4/src/
muse1.7b4/src/db/
muse1.7b4/src/files/
muse1.7b4/src/io/
muse1.7b4/src/prog/
muse1.7b4/src/util/
/* nalloc.c */
/* $Id: nalloc.c,v 1.5 1993/07/25 19:06:30 nils Exp $ */

/* Memory allocation routines Written By Lawrence Foard */
#include <stdio.h>
#include "nalloc.h"
#include "db.h"
#include "config.h"
#include "externs.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)
	  {
	    char buf[80];
#ifdef MALLOCDEBUG
	    blks[a].blk=(char *)malloc(SBSIZE);
#else
	    blks[a].blk=(char *)sbrk(SBSIZE);
#endif
	    sprintf(buf,"new block %d(#%d) used",a*SBSIZE,a);
	    log_io(buf);
	  }
	blks[a].owner=na;
	return(a);
      }
  return(-1);  
}

/* return a pointer to an area containing size bytes (size<SBSIZE) */
void *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=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=(void *)((((unsigned int)p)+sizeof(int)) & ~(sizeof(int)-1));
  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;
     void *item;
{                     
  POINT *tmp=(POINT *)item;
  tmp->next=na->free;
  na->free=tmp;
}


/* do binary search to find block pointer belongs to */
int findit(argptr)
     void *argptr;
{
  int b;
  char *ptr;
  ptr=(char *)argptr;
  
  /* 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);
  log_error("pointer not found");
  return -1;
#ifdef fooglewizer  
  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 ) {
	log_error("Pointer not in block");
	report();
	return -1;
      }
      return m;
    }        
    if ( blks[m].blk && (blks[m].blk < ptr) )
      b=m;
    else
      t=m;
  }    
  log_error("Pointer out of range");
  report();
  return(-1);
#endif /* fooglewiezer */
}


void na_unalloc(na,data)
     NALLOC *na;
     void *data;
{
  int a;
  /*  data-=sizeof(int);
      a= *((int*)data);   */
  if (-1==(a=findit(data)))
    {
      log_error("Can't find pointer");
      report();
      return;
    }
  
  if ((a<0) || (a>MAXBLK))
    {         
      log_error("Attempt to unalloc messed up block");
      report();
      return;
    }
  if (blks[a].owner!=na)
    {
      report();
      log_error("Attempt to unalloc unowned block");
      return;
    }
  if (blks[a].used<=0)
    {
      report();
      log_error("Attempt to unalloc too many strings");
      return;
    }
  blks[a].used--; 
  /*  if (findit(data)!=a)
      fprintf(stderr,"search failed\n");*/
}

extern NALLOC *glurp;

char *glurpdup(s)
     char *s;
{
  char *op;
  op = na_alloc(glurp,strlen(s)+1);
  strcpy(op,s);
  return op;
}

/* routines to deal with big chunks of memory */
char *bigalloc(size)
     int size;
{
  int a,b;
  char *ptr;
  log_io(tprintf("bigalloc=%d",size));
  /* 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)
     void *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