439 lines
		
	
	
	
		
			8.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			439 lines
		
	
	
	
		
			8.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #ifndef NORCSID
 | |
| static char rcsid[] = "$Id$";
 | |
| #endif
 | |
| 
 | |
| #include <stdlib.h>
 | |
| #include <stdio.h>
 | |
| #include "param.h"
 | |
| #include "types.h"
 | |
| #include "tes.h"
 | |
| #include "assert.h"
 | |
| #include "alloc.h"
 | |
| #include "line.h"
 | |
| #include "lookup.h"
 | |
| #include "proinf.h"
 | |
| 
 | |
| /*
 | |
|  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
 | |
|  * See the copyright notice in the ACK home directory, in the file "Copyright".
 | |
|  *
 | |
|  * Author: Hans van Staveren
 | |
|  */
 | |
| 
 | |
| #ifdef USEMALLOC
 | |
| 
 | |
| short * myalloc();
 | |
| 
 | |
| #define newcore(size) myalloc(size)
 | |
| #define oldcore(p,size) free(p)
 | |
| 
 | |
| #else
 | |
| 
 | |
| #undef CORECHECK	/* if defined tests are made to insure
 | |
| 			   each block occurs at most once */
 | |
| 
 | |
| #define CCHUNK	1024	/* number of shorts asked from system */
 | |
| 
 | |
| short *newcore(),*freshcore();
 | |
| extern char *sbrk();
 | |
| 
 | |
| #ifdef COREDEBUG
 | |
| int shortsasked=0;
 | |
| #endif
 | |
| 
 | |
| #endif
 | |
| 
 | |
| /*
 | |
|  * The following two sizetables contain the sizes of the various kinds
 | |
|  * of line and argument structures.
 | |
|  * Care has been taken to make this table implementation independent,
 | |
|  * but if you think very hard you might find a compiler failing the
 | |
|  * assumptions made.
 | |
|  * A wasteful but safe approach is to replace every line of them by
 | |
|  *  sizeof(line_t)
 | |
|  * and
 | |
|  *  sizeof(arg_t)
 | |
|  * respectively.
 | |
|  */
 | |
| 
 | |
| #define LBASE (sizeof(line_t)-sizeof(un_l_a))
 | |
| 
 | |
| int lsizetab[] = {
 | |
| 	LBASE,
 | |
| 	LBASE+sizeof(short),
 | |
| 	LBASE+sizeof(offset),
 | |
| 	LBASE+sizeof(num_p),
 | |
| 	LBASE+sizeof(sym_p),
 | |
| 	LBASE+sizeof(s_la_sval),
 | |
| 	LBASE+sizeof(s_la_lval),
 | |
| 	LBASE+sizeof(arg_p),
 | |
| 	LBASE
 | |
| };
 | |
| 
 | |
| #define ABASE (sizeof(arg_t)-sizeof(un_a_a))
 | |
| 
 | |
| int asizetab[] = {
 | |
| 	ABASE+sizeof(offset),
 | |
| 	ABASE+sizeof(num_p),
 | |
| 	ABASE+sizeof(sym_p),
 | |
| 	ABASE+sizeof(s_a_val),
 | |
| 	ABASE+sizeof(argb_t),
 | |
| 	ABASE+sizeof(s_a_con),
 | |
| 	ABASE+sizeof(s_a_con),
 | |
| 	ABASE+sizeof(s_a_con),
 | |
| };
 | |
| 
 | |
| /*
 | |
|  * alloc routines:
 | |
|  * Two parts:
 | |
|  *   1)	typed alloc and free routines
 | |
|  *   2) untyped raw core allocation
 | |
|  */
 | |
| 
 | |
| /*
 | |
|  * PART 1
 | |
|  */
 | |
| 
 | |
| line_p	newline(optyp) int optyp; {
 | |
| 	register line_p lnp;
 | |
| 	register kind=optyp;
 | |
| 
 | |
| 	if (kind>OPMINI)
 | |
| 		kind = OPMINI;
 | |
| 	lnp = (line_p) newcore(lsizetab[kind]);
 | |
| 	lnp->l_optyp = optyp;
 | |
| 	return(lnp);
 | |
| }
 | |
| 
 | |
| oldline(lnp) register line_p lnp; {
 | |
| 	register kind=lnp->l_optyp&BMASK;
 | |
| 
 | |
| 	if (kind>OPMINI)
 | |
| 		kind = OPMINI;
 | |
| 	if (kind == OPLIST)
 | |
| 		oldargs(lnp->l_a.la_arg);
 | |
| 	oldcore((short *) lnp,lsizetab[kind]);
 | |
| }
 | |
| 
 | |
| arg_p newarg(kind) int kind; {
 | |
| 	register arg_p ap;
 | |
| 
 | |
| 	ap = (arg_p) newcore(asizetab[kind]);
 | |
| 	ap->a_typ = kind;
 | |
| 	return(ap);
 | |
| }
 | |
| 
 | |
| oldargs(ap) register arg_p ap; {
 | |
| 	register arg_p	next;
 | |
| 
 | |
| 	while (ap != (arg_p) 0) {
 | |
| 		next = ap->a_next;
 | |
| 		switch(ap->a_typ) {
 | |
| 		case ARGSTR:
 | |
| 			oldargb(ap->a_a.a_string.ab_next);
 | |
| 			break;
 | |
| 		case ARGICN:
 | |
| 		case ARGUCN:
 | |
| 		case ARGFCN:
 | |
| 			oldargb(ap->a_a.a_con.ac_con.ab_next);
 | |
| 			break;
 | |
| 		}
 | |
| 		oldcore((short *) ap,asizetab[ap->a_typ]);
 | |
| 		ap = next;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| oldargb(abp) register argb_p abp; {
 | |
| 	register argb_p next;
 | |
| 
 | |
| 	while (abp != (argb_p) 0) {
 | |
| 		next = abp->ab_next;
 | |
| 		oldcore((short *) abp,sizeof (argb_t));
 | |
| 		abp = next;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| reg_p newreg() {
 | |
| 
 | |
| 	return((reg_p) newcore(sizeof(reg_t)));
 | |
| }
 | |
| 
 | |
| oldreg(rp) reg_p rp; {
 | |
| 
 | |
| 	oldcore((short *) rp,sizeof(reg_t));
 | |
| }
 | |
| 
 | |
| num_p newnum() {
 | |
| 
 | |
| 	return((num_p) newcore(sizeof(num_t)));
 | |
| }
 | |
| 
 | |
| oldnum(lp) num_p lp; {
 | |
| 
 | |
| 	oldcore((short *) lp,sizeof(num_t));
 | |
| }
 | |
| 
 | |
| offset *newrom() {
 | |
| 
 | |
| 	return((offset *) newcore(MAXROM*sizeof(offset)));
 | |
| }
 | |
| 
 | |
| sym_p newsym(len) int len; {
 | |
| 	/*
 | |
| 	 * sym_t includes a 2 character s_name at the end
 | |
| 	 * extend this structure with len-2 characters
 | |
| 	 */
 | |
| 	return((sym_p) newcore(sizeof(sym_t) - 2 + len));
 | |
| }
 | |
| 
 | |
| argb_p newargb() {
 | |
| 
 | |
| 	return((argb_p) newcore(sizeof(argb_t)));
 | |
| }
 | |
| 
 | |
| #ifndef USEMALLOC
 | |
| 
 | |
| /******************************************************************/
 | |
| /******   Start of raw core management package    *****************/
 | |
| /******************************************************************/
 | |
| 
 | |
| #define MAXSHORT 30	/* Maximum number of shorts one can ask for */
 | |
| 
 | |
| short *freelist[MAXSHORT];
 | |
| 
 | |
| typedef struct coreblock {
 | |
| 	struct coreblock *co_next;
 | |
| 	short co_size;
 | |
| } core_t,*core_p;
 | |
| 
 | |
| #define SINC	(sizeof(core_t)/sizeof(short))
 | |
| #ifdef COREDEBUG
 | |
| coreverbose() {
 | |
| 	register size;
 | |
| 	register short *p;
 | |
| 	register sum;
 | |
| 
 | |
| 	sum = 0;
 | |
| 	for(size=1;size<MAXSHORT;size++)
 | |
| 		for (p=freelist[size];p!=0;p = *(short **) p)
 | |
| 			sum += size;
 | |
| 	fprintf(stderr,"Used core %u\n",(shortsasked-sum)*sizeof(short));
 | |
| }
 | |
| #endif
 | |
| 
 | |
| #ifdef SEPID
 | |
| 
 | |
| compactcore() {
 | |
| 	register core_p corelist=0,tp,cl;
 | |
| 	int size;
 | |
| 
 | |
| #ifdef COREDEBUG
 | |
| 	fprintf(stderr,"Almost out of core\n");
 | |
| #endif
 | |
| 	for(size=SINC;size<MAXSHORT;size++) {
 | |
| 		while ((tp = (core_p) freelist[size]) != (core_p) 0) {
 | |
| 			freelist[size] = (short *) tp->co_next;
 | |
| 			tp->co_size = size;
 | |
| 			if (corelist==0 || tp<corelist) {
 | |
| 				tp->co_next = corelist;
 | |
| 				corelist = tp;
 | |
| 			} else {
 | |
| 				for(cl=corelist;cl->co_next != 0 && tp>cl->co_next;
 | |
| 							cl = cl->co_next)
 | |
| 					;
 | |
| 				tp->co_next = cl->co_next;
 | |
| 				cl->co_next = tp;
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 	while (corelist != 0) {
 | |
| 		while ((short *) corelist->co_next ==
 | |
| 		    (short *) corelist + corelist->co_size) {
 | |
| 			corelist->co_size += corelist->co_next->co_size;
 | |
| 			corelist->co_next =  corelist->co_next->co_next;
 | |
| 		}
 | |
| 		assert(corelist->co_next==0 ||
 | |
| 			(short *) corelist->co_next >
 | |
| 			    (short *) corelist + corelist->co_size);
 | |
| 		while (corelist->co_size >= MAXSHORT+SINC) {
 | |
| 			oldcore((short *) corelist + corelist->co_size-(MAXSHORT-1),
 | |
| 				sizeof(short)*(MAXSHORT-1));
 | |
| 			corelist->co_size -= MAXSHORT;
 | |
| 		}
 | |
| 		if (corelist->co_size >= MAXSHORT) {
 | |
| 			oldcore((short *) corelist + corelist->co_size-SINC,
 | |
| 				sizeof(short)*SINC);
 | |
| 			corelist->co_size -= SINC;
 | |
| 		}
 | |
| 		cl = corelist->co_next;
 | |
| 		oldcore((short *) corelist, sizeof(short)*corelist->co_size);
 | |
| 		corelist = cl;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| short *grabcore(size) int size; {
 | |
| 	register short *p;
 | |
| 	register trysize;
 | |
| 
 | |
| 	/*
 | |
| 	 * Desperate situation, can't get more core from system.
 | |
| 	 * Postpone giving up just a little bit by splitting up
 | |
| 	 * larger free blocks if possible.
 | |
| 	 * Algorithm is worst fit.
 | |
| 	 */
 | |
| 
 | |
| 	assert(size<2*MAXSHORT);
 | |
| 	for(trysize=2*MAXSHORT-2; trysize>size; trysize -= 2) {
 | |
| 		p = freelist[trysize/sizeof(short)];
 | |
| 		if ( p != (short *) 0) {
 | |
| 			freelist[trysize/sizeof(short)] = *(short **) p;
 | |
| 			oldcore(p+size/sizeof(short),trysize-size);
 | |
| 			return(p);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/*
 | |
| 	 * Can't get more core from the biggies, try to combine the
 | |
| 	 * little ones. This is expensive but probably better than
 | |
| 	 * giving up.
 | |
| 	 */
 | |
| 
 | |
| 	compactcore();
 | |
| 	if ((p=freelist[size/sizeof(short)]) != 0) {
 | |
| 		freelist[size/sizeof(short)] = * (short **) p;
 | |
| 		return(p);
 | |
| 	}
 | |
| 	for(trysize=2*MAXSHORT-2; trysize>size; trysize -= 2) {
 | |
| 		p = freelist[trysize/sizeof(short)];
 | |
| 		if ( p != (short *) 0) {
 | |
| 			freelist[trysize/sizeof(short)] = *(short **) p;
 | |
| 			oldcore(p+size/sizeof(short),trysize-size);
 | |
| 			return(p);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/*
 | |
| 	 * That's it then. Finished.
 | |
| 	 */
 | |
| 
 | |
| 	return(0);
 | |
| }
 | |
| #endif	/* SEPID */
 | |
| 
 | |
| short *newcore(size) int size; {
 | |
| 	register short *p,*q;
 | |
| 
 | |
| 	size = (size + sizeof(int) - 1) & ~(sizeof(int) - 1);
 | |
| 	if( size < 2*MAXSHORT ) {
 | |
| 		if ((p=freelist[size/sizeof(short)]) != (short *) 0)
 | |
| 			freelist[size/sizeof(short)] = *(short **) p;
 | |
| 		else {
 | |
| 			p = freshcore(size);
 | |
| #ifdef SEPID
 | |
| 			if (p == (short *) 0)
 | |
| 				p = grabcore(size);
 | |
| #endif
 | |
| 		}
 | |
| 	} else
 | |
| 		p = freshcore(size);
 | |
| 	if (p == 0)
 | |
| 		error("out of memory");
 | |
| 	for (q=p; size > 0 ; size -= sizeof(short))
 | |
| 		*q++ = 0;
 | |
| 	return(p);
 | |
| }
 | |
| 
 | |
| #ifndef USEMALLOC
 | |
| 
 | |
| /*
 | |
|  * stdio uses malloc and free.
 | |
|  * you can use these as substitutes
 | |
|  */
 | |
| 
 | |
| char *malloc(size) int size; {
 | |
| 
 | |
| 	/*
 | |
| 	 * malloc(III) is called by stdio,
 | |
| 	 * this routine is a substitute.
 | |
| 	 */
 | |
| 
 | |
| 	return( (char *) newcore(size));
 | |
| }
 | |
| 
 | |
| free() {
 | |
| 
 | |
| }
 | |
| #endif
 | |
| 
 | |
| oldcore(p,size) short *p; int size; {
 | |
| #ifdef CORECHECK
 | |
| 	register short *cp;
 | |
| #endif
 | |
| 
 | |
| 	assert(size<2*MAXSHORT);
 | |
| #ifdef CORECHECK
 | |
| 	for (cp=freelist[size/sizeof(short)]; cp != (short *) 0;
 | |
| 	    cp = *(short **) cp)
 | |
| 		assert(cp != p);
 | |
| #endif
 | |
| 	*(short **) p = freelist[size/sizeof(short)];
 | |
| 	freelist[size/sizeof(short)] = p;
 | |
| }
 | |
| 
 | |
| short *ccur,*cend;
 | |
| 
 | |
| coreinit(p1,p2) short *p1,*p2; {
 | |
| 
 | |
| 	/*
 | |
| 	 * coreinit is called with the boundaries of a piece of
 | |
| 	 * memory that can be used for starters.
 | |
| 	 */
 | |
| 
 | |
| 	ccur = p1;
 | |
| 	cend = p2;
 | |
| }
 | |
| 
 | |
| short *freshcore(size) int size; {
 | |
| 	register short *temp;
 | |
| 	static int cchunk=CCHUNK;
 | |
| 	
 | |
| 	while(&ccur[size/sizeof(short)] >= cend && cchunk>0) {
 | |
| 		do {
 | |
| 			temp = (short *) sbrk(cchunk*sizeof(short));
 | |
| 			if (temp == (short *) -1)
 | |
| 				cchunk >>= 1;
 | |
| 			else if (temp != cend)
 | |
| 				ccur = cend = temp;
 | |
| 		} while (temp == (short *) -1 && cchunk>0);
 | |
| 		cend += cchunk;
 | |
| #ifdef COREDEBUG
 | |
| 		shortsasked += cchunk;
 | |
| #endif
 | |
| 	}
 | |
| 	if (cchunk==0)
 | |
| 		return(0);
 | |
| 	temp = ccur;
 | |
| 	ccur = &ccur[size/sizeof(short)];
 | |
| 	return(temp);
 | |
| }
 | |
| 
 | |
| #else	/* USEMALLOC */
 | |
| 
 | |
| coreinit() {
 | |
| 
 | |
| 	/*
 | |
| 	 * Empty function, no initialization needed
 | |
| 	 */
 | |
| }
 | |
| 
 | |
| short *myalloc(size) register size; {
 | |
| 	register short *p,*q;
 | |
| 
 | |
| 	p = (short *)malloc(size);
 | |
| 	if (p == 0)
 | |
| 		error("out of memory");
 | |
| 	for(q=p;size>0;size -= sizeof(short))
 | |
| 		*q++ = 0;
 | |
| 	return(p);
 | |
| }
 | |
| #endif
 |