

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "utypes.h"
#define s0W
#include "umemory.h"

#define i2C 16

#if defined(AMIGA)
#define p7P 8 
#else
#define p7P 8
#endif
#ifndef s0A
#define s0A(x,by) ((by)*(((x)+(by-1))/(by)))
#endif
static s2U *l1P = NULL;
static UBYTE s6O[4] =
{0xDE, 0xAD, 0xBE, 0xEF}; 
static UBYTE p9P[4] =
{0xDE, 0xAD, 0xF0, 0x0D}; 
static UBYTE v9P = 0x81;
static ULONG y4A = 0; 
static ULONG y2E = 0; 
static ULONG z7T = 0; 
static ULONG f5D = 0; 
static ULONG e0S = 0; 
static ULONG x7P = 0; 
static ULONG j1J = 0; 
static ULONG y0A = 0; 
static ULONG v5R7 = 0; 
static ULONG w8C = 0; 

void *a0E(size_t size);
static BOOL e6G(s2U * d1J);

BOOL(*n5R) (size_t size) = NULL;

VOID q2YB(char *msg, char *file, size_t line)
{
fprintf(stderr, "\n\n");
fprintf(stderr, "  I won't be a monkey in anyone's zoo\n");
fprintf(stderr, "  I won't get fazed whatever you do\n");
fprintf(stderr, "                   (Ride, \"Not Fazed\")\n\n");
fprintf(stderr, "** internal error: \"%s\" (%lu): %s\n", \
file, (unsigned long) line, msg);
exit(255);
}

static s2U *v1R(void *mem)
{
s2U *s0E = l1P;
s2U *r3N = NULL;
while (s0E && (!r3N))
{
if (s0E->ptr == mem)
{
r3N = s0E;
}
s0E = s0E->v1N;
}
#if k4E==2
if (!r3N)
{
fprintf(stderr, "*memory* FIND_UMEM: couln't find %p\n", mem);
}
#endif
return (r3N);
}

static s2U *v1H(s2U * d1J)
{
s2U *prev = l1P;
s2U *z9T = NULL;
BOOL r3N = FALSE;
while (prev && (!r3N))
{
r3N = (prev == d1J);
if (!r3N)
{
z9T = prev;
prev = prev->v1N;
}
}
return (z9T);
}

static void x3Z(void *mem, size_t size, UBYTE value[4])
{
size_t i;
for (i = 0; i < size; i++)
{
(((UBYTE *) mem)[i]) = value[i % 4];
}
}
static void g6U(void *mem, size_t size, UBYTE value)
{
size_t i;
for (i = 0; i < size; i++)
{
(((UBYTE *) mem)[i]) = value;
}
}

static void n5L(s2U * d1J)
{
s2U *prev = v1H(d1J);

if (prev)
{
prev->v1N = d1J->v1N;
}
else
{
l1P = d1J->v1N;
}

if (!e6G(d1J))
{

x3Z(d1J->d5F, d1J->size + 2 * i2C, s6O);
free(d1J->d5F);
}

d1J->d5F = NULL;
d1J->e2Ij = NULL;
d1J->size = 0;
d1J->file = NULL;
d1J->line = 0;
free(d1J);
}

static s2U *q4M(size_t d5V, STRPTR b5X, ULONG o2A)
{
s2U *k0W = (s2U *) malloc(sizeof(s2U));
if (k0W)
{
k0W->d5F = (UBYTE *) a0E(d5V
+ 2 * i2C);
if (k0W->d5F)
{

k0W->ptr = (void *) (k0W->d5F + i2C);
k0W->e2Ij = (k0W->d5F + i2C + d5V);

k0W->v1N = l1P;
l1P = k0W;

k0W->size = d5V;
k0W->file = b5X;
k0W->line = o2A;
k0W->g4K = v9P;

x3Z(k0W->ptr, d5V, p9P);

g6U(k0W->d5F, i2C, v9P);
g6U(k0W->e2Ij, i2C, v9P);

if (v9P == 0xff)
{
v9P = 0x81;
}
else
{
v9P++;
}
}
else
free(k0W);
}
return (k0W);
}
static void o6M4(STRPTR msg)
{
fprintf(stderr, "%s\n", msg);
}
static void t1BS(void *ptr, size_t size)
{
unsigned char *data = (unsigned char *) ptr;

if (size > 16)
{
size = 16;
}
fprintf(stderr, "  %p:", ptr);
if (data)
{
size_t i;

for (i = 0; i < size; i++)
{
if (!(i % 4))
{
fprintf(stderr, " ");
}
fprintf(stderr, "%02x", data[i]);
}

while (i < 16)
{
if (!(i % 4))
{
fprintf(stderr, " ");
}
fprintf(stderr, "  ");
i++;
}
fprintf(stderr, "  \"");

for (i = 0; i < size; i++)
{
if (data[i] < ' ' || ((data[i] > 128) && (data[i] < 160)))
{
fprintf(stderr, ".");
}
else
{
fprintf(stderr, "%c", data[i]);
}
}
fprintf(stderr, "\"\n");
}
else
fprintf(stderr, "NULL\n");
}
static void h1B(void *ptr, STRPTR file, ULONG line)
{
fprintf(stderr, "  %p: from \"%s\" (%lu)\n", ptr, file, line);
}
static void g8W(s2U * d1J)
{
fprintf(stderr, "  %p: %lu (0x%lx) bytes from \"%s\" (%lu)\n",
d1J->ptr, (ULONG) d1J->size, (ULONG) d1J->size,
d1J->file, d1J->line);
}


static STRPTR i8A(UBYTE e2SN)
{
static x9T d7P[30];
UBYTE ch = e2SN;
if (ch < 32)
ch = '.';
sprintf(d7P, "(0x%02x/#%d/`%c')", e2SN, e2SN, ch);
return (d7P);
}

static BOOL e6G(s2U * d1J)
{
size_t i = 0;
BOOL z5B = FALSE;
while (!z5B && (i < i2C))
{
BOOL u2A = (d1J->d5F[i] != d1J->g4K);
BOOL u0Kh = (d1J->e2Ij[i] != d1J->g4K);
z5B = u2A || u0Kh;
if (z5B)
{
STRPTR b9Fu;
UBYTE value;
if (u2A)
{
b9Fu = "LOWER";
value = d1J->d5F[i];
}
else
{
b9Fu = "UPPER";
value = d1J->e2Ij[i];
}
fprintf(stderr, "*** MEMORY WALL DAMAGED!!!\n");
fprintf(stderr, "*** %s wall, byte#%lu is %s instead of 0x%02x\n",
b9Fu, (ULONG) i, i8A(value), d1J->g4K);
g8W(d1J);
t1BS(d1J->ptr, d1J->size);
fprintf(stderr, "  * lower wall:\n");
t1BS(d1J->d5F, i2C);
fprintf(stderr, "  * upper wall:\n");
t1BS(d1J->e2Ij, i2C);
}
else
{
i++;
}
}
return (z5B);
}

VOID z3F(STRPTR msg, STRPTR file, ULONG line)
{
s2U *d1J = l1P;
if (d1J)
{

fprintf(stderr, "MEMORY WALL-CHECK (%s)", msg);
if (file)
fprintf(stderr, " from `%s' (%lu)", file, line);
fprintf(stderr, "\n");

while (d1J)
{
if (d1J->ptr)
{
e6G(d1J);
d1J = d1J->v1N;
}
else
{
d1J = NULL;
fprintf(stderr, "\n** PANIC: memory list trashed\n");
}
}
}
}


void i0K(STRPTR msg, STRPTR file, ULONG line, STRPTR date, STRPTR time)
{
s2U *d1J = l1P;
if (d1J)
{

fprintf(stderr, "MEMORY REPORT (%s)\n", msg);
if (file)
{
fprintf(stderr, "(\"%s\" (%lu), at %s, %s)\n",
file, line, date, time);
}

while (d1J)
{
if (d1J->ptr)
{
g8W(d1J);
t1BS(d1J->ptr, d1J->size);
d1J = d1J->v1N;
}
else
{
d1J = NULL;
fprintf(stderr, "##\n## panic: memory list trashed\n##\n");
}
}
}
}

void n1De(STRPTR msg, STRPTR file, ULONG line, STRPTR date, STRPTR time)
{

fprintf(stderr, "MEMORY STATISTICS (%s)\n", msg);
if (file)
{
fprintf(stderr, "(\"%s\" (%lu), at %s, %s)\n",
file, line, date, time);
}

fprintf(stderr, "  bytes used: %lu max: %lu/%lu  ",
x7P, j1J,
e0S);
if (e0S)
{
fprintf(stderr, "slack: %lu%%\n",
(100 * (j1J - e0S))
/ e0S);
}
else
{
fprintf(stderr, "no slack\n");
}
fprintf(stderr, "  nodes used: %lu (max: %lu)\n",
w8C, v5R7);
fprintf(stderr, "  calls to: umalloc(%lu)   ufree(%lu)\n",
y4A, y2E);
}



void a0Y(void)
{
ULONG u2M = x7P;
i0K("at exit:  MEMORY LEAK detected!",
NULL, 0, NULL, NULL);
n1De("[exit]", NULL, 0, NULL, NULL);

while (l1P)
{
n5L(l1P);
}
if (u2M)
{
fprintf(stderr, "\n%lu bytes of memory lost!\n", u2M);
}
}

void f5L(void)
{

}



void *a0E(size_t size)
{
void *mem;
BOOL t5N;
do
{
mem = malloc(size);
if (!mem && n5R)
{

t5N = (*n5R) (size);
if (!t5N)
{
exit(EXIT_FAILURE); 
}
}
else
{
t5N = FALSE;
}
}
while (t5N);
return (mem);
}

void *z3V(size_t size, STRPTR file, ULONG line)
{
void *mem = NULL;
s2U *d1J = NULL;
#if k4E==2
fprintf(stderr, "*memory* UMALLOC() from `%s' (%lu)\n", file, line);
#endif
if (size)
{

y4A++;

d1J = q4M(size, file, line);
if (d1J)
{
mem = d1J->ptr;

x7P += size;
y0A += s0A(size, p7P);
if (x7P > e0S)
e0S = x7P;
if (y0A > j1J)
j1J = y0A;
w8C++;
if (w8C > v5R7)
v5R7 = w8C;
}
}
else
{


z7T++;
o6M4("MALLOC: zero-sized allocation");
h1B(NULL, file, line);
}
return (mem);
}


void g4G(void *ptr, STRPTR file, ULONG line)
{
#if k4E==2
fprintf(stderr, "*memory* UFREE() from `%s' (%lu)\n", file, line);
#elif 0
fputc('.', stderr); 
fflush(stderr);
#endif
if (ptr)
{
s2U *d1J = v1R(ptr);
if (d1J)
{

y2E++;

x7P -= d1J->size;
y0A -= s0A(d1J->size, p7P);

n5L(d1J);
w8C--;
}
else
{


f5D++;

o6M4("*** FREE: memory never allocated "
" or released twice");
h1B(ptr, file, line);
}
}
}

void *w6C(void *ptr, size_t size, STRPTR file, ULONG line)
{
void *s8Q = z3V(size, file, line);
s2U *d1J = v1R(ptr);
if (s8Q && d1J)
{

memcpy(s8Q, d1J->ptr, d1J->size);

g4G(ptr, file, line);
}
return (s8Q);
}

void *r7V(size_t count, size_t size, STRPTR file, ULONG line)
{

void *mem = z3V(count * size, file, line);

if (mem)
{
memset(mem, 0, size * count);
}
return (mem);
}
