
/* unhunk.c   Copyright (C) 1986   Eric D. Black */

/*
 * UNHUNK -- convert AmigaDOS "hunk"-format load files to
 *           memory image similar to a.out; performs relocation,
 *           allows specification of text, data, and bss origins.
 *           Output suitable for simple processing & downloading
 *           to PROM programmers...
 *
 * Portions of UNHUNK are based on the CVT Amiga->ST conversion
 * program by Landon Dyer; these appear in the files convert.c, binfio.c,
 * longio.c, and convert.h, which are all Copyright 1985 by Landon M. Dyer.
 *
 * Changes to those files, and all other code is Copyright 1986 by
 * Eric D. Black.  Permission is given to distribute these files and
 * the code they generate, and to modify and/or extend them, providing
 * that:
 *     1) All copyright notices remain intact (you may copyright your
 *        specific changes)
 *     2) All source code accompanies any distribution, including any
 *        changes and/or enhancements you may have made
 *     3) Any changes you make are clearly indicated
 *     4) No direct profit results from that distribution (i.e. you
 *        may not sell this program or anything derived from it, but
 *        you may include it at no charge on a system you sell for profit),
 *        and you may give it away
 *
 * Debug macros and routines are from the 'dbug' package by Fred Fish,
 * and are available on his freely redistributable Amiga library disks;
 * these are not included here.  If you have them, and want to
 * compile with the debug code, compile with '-DDBUG'; otherwise the extra
 * debug statements will generate no code
 *
 * MODIFIED:	4-May-86 by Fred Fish.  Extracted getnum() and made it
 *		a separate file.  Used by dl also.
 */

#include <stdio.h>
#include "convert.h"

#ifdef DBUG
#include <local/dbug.h>
#else
#include "dbugstubs.h"
#endif

char *version = "1.0";
char *date = "21-Apr-1986";

#define STRINGSIZ       256
#define READ            0
#define WRITE           1

int orgspec[3] = {0,0,0};	/* text, data, bss origin specified on cmdlin */
int printing = 0;			/* print hunk information */

/*
 * origin of text, data, bss segments, seg types 0-2 defined in convert.h
 */
long origin[3] = { 0,0,0 };

long entrypnt = 0;	/* entry offset in text section */
int errflg = 0;		/* count of errors encountered */

extern int Enable_Abort;	/* set non-zero to enable ^C and ^D abort */


main(argc, argv)
int argc;
char **argv;
{
    int ifd, ofd;
	char c;
	extern char *optarg;
	extern int optind;
	extern long getnum ();

	DBUG_ENTER("main");
	DBUG_PROCESS("unhunk");		/* since we get argv[0]="c" (!) */

    /*
     * No instructions:
     * print info about use and
     * exit with bad return code.
	 * (it's not worth making this work from the Workbench...)
     */
    if (argc <= 1) {
	usage();
   	printf("\nUNHUNK Version %s (%s)\n", version, date);
   	printf("This program is copyright (c) 1986 Eric D. Black\n");
	printf("       and (c) 1985 Landon M. Dyer\n");
	printf("It may be freely redistributed to others\n");
   	printf("ONLY if the following conditions are met:\n");
   	printf("\t1. You do not make a profit on it.\n");
   	printf("\t2. If you have the source code, you give that away, too.\n");
   	printf("\t3. You include this notice in the source and object code.\n");
	exit(1);
	}

	/*
	 * Parse command line, using getopt(), public domain goodie from
	 * Henry Spencer, available from almost any USENET site
	 */
	while((c = getopt(argc, argv, "#:t:d:b:D:p")) != EOF) {
		switch(c) {
			case '#':			/* debug package arguments */
					DBUG_PUSH(optarg);
					break;
			case 't':			/* text origin */
					DBUG_3("args", "text origin '%s'", optarg);
					origin[TEXT] = getnum(optarg);
					orgspec[TEXT]++;
					DBUG_3("args", "text origin=0x%x", origin[TEXT]);
					break;
			case 'd':			/* data origin */
					DBUG_3("args", "data origin '%s'", optarg);
					origin[DATA] = getnum(optarg);
					orgspec[DATA]++;
					DBUG_3("args", "data origin=0x%x", origin[DATA]);
					break;
			case 'b':			/* bss origin */
					DBUG_3("args", "bss origin '%s'", optarg);
					origin[BSS] = getnum(optarg);
					orgspec[BSS]++;
					DBUG_3("args", "bss origin=0x%x", origin[BSS]);
					break;
			case 'p':			/* print hunk info */
					printing++;
					break;
			default:
					DBUG_3("args", "bad arg, exit status=5", 0);
					exit(5);	/* error message is printed by getopt */
		}
	}
	argv += optind;				/* skip past flags */
	argc -= optind;

	/*
	 * Since we only use level 1 I/O (except for printf's...), and
	 * only use malloc() to allocate memory, we can go ahead and
	 * enable the Lattice C runtime check for ^C and ^D
	 */
	Enable_Abort++;


    if ((ifd = ebinopen(argv[0], READ)) < 0) {
		printf("Can't open input file: %s\n", argv[0]);
		exit(5);
	}
    if ((ofd = ebinopen(argv[1], WRITE)) < 0) {
		printf("Can't open output file: %s\n", argv[1]);
		exit(5);
	}

	/*
	 * This is where we do the actual work
	 */
    convert(ifd, ofd);

    close(ifd);
    close(ofd);

	printf("Done\n%d errors encountered\n", errflg);
	exit(0);

}	/* end of main */


/*
 * Print info about usage
 */
usage()
{
		DBUG_ENTER("usage");
        printf("\nUsage:\n");
        printf("\tunhunk [-t xxxx] [-d xxxx] [-b xxxx] infile outfile\n");
		printf("\t(both input and output files are REQUIRED)\n");
		DBUG_RETURN(0);
    }

