/*
 * prg2out - convert gemdos .prg to minix a.out
 *	info derived from
 *		minixcvt.c - thanks frans (meulenbr@cst.prl.philips.nl)
 *	and	(re-hacked) relmix.c provided with minix St 
 *		++jrb (bammi@sargsun.ces.cwru.edu)
 */
#include "st-out.h"

extern long	lseek();

struct aexec	head;

char		buff[16384];
int		fi, fo;
char		*progname;
char		*chmemstr;

main(argc,argv)
int argc;
char *argv[];
{
	register int	part, n;
	register long	left;

	progname = argv[0];
	if (argc > 1)
		switch (argv[1][0]) { 
		case '-':
		case '+':
		case '=':
			chmemstr = argv[1];
			argc--;
			argv++;
		}
	if (argc != 3)
		error('f', "Usage: %s [+-= amount] infile outfile", progname);
	if ((fi = open(argv[1], 0)) < 0)
		error('f',"Couldn't open %s for input",argv[1]);
	if ((fo = creat(argv[2], 0666)) < 0)
		error('f',"Couldn't open %s for output",argv[2]);

	/*
	 * read header and copy to output
	 */
	if (read(fi, &head, sizeof(struct aexec)) != sizeof(struct aexec))
		error('f', "read error (magic)");
	if (head.a_magic != CMAGIC)
		error('f', "bad magic %04x, must be %04x",
			head.a_magic, CMAGIC);
	if (head.a_isreloc != 0)
		error('f', "no relocation info present");

	/* write out minix head */
	minixhead();

	/*
	 * copy text+data
	 */
	left = head.a_text + head.a_data;
	part = sizeof(buff);
	while (left) {
		n = left > part ? part : left;
		if (read(fi, buff, n) != n)
			error('f', "read error (text+data)");
		if (write(fo, buff, n) != n)
			error('f', "write error(text+data)");
		left -= n;
	}

	/*
	 * skip symbols
	 */
	if (head.a_syms > 0)
		if (lseek(fi, head.a_syms, 1) != 
	             (sizeof(struct aexec) + head.a_text + head.a_data + head.a_syms))
			error('f', "seek error");

	/*
	 * copy relocation info
	 */
	while((n = read(fi, buff, sizeof(buff))) > 0)
		if(write(fo, buff, n) != n)
			error('f',"write error(reloc)");
	if(n != 0)
		error('f', "read error(reloc)");
	close(fi); close(fo);
}

minixhead()
{
	long		mh[8];
	char		mb[32];
	long		stack;
	long		chmem();

	mh[0] = 0x04100301L;
	mh[1] = 0x00000020L;
	mh[2] = head.a_text;
	mh[3] = head.a_data;
	mh[4] = head.a_bss;
	mh[5] = 0;
	stack = 0x00010000L - (mh[3] + mh[4]);
	if ((mh[0] & 0x00200000L) == 0)		/* not SEPARATE */
		stack -= mh[2];
	while (stack < 0)
		stack += 0x00010000L;
	if (chmemstr)
		stack = chmem(chmemstr, stack);
	printf("%ld bytes assigned to stack+malloc area\n", stack);
	mh[6] = stack + (mh[3] + mh[4]);
	if ((mh[0] & 0x00200000L) == 0)		/* not SEPARATE */
		mh[6] += mh[2];
	mh[7] = 0;
	putstruc((char *)mh, "M44444444", mb);
	if (write(fo, mb, sizeof(mb)) != sizeof(mb))
		error('f', "write error(head)");
}

long chmem(str, old)
char *str;
long old;
{
	register long num, new;
	long atol();

	num = atol(str+1);
	if (num == 0)
		error('f', "bad chmem amount %s", str+1);
	switch (str[0]) {
	case '-':
		new = old - num; break;
	case '+':
		new = old + num; break;
	case '=':
		new = num; break;
	}
	return(new);
}

/* VARARGS2 */
error(t,s,a,b,c,d,e,f,g,h,i,j)
char t;
char *s;
{
	printf("%s: ",progname);
	printf(s,a,b,c,d,e,f,g,h,i,j);
	printf("\n");
	switch (t) {
	case 'w':
		return;
	case 'f':
		exit(1);
	case 'a':
		abort();
	default:
		error('w',"Illegal error type: '%c'",t);
	}
}

#include "putstruc.c"
