#

/* Convert b.out format files to .ldb files. Handles BSS
 * and can put out a specified base address.
 * Converted from ldlda by lwa 9/25/83.
 *
 *	[Note:  ldb format changed.  This code not yet updated.  The first two
 * bytes changed from 1,0 to 2,0 to distinguish it from lda format.
 */


#include <stdio.h>
#include "defs.h"
#include "/usr/sun/include/b.out.h"


/* output one char, modifying checksum */

#define	putchkc(c)	checksum -= c; 	putc(c, output)

/* macros to extract byte fields from a longword */

#define	lobyte(a)	((a) & 0xFF)
#define	midbyte(a)	(((a) >> 8) & 0xFF)
#define	upbyte(a)	(((a) >> 16) & 0xFF)
#define	hibyte(a)	(((a) >> 24) & 0xFF)

#define	LDBHSIZE	14		/* size of ldb header in bytes */

FILE *input;		/* ptr to input file buffer */
FILE *output;		/* ptr to output file buffer */

long strtloc =	0;	/* start location to put out */
int nflag = 0;		/* no-go flag - causes entry point to be set to -1 */

struct	bhdr	hdr;	/* file header */

char checksum = 0;	/* checksum used in ouputing lda blks */


main(argc, argv)
char	**argv;

{	int	outdes;
	register int	i;

	if (argc < 3) {
		printf("Usage: ldldb <infil> <outfil> {-b strtloc} {-n}\n");
		exit(1);
		}

	if ((input = fopen(argv[1], "r")) == NULL) {
		printf("File not found: %s\n", argv[1]);
		exit(1);
		}

	if ((outdes = creat(argv[2], 0666)) == -1) {
		printf("Could not create: %s\n", argv[2]);
		exit(1);
		}
	if ((output = fdopen(outdes, "w")) == NULL) {
		printf("Could not write %s\n", argv[2]);
		exit(1);
		}

	if (argc > 3) {
		for (i = 3; i <= (argc - 1); i++) {
			if (strcmp(argv[i], "-b") == 0) {
				i++;
				if ((i >= argc) ||
				     sscanf(argv[i], "%X", &strtloc) != 1) {
					printf("start addr not a hex number\n");
					exit(1);
				}
			} else if (strcmp(argv[i], "-n") == 0) {
				nflag++;
			} else {
				printf("Unknown flag %s supplied\n", argv[i]);
				exit(1);
			}
		}
	}

	gethdr();	/* read header data */
	cvt();		/* read and flush data */

	fclose(input);
	fclose(output);
	exit(0);
}


/* read in header from b.out file */

gethdr()

{	if (fread(&hdr,sizeof(struct bhdr),1,input) != 1) {
		printf("Input file truncated\n");
		exit(1);
	}

	if (hdr.fmagic != FMAGIC) { /* this only accepts 407 format files */
		printf("File format not 407\n");
		exit(1);
		}
}


/* read in and dump out data in file */

cvt()

{
	reg	uns	filsize;	/* bytes in b.out text & data */
	reg	uns	bsize;		/* bytes in bss */
	reg	uns	size;		/* bytes in ldb file (except csum) */
	reg	int	i;		/* for reading in bytes of file */

	filsize = hdr.tsize + hdr.dsize;
	bsize = hdr.bsize;
	size = filsize + bsize + LDBHSIZE; /* nbytes for ldb header */

	putchkc(1);			/* put out block hdr */
	putchkc(0);

 	putchkc(hibyte(size));		/* now put out nbytes */
	putchkc(upbyte(size));
	putchkc(midbyte(size));
	putchkc(lobyte(size));

 	putchkc(hibyte(strtloc));	/* put out load point */
	putchkc(upbyte(strtloc));
	putchkc(midbyte(strtloc));
	putchkc(lobyte(strtloc));

	if (nflag) {			/* no-go set? */
		putchkc(0xFF);		/* yes, put out -1 for entry */
		putchkc(0xFF);
		putchkc(0xFF);
		putchkc(0xFF);
	} else {
	 	putchkc(hibyte(hdr.entry)); /* put out entry location */
		putchkc(upbyte(hdr.entry));
		putchkc(midbyte(hdr.entry));
		putchkc(lobyte(hdr.entry));
	}

	while(filsize-- > 0) {	/* read in and output blocks of text/data */
		if ((i = getc(input)) == EOF) {
			printf("Unexpected EOF\n");
			exit(1);
		}
		putchkc(i);
	}	

	while(bsize-- > 0) {	/* now do BSS */
		putchkc(0);
	}

	putc(checksum, output);	/* put out that checksum too */
}
