;:ts=8
	far	code
	far	data
;//  These are memory allocation routines which take the place of the
;//  normal malloc and free routines.  They substitute for the normal
;//  routines through define statements which are in the include
;//  file "memcheck.h".  They call the normal system malloc and free
;//  routines.
;//
;//  These routines allocate extra memory on each end of the users
;//  memory which is filled with check bits that allow us to detect
;//  overwrites which extend past either end of the memory which
;//  the main program thinks was allocated.  Some parts of these routines
;//  are specific to the Aztec C routines in that we count on there
;//  being one long word immediately before the pointer which is
;//  returned by the normal malloc and which is somehow significant
;//  to the normal malloc.  These routines insure that this word
;//  does not change.
;//
;
;//  Don't include memcheck.h, or we create a circular reference through
;//  the define of malloc and free
;#include	<stdio.h>
;#include	<stdlib.h>
;
;
;//  memcheck_validate_pointer (void* ptr)
;//
;//  Checks to verify that a pointer passed to this routine was originally
;//  returned by the debug_malloc routine.  Prints error messages if not
;//  Returns non-zero if all is OK, 0 if there was a problem.
;//
;short memcheck_validate_pointer (void* ptr)  {
# 30 'memcheck.c' 586899804
| .2
	xdef	_memcheck_validate_pointer
_memcheck_validate_pointer:
	movem.l	d2/a3,-(sp)
	move.l	12(sp),a3
;	short err;
;	
;	//  this adjustment must match that which was done in my_malloc
;	ptr = (void*)((char*)ptr - 8);
~ err d2 "i"
~~ ptr a3 "#v"
^^^^	lea	-8(a3),a3
;
;	err = 0;
^^	move.l	#0,d2
;	//  check the word at each end of the users space
;	if (((long*)(ptr))[1] != 0xABDFBCFE)  {
^^	cmp.l	#-1411400450,4(a3)
	beq	.10001
;		err++;
^	add.w	#1,d2
;		printf ("free 0x%08lX: low end overwrite\n", (long)((char*)ptr + 8));
^	lea	8(a3),a0
	move.l	a0,-(sp)
	pea	.1+0
	jsr	_printf
;	}	
^;	if (((long*)(ptr))[((long*)(ptr))[0] + 2] != 0xF3E4ABBC)  {
	add.w	#8,sp
.10001
^	move.l	(a3),d0
	asl.l	#2,d0
	cmp.l	#-203117636,8(a3,d0.l)
	beq	.10002
;		err++;	
^	add.w	#1,d2
;		printf ("free 0x%08lX: high end overwrite\n", (long)((char*)ptr + 8));
^	lea	8(a3),a0
	move.l	a0,-(sp)
	pea	.1+33
	jsr	_printf
;	}	
^;	//  check the word which (I think) the Aztec routines use to track memory	
;	if (((long*)(ptr))[((long*)(ptr))[0] + 3] != ((long*)(ptr))[-1])  {
	add.w	#8,sp
.10002
^^	move.l	(a3),d0
	asl.l	#2,d0
	move.l	12(a3,d0.l),d0
	cmp.l	-4(a3),d0
	beq	.10003
;		err++;
^	add.w	#1,d2
;		printf ("free 0x%08lX: lost system tracking word\n", (long)((char*)ptr + 8));
^	lea	8(a3),a0
	move.l	a0,-(sp)
	pea	.1+67
	jsr	_printf
;	}
^;		
;	if (err)
	add.w	#8,sp
.10003
^^;		return 0;
	tst.w	d2
	beq	.10004
^	move.l	#0,d0
.3
	movem.l	(sp)+,d2/a3
	rts
;	return 1;
.10004
^	move.l	#1,d0
	bra	.3
;}
^.2
.1
	dc.b	102,114,101,101,32,48,120,37,48,56,108,88,58,32,108
	dc.b	111,119,32,101,110,100,32,111,118,101,114,119,114,105,116
	dc.b	101,10,0,102,114,101,101,32,48,120,37,48,56,108,88
	dc.b	58,32,104,105,103,104,32,101,110,100,32,111,118,101,114
	dc.b	119,114,105,116,101,10,0,102,114,101,101,32,48,120,37
	dc.b	48,56,108,88,58,32,108,111,115,116,32,115,121,115,116
	dc.b	101,109,32,116,114,97,99,107,105,110,103,32,119,111,114
	dc.b	100,10,0
	ds	0
;
;
;
;
;void* debug_malloc(size_t size)  {
# 60
| .5
	xdef	_debug_malloc
_debug_malloc:
	movem.l	d2/d3/a3,-(sp)
	move.l	16(sp),d2
;	void* ptr;
;	long n_longs;
;	//  current code only works for sizes which are multiples of 4
;	if ((size%4) != 0)  {
~ ptr a3 "#v"
~ n_longs d3 "l"
~~ size d2 "L"
^^^^	move.l	d2,d0
	and.l	#3,d0
	beq	.10005
;		printf ("malloc %ld; current code requires multiple of 4\n", size);
^	move.l	d2,-(sp)
	pea	.4+0
	jsr	_printf
;		return 0;
^	move.l	#0,d0
	add.w	#8,sp
.6
	movem.l	(sp)+,d2/d3/a3
	rts
;	}
^;	n_longs = size/4;
.10005
^	move.l	d2,d3
	lsr.l	#2,d3
;	
;//	printf ("** user wants %ld bytes; ", size);	
;	//  zero size request is special
;	if (size == 0)
^^^^;		return NULL;
	tst.l	d2
	bne	.10006
^	move.l	#0,d0
	bra	.6
;		
;	//  increase size by the amount we use and get memory	
;	ptr = malloc (size + 16);
.10006
^^^	move.l	d2,a0
	pea	16(a0)
	jsr	_malloc
	move.l	d0,a3
;	if (ptr == NULL)  {
^	move.l	a3,d0
	add.w	#4,sp
	bne	.10007
;//		printf ("unavailable.\n");
;		return NULL;
^^	move.l	#0,d0
	bra	.6
;	}	
^;	
;	//  if we got memory, then fill in the check bytes at the header
;	//  and footer, record the length of the allocation, and save the
;	//  word which I think the normal malloc uses to track memory
;	//  allocation
;	((long*)(ptr))[0] = n_longs;
.10007
^^^^^^	move.l	d3,(a3)
;	((long*)(ptr))[1] = 0xABDFBCFE;
^	move.l	#-1411400450,4(a3)
;	((long*)(ptr))[n_longs+2] = 0xF3E4ABBC;
^	move.l	d3,d0
	asl.l	#2,d0
	move.l	#-203117636,8(a3,d0.l)
;	((long*)(ptr))[n_longs+3] = ((long*)(ptr))[-1];
^	move.l	d3,d0
	asl.l	#2,d0
	move.l	-4(a3),12(a3,d0.l)
;	
;	//  adjust the pointer to the middle of the actual allocated block
;	//  before returning to the user
;	ptr = (void*)((char*)ptr + 8);
^^^^	lea	8(a3),a3
;//	printf ("returning pointer 0x%08lX\n", (long)ptr);
;	return (void*)ptr;
^^	move.l	a3,d0
	bra	.6
;}
^.5
.4
	dc.b	109,97,108,108,111,99,32,37,108,100,59,32,99,117,114
	dc.b	114,101,110,116,32,99,111,100,101,32,114,101,113,117,105
	dc.b	114,101,115,32,109,117,108,116,105,112,108,101,32,111,102
	dc.b	32,52,10,0
	ds	0
;
;
;
;void debug_free (void *ptr)  {
# 100
| .8
	xdef	_debug_free
_debug_free:
	movem.l	a3,-(sp)
	move.l	8(sp),a3
;//	printf ("** freeing 0x%08lX;  ", ptr);
;	//  A NULL pointer is special
;	if (ptr == NULL)
~~ ptr a3 "#v"
^^^;		return;
	move.l	a3,d0
	bne	.10008
^.9
	movem.l	(sp)+,a3
	rts
;
;	//  check pointer and print any error messages
;	memcheck_validate_pointer (ptr);
.10008
^^^	move.l	a3,-(sp)
	jsr	_memcheck_validate_pointer
;	
;	//  Adjust pointer and pass to the normal free routine.
;	//  This adjustment must match that which was done in my_malloc
;	ptr = (void*)((char*)ptr - 8);
^^^^	lea	-8(a3),a3
;	free (ptr);
^	move.l	a3,-(sp)
	jsr	_free
;//	printf ("freed\n");
;}
^^	add.w	#8,sp
	bra	.9
.8
;
;			
;
# 116
|
~ _debug_free * "(v"
~ _debug_malloc * "(#v"
~ _memcheck_validate_pointer * "(i"
~ ''
~ 1 2 8
~ quot 0 "l"
~ rem 4 "l"
~ ''
~ 2 2 4
~ quot 0 "i"
~ rem 2 "i"
~ _malloc * "(#v"
~ _free * "(v"
~ ldiv_t ":" 1
~ div_t ":" 2
~ wchar_t "c"
~ '__stdio'
~ 3 8 22
~ _bp 0 "#C"
~ _bend 4 "#C"
~ _buff 8 "#C"
~ _flags 12 "I"
~ _unit 14 "c"
~ _bytbuf 15 "C"
~ _buflen 16 "L"
~ _tmpnum 20 "I"
~ _printf * "(i"
~ FILE ":" 3
~ fpos_t "l"
~ size_t "L"
~ va_list "#c"
	xref	_malloc
	xref	_free
	xref	_printf
	xref	.begin
	dseg
	end
