unc - 68000 disassembler (Part 2 of 2)

sources-request at panda.UUCP sources-request at panda.UUCP
Sat Mar 15 01:00:16 AEST 1986


Mod.sources:  Volume 4, Issue 31
Submitted by: turner at imagen.UUCP <talcott!topaz!Shasta!imagen!Jim.Turner>

#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	iset.c
#	libmtch.c
#	main.c
#	prin.c
#	robj.c
# This archive created: Thu Mar 13 18:56:11 1986
export PATH; PATH=/bin:$PATH
echo shar: extracting "'iset.c'" '(19541 characters)'
if test -f 'iset.c'
then
	echo shar: will not over-write existing file "'iset.c'"
else
cat << \SHAR_EOF > 'iset.c'
/*
 *	SCCS:	@(#)iset.c	1.2	11/2/84	14:18:23
 *	Decode instructions.
 *
 ***********************************************************************
 *	This software is copyright of
 *
 *		John M Collins
 *		47 Cedarwood Drive
 *		St Albans
 *		Herts, AL4 0DN
 *		England			+44 727 57267
 *
 *	and is released into the public domain on the following conditions:
 *
 *		1.  No free maintenance will be guaranteed.
 *		2.  Nothing may be based on this software without
 *		    acknowledgement, including incorporation of this
 *		    notice.
 *
 *	Notwithstanding the above, the author welcomes correspondence and bug
 *	fixes.
 ***********************************************************************
 */

#include <stdio.h>
#include <a.out.h>
#include "unc.h"

ef_fids	mainfile;
long	endt;

void	gette(), putte();
void	mkdref();
long	gettw();
symbol	textlab();

int	l1(), l2(), el1(), lea(), lmove(), lcbch(), jj();
int	limed(), lsbit(), lmvml(), lone(), loone(), lonew(), lonel();

int	pmove(), pcbch(), pdbcc(), pscc(), pcs(), pmovc(), pstop(), pexg();
int	pimed(), pmovp(), psbit(), pdbit(), pcs2(), pone(), ppea();
int	plea(), pdreg(), pmvml(), ptrap(), plink(), pareg(), podreg();
int	pqu(), pmqu(), ptreg(), pcmpm(), pomode(), pmshf(), pshf();

struct	opstr	{
	unsigned  short	 mask;
	unsigned  short  match;
	int	(*opsize)();
	int	(*opprin)();
	char	*prarg;
} optab[] = {
	0xf000, 0x2000, lmove, pmove, "l",
	0xf000, 0x3000, lmove, pmove, "w",
	0xf000, 0x1000, lmove, pmove, "b",
	0xf000, 0x6000, lcbch, pcbch, 0,
	0xffbf, 0x003c, l2,    pcs,   "or",
	0xff00, 0x0000, limed, pimed, "or",
	0xffbf, 0x023c, l2,    pcs,   "and",
	0xff00, 0x0200, limed, pimed, "and",
	0xff00, 0x0400, limed, pimed, "sub",
	0xff00, 0x0600, limed, pimed, "add",
	0xffbf, 0x0a3c, l2,    pcs,   "eor",
	0xff00, 0x0a00, limed, pimed, "eor",
	0xff00, 0x0c00, limed, pimed, "cmp",
	0xf138, 0x0108, l2,    pmovp, 0,
	0xff00, 0x0800, lsbit, psbit, 0,
	0xf100, 0x0100, lonew, pdbit, 0,
	0xffc0, 0x40c0, lonew, pcs2,  "sr",
	0xff00, 0x4000, lone,  pone,  "negx",
	0xff00, 0x4200, lone,  pone,  "clr",
	0xffc0, 0x44c0, lonew, pcs2,  "cc",
	0xff00, 0x4400, lone,  pone,  "neg",
	0xffc0, 0x46c0, lonew, pcs2,  "sr",
	0xff00, 0x4600, lone,  pone,  "not",
	0xffc0, 0x4800, lonew, ppea,  "nbcd",
	0xfff8, 0x4840, l1,    pdreg, "swap",
	0xffc0, 0x4840, lonel, ppea,  "pea",
	0xfff8, 0x4880, l1,    pdreg, "extw",
	0xfff8, 0x48c0, l1,    pdreg, "extl",
	0xfb80, 0x4880, lmvml, pmvml, 0,
	0xffc0, 0x4ac0, lonew, ppea,  "tas",
	0xff00, 0x4a00, lone,  pone,  "tst",
	0xfff0, 0x4e40, l1,    ptrap, 0,
	0xfff8, 0x4e50, l2,    plink, 0,
	0xfff8, 0x4e58, l1,    pareg, "unlk\t%s",
	0xfff8, 0x4e60, l1,    pareg, "movl\t%s,usp",
	0xfff8, 0x4e68, l1,    pareg, "movl\tusp,%s",
	0xffff, 0x4e70, l1,    pareg, "reset",
	0xffff, 0x4e71, l1,    pareg, "nop",
	0xffff, 0x4e72, l2,    pstop, 0,
	0xffff, 0x4e73, el1,   pareg, "rte",
	0xffff, 0x4e75, el1,   pareg, "rts",
	0xffff, 0x4e76, l1,    pareg, "trapv",
	0xffff, 0x4e77, el1,   pareg, "rtr",
	0xfffe, 0x4e7a, l2,    pmovc, 0,
	0xffc0, 0x4e80, jj,    ppea,  "jsr",
	0xffc0, 0x4ec0, jj,    ppea,  "jmp",
	0xf1c0, 0x4180, lonew, podreg,"chk",
	0xf1c0, 0x41c0, lonel, plea,  0,
	0xf0f8, 0x50c8, lcbch, pdbcc, 0,
	0xf0c0, 0x50c0, lonew, pscc,  0,
	0xf100, 0x5000, lone,  pqu,   "add",
	0xf100, 0x5100, lone,  pqu,   "sub",
	0xf100, 0x7000, l1,    pmqu,  0,
	0xf1c0, 0x80c0, lonew, podreg,"divu",
	0xf1c0, 0x81c0, lonew, podreg,"divs",
	0xf1f0, 0x8100, l1,    ptreg, "sbcd",
	0xf000, 0x8000, loone, pomode,"or",
	0xf1f0, 0x9100, l1,    ptreg, "subxb",
	0xf1f0, 0x9140, l1,    ptreg, "subxw",
	0xf1f0, 0x9180, l1,    ptreg, "subxl",
	0xf000, 0x9000, loone, pomode,"sub",
	0xf1f8, 0xb108, l1,    pcmpm, "cmpmb",
	0xf1f8, 0xb148, l1,    pcmpm, "cmpmw",
	0xf1f8, 0xb188, l1,    pcmpm, "cmpml",
	0xf100, 0xb000, loone, pomode,"cmp",
	0xf1c0, 0xb1c0, loone, pomode,"cmp",
	0xf100, 0xb100, loone, pomode,"eor",
	0xf1c0, 0xc0c0, lonew, podreg,"mulu",
	0xf1c0, 0xc1c0, lonew, podreg,"muls",
	0xf1f0, 0xc100, l1,    ptreg, "abcd",
	0xf130, 0xc100, l1,    pexg,  0,
	0xf000, 0xc000, loone, pomode,"and",
	0xf1f0, 0xd100, l1,    ptreg, "addxb",
	0xf1f0, 0xd140, l1,    ptreg, "addxw",
	0xf1f0, 0xd180, l1,    ptreg, "addxl",
	0xf000, 0xd000, loone, pomode,"add",
	0xf8c0, 0xe0c0, lonew, pmshf,  0,
	0xf000, 0xe000, l1,    pshf,   0,
	0
};

char	*areg[] = { "a0", "a1", "a2", "a3", "a4", "a5", "a6", "sp"};
char	*cclist[] = { "hi", "ls", "cc", "cs", "ne", "eq", "vc", "vs",
			"pl", "mi", "ge", "lt", "gt", "le"};
	
char	*shtype[] = { "as", "ls", "rox", "ro" };
char	*bittyp[] = { "tst", "chg", "clr", "set" };

char	*creg[] = { "sfc", "dfc", "usp", "vbr" };

/*
 *	Length functions.
 */

int	l1()
{
	return	1;
}

int	l2()
{
	return	2;
}

int	el1(te)
t_entry	*te;
{
	te->t_bchtyp = T_UNBR;
	return	1;
}

int	lea(instr, size, pos)
unsigned  instr, size;
long	pos;
{
	switch  ((instr >> 3) & 0x7)  {
	case  0:
	case  1:
	case  2:
	case  3:
	case  4:
		return	1;
	case  5:
	case  6:
		return	2;
	default:
		switch  (instr & 0x7)  {
		case  0:
		case  2:
		case  3:
			return	2;
		case  1:
			mkdref(pos, size);
			return	3;
		case  4:
			if  (size > 2)
				return	3;
			return	2;
		default:
			return	0;
		}
	}
}

/*
 *	Lengths of move instructions.
 */

int	lmove(te, pos)
t_entry	*te;
long	pos;
{
	register  unsigned  tc  =  te->t_contents;
	unsigned  sz  =  1;
	int	lng, lng2;
	
	lng  = tc & 0xf000;
	if  (lng == 0x3000)
		sz = 2;
	else  if  (lng == 0x2000)
		sz = 4;
	
	if  ((lng = lea(tc, sz, pos+2)) <= 0)
		return	0;
	lng2 = lea(((tc>>3) & 0x38) | ((tc>>9) & 0x7), sz, pos+lng+lng);
	if  (lng2 <= 0)
		return	0;
	return	lng + lng2 - 1;
}

/*
 *	Lengths for conditional branches and dbcc instructions.
 */

int	lcbch(te, pos)
t_entry	*te;
long	pos;
{
	unsigned  tc  =  te->t_contents;
	long	dest  =  pos + 2;
	int	res   =  2;
	
	if  ((tc & 0xf000) == 0x5000  ||  (tc & 0xff) == 0)
		dest += (short)gettw(&mainfile, pos+2, R_WORD);
	else  {
		dest += (char) tc;
		res = 1;
	}
	if  ((tc & 0xff00) == 0x6000)
		te->t_bchtyp = T_UNBR;
	else  if  ((tc & 0xff00) == 0x6100)
		te->t_bchtyp = T_JSR;
	else
		te->t_bchtyp = T_CONDBR;

	te->t_relsymb = textlab(dest, pos);
	return	res;
}

int	jj(te, pos)
t_entry	*te;
long	pos;
{
	unsigned  tc  =  te->t_contents;
	t_entry	nextl;
	
	te->t_bchtyp = (tc & 0x40)? T_UNBR: T_JSR;
	if  ((tc & 0x3f) == 0x39)  {
		gette(&mainfile, pos+2, &nextl);
		if  (nextl.t_relsymb == NULL)  {
			nextl.t_relsymb = textlab(gettw(&mainfile, pos+2, R_LONG), pos);
			putte(&mainfile, pos+2, &nextl);
		}
		te->t_relsymb = nextl.t_relsymb;	/*  Easy ref  */
	}
	return	lea(tc, 4, pos+2);
}

int	limed(te, pos)
t_entry	*te;
long	pos;
{
	unsigned  tc  =  te->t_contents;
	int	lng;
	
	/*
	 *	Specifically exclude byte address register operands,
	 *	and ones which have lengths of 3.
	 */

	if  ((tc & 0xf8) == 0x08)
		return  0;
	
	if  ((tc & 0xc0) >= 0x80)  {
		if  (tc & 0x40)
			return  0;
		lng = lea(tc, 4, pos+6);
		if  (lng > 0)
			lng += 2;
	}
	else  {
		lng = lea(tc, (unsigned)((tc & 0xc0)?2:1), pos+4);
		if  (lng > 0)
			lng++;
	}
	return	lng;
}

int	lsbit(te, pos)
t_entry	*te;
long	pos;
{
	int	lng = lea(te->t_contents, 1, pos+4);
	
	if  (lng > 0)
		lng++;
	return	lng;
}

int	lmvml(te, pos)
t_entry	*te;
long	pos;
{
	int	lng = lea(te->t_contents,
			(unsigned)(te->t_contents&0x40? 4:2), pos+4);
	
	if  (lng > 0)
		lng++;
	return	lng;
}

/*
 *	Length depends on bits 6 and 7 of instruction.
 */

int	lone(te, pos)
t_entry	*te;
long	pos;
{
	unsigned  tc  =  te->t_contents;
	
	return	lea(tc, 1 << ((tc >> 6) & 3), pos+2);
}

/*
 *	Length depends on bits 6-8 of instruction.
 */

int	loone(te, pos)
t_entry	*te;
long	pos;
{
	unsigned  tc  =  te->t_contents;
	
	switch  ((tc >> 6) & 7)  {
	case  0:
	case  4:
		return	lea(tc, 1, pos+2);
	case  1:
	case  3:
	case  5:
		return  lea(tc, 2, pos+2);
	case  2:
	case  6:
	case  7:
		return	lea(tc, 4, pos+2);
	}
	/*NOTREACHED*/
}

int	lonew(te, pos)
t_entry	*te;
long	pos;
{
	return	lea(te->t_contents, 2, pos+2);
}

int	lonel(te, pos)
t_entry	*te;
long	pos;
{
	return	lea(te->t_contents, 4, pos+2);
}

/*
 *	Print routines.
 */

int	findleng(tc)
unsigned  tc;
{
	switch  ((tc >> 6) & 3)  {
	case  0:
		return	'b';
	case  1:
		return	'w';
	default:
		return	'l';
	}
}

void	piword(disp)
unsigned  disp;
{
	int	szc;
	
	(void) printf("@(0x%x,", disp & 0xff);
	if  (disp & 0x8000)
		(void) printf("%s", areg[(disp >> 12) & 0x7]);
	else
		(void) printf("d%d", (disp >> 12) & 0x7);
	szc = 'w';
	if  (disp & (1 << 10))
		szc = 'l';
	(void) printf(":%c)", szc);
}

void	paddr(pos)
long	pos;
{
	t_entry	tent;
	symbol	symb;
	
	gette(&mainfile, pos, &tent);
	if  (tent.t_relsymb != NULL)  {
		symb = tent.t_relsymb;
		if  (symb->s_lsymb != 0)
			(void) printf("%u$", symb->s_lsymb);
		else
			(void) printf("%s", symb->s_name);
		if  (tent.t_reldisp != 0)
			(void) printf("+0x%x", tent.t_reldisp);
		return;
	}
	(void) printf("0x%x", gettw(&mainfile, pos, R_LONG));
}

int	prea(ea, pos, sz)
unsigned  ea, sz;
long	pos;			/*  Address of previous word to extn  */
{
	unsigned  reg  =  ea & 0x7;
	long	disp;
	
	pos += 2;
	
	switch  ((ea >> 3) & 0x7)  {
	case  0:
		(void) printf("d%d", reg);
		return	0;
	case  1:
		(void) printf("%s", areg[reg]);
		return	0;
	case  2:
		(void) printf("%s@", areg[reg]);
		return	0;
	case  3:
		(void) printf("%s at +", areg[reg]);
		return	0;
	case  4:
		(void) printf("%s at -", areg[reg]);
		return	0;
	case  5:
		disp = gettw(&mainfile, pos, R_WORD);
		(void) printf("%s@(0x%x)", areg[reg], disp);
		return	2;
	case  6:
		(void) printf("%s", areg[reg]);
		piword((unsigned) gettw(&mainfile, pos, R_WORD));
		return	2;
	default:
		switch  (reg)  {
		case  0:
			disp = gettw(&mainfile, pos, R_WORD);
			(void) printf("0x%x:w", disp);
			return	2;
		case  1:
			paddr(pos);
			return	4;
		case  2:
			disp = gettw(&mainfile, pos, R_WORD);
			(void) printf("pc@(0x%x)", disp);
			return	2;
		case  3:
			(void) printf("pc");
			piword((unsigned) gettw(&mainfile, pos, R_WORD));
			return	2;
		case  4:
			(void) printf("#");
			if  (sz < 4)
				(void) printf("0x%x", gettw(&mainfile, pos, R_WORD));
			else
				paddr(pos);
			return	sz;
		default:
			(void) fprintf(stderr, "Funny mode\n");
			exit(220);
		}
	}
	/*NOTREACHED*/
}
	
int	pmove(te, pos)
t_entry	*te;
long	pos;
{
	unsigned  sz  =  2;
	unsigned  tc  =  te->t_contents;
	
	(void) printf("mov%s\t", optab[te->t_iindex].prarg);
	
	if  ((tc & 0xf000) == 0x2000)
		sz = 4;
	
	pos += prea(tc, pos, sz);
	putchar(',');
	(void) prea(((tc >> 9) & 0x7) | ((tc >> 3) & 0x38), pos, sz);
}

int	pcbch(te)
t_entry	*te;
{
	int	cc = ((te->t_contents >> 8) & 0xf) - 2;
	char	*msg;
	register  symbol  ts;
	
	if  (cc < 0)
		msg = cc < -1? "ra": "sr";
	else
		msg = cclist[cc];
	(void) printf("b%s", msg);
	if  (te->t_lng < 2)
		(void) printf("s");
	ts = te->t_relsymb;
	if  (ts->s_lsymb != 0)
		(void) printf("\t%u$", ts->s_lsymb);
	else
		(void) printf("\t%s", ts->s_name);
}

int	pdbcc(te)
t_entry	*te;
{
	unsigned  tc  =  te->t_contents;
	int	cc = ((tc >> 8) & 0xf) - 2;
	char	*msg;
	register  symbol  ts;
	
	if  (cc < 0)
		msg = cc < -1? "t": "f";
	else
		msg = cclist[cc];
	ts = te->t_relsymb;
	(void) printf("db%s\td%d,", msg, tc & 0x7);
	if  (ts->s_lsymb)
		(void) printf("%u$", ts->s_lsymb);
	else
		(void) printf("%s", ts->s_name);
}

int	pscc(te, pos)
t_entry	*te;
long	pos;
{
	unsigned  tc  =  te->t_contents;
	int	cc = ((tc >> 8) & 0xf) - 2;
	char	*msg;
	
	if  (cc < 0)
		msg = cc < -1? "t": "f";
	else
		msg = cclist[cc];
	(void) printf("s%s\t", msg);
	(void) prea(tc, pos, 1);
}

int	pcs(te, pos)
t_entry	*te;
long	pos;
{
	long	disp  =  gettw(&mainfile, pos+2, R_WORD);
	
	(void) printf("%s", optab[te->t_iindex].prarg);
	if  ((te->t_contents & 0xc0) == 0)
		(void) printf("b\t#0x%x,cc", disp);
	else
		(void) printf("w\t#0x%x,sr", disp);
}

int	pmovc(te, pos)
t_entry	*te;
long	pos;
{
	int	disp = gettw(&mainfile, pos+2, R_WORD);
	int	ctrl = ((disp >> 10) & 2) | (disp & 1);

	(void) printf("movec\t");
	if  ((te->t_contents & 1) == 0)
		(void) printf("%s,", creg[ctrl]);
	if  (disp & 0x8000)
		(void) printf("%s", areg[(disp >> 12) & 7]);
	else
		(void) printf("d%d", disp >> 12);
	if  (te->t_contents & 1)
		(void) printf(",%s", creg[ctrl]);
}

int	pimed(te, pos)
t_entry	*te;
long	pos;
{
	int	sz = findleng(te->t_contents);
	
	(void) printf("%s%c\t#", optab[te->t_iindex].prarg, sz);
	if  (sz == 'l')  {
		paddr(pos+2);
		putchar(',');
		(void) prea(te->t_contents, pos+4, 4);
	}
	else  {
		(void) printf("0x%x,", gettw(&mainfile, pos+2, R_WORD));
		(void) prea(te->t_contents, pos+2, 2);
	}
}

int	pmovp(te, pos)
t_entry	*te;
long	pos;
{
	unsigned  tc  =  te->t_contents;
	long	disp  =  gettw(&mainfile, pos+2, R_WORD);
	int	dreg = tc >> 9;
	char	*ar = areg[tc & 0x7];
	
	(void) printf("movep");
	if  (tc & (1 << 6))
		putchar('l');
	else
		putchar('w');

	if  (tc & (1 << 7))
		(void) printf("\td%d,%s@(0x%x)", dreg, ar, disp);
	else
		(void) printf("\t%s@(0x%x),d%d", ar, disp, dreg);
}

int	psbit(te, pos)
t_entry	*te;
long	pos;
{
	unsigned  tc  =  te->t_contents;
	
	(void) printf("b%s\t#%d,", bittyp[(tc >> 6) & 0x3], gettw(&mainfile, pos+2, R_WORD));
	(void) prea(tc, pos+2, 1);
}

/*ARGSUSED*/
int	pstop(te, pos)
t_entry	*te;
long	pos;
{
	(void) printf("stop\t#0x%x", gettw(&mainfile, pos+2, R_WORD));
}

int	pdbit(te, pos)
t_entry	*te;
long	pos;
{
	unsigned  tc  =  te->t_contents;
	
	(void) printf("b%s\td%d,", bittyp[(tc >> 6) & 0x3], (tc >> 9) & 0x7);
	(void) prea(tc, pos, 1);
}

int	pcs2(te, pos)
t_entry	*te;
long	pos;
{
	unsigned  tc  =  te->t_contents;
	
	(void) printf("movw\t");
	if  ((tc & 0xffc0) == 0x40c0)  {
		(void) printf("sr,");
		(void) prea(tc, pos, 2);
	}
	else  {
		(void) prea(tc, pos, 2);
		(void) printf(",%s", optab[te->t_iindex].prarg);
	}
}

int	pone(te, pos)
t_entry	*te;
long	pos;
{
	unsigned  tc  =  te->t_contents;
	int	sz = findleng(tc);
	
	(void) printf("%s%c\t", optab[te->t_iindex].prarg, sz);
	(void) prea(tc, pos, (unsigned)(sz == 'l'? 4: 2));
}

int	ppea(te, pos)	/*  nbcd, pea, tas, jmp, jsr  */
t_entry	*te;
long	pos;
{
	(void) printf("%s\t", optab[te->t_iindex].prarg);
	(void) prea(te->t_contents, pos, (unsigned)(te->t_lng > 2? 4: 2));
}


int	plea(te, pos)
t_entry	*te;
long	pos;
{
	(void) printf("lea\t");
	(void) prea(te->t_contents, pos, 4);
	(void) printf(",%s", areg[(te->t_contents >> 9) & 0x7]);
}

int	pdreg(te)
t_entry	*te;
{
	(void) printf("%s\td%d", optab[te->t_iindex].prarg, te->t_contents & 7);
}


int	pmvml(te, pos)
t_entry	*te;
long	pos;
{
	unsigned  tc  =  te->t_contents;
	register  unsigned  dw  =  gettw(&mainfile, pos+2, R_WORD);
	unsigned  sz = 4;
	int	sc = 'l';
	register  int	i;
	register  unsigned  bit;
	
	(void) printf("movem");
	if  ((tc & 0x40) == 0)  {
		sc = 'w';
		sz = 2;
	}
	
	(void) printf("%c\t", sc);
	
	if  (tc & 0x400)  {
		(void) prea(tc, pos+2, sz);
		(void) printf(",#0x%x", dw);
	}
	else  {
		(void) printf("#0x%x,", dw);
		(void) prea(tc, pos+2, sz);
	}
	
	(void) printf("\t|");
	
	if  ((tc & 0x38) == 0x20)  {
		bit = 0x8000;
		for  (i = 0;  i < 8;  i++)  {
			if  (dw & bit)
				(void) printf(" d%d", i);
			bit >>= 1;
		}
		for  (i = 0;  i < 8;  i++)  {
			if  (dw & bit)
				(void) printf(" %s", areg[i]);
			bit >>= 1;
		}
	}
	else  {
		bit = 1;
		for  (i = 0;  i < 8;  i++)  {
			if  (dw & bit)
				(void) printf(" d%d", i);
			bit <<= 1;
		}
		for  (i = 0;  i < 8;  i++)  {
			if  (dw & bit)
				(void) printf(" %s", areg[i]);
			bit <<= 1;
		}
	}
}

int	ptrap(te)
t_entry	*te;
{
	(void) printf("trap\t#0x%x", te->t_contents & 0xf);
}

int	plink(te, pos)
t_entry	*te;
long	pos;
{
	(void) printf("link\t%s,#0x%x", areg[te->t_contents & 0x7],
				gettw(&mainfile, pos+2, R_WORD));
}


int	pareg(te)
t_entry	*te;
{
	(void) printf(optab[te->t_iindex].prarg, areg[te->t_contents & 0x7]);
}

int	podreg(te, pos)
t_entry	*te;
long	pos;
{
	unsigned  tc  =  te->t_contents;
	
	(void) printf("%s\t", optab[te->t_iindex].prarg);
	(void) prea(tc, pos, 2);
	(void) printf(",d%d", (tc >> 9) & 0x7);
}

int	pqu(te, pos)
t_entry	*te;
long	pos;
{
	unsigned  tc  =  te->t_contents;
	int	sz  =  findleng(tc);
	int	amt = (tc >> 9) & 0x7;
	
	if  (amt == 0)
		amt = 8;
	(void) printf("%sq%c\t#%d,", optab[te->t_iindex].prarg, sz, amt);
	(void) prea(tc, pos, (unsigned)(sz == 'l'? 4: 2));
}

int	pmqu(te)
t_entry	*te;
{
	unsigned  tc  =  te->t_contents;

	(void) printf("moveq\t#0x%x,d%d", (char)tc, (tc >> 9) & 0x7);
}

int	ptreg(te)
t_entry	*te;
{
	register  unsigned  tc  =  te->t_contents;
	int	rx = (tc >> 9) & 0x7;
	int	ry = tc & 0x7;

	(void) printf("%s\t", optab[te->t_iindex].prarg);
	if  (tc & 0x8)
		(void) printf("%s at -,%s at -", areg[ry], areg[rx]);
	else
		(void) printf("d%d,d%d", ry, rx);
}

int	pcmpm(te)
t_entry	*te;
{
	register  unsigned  tc  =  te->t_contents;

	(void) printf("%s\t%s at +,%s at +", optab[te->t_iindex].prarg,
		areg[tc & 7], areg[(tc >> 9) & 7]);
}

int	pomode(te, pos)
t_entry	*te;
long	pos;
{
	unsigned  tc  =  te->t_contents;
	char	bef[4], aft[4];
	int	sz;
	int	reg = (tc >> 9) & 7;

	bef[0] = aft[0] = '\0';
	
	switch  ((tc >> 6) & 7)  {
	case  0:
		sz = 'b';
		goto  toreg;
	case  1:
		sz = 'w';
		goto  toreg;
	case  2:
		sz = 'l';
	toreg:
		(void) sprintf(aft, ",d%d", reg);
		break;
	case  3:
		sz = 'w';
		goto  toareg;
	case  7:
		sz = 'l';
	toareg:
		(void) sprintf(aft, ",%s", areg[reg]);
		break;
	case  4:
		sz = 'b';
		goto  frreg;
	case  5:
		sz = 'w';
		goto  frreg;
	case  6:
		sz = 'l';
	frreg:
		(void) sprintf(bef, "d%d,", reg);
		break;
	}

	(void) printf("%s%c\t%s", optab[te->t_iindex].prarg, sz, bef);
	(void) prea(tc, pos, (unsigned)(sz == 'l'? 4: 2));
	(void) printf(aft);
}

int	pexg(te)
t_entry	*te;
{
	unsigned  tc  =  te->t_contents;
	int	r1 = (tc >> 9) & 7, r2 = tc & 7;

	(void) printf("exg\t");
	
	if  ((tc & 0x00f8) == 0x0048)
		(void) printf("%s,", areg[r1]);
	else
		(void) printf("d%d,", r1);
	if  (tc & 0x8)
		(void) printf("%s", areg[r2]);
	else
		(void) printf("d%d", r2);
}
	
int	pmshf(te, pos)
t_entry	*te;
long	pos;
{
	unsigned  tc  =  te->t_contents;
	
	(void) printf("%s%cw\t", shtype[(tc >> 9) & 3], tc & 0x100? 'l': 'r');
	(void) prea(tc, pos, 2);
}

int	pshf(te)
t_entry	*te;
{
	unsigned  tc  =  te->t_contents;
	int	sz  =  findleng(tc);
	int	disp = (tc >> 9) & 7;

	(void) printf("%s%c%c\t", shtype[(tc >> 3) & 3], tc & 0x100? 'l': 'r', sz);
	if  (tc & 0x20)
		(void) printf("d%d", disp);
	else
		(void) printf("#%d", disp == 0? 8: disp);
	(void) printf(",d%d", tc & 7);
}

/*
 *	Find length etc of instruction.
 */

int	findinst(te, pos)
register  t_entry  *te;
long	pos;
{
	register  struct  opstr	*op;
	unsigned  tc  =  te->t_contents;
	int	lng = 0;
	register  int	i;

	te->t_type = T_BEGIN;
	te->t_bchtyp = T_NOBR;
	
	for  (op = &optab[0];  op->mask;  op++)  {
		if  ((tc & op->mask) == op->match)  {
			te->t_iindex = op - optab;
			lng = (op->opsize)(te, pos);
			break;
		}
	}

	for  (i = 1;  i < lng;  i++)  {
		t_entry	ctent;
		long	npos = pos+i+i;
		
		if  (npos >= endt)
			goto  clearem;
		gette(&mainfile, npos, &ctent);
		if  (ctent.t_bdest || ctent.t_dref)  {
clearem:		for  (i--; i > 0; i--)  {
				npos = pos + i + i;
				gette(&mainfile, npos, &ctent);
				ctent.t_type = T_UNKNOWN;
				putte(&mainfile, npos, &ctent);
			}
			lng = 0;
			goto  ginv;
		}
		ctent.t_type = T_CONT;
		putte(&mainfile, npos, &ctent);
	}
	
	if  (lng <= 0)  {
ginv:		te->t_vins = 0;
		te->t_lng = 1;
		te->t_type = T_UNKNOWN;
		te->t_bchtype = T_NOBR;
	}
	else
		te->t_lng = lng;
	return	lng;
}

/*
 *	Print instruction.
 */

void	prinst(te, pos)
t_entry	*te;
long	pos;
{
	putchar('\t');
	(optab[te->t_iindex].opprin)(te, pos);
	putchar('\n');
}
SHAR_EOF
if test 19541 -ne "`wc -c < 'iset.c'`"
then
	echo shar: error transmitting "'iset.c'" '(should have been 19541 characters)'
fi
fi
echo shar: extracting "'libmtch.c'" '(7242 characters)'
if test -f 'libmtch.c'
then
	echo shar: will not over-write existing file "'libmtch.c'"
else
cat << \SHAR_EOF > 'libmtch.c'
/*
 *	SCCS:	@(#)libmtch.c	1.2	11/2/84	14:18:55
 *	Read library files.
 *
 ***********************************************************************
 *	This software is copyright of
 *
 *		John M Collins
 *		47 Cedarwood Drive
 *		St Albans
 *		Herts, AL4 0DN
 *		England			+44 727 57267
 *
 *	and is released into the public domain on the following conditions:
 *
 *		1.  No free maintenance will be guaranteed.
 *		2.  Nothing may be based on this software without
 *		    acknowledgement, including incorporation of this
 *		    notice.
 *
 *	Notwithstanding the above, the author welcomes correspondence and bug
 *	fixes.
 ***********************************************************************
 */

#include <stdio.h>
#include <fcntl.h>
#include <a.out.h>
#include <ar.h>
#include <setjmp.h>
#include "unc.h"

long	lseek();
void	bfopen(), bfclose(), nomem();
void	rrell2(), markmatch();
char	*strchr(), *strrchr(), *strncpy(), *strcat(), *strcpy(), *malloc();
int	matchup();
long	findstart();

char	verbose;		/*  Tell the world what we are doing  */
char	*tfnam;
char	*cfile;
ef_fids	mainfile;
struct	commit	dreltab;
int	donedrel, donebrel;
long	trelpos, drelpos, brelpos;
static	struct	libit	currlib = {-1, 0, -1, ""};

void	lclash(str)
char	*str;
{
	(void) fprintf(stderr, "Library scan failure - %s\n", str);
	(void) fprintf(stderr, "Searching %s\n", cfile);
	if  (currlib.lf_name[0])
		(void) fprintf(stderr, "Member is %s\n", currlib.lf_name);
	exit(255);
}

/*
 *	Find next member.
 */

long	nextmemb(lfd)
register  struct  libit	 *lfd;
{
	struct	ar_hdr	arbuf;
	
	if  (lfd->lf_next < 0)
		return	-1;
	
	(void) lseek(lfd->lf_fd, lfd->lf_next, 0);
	if  (read(lfd->lf_fd, (char *)&arbuf, sizeof(arbuf)) != sizeof(arbuf))  {
		lfd->lf_next = -1;
		return	-1;
	}
	(void) strncpy(lfd->lf_name, arbuf.ar_name, sizeof(lfd->lf_name));
	lfd->lf_offset = lfd->lf_next + sizeof(arbuf);
	lfd->lf_next = (lfd->lf_offset + arbuf.ar_size + 1) & ~1;
	return	lfd->lf_offset;
}

/*
 *	Decode a file name thus -
 *
 *	-lxxx decode as /lib/libxxx.a /usr/lib/libxxx.a etc
 *	-Lxxx forget "lib" ".a" bit thus -Lcrt0.o
 *	or read LDPATH environment var to give list of directories as sh
 *	(default /lib:/usr/lib).
 *
 *	Alternatively treat as normal pathname.
 *
 *	File names may be followed by (membername) if the file is an archive,
 *	thus
 *
 *		-lc(printf.o)
 *
 *	in which case the specified module is fetched.
 */

struct	libit	*getfnam(str)
char	*str;
{
	char	*bp, *ep = NULL, *pathb, *pathe, *fullpath = NULL;
	static	char	*pathn;
	extern	char	*getenv();
	long	magic;
	struct	ar_hdr	arhdr;
	int	fd;

	if  ((bp = strrchr(str, '(')) != NULL &&
		 (ep = strrchr(str, ')')) != NULL)
		*ep = *bp = '\0';

	if  (str[0] == '-'  &&  (str[1] == 'l' || str[1] == 'L'))  {
		if  (pathn == NULL)  {
			if  ((pathn = getenv("LDPATH")) == NULL)
				pathn = "/lib:/usr/lib";
		}
		fullpath = malloc((unsigned)(strlen(pathn) + strlen(str) + 1));
		if  (fullpath == NULL)
			nomem();
		pathb = pathn;
		do  {
			pathe = strchr(pathb, ':');
			if  (*pathb == ':')
				fullpath[0] = '\0';
			else  {
				if  (pathe != NULL)
					*pathe = '\0';
				(void) strcpy(fullpath, pathb);
				(void) strcat(fullpath, "/");
				if  (pathe != NULL)
					*pathe = ':';
			}
			if  (str[1] == 'l')
				(void) strcat(fullpath, "lib");
			(void) strcat(fullpath, &str[2]);
			if  (str[1] == 'l')
				(void) strcat(fullpath, ".a");
			if  ((fd = open(fullpath, O_RDONLY)) >= 0)
				goto  found;
			pathb = pathe + 1;
		}   while  (pathe != NULL);
		
		(void) fprintf(stderr, "Unable to locate lib%s.a in %s\n",
			&str[2], pathn);
		exit(101);
	}
	else  if  ((fd = open(str, O_RDONLY)) < 0)  {
		(void) fprintf(stderr, "Cannot open %s\n", str);
		exit(102);
	}
	
found:

	if  ((read(fd, (char *) &magic, sizeof(magic)) != sizeof(magic)  ||
		magic != ARMAG))  {
		if  (ep != NULL)  {
			(void) fprintf(stderr, "%s is not library file\n",
					fullpath != NULL? fullpath: str);
			exit(103);
		}
		if  (fullpath != NULL)
			free(fullpath);
		currlib.lf_fd = fd;
		currlib.lf_offset = 0;
		currlib.lf_next = -1;
		currlib.lf_name[0] = '\0';
		return  &currlib;
	}
	
	/*
	 *	It appears to be a library file - see if we want a specific
	 *	one.
	 */
	
	if  (ep != NULL)  {
		currlib.lf_offset = sizeof(magic) + sizeof(struct ar_hdr);
		for  (;;)  {
			if  (read(fd, &arhdr, sizeof(arhdr)) != sizeof(arhdr))  {
				(void) fprintf(stderr, "Cannot find member %s in %s\n",
					bp+1, fullpath?fullpath: str);
				exit(103);
			}
			if  (strncmp(bp+1, arhdr.ar_name, sizeof(arhdr.ar_name)) == 0)
				break;
			currlib.lf_offset += arhdr.ar_size + sizeof(arhdr) + 1;
			currlib.lf_offset &= ~ 1;
			(void) lseek(fd, (long)(currlib.lf_offset - sizeof(arhdr)), 0);
		}
		if  (fullpath != NULL)
			free(fullpath);
		currlib.lf_fd = fd;
		currlib.lf_next = -1;
		currlib.lf_name[0] = '\0';
		*bp = '(';
		*ep = ')';
		return	&currlib;
	}
	
	/*
	 *	Otherwise point to 1st member in library.
	 */
	
	if  (read(fd, &arhdr, sizeof(arhdr)) != sizeof(arhdr))  {
		(void) fprintf(stderr, "Library %s empty\n", fullpath? fullpath: str);
		exit(104);
	}
	if  (fullpath != NULL)
		free(fullpath);
	currlib.lf_offset = sizeof(magic) + sizeof(arhdr);
	currlib.lf_next = currlib.lf_offset + arhdr.ar_size + 1;
	currlib.lf_next &= ~1;
	currlib.lf_fd = fd;
	(void) strncpy(currlib.lf_name, arhdr.ar_name, sizeof(currlib.lf_name));
	return	&currlib;
}

/*
 *	Process library files.
 */

#define	MINTEXT	6

void	lscan(nfiles, fnames)
int	nfiles;
char	**fnames;
{
	ef_fids	libfile;
	register  ef_fid  ll = &libfile;
	register  struct  libit	 *clf;
	extern	symbol	dolsymb();
	int	firstfile;
	
	for  (;  nfiles > 0;  fnames++, nfiles--)  {
		clf = getfnam(*fnames);
		cfile = *fnames;
		firstfile = 1;
		do  {
			bfopen(tfnam, ll);

			/*
			 *	If file is garbled, silently forget it and go
			 *	on to the next one.
			 */

			if  (!rtext(clf->lf_fd, clf->lf_offset, ll))
				goto  closeit;
				
			if  (ll->ef_tsize < MINTEXT)
				goto  closeit;
				
			if  (!rdata(clf->lf_fd, clf->lf_offset, ll))
				goto  closeit;
				
			if  (rrell1(clf->lf_fd, clf->lf_offset, ll) < 0)
				goto  closeit;
				
			/*
			 *	If first file in library, find it from
			 *	beginning of main file.
			 */
			
			if  (firstfile)  {
				if  ((trelpos = findstart(&mainfile, ll)) < 0)
					goto  closeit;
				firstfile = 0;
			}
			else   if  (!matchup(&mainfile, ll, trelpos))
					goto  closeit;
			
			/*
			 *	Found a match.
			 */
			
			if  (!rsymb(clf->lf_fd, clf->lf_offset, dolsymb, ll))  {
				(void) fprintf(stderr, "Corrupt file %s\n",
							*fnames);
				exit(150);
			}
			
			donedrel = 0;
			donebrel = 0;
			rrell2(clf->lf_fd, clf->lf_offset, ll);
			if  (verbose)  {
				(void) fprintf(stderr, "Found: ");
				if  (clf->lf_name[0])
					(void) fprintf(stderr, "%.14s in ",
							clf->lf_name);
				(void) fprintf(stderr, "%s\n", *fnames);
			}
			if  (libfile.ef_stvec != NULL)  {
				free(libfile.ef_stvec);
				libfile.ef_stvec = NULL;
				libfile.ef_stcnt = 0;
			}
			dreltab.c_int = 0;
				
			/*
			 *	Start looking next time round
			 *	where last one left off.
			 */
			
			markmatch(&mainfile, ll, trelpos);
			trelpos += libfile.ef_tsize;
closeit:
			bfclose(ll);
		}  while  (nextmemb(clf) >= 0);
	}
}
SHAR_EOF
if test 7242 -ne "`wc -c < 'libmtch.c'`"
then
	echo shar: error transmitting "'libmtch.c'" '(should have been 7242 characters)'
fi
fi
echo shar: extracting "'main.c'" '(6255 characters)'
if test -f 'main.c'
then
	echo shar: will not over-write existing file "'main.c'"
else
cat << \SHAR_EOF > 'main.c'
/*
 *	SCCS:	@(#)main.c	1.2	11/2/84	14:19:31
 *	Main routine etc.
 *
 ***********************************************************************
 *	This software is copyright of
 *
 *		John M Collins
 *		47 Cedarwood Drive
 *		St Albans
 *		Herts, AL4 0DN
 *		England			+44 727 57267
 *
 *	and is released into the public domain on the following conditions:
 *
 *		1.  No free maintenance will be guaranteed.
 *		2.  Nothing may be based on this software without
 *		    acknowledgement, including incorporation of this
 *		    notice.
 *
 *	Notwithstanding the above, the author welcomes correspondence and bug
 *	fixes.
 ***********************************************************************
 */

#include <stdio.h>
#include <fcntl.h>
#include <a.out.h>
#include <sys/var.h>
#include "unc.h"

#define	LINELNG	70

void	inturdat(), intutext(), intudat(), intlsym();
void	ptext(), pdata(), pabs(), pbss(), lscan();

ef_fids	mainfile;

int	par_entry, par_round;	/*  68000 parameters  */
int	nmods;			/*  Number of modules it looks like  */

char	*tfnam = "split";

char	lsyms;			/*  Generate local symbols  */
char	verbose;		/*  Tell the world what we are doing  */
char	noabs;			/*  No non-global absolutes  */
int	rel;			/*  File being analysed is relocatable  */
int	lpos;

symbol	dosymb();
struct	libit	*getfnam();

/*
 *	Get hex characters, also allowing for 'k' and 'm'.
 */

int	ghex(str)
register  char	*str;
{
	register  int	result = 0;
	register  int	lt;

	for  (;;)  {
		lt = *str++;
		switch  (lt)  {
		default:
err:			(void) fprintf(stderr, "Invalid hex digit \'%c\'\n", lt);
			exit(1);
			
		case '\0':
			return	result;
			
		case '0':case '1':case '2':case '3':case '4':
		case '5':case '6':case '7':case '8':case '9':
			result = (result << 4) + lt - '0';
			continue;
			
		case 'a':case 'b':case 'c':case 'd':case 'e':case 'f':
			result = (result << 4) + lt - 'a' + 10;
			continue;

		case 'A':case 'B':case 'C':case 'D':case 'E':case 'F':
			result = (result << 4) + lt - 'A' + 10;
			continue;
		
		case 'k':case 'K':
			if  (*str != '\0')
				goto  err;
			return  result << 10;
			
		case 'm':case 'M':
			if  (*str != '\0')
				goto  err;
			return  result << 20;
		}
	}
}

/*
 *	Process entry line options.  Return number dealt with.
 */

int	doopts(av)
char	*av[];
{
	register  int	cnt = 0, lt;
	register  char	*arg;
	struct	var	vs;
	
	uvar(&vs);
	par_entry = vs.v_ustart;
	par_round = vs.v_txtrnd - 1;
	
	for  (;;)  {
		arg = *++av;
		if  (*arg++ != '-')
			return	cnt;
		cnt++;
		
nx:		switch  (lt = *arg++)  {
		default:
			(void) fprintf(stderr, "Bad option -%c\n", lt);
			exit(1);
			
		case  '\0':
			continue;
			
		case  'l':	/*  A file name  */
		case  'L':
			return	cnt - 1;
			
		case  's':
			lsyms++;
			goto  nx;
			
		case  'v':
			verbose++;
			goto  nx;
			
		case  'a':
			noabs++;
			goto  nx;

		case  'R':
		case  'N':
			if  (*arg == '\0')  {
				cnt++;
				arg = *++av;
				if  (arg == NULL)  {
bo:					(void) fprintf(stderr,"Bad -%c option\n",lt);
					exit(1);
				}
			}
			if  (lt == 'R')
				par_entry = ghex(arg);
			else
				par_round = ghex(arg) - 1;
			continue;
			
		case  't':
			if  (*arg == '\0')  {
				cnt++;
				arg = *++av;
				if  (arg == NULL)
					goto  bo;
			}
			tfnam = arg;
			continue;
			
		case  'o':
			if  (*arg == '\0')  {
				cnt++;
				arg = *++av;
				if  (arg == NULL)
					goto  bo;
			}
			if  (freopen(arg, "w", stdout) == NULL)  {
				(void) fprintf(stderr, "Help! cant open %s\n", arg);
				exit(20);
			}
			continue;
		}
	}
}
	
/*
 *	Open binary files.  Arrange to erase them when finished.
 */

void	bfopen(nam, fid)
char	*nam;
ef_fid	fid;
{
	char	fnam[80];
	
	(void) sprintf(fnam, "%s.tx", nam);
	if  ((fid->ef_t = open(fnam, O_RDWR|O_CREAT, 0666)) < 0)  {
efil:		(void) fprintf(stderr, "Help could not open %s\n", fnam);
		exit(4);
	}
	(void) unlink(fnam);
	(void) sprintf(fnam, "%s.dt", nam);
	if  ((fid->ef_d = open(fnam, O_RDWR|O_CREAT, 0666)) < 0)
		goto  efil;
	(void) unlink(fnam);
}

/*
 *	Close binary files.  They should get zapped anyway.
 */

void	bfclose(fid)
ef_fid	fid;
{
	(void) close(fid->ef_t);
	(void) close(fid->ef_d);
}

/*
 *	Main routine.
 */

main(argc, argv)
int	argc;
char	*argv[];
{
	int	i;
	char	*progname = argv[0];
	char	*msg;
	register  struct  libit  *lfd;
	
	i = doopts(argv);
	argc -= i;
	argv += i;
	
	if  (argc < 2)  {
		(void) fprintf(stderr, "Usage: %s [ options ] file\n", progname);
		exit(1);
	}
	
	lfd = getfnam(argv[1]);
	if  (lfd->lf_next > 0)  {
		(void) fprintf(stderr, "Main file (%s) cannot be library\n", argv[1]);
		exit(2);
	}
	
	bfopen(tfnam, &mainfile);
	if  (verbose)
		(void) fprintf(stderr, "Scanning text\n");
	if  (!rtext(lfd->lf_fd, lfd->lf_offset, &mainfile))  {
		msg = "text";
bf:		(void) fprintf(stderr, "Bad format input file - reading %s\n", msg);
		exit(5);
	}
	if  (verbose)
		(void) fprintf(stderr, "Scanning data\n");
	if  (!rdata(lfd->lf_fd, lfd->lf_offset, &mainfile))  {
		msg = "data";
		goto  bf;
	}
	if  (verbose)
		(void) fprintf(stderr, "Scanning symbols\n");
	if  (!rsymb(lfd->lf_fd, lfd->lf_offset, dosymb, &mainfile))  {
		msg = "symbols";
		goto  bf;
	}
	if  (verbose)
		(void) fprintf(stderr, "Scanning for relocation\n");
	if  ((rel = rrel(lfd->lf_fd, lfd->lf_offset, &mainfile)) < 0)  {
		msg = "reloc";
		goto  bf;
	}
	
	if  (rel)  {
		if  (verbose)
			(void) fprintf(stderr, "File is relocatable\n");
		if  (argc > 2)
			(void) fprintf(stderr, "Sorry - no scan on reloc files\n");
	}
	else
		lscan(argc - 2, &argv[2]);

	if  (verbose)
		(void) fprintf(stderr, "End of input\n");
	
	(void) close(lfd->lf_fd);
	if  (nmods > 0)
		(void) fprintf(stderr, "Warning: at least %d merged modules\n",
			nmods + 1);

	if  (mainfile.ef_stvec != NULL)  {
		free(mainfile.ef_stvec);
		mainfile.ef_stvec = NULL;
		mainfile.ef_stcnt = 0;
	}
	
	if  (verbose)
		(void) fprintf(stderr, "Text anal 1\n");
	intutext();
	if  (verbose)
		(void) fprintf(stderr, "Data anal 1\n");
	intudat(&mainfile);
	if  (!rel)  {
		if  (verbose)
			(void) fprintf(stderr, "Data anal 2\n");
		inturdat(&mainfile);
	}
	if  (lsyms)  {
		if  (verbose)
			(void) fprintf(stderr, "Local symbol scan\n");
		intlsym();
	}
	pabs();
	ptext(&mainfile);
	pdata(&mainfile);
	pbss(&mainfile);
	bfclose(&mainfile);
	exit(0);
}
SHAR_EOF
if test 6255 -ne "`wc -c < 'main.c'`"
then
	echo shar: error transmitting "'main.c'" '(should have been 6255 characters)'
fi
fi
echo shar: extracting "'prin.c'" '(5480 characters)'
if test -f 'prin.c'
then
	echo shar: will not over-write existing file "'prin.c'"
else
cat << \SHAR_EOF > 'prin.c'
/*
 *	SCCS:	@(#)prin.c	1.2	11/2/84	14:19:47
 *	Print stuff.
 *
 ***********************************************************************
 *	This software is copyright of
 *
 *		John M Collins
 *		47 Cedarwood Drive
 *		St Albans
 *		Herts, AL4 0DN
 *		England			+44 727 57267
 *
 *	and is released into the public domain on the following conditions:
 *
 *		1.  No free maintenance will be guaranteed.
 *		2.  Nothing may be based on this software without
 *		    acknowledgement, including incorporation of this
 *		    notice.
 *
 *	Notwithstanding the above, the author welcomes correspondence and bug
 *	fixes.
 ***********************************************************************
 */

#include <stdio.h>
#include <a.out.h>
#include "unc.h"

#define	LINELNG	70

void	gette(), getde();
long	gettw(), getdw();
void	prinst();

char	noabs;			/*  No non-global absolutes  */
int	rel;			/*  File being analysed is relocatable  */
int	lpos;

struct	commit	abstab, comtab;

/*
 *	Print absolute and common values.
 */

void	pabs()
{
	register  int	i;
	register  symbol  cs;

	for  (i = 0;  i < abstab.c_int;  i++)
	
	for  (i = 0;  i < abstab.c_int;  i++)  {
		cs = abstab.c_symb[i];
		if  (cs->s_glob)
			(void) printf("\t.globl\t%s\n", cs->s_name);
		else  if  (noabs)
			continue;
		(void) printf("%s\t=\t0x%lx\n", cs->s_name, cs->s_value);
	}
	for  (i = 0;  i < comtab.c_int;  i++)  {
		cs = comtab.c_symb[i];
		(void) printf("\t.comm\t%s,%d\n", cs->s_name, cs->s_value);
	}
}

/*
 *	Print out labels.
 */

void	plabs(ls, seg)
register  symbol  ls;
int	seg;
{
	for  (; ls != NULL;  ls = ls->s_link)  {
		if  (ls->s_type != seg)
			continue;
		if  (ls->s_lsymb)  {
			(void) printf("%u$:\n", ls->s_lsymb);
			return;		/*  Set last  */
		}
		if  (ls->s_glob)
			(void) printf("\n\t.globl\t%s", ls->s_name);
		(void) printf("\n%s:\n", ls->s_name);
	}
}

/*
 *	Print out text.
 */

void	ptext(fid)
register  ef_fid  fid;
{
	register  long	tpos, endt;
	t_entry	tstr;

	(void) printf(".text\n");
	
	tpos = fid->ef_tbase;
	endt = tpos + fid->ef_tsize;
contin:	
	for  (;  tpos < endt;  tpos += tstr.t_lng * 2)  {
		gette(fid, tpos, &tstr);
		plabs(tstr.t_lab, TEXT);
		if  (tstr.t_type == T_BEGIN)
			prinst(&tstr, tpos);
		else  if  (tstr.t_relsymb != NULL)  {
			(void) printf("\t.long\t%s", tstr.t_relsymb->s_name);
			if  (tstr.t_relsymb->s_type!=TEXT &&
				tstr.t_relsymb->s_type!=DATA)
				(void) printf("+0x%x", gettw(fid, tpos, R_LONG));
			putchar('\n');
			tpos += 4;
			goto  contin;
		}
		else
			(void) printf("\t.word\t0x%x\n", tstr.t_contents);
	}

	/*
	 *	Print out any trailing label.
	 */
	
	gette(fid, tpos, &tstr);
	plabs(tstr.t_lab, TEXT);
}

/*
 *	Print out data.
 */

void	pdata(fid)
register  ef_fid  fid;
{
	register  long	dpos, endd;
	register  int	lng;
	unsigned  ctyp;
	int	had, par, inc;
	char	*msg;
	d_entry	dstr;
	
	(void) printf("\n.data\n");
	
	dpos = fid->ef_dbase;
	endd = dpos + fid->ef_dsize;

	while  (dpos < endd)  {
		
		getde(fid, dpos, &dstr);
		plabs(dstr.d_lab, DATA);
			
		switch  (dstr.d_type)  {
		case  D_CONT:
			(void) fprintf(stderr, "Data sync error\n");
			exit(200);
			
		case  D_ASC:
		case  D_ASCZ:
			ctyp = dstr.d_type;
			lng = dstr.d_lng;
			(void) printf("\t.asci");
			if  (ctyp == D_ASC)
				(void) printf("i\t\"");
			else  {
				(void) printf("z\t\"");
				lng--;
			}
				
			while  (lng > 0)  {
				getde(fid, dpos, &dstr);
				switch  (dstr.d_contents)  {
				default:
					if  (dstr.d_contents < ' ' ||
						dstr.d_contents > '~')
						(void) printf("\\%.3o", dstr.d_contents);
					else
						putchar(dstr.d_contents);
					break;
				case  '\"':
				case  '\'':
				case  '\\':
				case  '|':
					(void) printf("\\%c", dstr.d_contents);
					break;
				case  '\b':
					(void) printf("\\b");
					break;
				case  '\n':
					(void) printf("\\n");
					break;
				case  '\r':
					(void) printf("\\r");
					break;
				}
				
				lng--;
				dpos++;
			}
			(void) printf("\"\n");
			if  (ctyp == D_ASCZ)
				dpos++;
			break;

		case  D_BYTE:
			msg = "byte";
			par = R_BYTE;
			inc = 1;
			goto  wrest;
			
		case  D_WORD:
			msg = "word";
			par = R_WORD;
			inc = 2;
			goto  wrest;
			
		case  D_LONG:
			msg = "long";
			par = R_LONG;
			inc = 4;
		wrest:
			(void) printf("\t.%s\t", msg);
			lng = dstr.d_lng;
			lpos = 16;
			had = 0;
			while  (lng > 0)  {
				if  (lpos > LINELNG)  {
					(void) printf("\n\t.%s\t", msg);
					lpos = 16;
				}
				else  if  (had)
					lpos += printf(", ");

				lpos += printf("0x%x", getdw(fid, dpos, par));
				lng -= inc;
				dpos += inc;
				had++;
			}
			putchar('\n');
			break;

		case  D_ADDR:
			(void) printf("\t.long\t");
			lng = dstr.d_lng;
			lpos = 16;
			had = 0;
			while  (lng > 0)  {
				if  (lpos > LINELNG)  {
					(void) printf("\n\t.long\t");
					lpos = 16;
				}
				else  if  (had)
					lpos += printf(", ");

				getde(fid, dpos, &dstr);
				lpos += printf("%s", dstr.d_relsymb->s_name);
				lng -= sizeof(long);
				dpos += sizeof(long);
				had++;
			}
			putchar('\n');
			break;
		}
	}
	
	/*
	 *	Print trailing label.
	 */
	
	getde(fid, dpos, &dstr);
	plabs(dstr.d_lab, DATA);
}

void	pbss(fid)
register  ef_fid  fid;
{
	register  long	bpos = fid->ef_bbase;
	long	endb = fid->ef_end;
	d_entry	bstr;
	
	(void) printf("\n.bss\n");
	
	while  (bpos < endb)  {
		getde(fid, bpos, &bstr);
		plabs(bstr.d_lab, BSS);
		(void) printf("\t.space\t%d\n", bstr.d_lng);
		bpos += bstr.d_lng;
	}
	
	getde(fid, endb, &bstr);
	plabs(bstr.d_lab, BSS);
}
SHAR_EOF
if test 5480 -ne "`wc -c < 'prin.c'`"
then
	echo shar: error transmitting "'prin.c'" '(should have been 5480 characters)'
fi
fi
echo shar: extracting "'robj.c'" '(18429 characters)'
if test -f 'robj.c'
then
	echo shar: will not over-write existing file "'robj.c'"
else
cat << \SHAR_EOF > 'robj.c'
/*
 *	SCCS:	@(#)robj.c	1.2	11/2/84	14:19:59
 *	Read object files.
 *
 ***********************************************************************
 *	This software is copyright of
 *
 *		John M Collins
 *		47 Cedarwood Drive
 *		St Albans
 *		Herts, AL4 0DN
 *		England			+44 727 57267
 *
 *	and is released into the public domain on the following conditions:
 *
 *		1.  No free maintenance will be guaranteed.
 *		2.  Nothing may be based on this software without
 *		    acknowledgement, including incorporation of this
 *		    notice.
 *
 *	Notwithstanding the above, the author welcomes correspondence and bug
 *	fixes.
 ***********************************************************************
 *
 *	This particular module will obviously have to be munged beyond
 *	recognition for another object format.
 */

#include <stdio.h>
#include <a.out.h>
#include "unc.h"

void	gette(), getde(), setde(), putte(), putde();
long	gettw(), getdw();
void	reallst(), lclash(), nomem(), unimpl();
void	addit();
char	*malloc();
long	lseek();

int	par_entry, par_round, nmods, donedrel, donebrel;
struct	commit	abstab, comtab, dreltab;
long	trelpos, drelpos, brelpos;

ef_fids	mainfile;

symbol	lookup(), inventsymb(), getnsymb();

#define	DBSIZE	100
#define	STINIT	20

/*
 *	Read text segment.  Return 0 if not ok.
 */

int	rtext(inf, offset, outf)
int	inf;		/*  a.out file (possibly in library)  */
long	offset;		/*  Offset from start of inf of a.out file  */
ef_fid	outf;		/*  Output file descriptor  */
{
	t_entry		tstr;
	struct	bhdr	filhdr;
	register  long	size;
	register  int	i, l;
	unsigned  short	inbuf[DBSIZE/2];

	/*
	 *	Initialise fields in structure.
	 */
	
	tstr.t_type = T_UNKNOWN;
	tstr.t_vins = 1;		/*  For the moment  */
	tstr.t_bdest = 0;
	tstr.t_gbdest = 0;
	tstr.t_lng = 1;
	tstr.t_reloc = R_NONE;
	tstr.t_rdisp = 0;
	tstr.t_isrel = 0;
	tstr.t_amap = 0;
	tstr.t_dref = 0;
	tstr.t_relsymb = NULL;
	tstr.t_reldisp = 0;
	tstr.t_lab = NULL;
	tstr.t_lsymb = 0;
	tstr.t_refhi = 0;
	tstr.t_reflo = 0x7fffffff;
	tstr.t_match = 0;
	
	/*
	 *	Read a.out header.
	 */
	
	(void) lseek(inf, offset, 0);

	if  (read(inf, (char *)&filhdr, sizeof(filhdr)) != sizeof(filhdr))
		return	0;

	if  (filhdr.fmagic != FMAGIC  &&  filhdr.fmagic != NMAGIC)
		return	0;

	/*
	 *	Warn user if entry point does not tie up.
	 */
	
	if  (filhdr.entry != par_entry)
		(void) fprintf(stderr, "Warning: File has -R%X\n", filhdr.entry);

	outf->ef_entry = filhdr.entry;
	outf->ef_tbase = filhdr.entry;
	outf->ef_dbase = filhdr.tsize + filhdr.entry;

	if  (filhdr.fmagic == NMAGIC)
		outf->ef_dbase = (outf->ef_dbase + par_round) & (~par_round);

	outf->ef_bbase = outf->ef_dbase + filhdr.dsize;
	outf->ef_end = outf->ef_bbase + filhdr.bsize;

	outf->ef_tsize = filhdr.tsize;
	outf->ef_dsize = filhdr.dsize;
	outf->ef_bsize = filhdr.bsize;
	
	(void) lseek(inf, offset + TEXTPOS, 0);
	
	size = outf->ef_tsize;
	
	while  (size > 1)  {
		l = size > DBSIZE? DBSIZE: size;
		if  (read(inf, (char *)inbuf, l) != l)
			return	0;
		l /= 2;
		for  (i = 0;  i < l;  i++)  {
			tstr.t_contents = inbuf[i];
			(void) write(outf->ef_t, (char *)&tstr, sizeof(tstr));
		}
		size -= l + l;
	}
	
	/*
	 *	Extra one to cope with "etext".
	 */
	
	(void) write(outf->ef_t, (char *)&tstr, sizeof(tstr));
	return	1;
}

/*
 *	Same sort of thing for the data segment.
 */

int	rdata(inf, offset, outf)
int	inf;		/*  a.out file (possibly in library)  */
long	offset;		/*  Offset from start of inf of a.out file  */
ef_fid	outf;		/*  Output file descriptor  */
{
	d_entry		dstr;
	struct	bhdr	filhdr;
	register  long	size;
	register  int	i, l;
	unsigned  char	inbuf[DBSIZE];

	/*
	 *	Initialise fields in structure.
	 */
	
	dstr.d_type = D_BYTE;
	dstr.d_reloc = R_NONE;
	dstr.d_lng = 1;
	dstr.d_relsymb = NULL;
	dstr.d_reldisp = 0;
	dstr.d_lab = NULL;
	
	/*
	 *	Read a.out header.
	 */
	
	(void) lseek(inf, offset, 0);

	if  (read(inf, (char *)&filhdr, sizeof(filhdr)) != sizeof(filhdr))
		return	0;

	(void) lseek(inf, offset + DATAPOS, 0);
	
	size = outf->ef_dsize;
	
	while  (size > 0)  {
		l = size > DBSIZE? DBSIZE: size;
		if  (read(inf, (char *)inbuf, l) != l)
			return	0;
		for  (i = 0;  i < l;  i++)  {
			dstr.d_contents = inbuf[i];
			(void) write(outf->ef_d, (char *)&dstr, sizeof(dstr));
		}
		size -= l;
	}
	
	/*
	 *	Repeat for BSS segment.
	 */

	dstr.d_contents = 0;
	for  (size = outf->ef_bsize;  size > 0;  size--)
		(void) write(outf->ef_d, (char *)&dstr, sizeof(dstr));
	
	/*
	 *	Extra one to cope with "end".
	 */
	
	(void) write(outf->ef_d, (char *)&dstr, sizeof(dstr));
	return	1;
}

/*
 *	Process symbol table segment.
 */

int	rsymb(inf, offset, dproc, outf)
int	inf;		/*  a.out file (possibly in library)  */
long	offset;		/*  Offset from start of inf of a.out file  */
symbol	(*dproc)();
register  ef_fid  outf;	/*  Output file descriptor  */
{
	register  symbol  csym;
	struct	bhdr	filhdr;
	struct	sym	isym;
	register  long	size;
	register  int	i, l;
	char	inbuf[SYMLENGTH+1];

	/*
	 *	Read a.out header.
	 */
	
	(void) lseek(inf, offset, 0);

	if  (read(inf, (char *)&filhdr, sizeof(filhdr)) != sizeof(filhdr))
		return	0;

	offset += SYMPOS;
	size = filhdr.ssize;
	if  (size <= 0)
		return	1;

	/*
	 *	Guesstimate symbol table vector size.
	 */

	l = size / (sizeof(struct sym) + 4);
	if  (l <= 0)
		l = STINIT;

	outf->ef_stvec = (symbol *) malloc(l * sizeof(symbol));
	if  (outf->ef_stvec == NULL)
		nomem();

	outf->ef_stcnt = 0;
	outf->ef_stmax = l;
	
	while  (size > sizeof(struct sym))  {
		(void) lseek(inf, offset, 0);
		if  (read(inf, (char *)&isym, sizeof(isym)) != sizeof(isym))
			return	0;
		size -= sizeof(isym);
		l = SYMLENGTH;
		if  (l > size)
			l = size;
		if  (read(inf, inbuf, l) != l)
			return	0;
		inbuf[l] = '\0';
		for  (i = 0; inbuf[i] != '\0';  i++)
			;
		size -= i + 1;
		offset += sizeof(isym) + i + 1;
		csym = (*dproc)(lookup(inbuf), isym.stype, isym.svalue, outf);
		if  (outf->ef_stcnt >= outf->ef_stmax)
			reallst(outf);
		outf->ef_stvec[outf->ef_stcnt++] = csym;
	}
	return	1;
}

/*
 *	Process relocation stuff.  -1 error, 0 no relocation, 1 relocation.
 */

int	rrel(inf, offset, outf)
int	inf;		/*  a.out file (possibly in library)  */
long	offset;		/*  Offset from start of inf of a.out file  */
ef_fid	outf;		/*  Output file descriptor  */
{
	struct	bhdr	filhdr;
	struct	reloc	crel;
	t_entry	tstr;
	d_entry	dstr;
	register  long	size;
	long	cont, pos;

	/*
	 *	Read a.out header.
	 */
	
	(void) lseek(inf, offset, 0);

	if  (read(inf, (char *)&filhdr, sizeof(filhdr)) != sizeof(filhdr))
		return	-1;
	if  (filhdr.rtsize <= 0  &&  filhdr.rdsize <= 0)
		return	0;

	size  =  filhdr.rtsize;

	(void) lseek(inf, RTEXTPOS + offset, 0);
	while  (size >= sizeof(struct reloc))  {
		if  (read(inf, (char *)&crel, sizeof(crel)) != sizeof(crel))
			return	-1;

		pos = crel.rpos + outf->ef_tbase;
		gette(outf, pos, &tstr);
		tstr.t_reloc = crel.rsize + 1;	/*  Fiddle!  YUK!!!  */
		tstr.t_rdisp = crel.rdisp;
		tstr.t_rptr = crel.rsegment;
		if  (crel.rsegment == REXT)  {
			if  (crel.rsymbol >= outf->ef_stcnt)
				return  -1;
			tstr.t_relsymb = outf->ef_stvec[crel.rsymbol];
			tstr.t_reldisp = gettw(outf, pos, (int)crel.rsize+1);
		}
		else  {
			cont = gettw(outf, pos, (int)crel.rsize+1);
			tstr.t_relsymb = getnsymb(outf, crel.rsegment, cont);
		}
		tstr.t_relsymb->s_used++;
		putte(outf, pos, &tstr);
		size -= sizeof(crel);
	}
	
	/*
	 *	And now repeat all that for data relocations.
	 */
	
	size  =  filhdr.rdsize;
	
	(void) lseek(inf, RDATAPOS + offset, 0);
	while  (size >= sizeof(struct reloc))  {
		if  (read(inf, (char *)&crel, sizeof(crel)) != sizeof(crel))
			return	-1;

		pos = crel.rpos + outf->ef_dbase;
		getde(outf, pos, &dstr);
		dstr.d_reloc = crel.rsize + 1;	/*  Fiddle!  YUK!!!  */
		dstr.d_rptr = crel.rsegment;

		if  (crel.rsegment == REXT)  {
			if  (crel.rsymbol >= outf->ef_stcnt)
				return  -1;
			dstr.d_relsymb = outf->ef_stvec[crel.rsymbol];
			dstr.d_reldisp = getdw(outf, pos, (int)crel.rsize+1);
		}
		else  {
			cont = getdw(outf, pos, (int)crel.rsize+1);
			dstr.d_relsymb = getnsymb(outf, crel.rsegment, cont);
			if  (dstr.d_relsymb->s_type == TEXT)  {
				gette(outf, cont, &tstr);
				tstr.t_dref = 1;
				putte(outf, cont, &tstr);
			}
		}
		switch  (crel.rsize)  {
		default:
			unimpl("Data byte relocation");
			break;
		case  RWORD:
			unimpl("data word reloc");
			dstr.d_type = D_WORD;
			dstr.d_lng = 2;
			setde(outf, pos+1, D_CONT, 1);
			break;
		case  RLONG:
			dstr.d_type = D_ADDR;
			dstr.d_lng = 4;
			setde(outf, pos+1, D_CONT, 1);
			setde(outf, pos+2, D_CONT, 1);
			setde(outf, pos+3, D_CONT, 1);
			break;
		}
		dstr.d_relsymb->s_used++;
		putde(outf, pos, &dstr);
		size -= sizeof(crel);
	}
	return 1;
}

/*
 *	Process a symbol.
 */

symbol	dosymb(sy, type, val, fid)
register  symbol  sy;
int	type;
long	val;
ef_fid	fid;
{
	t_entry	tstr;
	d_entry	dstr;
	
	if  (!sy->s_newsym)  {
		if  (type & EXTERN)  {
			(void) fprintf(stderr, "Duplicate symbol %s\n", sy->s_name);
			exit(10);
		}
		if  (++sy->s_defs > nmods)
			nmods = sy->s_defs;
		sy = inventsymb("DUP");
	}

	sy->s_value = val;
	
	switch  (type)  {
	default:
		return	NULL;
		
	case  EXTERN|UNDEF:
		if  (val != 0)  {
			sy->s_type = COMM;
			addit(&comtab, sy);
		}
		else
			sy->s_type = N_UNDF;
		sy->s_glob = 1;
		break;
		
	case  EXTERN|ABS:
		sy->s_type = N_ABS;
		sy->s_glob = 1;
		addit(&abstab, sy);
		break;
		
	case  ABS:
		sy->s_type = N_ABS;
		addit(&abstab, sy);
		break;
		
	case  EXTERN|TEXT:
	case  TEXT:
		sy->s_type = N_TEXT;
		gette(fid, val, &tstr);
		tstr.t_bdest = 1;
		if  (type & EXTERN)  {
			tstr.t_gbdest = 1;
			sy->s_glob = 1;
		}
		sy->s_link = tstr.t_lab;
		tstr.t_lab = sy;
		putte(fid, val, &tstr);
		break;
		
	case  BSS:
	case  EXTERN|BSS:
		sy->s_type = N_BSS;
		goto	datrest;
	case  DATA:
	case  EXTERN|DATA:
		sy->s_type = N_DATA;
	datrest:
		getde(fid, val, &dstr);
		if  (type & EXTERN)
			sy->s_glob = 1;
		sy->s_link = dstr.d_lab;
		dstr.d_lab = sy;
		putde(fid, val, &dstr);
		break;
	}
	
	sy->s_newsym = 0;
	return	sy;
}

/*
 *	Process relocation stuff in putative library modules.
 *	The main function of all this is to mark which bits of the text
 *	not to look at as I compare the stuff.
 *
 *	As with "rrel", return -1 error, 0 no relocation, 1 relocation.
 */

int	rrell1(inf, offset, outf)
int	inf;		/*  a.out file (possibly in library)  */
long	offset;		/*  Offset from start of inf of a.out file  */
ef_fid	outf;		/*  Output file descriptor  */
{
	struct	bhdr	filhdr;
	struct	reloc	crel;
	t_entry	tstr;
	register  long	size;
	long	pos;

	/*
	 *	Read a.out header.
	 */
	
	(void) lseek(inf, offset, 0);

	if  (read(inf, (char *)&filhdr, sizeof(filhdr)) != sizeof(filhdr))
		return	-1;
	if  (filhdr.rtsize <= 0  &&  filhdr.rdsize <= 0)
		return	0;

	size  =  filhdr.rtsize;

	(void) lseek(inf, RTEXTPOS + offset, 0);
	while  (size >= sizeof(struct reloc))  {
		if  (read(inf, (char *)&crel, sizeof(crel)) != sizeof(crel))
			return	-1;

		pos = crel.rpos + outf->ef_tbase;
		gette(outf, pos, &tstr);
		tstr.t_reloc = crel.rsize + 1;	/*  Fiddle!  YUK!!!  */
		tstr.t_rdisp = crel.rdisp;
		tstr.t_rptr = crel.rsegment;
		tstr.t_isrel = 1;
		putte(outf, pos, &tstr);
		if  (crel.rsize == RLONG)  {
			gette(outf, pos+2, &tstr);
			tstr.t_isrel = 1;
			putte(outf, pos+2, &tstr);
		}
		size -= sizeof(crel);
	}
	
	/*
	 *	Dont bother with data relocation at this stage. We'll
	 *	tie that up later.
	 */
	
	return 1;
}

/*
 *	Process a symbol in library file.  The extern variable trelpos gives
 *	the place in the main file where the library module is relocated.
 *	We don't know the data position until we do the final merge, perhaps
 *	not even then.
 */

symbol	dolsymb(sy, type, val, fid)
register  symbol  sy;
int	type;
long	val;
ef_fid	fid;
{
	t_entry	tstr;
	
	switch  (type)  {
	default:
		return	NULL;
		
	case  EXTERN|UNDEF:
		if  (!sy->s_newsym)
			return	sy;
		sy->s_value = val;
		if  (val != 0)  {
			sy->s_type = COMM;
			addit(&dreltab, sy);
		}
		else
			sy->s_type = N_UNDF;
		sy->s_glob = 1;
		break;
		
	case  EXTERN|ABS:
		if  (!sy->s_newsym)  {
			if  (sy->s_type != N_ABS || sy->s_value != val)
				lclash("abs");
		}
		sy->s_type = N_ABS;
		sy->s_value = val;
		sy->s_glob = 1;
		addit(&abstab, sy);
		break;
		
	case  EXTERN|TEXT:
		sy->s_type = N_TEXT;
		val += trelpos - fid->ef_tbase;
		if  (!sy->s_newsym)  {
			if  (val != sy->s_value)
				lclash("tsym");
			return	sy;
		}
		sy->s_value = val;
		gette(&mainfile, val, &tstr);
		tstr.t_bdest = 1;
		tstr.t_gbdest = 1;
		sy->s_glob = 1;
		sy->s_link = tstr.t_lab;
		tstr.t_lab = sy;
		putte(&mainfile, val, &tstr);
		break;

	case  EXTERN|BSS:
		if  (!sy->s_newsym)
			return	sy;
		sy->s_type = N_BSS;
		sy->s_value = val - fid->ef_bbase;
		goto	datrest;

	case  EXTERN|DATA:
		if  (!sy->s_newsym)
			return	sy;
		sy->s_type = N_DATA;
		sy->s_value = val - fid->ef_dbase;
	datrest:
		sy->s_glob = 1;
		addit(&dreltab, sy);
		break;
	}
	
	sy->s_newsym = 0;
	return	sy;
}

/*
 *	Change definition of undefined symbol as we define it.
 */

void	reassign(sy, val)
register  symbol  sy;
long	val;
{
	sy->s_value = val;

	if  (val < mainfile.ef_tbase)  {
		sy->s_type = N_ABS;
		addit(&abstab, sy);
	}
	else  if  (val < mainfile.ef_dbase)  {
		t_entry	tstr;
		
		sy->s_type = N_TEXT;
		gette(&mainfile, val, &tstr);
		tstr.t_bdest = 1;
		tstr.t_gbdest = 1;
		sy->s_glob = 1;
		sy->s_link = tstr.t_lab;
		tstr.t_lab = sy;
		putte(&mainfile, val, &tstr);
	}
	else  {
		d_entry dstr;
		
		sy->s_type = val < mainfile.ef_bbase? N_DATA: N_BSS;
		getde(&mainfile, val, &dstr);
		sy->s_link = dstr.d_lab;
		dstr.d_lab = sy;
		putde(&mainfile, val, &dstr);
	}
}

/*
 *	When we discover where bss or data come, reallocate the table.
 */

void	zapdat(seg, inc)
int	seg;
long	inc;
{
	register  int	i;
	register  symbol  csymb;
	d_entry	dent;
	
	for  (i = 0;  i < dreltab.c_int;  i++) {
		csymb = dreltab.c_symb[i];
		if  (csymb->s_type != seg)
			continue;
		csymb->s_value += inc;
		getde(&mainfile, csymb->s_value, &dent);
		csymb->s_link = dent.d_lab;
		dent.d_lab = csymb;
		putde(&mainfile, csymb->s_value, &dent);
	}
}

/*
 *	Process relocation stuff in library module which we are inserting.
 *	Horrors if something goes wrong.
 */

void	rrell2(inf, offset, outf)
int	inf;		/*  a.out file (possibly in library)  */
long	offset;		/*  Offset from start of inf of a.out file  */
ef_fid	outf;		/*  Output file descriptor  */
{
	struct	bhdr	filhdr;
	struct	reloc	crel;
	t_entry	mtstr;
	d_entry	mdstr;
	register  long	size;
	register  symbol  csymb;
	long	pos, mpos, mval, lval;
	int	dhere = 0;		/*  Mark whether bss done  */

	/*
	 *	Read a.out header.
	 */
	
	(void) lseek(inf, offset, 0);

	if  (read(inf, (char *)&filhdr, sizeof(filhdr)) != sizeof(filhdr))
		return;
	if  (filhdr.rtsize <= 0  &&  filhdr.rdsize <= 0)
		return;

	size  =  filhdr.rtsize;

	(void) lseek(inf, RTEXTPOS + offset, 0);
	for  (;  size >= sizeof(struct reloc);  size -= sizeof(crel))  {
		if  (read(inf, (char *)&crel, sizeof(crel)) != sizeof(crel))
			lclash("rd trel");

		pos = crel.rpos + outf->ef_tbase;
		mpos = crel.rpos + trelpos;
		gette(&mainfile, mpos, &mtstr);
		lval = gettw(outf, pos, (int)crel.rsize+1);
		mval = gettw(&mainfile, mpos, (int)crel.rsize+1);
		
		switch  (crel.rsegment)  {
		case  RTEXT:
			if  (lval + trelpos - outf->ef_tbase != mval)
				lclash("Trel");
			continue;
		case  RDATA:
			if  (donedrel)  {
				if  (lval + drelpos - outf->ef_dbase != mval)
					lclash("Drel");
			}
			else  {
				donedrel++;
				drelpos = mval - lval + outf->ef_dbase;
			}
			continue;
		case  RBSS:
			if  (donebrel)  {
				if  (lval + brelpos - outf->ef_bbase != mval)
					lclash("brel");
			}
			else  {
				donebrel++;
				brelpos = mval - lval + outf->ef_bbase;
			}
			continue;
		case  REXT:
			if  (crel.rsymbol >= outf->ef_stcnt)
				lclash("Bad sy no");
			csymb = outf->ef_stvec[crel.rsymbol];
			if  (csymb == NULL)
				continue;
			switch  (csymb->s_type)  {
			case  N_UNDF:
				reassign(csymb, mval - lval);
				break;
			case  N_ABS:
				if  (lval + csymb->s_value != mval)
					lclash("abs rel");
				break;
			case  N_TEXT:
				if  (lval + csymb->s_value != mval)
					lclash("text rel");
				break;
			case  N_DATA:
				if  (lval + csymb->s_value != mval)
					lclash("data rel");
				break;
			case  N_BSS:
				if  (lval + csymb->s_value != mval)
					lclash("bss rel");
				break;
			case  COMM:
				reassign(csymb, mval - lval);
				break;
			}
			mtstr.t_relsymb = csymb;
			mtstr.t_reldisp = lval;
			break;
		}
	}
	
	/*
	 *	Relocate data and bss if possible.
	 */
	
	if  (donebrel)  {
		zapdat(N_BSS, brelpos);
		dhere++;
	}
	
	if  (!donedrel)
		return;
		

	zapdat(N_DATA, drelpos);
	
	/*
	 *	And now repeat all that for data relocations if possible
	 */
	
	size  =  filhdr.rdsize;
	
	(void) lseek(inf, RDATAPOS + offset, 0);
	for  (;  size >= sizeof(struct reloc); size -= sizeof(crel))  {
		if  (read(inf, (char *)&crel, sizeof(crel)) != sizeof(crel))
			lclash("Rd drel");

		if  (crel.rsize != RLONG)
			continue;

		pos = crel.rpos + outf->ef_dbase;
		mpos = crel.rpos + drelpos;
		getde(&mainfile, mpos, &mdstr);
		lval = getdw(outf, pos, (int)crel.rsize+1);
		mval = getdw(&mainfile, mpos, (int)crel.rsize+1);
		switch  (crel.rsegment)  {
		case  RTEXT:
			if  (lval + trelpos - outf->ef_tbase != mval)
				lclash("Trel-d");
			continue;
		case  RDATA:
			if  (lval + drelpos - outf->ef_dbase != mval)
				lclash("Drel-d");
			continue;
		case  RBSS:
			if  (donebrel)  {
				if  (lval + brelpos - outf->ef_bbase != mval)
					lclash("brel");
			}
			else  {
				donebrel++;
				brelpos = mval - lval + outf->ef_bbase;
			}
			continue;
		case  REXT:
			if  (crel.rsymbol >= outf->ef_stcnt)
				lclash("Bad sy no");
			csymb = outf->ef_stvec[crel.rsymbol];
			if  (csymb == NULL)
				continue;
			switch  (csymb->s_type)  {
			case  N_UNDF:
				reassign(csymb, mval - lval);
				break;
			case  N_ABS:
				if  (lval + csymb->s_value != mval)
					lclash("abs rel");
				break;
			case  N_TEXT:
				if  (lval + csymb->s_value != mval)
					lclash("text rel");
				break;
			case  N_DATA:
				if  (lval + csymb->s_value != mval)
					lclash("data rel");
				break;
			case  N_BSS:
				if  (lval + csymb->s_value != mval)
					lclash("bss rel");
				break;
			case  COMM:
				reassign(csymb, mval - lval);
				break;
			}
			mtstr.t_relsymb = csymb;
			mtstr.t_reldisp = lval;
			break;
		}
	}

	if  (dhere || !donebrel)
		return;

	zapdat(N_BSS, brelpos);
}
SHAR_EOF
if test 18429 -ne "`wc -c < 'robj.c'`"
then
	echo shar: error transmitting "'robj.c'" '(should have been 18429 characters)'
fi
fi
exit 0
#	End of shell archive



More information about the Mod.sources mailing list