/*
 *      Copyright (c) 1991 Paul Campbell
 *      All Rights Reserved
 *      THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF Paul Campbell
 *      The copyright notice above does not evidence any
 *      actual or intended publication of such source code.
 */
 
#include <stdio.h>
#include "lex.h"
FILE *fcode;
unsigned char *buff;
unsigned short offset = 0;
unsigned short addr_val = 0;
unsigned short addr_pc;
unsigned char *out;
extern unsigned short pc;
extern int pass, valid, op_size;
extern int bin, intel;

#define BUFF_LEN	65536

void 
code_init()
{
	buff = (unsigned char *)malloc(BUFF_LEN);
	if (buff == NULL) {
		fprintf(stderr, "Not enough space for internal buffers\n");
		exit(2);
	}
	out = buff;
}

void dump_addr();
void
dump_out()
{
	unsigned short i, j, k, s;
	
	if (offset == 0)
		return;
	if (addr_val)
		dump_addr();
	if (bin) {
		fwrite((unsigned char *)&offset, sizeof(offset), 1, 	 fcode);
		fwrite(buff, 					 1, 			 offset, fcode);
	} else
	if (intel) {
		for (i = 0; i < offset; ) {
			j = offset - i;
			if (j > 32)
				j = 32;
			s = (j + (addr_pc&0xff) + ((addr_pc>>8)&0xff))&0xff;
			fprintf(fcode, ":%02x%04x00",j&0xff,addr_pc);
			for (k = 0; k < j; k++, i++) {
				s += buff[i]&0xff;
				fprintf(fcode, "%02x", buff[i]&0xff);
			}
			s = (256 - (s&0xff))&0xff;
			fprintf(fcode, "%02x%c%c", s, 13, 10);
			addr_pc += j;
		}
	}
	offset = 0;
	out = buff;
}

void
dump_done()
{
	dump_out();
	if (intel) {
		fprintf(fcode, ":00000001ff%c%c",13,10);
	}
}

void
emit1(unsigned char c1)
{
	if ((offset+4) >= BUFF_LEN)
		dump_out();
	*out++ = c1;
	offset++;
}

void
emit2(unsigned char c1, unsigned char c2)
{
	if ((offset+4) >= BUFF_LEN)
		dump_out();
	*out++ = c1;
	*out++ = c2;
	offset+=2;
}

void
emit3(unsigned char c1, unsigned char c2, unsigned char c3)
{
	if ((offset+4) >= BUFF_LEN)
		dump_out();
	*out++ = c1;
	*out++ = c2;
	*out++ = c3;
	offset+=3;
}

void
set_val( struct dict *dp, unsigned short val, unsigned char b)
{
	if (dp->valid && dp->val != val) {
		yyerror("Duplicate name '%s'", (long)dp->name,0,0,0,0,0);
	} else {
		dp->valid = 1;
		dp->val = val;
		dp->bits = b;
	}
}

void
set_addr()
{
	dump_out();
	addr_val = 1;
	addr_pc  = pc;
}

void
dump_addr()
{
	unsigned short flag;
	
	flag = 0xffff;
	addr_val = 0;
	if (bin) {
		fwrite((unsigned char *)&flag,    sizeof(flag),    1, fcode);
		fwrite((unsigned char *)&addr_pc, sizeof(addr_pc), 1, fcode);
	}
}

void
new_label(struct dict *dp)
{
	if (dp->valid && dp->val != pc) {
		yyerror("Duplicate name '%s'", (long)dp->name,0,0,0,0,0);
	} else {
		dp->valid = 1;
		dp->val = pc;
		dp->bits = 0;
	}
}

