

/*************************************************************************

                      Copyright (c) 1984 by Nick de Smith

        This software is supplied for interest and non-profit making
        purposes  only.   Under  no  circumstance  shall it be lent,
        copied or otherwise used for profit.  All  rights  regarding
        the  use  and  ownership of this software shall at all times
        remain with the author, who does not guarantee the  accuracy
        or  reliabilty  of this software and who will not accept any
        liability for its use.

        This software may not be copied or distributed  without  the
        inclusion of the above copyright notice.

        January 31st 1984

*************************************************************************/


/*************************************************************************


	Program :	CAM

	Module	:	CAM.C	(the root)

	Author	:	Nick de Smith		November/December 1982

	Description :

			Root file of the object module disassembler. This
			module handles all the command parsing and dispatch
			to the real code.

*************************************************************************/

#define	MAIN				/* Force once only code in CAM.H*/

#include	<stdio.h>

#include	"cam.h"

#include	"camtbl.h"


/*************************************************************************
*
*
*				m a i n
*				-------
*
*	Only entry point to the object module dis-assembler. This
*	routine called by run-time support $$main.
*
*	The technique used to enable/disable certain features is rather
*	nasty as it involves explicitly patching the drive tables. At
*	some later date/in a later version I will include a neat routine
*	to auto-patch the tables. Maybe "table(0nnnnnn, "inst", new_type)".
*
*************************************************************************/
global
main(argc, argv)
char	*argv[];
{
	register int i,c;
	register char *p, *o;

	file = NULL;
	o    = option;

	for (i = 1; i < argc; ++i) {
		p = argv[i];
#ifdef	c_vms
		if (*p == '-' || *p == '/') {
			p++;
#else
		if (*p++ == '-') {
#endif
			while (c = *p++) {
				switch (*o++ = isupper(c) ? tolower(c) : c) {

				case 'a':	/* Disable output of	*/
						/* absolute global defs	*/
					abs_g = FALSE;
					break;

				case 'b':	/* All binary is to be	*/
						/* .byte/.word types	*/
					b_flag = TRUE;
					break;

				case 'c':	/* Disable code output	*/
					code = FALSE;
					break;

				case 'd':	/* Enable debug mode	*/
					debug = TRUE;
					break;

				case 'i':	/* Ignore load address	*/
						/* mismatches (YUK)	*/
					i_flag = TRUE;
					break;

				case 'l':	/* Disable line numbers	*/
					lines = FALSE;
					break;

				case 'n':	/* Resolve numbers in	*/
						/* an STB (not yet!)	*/
					numbers = TRUE;
					break;

				case 'o':	/* Disable octal output	*/
					octal = FALSE;
					break;

				case 'p':	/* Enable psect table	*/
					psect_f = TRUE;
					break;

				case 'q':	/* Output psect defns.	*/
					q_flag = TRUE;
					break;

				case 'r':	/* Disable output of	*/
						/* referenced globals	*/
					ref_g = FALSE;
					break;

				case 's':	/* Output sorted abs	*/
						/* global definitions	*/
					sort_g = TRUE;
					break;

				case 't':	/* Disable ascii output	*/
					ascii = FALSE;
					break;

		/* Table patch options	*/

				case 'e':	/* Use RSX not RSTS emts*/
					x104[0].t_flags = T_END | T_NNN;
					x104[0].t_next  = emtext;
					x10437[7].t_next  = "dir$";
					break;

				case 'f':	/* Disable floating pt.	*/
					x1[7].t_flags = T_END | T_NNNNNN;
					x1[7].t_next  = word;
					break;

				case 'k':	/* Disable kernal opcodes */
					/* halt		*/
					x00000[0].t_flags = T_END | T_NNNNNN;
					x00000[0].t_next  = word;
					/* wait		*/
					x00000[1].t_flags = T_END | T_NNNNNN;
					x00000[1].t_next  = word;
					/* reset	*/
					x00000[5].t_flags = T_END | T_NNNNNN;
					x00000[5].t_next  = word;
					/* mfpt		*/
					x00000[7].t_flags = T_END | T_NNNNNN;
					x00000[7].t_next  = word;
					/* mfpi		*/
					x006[5].t_flags = T_END | T_NNNNNN;
					x006[5].t_next  = word;
					/* mtpi		*/
					x006[6].t_flags = T_END | T_NNNNNN;
					x006[6].t_next  = word;
					/* mtps		*/
					x106[4].t_flags = T_END | T_NNNNNN;
					x106[4].t_next  = word;
					/* mfpd		*/
					x106[5].t_flags = T_END | T_NNNNNN;
					x106[5].t_next  = word;
					/* mtpd		*/
					x106[6].t_flags = T_END | T_NNNNNN;
					x106[6].t_next  = word;
					/* mfps		*/
					x106[7].t_flags = T_END | T_NNNNNN;
					x106[7].t_next  = word;
					break;

				case 'm':	/* Disable 'macros'	*/
					/* change PUSH/POP to MOV	*/
					x0[1].t_flags	= T_END | T_SSDD;
					x0[1].t_next	= "mov";
					/* change PUSH to CLR -(SP)	*/
					x005[0].t_flags	= T_END | T_SS;
					x005[0].t_next	= "clr";
					/* change POP to TST (SP)+	*/
					x005[7].t_flags	= T_END | T_SS;
					x005[7].t_next	= "tst";
					/* change CALL to JSR		*/
					x00[4].t_flags	= T_END | T_RDD;
					x00[4].t_next	= "jsr";
					/* change RETURN to RTS		*/
					x0002[0].t_flags= T_END | T_R;
					x0002[0].t_next	= "rts";
					/* change JMP/JMPX to JMP	*/
					x000[1].t_flags	= T_END | T_SS;
					break;

				default:
					usage();
				}
			}
		}
		else
			if (file)
				usage();
			else
				file = argv[i];
	}
	if (!file)
		usage();
	disassemble(file);

}


/*************************************************************************
*
*
*			d i s a s s e m b l e
*			---------------------
*
*	Dis-assemble the named file.
*
*************************************************************************/
local
disassemble(file_)
char	*file_;
{
	open(file_);

	pass_1();			/* Pre-pass for globals/psects	*/

	pass_2();			/* Build local symbol tables	*/

	pass_3();			/* Output code/data		*/

	close();
}


/*************************************************************************
*
*
*				o p e n
*				-------
*
*	Open the named file for input.
*
*************************************************************************/
local
open(file_)
char	*file_;
{
	dbg("Opening \"%s\"\n", file_);

	if (!(ip = fopen(file_, "ru")))
		error("Failed to open \"%s\"", file_);
}

/*************************************************************************
*
*
*				c l o s e
*				---------
*
*	Close the input file.
*
*************************************************************************/
local
close()
{
	dbg("Closing input stream\n");

	if (fclose(ip))
		bug("Failed to close input stream");
}

/*************************************************************************
*
*
*				u s a g e
*				---------
*
*	How to luse this utility. Give yourself ten points if you can
*	remember what all the options do (I can't).
*
*************************************************************************/
local
usage()
{
	fprintf(stderr, "Usage: cam file.typ -stealfromnickpbdq");
	exit(1);
}
