101 lines
		
	
	
	
		
			2.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			101 lines
		
	
	
	
		
			2.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * File:  -  dis.c
 | 
						|
 *
 | 
						|
 * dispose() built in standard procedure in Pascal (6.6.5.3)
 | 
						|
 *
 | 
						|
 * Re-implementation of storage allocator for Ack Pascal compiler
 | 
						|
 * under Linux, and other UNIX-like systems.
 | 
						|
 *
 | 
						|
 * Written by Erik Backerud, 2010-10-01
 | 
						|
 *
 | 
						|
 * Original copyright and author info below:
 | 
						|
 */
 | 
						|
/* $Id$ */
 | 
						|
/*
 | 
						|
 * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
 | 
						|
 *
 | 
						|
 *          This product is part of the Amsterdam Compiler Kit.
 | 
						|
 *
 | 
						|
 * Permission to use, sell, duplicate or disclose this software must be
 | 
						|
 * obtained in writing. Requests for such permissions may be sent to
 | 
						|
 *
 | 
						|
 *      Dr. Andrew S. Tanenbaum
 | 
						|
 *      Wiskundig Seminarium
 | 
						|
 *      Vrije Universiteit
 | 
						|
 *      Postbox 7161
 | 
						|
 *      1007 MC Amsterdam
 | 
						|
 *      The Netherlands
 | 
						|
 *
 | 
						|
 */
 | 
						|
 | 
						|
/* Author: J.W. Stevenson */
 | 
						|
 | 
						|
#include	<pc_err.h>
 | 
						|
 | 
						|
#define assert()	/* nothing */
 | 
						|
 | 
						|
/*
 | 
						|
 * use a singly linked list of free blocks.
 | 
						|
 */
 | 
						|
struct adm {
 | 
						|
	struct adm	*next;
 | 
						|
	int		size;
 | 
						|
};
 | 
						|
 | 
						|
struct adm *freep = 0;			/* first element on free list */
 | 
						|
 | 
						|
extern void _trp(int);
 | 
						|
 | 
						|
/*
 | 
						|
 * Dispose
 | 
						|
 * Called with two arguments:
 | 
						|
 * n the size of the block to be freed, in bytes,
 | 
						|
 * pp address of pointer to data.
 | 
						|
 */
 | 
						|
void
 | 
						|
_dis(int n, struct adm **pp)
 | 
						|
{
 | 
						|
    struct adm *block;	/* the block of data being freed (inc. header) */
 | 
						|
    struct adm *p, *q;
 | 
						|
 | 
						|
    if (*pp == 0) {
 | 
						|
	_trp(EFREE);
 | 
						|
    }
 | 
						|
    block = *pp - 1;
 | 
						|
    if (freep == 0) {
 | 
						|
	freep = block;
 | 
						|
	block->next = 0;
 | 
						|
    } else {
 | 
						|
	q = 0;	/* trail one behind */
 | 
						|
	for (p = freep; p < block; p = p->next) {
 | 
						|
	    if (p == 0) {	/* We reached the end of the free list. */
 | 
						|
		break;
 | 
						|
	    }
 | 
						|
	    q = p;
 | 
						|
	    /* check if block is contained in the free block p */
 | 
						|
	    if (p+p->size > block) {
 | 
						|
		_trp(EFREE);
 | 
						|
	    }
 | 
						|
	}
 | 
						|
	if (p == block) {	/* this block already freed */
 | 
						|
	  _trp(EFREE);
 | 
						|
	}
 | 
						|
	if (q == 0) {	/* block is first */
 | 
						|
	    freep = block;
 | 
						|
	    block->next = p;
 | 
						|
	} else {
 | 
						|
	    q->next = block;
 | 
						|
	}
 | 
						|
	block->next = p;
 | 
						|
	/* merge with successor on free list? */
 | 
						|
	if (block + block->size == p) {
 | 
						|
	    block->size = block->size + p->size;
 | 
						|
	    block->next = p->next;
 | 
						|
	}
 | 
						|
	/* merge with preceding block on free list? */
 | 
						|
	if (q != 0 && q+q->size == block) {
 | 
						|
	    q->size = q->size + block->size;
 | 
						|
	    q->next = block->next;
 | 
						|
	}
 | 
						|
    }
 | 
						|
}   /* _dis */
 |