
/*
 * unexec.c
 *
 * By Marcel J.E. Mol               duteca!marcel
 *                                  marcel@duteca.tudelft.nl
 *
 * I hereby place this program into public domain ...
 *  ...  all those all those if and whats etc....
 * I'm completely unresponsible for any damage this program may cause you,
 * anyone, or anything else.
 *
 *
 * Unexec expects a input file consisting of lines which are usually
 * entered in the apple monitor. Remove the 'CALL -151' line from the file,
 * and the 'BSAVE ..' at the end of the file. Fed the resulting data to
 * unexec and binary data is output. When unexec has processed the file,
 * it prints the address of the first and last databyte on stderr. The binary
 * data contains all the bytes between the first and last address, even
 * if no data was in the input file for a specific address (unexec just
 * initializes a 64k byte array of zeros).
 * Thus each line in the input file looks like:
 *
 *    01F0: A2 00 A0 10 A9 00 BD 00 20 E8 D0 FA
 *
 * Usage: The program reads from a file or stdin, and outputs to
 *        stdout. I usually use the program as follows:
 *
 *           unexec  file.ex  > binfile
 */

#include <stdio.h>
#include <ctype.h>
#if defined(MSDOS)
# include <fcntl.h>
#endif

char * copyright = "@(#) unexec.c  2.2 26/03/90  (c) M.J.E. Mol";

unsigned char mem[65536];
int addr;
int memmin, memmax;
int tmp;
int b;
unsigned char buf[128];
int i;


main(argc, argv)
int argc;
char **argv;
{
    FILE *fp;

    if ((argc == 1) || (!strcmp(argv[1], "-"))) {
#if defined(MSDOS)
        setmode(fileno(stdout), O_BINARY);
#endif
	fp = stdin;
    }
    else {
#if defined(MSDOS)
        if ((fp = fopen(argv[1], "rb")) == NULL) {
#else
	if ((fp = fopen(argv[1], "r")) == NULL) {
#endif
	    perror(argv[1]);
	    exit(1);
	}
    }

    unexec(fp);

    exit(0);
	
} /* main */



unexec(fp)
FILE *fp;
{
    addr = -1;
    memmin = 100000;
    memmax = 0;
    tmp = 0;
    while (fgets(buf, 128, fp) != NULL) {
	i = 0;
	while (i <= strlen(buf)) {
	    if (buf[i] == ':') {
		addr = tmp;
		if ((addr < memmin) && (addr >= 0))
			memmin = addr;
		tmp = 0;
		i++;
		skipblank();
	    }
	    else if ((isspace(buf[i])) || (buf[i] == '\0')) {
		if (tmp > 255) 
			fprintf(stderr, "Assuming %d to be $FF\n", tmp);
		mem[addr++] = tmp;
		tmp = 0;
		skipblank();
	    }
	    else {
		if ((buf[i] >= '0') && (buf[i] <= '9'))
			tmp = (tmp << 4) + buf[i] - '0';
		else if ((buf[i] >= 'a') && (buf[i] <= 'f'))
			tmp = (tmp << 4) + buf[i] - 'a' + 10;
		else if ((buf[i] >= 'A') && (buf[i] <= 'F'))
			tmp = (tmp << 4) + buf[i] - 'A' + 10;
		else fprintf(stderr, "Illegal character %c\n", buf[i]);
		i++;
	    }
	}
	if (addr > memmax)
		memmax = addr;
    }
    for (i = memmin; i<= memmax; i++) 
	putchar(mem[i]);
    fprintf(stderr, "Lower address: %x\n", memmin);
    fprintf(stderr, "Higher address: %x\n", memmax);

} /* unexec */



skipblank()
{

        while ((isspace(buf[i]) || (buf[i] == '\0')) && i <= strlen(buf))
		i++;

} /* skipblank */
	
