

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

                      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	:	PASS1.C

	Author	:	Nick de Smith		November/December 1982

	Description :

			First pass of the object module disassembler

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

#define	MODULE

#include	<stdio.h>

#include	"cam.h"


/*************************************************************************
*
*
*				p a s s _ 1
*				-----------
*
*	First pass through the object file. This pass reads the GSD and
*	extracts all psect definitions, all global references and all
*	absolute global definitions.
*
*************************************************************************/
global
pass_1()
{
	pass = 1;

	rewind(ip);

	rec_num = 0;

	b_init();

	eom = egsd = FALSE;

	dbg("Started PASS_1\n");

	while (!eom && !egsd) {

		read_record(b_current);

		proc_1();

	};

	if (eom)
		bug("End of GSD not before EOM");

	dbg("Ended PASS_1\n");
}


/*************************************************************************
*
*
*				p r o c _ 1
*				-----------
*
*	Process a pass one object record. We only examine GSD type
*	entries. In a valid object file, there should be a EGSD entry
*	before the EOM. If this is not the case the object file is
*	corrupt/invalid format.
*
*************************************************************************/
local
proc_1()
{
	register int type;

	switch (type = next_word(b_current)) {

		case T_GSD:
			gsd_1();
			break;

		case T_EGSD:
			egsd = TRUE;
			dbg("End of GSD\n");
			break;

		case T_TEXT:
		case T_RELD:
		case T_ISD:
			break;

		case T_EOM:
			eom = TRUE;
			break;

		default:
			bug("Bad object record, type = %06o", type);
	}
}


/*************************************************************************
*
*
*				g s d _ 1
*				---------
*
*	Process a pass one GSD record.
*
*************************************************************************/
local
gsd_1()
{
	register int flags, _entry, value;
	int	temp;
	int	i[2];

	while (b_current->b_left) {
		i[0] = next_word(b_current);
		i[1] = next_word(b_current);
		flags = next_byte(b_current);
		_entry = next_byte(b_current);
		value = next_word(b_current);

		switch (_entry) {

			case T_MODN:
				modnam[0] = i[0];
				modnam[1] = i[1];
				break;

			case T_CSECT:
				/* Magic nos below are .rad50 ". ABS." */
				if (i[0] == 0127401 && i[1] == 0007624)
					flags = P_GBL | P_OVR;
				else
				if (*i)		/* Named .csect		*/
					flags = P_GBL | P_REL | P_OVR;
				else		/* Blank .csect		*/
					flags = P_REL;
				p_new(i, value, flags);
				break;

			case T_ISN:
				insert(seg_cur, value, i, S_STRONG);
				break;

			case T_TADDR:
				if (!((t_addr.s_flags = segtbl[temp = find(i)].p_flags) & P_REL)
				&& value == 1)
					break;
				t_addr.s_flags |= S_VALID;
				t_addr.s_name[0] = temp;
				t_addr.s_offset = value;
				insert(temp, value, i, S_WEAK | S_CREF | S_EXT);
				break;

			case T_GSN:
				if (!(flags & G_DEF)) {
					insert(seg_cur, 0, i, S_GREF);
					break;
				}
				if (!(flags & G_REL)) {
					abs_f = TRUE;
					if (!sort_g)
						insert(seg_cur, value, i,
						S_STRONG | S_GLOBAL | S_GABS);
				}
				insert(seg_cur, value, i, S_GLOBAL | S_STRONG);
				break;

			case T_PSECT:
				p_new(i, value, flags);
				break;

			case T_IDENT:
				ident_f = TRUE;
				_ident[0] = i[0];
				_ident[1] = i[1];
				break;

			case T_MARR:
				warn("Mapped array definition ignored\n");
				break;

			case T_COMP:
				warn("Completion routine address ignored\n");
				break;

			default:
				bug("Unknown GSD entry, type = %06o", _entry);
		}
	}
}


/*************************************************************************
*
*
*				p _ n e w
*				---------
*
*	Add a new .psect name to the list.
*
*************************************************************************/
local
p_new(name, length, flags)
int	name[];
int	length, flags;
{
	if (seg_max >= MAX_SEG)
		bug("Psect table overflow");

	seg_ptr = &segtbl[seg_cur = ++seg_max];
	seg_ptr->p_flags   = flags;
	seg_ptr->p_name[0] = name[0];
	seg_ptr->p_name[1] = name[1];
	seg_ptr->p_mlength = length;
	seg_ptr->p_dot	   = 0;
	seg_ptr->p_symb    = NULL;
}
