예제 #1
0
/* check to see if a move is appropriate */
static int chkMove(long m_size, long m_addr, long a_size)
{
	register int cost_m, cost_a;

	cost_m = NBYTE(m_size) + NBYTE(m_addr);
	cost_a = NBYTE(m_size) + m_size;
	if(cost_m >= cost_a)
		return 0;

	/* it's good but it may be better to merge it to an add */
	if(a_size > 0)
	{
		register int m_cost, a_cost;

		m_cost = cost_m + NBYTE(a_size) + a_size;
		a_size += m_size;
		a_cost = NBYTE(a_size) + a_size;

		/* it is better to merge! */
		if(m_cost >= a_cost)
			return 0;
	}

	return m_size;
}
예제 #2
0
파일: frbox.c 프로젝트: knusbaum/Wily
void
_frmergebox(Frame *f, int bn)		/* merge bn and bn+1 */
{
	Frbox *b;

	b = &f->box[bn];
	_frinsure(f, bn, NBYTE(&b[0])+NBYTE(&b[1])+1);
	strcpy((char*)runeindex(b[0].a.ptr, b[0].nrune), (char*)b[1].a.ptr);
	b[0].wid += b[1].wid;
	b[0].nrune += b[1].nrune;
	_frdelbox(f, bn+1, bn+1);
}
예제 #3
0
/* make a new add command */
static Move *makeAdd(char* beg, char* end, Move* last)
{
	register Move	*ip;

	ip = newMove(DELTA_ADD,(long)(end-beg),(long)(beg-Btar),NiL);
	if(!ip)
		return 0;

	/* remove small previous adjacent moves */
	while(last)
	{
		register int a_size, cost_m, cost_a;

		if(last->type == DELTA_ADD)
			break;

		cost_m = NBYTE(last->size) + NBYTE(last->addr) +
			 NBYTE(ip->size) + ip->size;
		a_size = ip->size + last->size;
		cost_a = NBYTE(a_size) + a_size;
		if(cost_m < cost_a)
			break;

		ip->size  = a_size;
		ip->addr -= last->size;
		last = delMove(last);
	}

	/* merge with adjacent adds */
	if(last && last->type == DELTA_ADD)
	{
		ip->size += last->size;
		ip->addr -= last->size;
		last = delMove(last);
	}

	if(last)
	{
		last->next = ip;
		ip->last = last;
	}
	return ip;
}
int movb(int addr, int addrs) {
	int n, z;

	put_value_b(addr, *get_byte_from_memory(addrs));

	int op = *get_byte_from_memory(addr);
	NBYTE(n, op);
	Z(z, op);

	set_flags(n, z, 0, flags.C);

	return 0;
}
예제 #5
0
/* write an instruction */
static int putMove(Move* ip)
{
	register char	inst;

	inst = ip->type;
	inst |= (NBYTE(ip->size)&07) << 3;
	if(ip->type == DELTA_MOVE)
	{
		inst |= NBYTE(ip->addr)&07;
		if(delputc(inst) < 0 ||
		   delputl(NBYTE(ip->size),ip->size) < 0 ||
		   delputl(NBYTE(ip->addr),ip->addr) < 0)
			return -1;
	}
	else
	{
		if(delputc(inst) < 0 ||
		   delputl(NBYTE(ip->size),ip->size) < 0 ||
		   delputs(ip->size,ip->addr) < 0)
			return -1;
	}
	return 0;
}
예제 #6
0
파일: frbox.c 프로젝트: knusbaum/Wily
static
void
dupbox(Frame *f, int bn)
{
	uchar *p;

	if(f->box[bn].nrune < 0)
		berror("dupbox");
	_fraddbox(f, bn, 1);
	if(f->box[bn].nrune >= 0){
		p = _frallocstr(NBYTE(&f->box[bn])+1);
		strcpy((char*)p, (char*)f->box[bn].a.ptr);
		f->box[bn+1].a.ptr = p;
	}
}
int cmpb(int addr, int addrs) {
	int n, z, v, c;
	int diff;

	diff = *get_byte_from_memory(addrs) - *get_byte_from_memory(addr);

	VBYTE(v, diff);
	CBYTE(c, diff);
	NBYTE(n, diff);
	Z(z, diff);

	set_flags(n, z, v, c); 

	return 0;
}
int incb(int addr, int addrs) {
	int n, z, v;
	int op;

	op = *get_byte_from_memory(addr) + 1;

	put_value_b(addr, *get_byte_from_memory(addr) + 1);
	
	VBYTE(v, op);
	NBYTE(n, op);
	Z(z, op);

	set_flags(n, z, v, flags.C);

	return 0;
}
예제 #9
0
파일: frstr.c 프로젝트: 4ad/sam
void
_frinsure(Frame *f, int bn, unsigned n)
{
	Frbox *b;
	uchar *p;

	b = &f->box[bn];
	if(b->nrune < 0)
		berror("_frinsure");
	if(ROUNDUP(b->nrune) > n)	/* > guarantees room for terminal NUL */
		return;
	p = _frallocstr(n);
	b = &f->box[bn];
	memmove(p, b->a.ptr, NBYTE(b)+1);
	free(b->a.ptr);
	b->a.ptr = p;
}
예제 #10
0
/* the real thing */
int
delta(char* src, long n_src, char* tar, long n_tar, int delfd)
{
	register char	*sp, *tp, *esrc, *etar;
	register long	size, addr;
	Suftree		*tree;
	Move		*moves, *last;
	char		inst, buf[BUFSIZE];

	/* initialize the output area */
	delinit(buf,delfd);

	/* output file sizes */
	inst = DELTA_TYPE | ((NBYTE(n_src)&07) << 3) | (NBYTE(n_tar)&07);
	if(delputc(inst) < 0)
		return -1;
	if(delputl(NBYTE(n_src),n_src) < 0 || delputl(NBYTE(n_tar),n_tar) < 0)
		return -1;

	/* bases */
	Bsrc = src;
	Btar = tar;
	esrc = src + n_src - 1;
	etar = tar + n_tar - 1;

	/* initialize list and last block */
	moves = 0;
	last = 0;

	/* try making suffix tree */
	if(!(tree = n_tar > 0 ? bldsuftree(src,n_src) : (Suftree*)0))
	{
		/* not enough space for tree, remove matching prefix and suffix */
		for(; src <= esrc && tar <= etar; ++src, ++tar)
			if(*src != *tar)
				break;
		if((size = src-Bsrc) > 0)
		{
			register int cost_m, cost_a;

			cost_m = NBYTE(size) + NBYTE(0);
			cost_a = NBYTE(size) + size;
			if(cost_m < cost_a)
			{
				moves = newMove(DELTA_MOVE,size,0L,NiL);
				if(!moves)
					return -1;
				n_src -= src-Bsrc;
				n_tar -= tar-Btar;
			}
			else
			{
				src = Bsrc;
				tar = Btar;
			}
		}

		for(sp = esrc, tp = etar; sp >= src && tp >= tar; --sp, --tp)
			if(*sp != *tp)
				break;
		if((size = esrc-sp) > 0)
		{
			addr = sp+1-Bsrc;
			if(chkMove(size,addr,0L) > 0)
			{
				last = newMove(DELTA_MOVE,size,addr,NiL);
				if(!last)
					return -1;
				esrc = sp;
				etar = tp;
				n_tar = etar-tar+1;
				n_src = esrc-src+1;
			}
		}

		/* try making the tree again */
		tree = n_tar > 0 ? bldsuftree(src,n_src) : (Suftree*)0;
	}

	/* compute block moves */
	tp = 0;
	while(n_tar > 0)
	{
		char	*match;

		if(tree)
			size = mtchsuftree(tree,tar,n_tar,&match);
		else	size = mtchstring(src,n_src,tar,n_tar,&match);
		if(size < 0)
			return -1;
		if(size > 0)
			size = chkMove(size,(long)(match-Bsrc),(long)(tp ? tp-tar : 0));

		/* output a block move */
		if(size > 0)
		{
			if(tp)
			{
				moves = makeAdd(tp,tar,moves);
				if(!moves)
					return -1;
				tp = 0;
			}
			moves = newMove(DELTA_MOVE,size,(long)(match-Bsrc),moves);
			if(!moves)
				return -1;
			tar += size;
			n_tar -= size;
		}
		else
		{
			if(!tp)
				tp = tar;
			tar += 1;
			n_tar -= 1;
		}
	}

	/* add any remaining blocks */
	if(tp)
	{
		if(last && chkMove(last->size,last->addr,(long)(tar-tp)) <= 0)
		{
			tar += last->size;
			last = delMove(last);
		}
		moves = makeAdd(tp,tar,moves);
		if(!moves)
			return -1;
	}
	if(last)
	{
		moves->next = last;
		last->last = moves;
	}

	/* release space use for string matching */
	if(tree)
		delsuftree(tree);
	else	mtchstring(NiL,0L,NiL,0L,NiL);

	/* optimize move instructions */
	if(moves)
	{
		register Move	*ip;

		ip = moves;
		while(ip->last)
			ip = ip->last;
		for(; ip; ip = ip->next)
			if(ip->type == DELTA_MOVE && ip->size <= (M_MAX+A_MAX))
				moves = ip = optMove(ip);

		while(moves->last)
			moves = moves->last;
	}

	/* write out the move instructions */
	addr = 0L;
	while(moves)
	{
		if(moves->type == DELTA_ADD)
			moves->addr = addr;
		addr += moves->size;
		if(putMove(moves) < 0)
			return -1;
		moves = delMove(moves);
	}

	/* write ending token */
	delputc((char)DELTA_TYPE);

	/* flush buffer */
	return delflush();
}
예제 #11
0
/* optimize a sequence of moves */
static Move *optMove(register Move* s)
{
	register long	add, m_cost, a_cost;
	register Move	*ip, *last;

	add = (s->last && s->last->type == DELTA_ADD) ? s->last->size : 0;

	m_cost = 0;
	a_cost = 0;
	for(ip = s; ip; ip = ip->next)
	{
		register long cost_m, cost_a;

		if(ip->type == DELTA_ADD || ip->size > (M_MAX+A_MAX))
			break;

		m_cost += 1+NBYTE(ip->size)+NBYTE(ip->addr);
		a_cost += ip->size;

		/* costs of alternatives */
		cost_m = m_cost;
		cost_a = a_cost;
		if(add > 0)
		{
			cost_m += 1 + add + NBYTE(add);
			cost_a += add;
		}
		if(ip->next && ip->next->type == DELTA_ADD)
		{
			cost_m += 1 + ip->next->size + NBYTE(ip->next->size);
			cost_a += ip->next->size;
		}
		cost_a += 1 + NBYTE(cost_a);

		/* conversion is bad */
		if(cost_m < cost_a)
			continue;

		/* convert the entire sequence to an add */
		s->type = DELTA_ADD;
		while(ip != s)
		{
			last = ip->last;
			s->size += ip->size;
			delMove(ip);
			ip = last;
		}

		/* merge adjacent adds */
		if((last = s->last) && last->type == DELTA_ADD)
		{
			last->size += s->size;
			delMove(s);
			s = last;
		} 
		if(s->next && s->next->type == DELTA_ADD)
		{
			s->size += s->next->size;
			delMove(s->next);
		}
		/* done */
		break;
	}
	return s;
}