#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#ifdef SMARTALLOC
typedef enum
{
False = 0,
True = 1
} Boolean;
#define EOS '\0'
#define V (void)
#define sm_min(a, b) ((a) < (b) ? (a) : (b))
struct queue
{
struct queue *qnext,
*qprev;
};
struct abufhead
{
struct queue abq;
unsigned ablen;
char *abfname;
unsigned short ablineno;
};
static struct queue abqueue = {
&abqueue, &abqueue};
static Boolean bufimode = False;
static void qinsert();
static struct queue *qdchain();
static void *smalloc(fname, lineno, nbytes)
char *fname;
int lineno;
unsigned nbytes;
{
char *buf;
assert(nbytes > 0);
nbytes += sizeof(struct abufhead) + 1;
if ((buf = malloc(nbytes)) != NULL)
{
qinsert(&abqueue, (struct queue *)buf);
((struct abufhead *)buf)->ablen = nbytes;
((struct abufhead *)buf)->abfname = bufimode ? NULL : fname;
((struct abufhead *)buf)->ablineno = (unsigned short)lineno;
buf[nbytes - 1] = (((long)buf) & 0xFF) ^ 0xC5;
buf += sizeof(struct abufhead);
}
return (void *)buf;
}
void sm_free(fp) void *fp;
{
char *cp = (char *)fp;
struct queue *qp;
assert(cp != NULL);
cp -= sizeof(struct abufhead);
qp = (struct queue *)cp;
assert(qp->qnext->qprev == qp);
assert(qp->qprev->qnext == qp);
assert(((unsigned char *)cp)[((struct abufhead *)cp)->ablen - 1] ==
((((long)cp) & 0xFF) ^ 0xC5));
V qdchain(qp);
V memset(cp, 0xAA, (int)((struct abufhead *)cp)->ablen);
free(cp);
}
void *sm_malloc(fname, lineno, nbytes)
char *fname;
int lineno;
unsigned nbytes;
{
void *buf;
if ((buf = smalloc(fname, lineno, nbytes)) != NULL)
{
V memset(buf, 0x55, (int)nbytes);
}
return buf;
}
void *sm_calloc(fname, lineno, nelem, elsize)
char *fname;
int lineno;
unsigned nelem, elsize;
{
void *buf;
if ((buf = smalloc(fname, lineno, nelem * elsize)) != NULL)
{
V memset(buf, 0, (int)(nelem * elsize));
}
return buf;
}
void *sm_realloc(fname, lineno, ptr, size)
char *fname;
int lineno;
void *ptr;
unsigned size;
{
unsigned osize;
void *buf;
assert(size > 0);
if (ptr == NULL)
return sm_malloc(fname, lineno, size);
osize = ((struct abufhead *)(((char *)ptr) -
sizeof(struct abufhead)))
->ablen -
(sizeof(struct abufhead) + 1);
if (size == osize)
{
return ptr;
}
if ((buf = smalloc(fname, lineno, size)) != NULL)
{
V memcpy(buf, ptr, (int)sm_min(size, osize));
if (size > osize)
{
V memset(((char *)buf) + osize, 0x55, (int)(size - osize));
}
sm_free(ptr);
}
return buf;
}
void *actuallymalloc(size)
unsigned size;
{
return malloc(size);
}
void *actuallycalloc(nelem, elsize)
unsigned nelem, elsize;
{
return calloc(nelem, elsize);
}
void *actuallyrealloc(ptr, size) void *ptr;
unsigned size;
{
return realloc(ptr, size);
}
void actuallyfree(cp) void *cp;
{
free(cp);
}
void sm_dump(bufdump)
Boolean bufdump;
{
struct abufhead *ap = (struct abufhead *)abqueue.qnext;
while (ap != (struct abufhead *)&abqueue)
{
if ((ap == NULL) ||
(ap->abq.qnext->qprev != (struct queue *)ap) ||
(ap->abq.qprev->qnext != (struct queue *)ap))
{
V fprintf(stderr,
"\nOrphaned buffers exist. Dump terminated following\n");
V fprintf(stderr,
" discovery of bad links in chain of orphaned buffers.\n");
V fprintf(stderr,
" Buffer address with bad links: %lx\n", (long)ap);
break;
}
if (ap->abfname != NULL)
{
unsigned memsize = ap->ablen - (sizeof(struct abufhead) + 1);
char errmsg[80];
V sprintf(errmsg,
"Orphaned buffer: %6u bytes allocated at line %d of %s\n",
memsize, ap->ablineno, ap->abfname);
V fprintf(stderr, "%s", errmsg);
if (bufdump)
{
unsigned llen = 0;
char *cp = ((char *)ap) + sizeof(struct abufhead);
errmsg[0] = EOS;
while (memsize)
{
if (llen >= 16)
{
V strcat(errmsg, "\n");
llen = 0;
V fprintf(stderr, "%s", errmsg);
errmsg[0] = EOS;
}
V sprintf(errmsg + strlen(errmsg), " %02X",
(*cp++) & 0xFF);
llen++;
memsize--;
}
V fprintf(stderr, "%s\n", errmsg);
}
}
ap = (struct abufhead *)ap->abq.qnext;
}
}
void sm_static(mode) int mode;
{
bufimode = (Boolean)(mode != 0);
}
static void qinsert(qhead, object) struct queue *qhead, *object;
{
assert(qhead->qprev->qnext == qhead);
assert(qhead->qnext->qprev == qhead);
object->qnext = qhead;
object->qprev = qhead->qprev;
qhead->qprev = object;
object->qprev->qnext = object;
}
static struct queue *qremove(qhead)
struct queue *qhead;
{
struct queue *object;
assert(qhead->qprev->qnext == qhead);
assert(qhead->qnext->qprev == qhead);
if ((object = qhead->qnext) == qhead)
return NULL;
qhead->qnext = object->qnext;
object->qnext->qprev = qhead;
return object;
}
static struct queue *qdchain(qitem)
struct queue *qitem;
{
assert(qitem->qprev->qnext == qitem);
assert(qitem->qnext->qprev == qitem);
return qremove(qitem->qprev);
}
#endif