[comp.sources.misc] v04i125: 680x0 COFF disassembler

alex@umbc3.UUCP (Alex S. Crain) (10/15/88)

Posting-number: Volume 4, Issue 125
Submitted-by: "Alex S. Crain" <alex@umbc3.UUCP>
Archive-name: 68kdisasm/Part1

	This is a dissassembler for 68K COFF machines, based on the unc 
program that went out over the net awhile back. It works really well, and alot
of people have shown an interest.

#!/bin/sh
# shar:	Shell Archiver  (v1.22)
#
#	Run the following text with /bin/sh to create:
#	  iset.c
#	  libmtch.c
#	  robj.c
#
sed 's/^X//' << 'SHAR_EOF' > iset.c &&
X/*
X *	SCCS:	@(#)iset.c	1.2	11/2/84	14:18:23
X *	Decode instructions.
X *
X ***********************************************************************
X *	This software is copyright of
X *
X *		John M Collins
X *		47 Cedarwood Drive
X *		St Albans
X *		Herts, AL4 0DN
X *		England			+44 727 57267
X *
X *	and is released into the public domain on the following conditions:
X *
X *		1.  No free maintenance will be guaranteed.
X *		2.  Nothing may be based on this software without
X *		    acknowledgement, including incorporation of this
X *		    notice.
X *
X *	Notwithstanding the above, the author welcomes correspondence and bug
X *	fixes.
X ***********************************************************************
X */
X
X#include <stdio.h>
X#include <a.out.h>
X#include <ldfcn.h>
X#include "unc.h"
X
Xef_fids	mainfile;
Xlong	endt;
X
Xvoid	gette(), putte();
Xvoid	mkdref();
Xlong	gettw();
Xsymbol	textlab();
X
Xint	l1(), l2(), el1(), lea(), lmove(), lcbch(), jj();
Xint	limed(), lsbit(), lmvml(), lone(), loone(), lonew(), lonel();
X
Xint	pmove(), pcbch(), pdbcc(), pscc(), pcs(), pmovc(), pstop(), pexg();
Xint	pimed(), pmovp(), psbit(), pdbit(), pcs2(), pone(), ppea();
Xint	plea(), pdreg(), pmvml(), ptrap(), plink(), pareg(), podreg();
Xint	pqu(), pmqu(), ptreg(), pcmpm(), pomode(), pmshf(), pshf();
X
Xstruct	opstr	{
X	unsigned  short	 mask;
X	unsigned  short  match;
X	int	(*opsize)();
X	int	(*opprin)();
X	char	*prarg;
X} optab[] = {
X	0xf000, 0x2000, lmove, pmove, ".l",
X	0xf000, 0x3000, lmove, pmove, ".w",
X	0xf000, 0x1000, lmove, pmove, ".b",
X	0xf000, 0x6000, lcbch, pcbch, 0,
X	0xffbf, 0x003c, l2,    pcs,   "or",
X	0xff00, 0x0000, limed, pimed, "or",
X	0xffbf, 0x023c, l2,    pcs,   "and",
X	0xff00, 0x0200, limed, pimed, "and",
X	0xff00, 0x0400, limed, pimed, "sub",
X	0xff00, 0x0600, limed, pimed, "add",
X	0xffbf, 0x0a3c, l2,    pcs,   "eor",
X	0xff00, 0x0a00, limed, pimed, "eor",
X	0xff00, 0x0c00, limed, pimed, "cmp",
X	0xf138, 0x0108, l2,    pmovp, 0,
X	0xff00, 0x0800, lsbit, psbit, 0,
X	0xf100, 0x0100, lonew, pdbit, 0,
X	0xffc0, 0x40c0, lonew, pcs2,  "sr",
X	0xff00, 0x4000, lone,  pone,  "negx",
X	0xff00, 0x4200, lone,  pone,  "clr",
X	0xffc0, 0x44c0, lonew, pcs2,  "cc",
X	0xff00, 0x4400, lone,  pone,  "neg",
X	0xffc0, 0x46c0, lonew, pcs2,  "sr",
X	0xff00, 0x4600, lone,  pone,  "not",
X	0xffc0, 0x4800, lonew, ppea,  "nbcd",
X	0xfff8, 0x4840, l1,    pdreg, "swap.w",
X	0xffc0, 0x4840, lonel, ppea,  "pea",
X	0xfff8, 0x4880, l1,    pdreg, "ext.w",
X	0xfff8, 0x48c0, l1,    pdreg, "ext.l",
X	0xfb80, 0x4880, lmvml, pmvml, 0,
X	0xffc0, 0x4ac0, lonew, ppea,  "tas",
X	0xff00, 0x4a00, lone,  pone,  "tst",
X	0xfff0, 0x4e40, l1,    ptrap, 0,
X	0xfff8, 0x4e50, l2,    plink, 0,
X	0xfff8, 0x4e58, l1,    pareg, "unlk\t%s",
X	0xfff8, 0x4e60, l1,    pareg, "mov.l\t%s,%%usp",
X	0xfff8, 0x4e68, l1,    pareg, "mov.l\t%%usp,%s",
X	0xffff, 0x4e70, l1,    pareg, "reset",
X	0xffff, 0x4e71, l1,    pareg, "nop",
X	0xffff, 0x4e72, l2,    pstop, 0,
X	0xffff, 0x4e73, el1,   pareg, "rte",
X	0xffff, 0x4e75, el1,   pareg, "rts",
X	0xffff, 0x4e76, l1,    pareg, "trapv",
X	0xffff, 0x4e77, el1,   pareg, "rtr",
X	0xfffe, 0x4e7a, l2,    pmovc, 0,
X	0xffc0, 0x4e80, jj,    ppea,  "jsr",
X	0xffc0, 0x4ec0, jj,    ppea,  "jmp",
X	0xf1c0, 0x4180, lonew, podreg,"chk",
X	0xf1c0, 0x41c0, lonel, plea,  0,
X	0xf0f8, 0x50c8, lcbch, pdbcc, 0,
X	0xf0c0, 0x50c0, lonew, pscc,  0,
X	0xf100, 0x5000, lone,  pqu,   "add",
X	0xf100, 0x5100, lone,  pqu,   "sub",
X	0xf100, 0x7000, l1,    pmqu,  0,
X	0xf1c0, 0x80c0, lonew, podreg,"divu",
X	0xf1c0, 0x81c0, lonew, podreg,"divs",
X	0xf1f0, 0x8100, l1,    ptreg, "sbcd",
X	0xf000, 0x8000, loone, pomode,"or",
X	0xf1f0, 0x9100, l1,    ptreg, "subx.b",
X	0xf1f0, 0x9140, l1,    ptreg, "subx.w",
X	0xf1f0, 0x9180, l1,    ptreg, "subx.l",
X	0xf000, 0x9000, loone, pomode,"sub",
X	0xf1f8, 0xb108, l1,    pcmpm, "cmp.b",		/* CMPM	*/
X	0xf1f8, 0xb148, l1,    pcmpm, "cmp.w",		/* CMPM	*/
X	0xf1f8, 0xb188, l1,    pcmpm, "cmp.l",		/* CMPM	*/
X	0xf100, 0xb000, loone, pomode,"cmp",
X	0xf1c0, 0xb1c0, loone, pomode,"cmp",
X	0xf100, 0xb100, loone, pomode,"eor",
X	0xf1c0, 0xc0c0, lonew, podreg,"mulu",
X	0xf1c0, 0xc1c0, lonew, podreg,"muls",
X	0xf1f0, 0xc100, l1,    ptreg, "abcd",
X	0xf130, 0xc100, l1,    pexg,  0,
X	0xf000, 0xc000, loone, pomode,"and",
X	0xf1f0, 0xd100, l1,    ptreg, "addx.b",
X	0xf1f0, 0xd140, l1,    ptreg, "addx.w",
X	0xf1f0, 0xd180, l1,    ptreg, "addx.l",
X	0xf000, 0xd000, loone, pomode,"add",
X	0xf8c0, 0xe0c0, lonew, pmshf,  0,
X	0xf000, 0xe000, l1,    pshf,   0,
X	0
X};
X
Xchar	*areg[] = { "%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%fp", "%sp"};
Xchar	*cclist[] = { "hi", "ls", "cc", "cs", "ne", "eq", "vc", "vs",
X			"pl", "mi", "ge", "lt", "gt", "le"};
X	
Xchar	*shtype[] = { "as", "ls", "rox", "ro" };
Xchar	*bittyp[] = { "tst", "chg", "clr", "set" };
X
Xchar	*creg[] = { "%sfc", "%dfc", "%usp", "%vbr" };
X
Xint swbegflg = 0;
X
X/*
X *	Length functions.
X */
X
Xint	l1()
X{
X	return	1;
X}
X
Xint	l2()
X{
X	return	2;
X}
X
Xint	el1(te)
Xt_entry	*te;
X{
X	te->t_bchtyp = T_UNBR;
X	return	1;
X}
X
Xint	lea(instr, size, pos)
Xunsigned  instr, size;
Xlong	pos;
X{
X	switch  ((instr >> 3) & 0x7)  {
X	case  0:
X	case  1:
X	case  2:
X	case  3:
X	case  4:
X		return	1;
X	case  5:
X	case  6:
X		return	2;
X	default:
X		switch  (instr & 0x7)  {
X		case  0:
X		case  2:
X		case  3:
X			return	2;
X		case  1:
X			mkdref(pos, size);
X			return	3;
X		case  4:
X			if  (size > 2)
X				return	3;
X			return	2;
X		default:
X			return	0;
X		}
X	}
X}
X
X/*
X *	Lengths of move instructions.
X */
X
Xint	lmove(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	register  unsigned  tc  =  te->t_contents;
X	unsigned  sz  =  1;
X	int	lng, lng2;
X	
X	lng  = tc & 0xf000;
X	if  (lng == 0x3000)
X		sz = 2;
X	else  if  (lng == 0x2000)
X		sz = 4;
X	
X	if  ((lng = lea(tc, sz, pos+2)) <= 0)
X		return	0;
X	lng2 = lea(((tc>>3) & 0x38) | ((tc>>9) & 0x7), sz, pos+lng+lng);
X	if  (lng2 <= 0)
X		return	0;
X	return	lng + lng2 - 1;
X}
X
X/*
X *	Lengths for conditional branches and dbcc instructions.
X */
X
Xint	lcbch(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	unsigned  tc  =  te->t_contents;
X	long	dest  =  pos + 2;
X	int	res   =  2;
X	
X	if  ((tc & 0xf000) == 0x5000  ||  (tc & 0xff) == 0)
X		dest += (short)gettw(&mainfile, pos+2, R_WORD);
X	else  {
X		dest += (char) tc;
X		res = 1;
X	}
X 	if ( dest < 0x290000 && (dest < mainfile.ef_tbase 
X 		|| dest >= mainfile.ef_tbase+mainfile.ef_tsize 
X 		|| (dest & 1) != 0 ))
X 		return 0;		/* Illegal branch destination */
X	if  ((tc & 0xff00) == 0x6000)
X		te->t_bchtyp = T_UNBR;
X	else  if  ((tc & 0xff00) == 0x6100)
X		te->t_bchtyp = T_JSR;
X	else
X		te->t_bchtyp = T_CONDBR;
X
X 	if ( dest < 0x290000 && ((te->t_relsymb = textlab(dest, pos)) == NULL )) {
X 		te->t_bchtyp = T_NOBR;/* Branch to a continuation */
X 		return 0;
X 	}
X	return	res;
X}
X
Xint	jj(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	unsigned  tc  =  te->t_contents;
X	t_entry	nextl;
X 	long dest;
X	
X	te->t_bchtyp = (tc & 0x40)? T_UNBR: T_JSR;
X	if ((tc & 0x3f) == 0x39) {
X		gette(&mainfile, pos+2, &nextl);
X		if  (nextl.t_relsymb == NULL)  {
X 			dest = gettw(&mainfile, pos + 2, R_LONG );
X 			if ( dest < 0x290000 && (dest < mainfile.ef_tbase
X 				|| dest >= mainfile.ef_tbase+mainfile.ef_tsize
X 				|| (dest & 1) != 0 ))
X 				return 0;	/* Illegal branch destination */
X 			if ( dest < 0x290000 && ( nextl.t_relsymb = textlab(dest, pos) ) == NULL )
X 			return 0;	/* Branch to a continuation */
X			putte(&mainfile, pos+2, &nextl);
X		}
X		te->t_relsymb = nextl.t_relsymb;	/*  Easy ref  */
X	}
X	else if ((tc & 0x3f) == 0x3a) {
X		gette(&mainfile, pos+2, &nextl);
X		if  (nextl.t_relsymb == NULL)  {
X			dest = pos+2+ (int)((short) 
X				gettw(&mainfile, pos + 2, R_WORD ));
X 			if ( dest < 0x290000 && (dest < mainfile.ef_tbase
X 			    || dest >= mainfile.ef_tbase+mainfile.ef_tsize
X 			    || (dest & 1) != 0 ))
X			return	lea(tc, 4, pos+2);
X 			if (dest < 0x290000 && 
X			    (nextl.t_relsymb = textlab(dest, pos)) == NULL)
X	 			return 0;	/* Branch to a continuation */
X			putte(&mainfile, pos+2, &nextl);
X		}
X		te->t_relsymb = nextl.t_relsymb;	/*  Easy ref  */
X	}
X	return	lea(tc, 4, pos+2);
X}
X
Xint	limed(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	unsigned  tc  =  te->t_contents;
X	int	lng;
X	
X	/*
X	 *	Specifically exclude byte address register operands,
X	 *	and ones which have lengths of 3.
X	 */
X
X	if  ((tc & 0xf8) == 0x08)
X		return  0;
X	
X	if  ((tc & 0xc0) >= 0x80)  {
X		if  (tc & 0x40)
X			return  0;
X		lng = lea(tc, 4, pos+6);
X		if  (lng > 0)
X			lng += 2;
X	}
X	else  {
X		lng = lea(tc, (unsigned)((tc & 0xc0)?2:1), pos+4);
X		if  (lng > 0)
X			lng++;
X	}
X	return	lng;
X}
X
Xint	lsbit(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	int	lng = lea(te->t_contents, 1, pos+4);
X	
X	if  (lng > 0)
X		lng++;
X	return	lng;
X}
X
Xint	lmvml(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	int	lng = lea(te->t_contents,
X			(unsigned)(te->t_contents&0x40? 4:2), pos+4);
X	
X	if  (lng > 0)
X		lng++;
X	return	lng;
X}
X
X/*
X *	Length depends on bits 6 and 7 of instruction.
X */
X
Xint	lone(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	unsigned  tc  =  te->t_contents;
X	
X	return	lea(tc, 1 << ((tc >> 6) & 3), pos+2);
X}
X
X/*
X *	Length depends on bits 6-8 of instruction.
X */
X
Xint	loone(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	unsigned  tc  =  te->t_contents;
X	
X	switch  ((tc >> 6) & 7)  {
X	case  0:
X	case  4:
X		return	lea(tc, 1, pos+2);
X	case  1:
X	case  3:
X	case  5:
X		return  lea(tc, 2, pos+2);
X	case  2:
X	case  6:
X	case  7:
X		return	lea(tc, 4, pos+2);
X	}
X	/*NOTREACHED*/
X}
X
Xint	lonew(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	if (te->t_contents == 0x4afc) { /* swbeg ... */
X		swbegflg++;
X		return (2 + gettw(&mainfile,pos+2,2));
X	}
X	return	lea(te->t_contents, 2, pos+2);
X}
X
Xint	lonel(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	return	lea(te->t_contents, 4, pos+2);
X}
X
X/*
X *	Print routines.
X */
X
X/*
X * print out small integers in decamil notation, all others in hex.
X */
X
Xvoid prind(n)
Xunsigned short n;
X{
X	if ((short) n > -128 && (short) n < 128)
X		(void) printf("%d", (long) ((short) n));
X	else
X		(void) printf("0x%x",(unsigned long) n);
X}
X   
Xint	findleng(tc)
Xunsigned  tc;
X{
X	switch  ((tc >> 6) & 3)  {
X	case  0:
X		return	'b';
X	case  1:
X		return	'w';
X	default:
X		return	'l';
X}
X}
X
X/* print @(0x4,d0.l) */
Xvoid	piword(reg,disp)
Xchar * reg;
Xunsigned  disp;
X{
Xint	szc;
X
X	(void) printf("%d(%s,", disp & 0xff, reg);
X	if  (disp & 0x8000) {
X		(void) fputs(areg[(disp >> 12) & 0x7]);
X		(void) putchar('.');
X	}
X	else
X		(void) printf("%%d%d.", (disp >> 12) & 0x7);
X	(void) putchar((disp & (1 << 10)) ? 'l' :'w');
X	(void) putchar(')');
X}
X
Xextern struct	commit	abstab;
X
Xvoid	paddr(pos)
Xlong	pos;
X{
X	t_entry	tent;
X	symbol	symb;
X
X	gette(&mainfile, pos, &tent);
X	if  (tent.t_relsymb != NULL)  {
X		symb = tent.t_relsymb;
X		if  (symb->s_lsymb != 0)
X			(void) printf("L%%%u", symb->s_lsymb);
X		else
X			(void) fputs(symb->s_name, stdout);
X		if  (tent.t_reldisp != 0)
X		    (void) printf("+0x%x", tent.t_reldisp);
X		return;
X	}
X	if ((pos = gettw(&mainfile, pos, R_LONG)) >= 0x290000)
X	 {
X	    register int i;
X	    for (i=0; i < abstab.c_int; i++)
X	        if (abstab.c_symb[i]->s_value == pos)
X		 {	     
X		    (void) fputs(abstab.c_symb[i]->s_name, stdout);
X		    return;
X		 }
X	 }
X	(void) printf("0x%x", pos);
X}
X
Xint	prea(ea, pos, sz)
Xunsigned  ea, sz;
Xlong	pos;			/*  Address of previous word to extn  */
X{
X	unsigned  reg  =  ea & 0x7;
X	long	disp;
X	t_entry	tent;
X	
X	pos += 2;
X	
X	switch  ((ea >> 3) & 0x7)  {
X	case  0:
X		(void) printf("%%d%d", reg);
X		return	0;
X	case  1:
X		(void) fputs(areg[reg], stdout);
X		return	0;
X	case  2:
X		(void) printf("(%s)", areg[reg]);
X		return	0;
X	case  3:
X		(void) printf("(%s)+", areg[reg]);
X		return	0;
X	case  4:
X		(void) printf("-(%s)", areg[reg]);
X		return	0;
X	case  5:
X		disp = gettw(&mainfile, pos, R_WORD);
X		(void) prind(disp);
X		(void) printf("(%s)", areg[reg]);
X		return	2;
X	case  6:
X		piword(areg[reg], (unsigned) gettw(&mainfile, pos, R_WORD));
X		return	2;
X	default:
X		switch  (reg)  {
X		case  0:
X			disp = gettw(&mainfile, pos, R_WORD);
X			(void) prind(disp);
X			(void) putchar('.');
X			(void) putchar('w');
X			return	2;
X		case  1:
X			paddr(pos);
X			return	4;
X		case  2:{
X			symbol symb;
X			register int addr;
X			disp = 
X			    ((short) gettw(&mainfile, pos, R_WORD));
X  			if ((addr=pos+disp) < 0  ||  
X			    addr-mainfile.ef_tbase > mainfile.ef_tsize ||
X			    (addr & 1) != 0)  
X				goto skiplabs;
X			gette(&mainfile, addr, &tent);
X			if  (tent.t_relsymb != NULL)  {
X				symb = tent.t_relsymb;
X			}
X			else if (tent.t_lab != NULL) {
X				symb = tent.t_lab;
X			}
X			else {
X		skiplabs:
X				(void) prind(disp);
X				(void) fputs("(%pc)", stdout);
X				return	2;
X			}
X			if  (symb->s_lsymb != 0)
X				(void) printf("L%%%u", symb->s_lsymb);
X			else
X				(void) fputs(symb->s_name, stdout);
X			if  (tent.t_reldisp != 0)
X				(void) printf("+0x%x", tent.t_reldisp);
X			return 2;
X			}
X		case  3:
X			piword("%pc", (unsigned)gettw(&mainfile, pos, R_WORD));
X			return	2;
X		case  4:
X			(void) putchar('&');
X			if  (sz < 4)
X				(void) prind(gettw(&mainfile, pos, R_WORD));
X			else
X				paddr(pos);
X			return	sz;
X		default:
X			(void) fprintf(stderr, "Funny mode\n");
X			exit(220);
X		}
X	}
X	/*NOTREACHED*/
X}
X	
Xint	pmove(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	unsigned  sz  =  2;
X	unsigned  tc  =  te->t_contents;
X	
X	(void) printf("mov%s\t", optab[te->t_iindex].prarg);
X	
X	if  ((tc & 0xf000) == 0x2000)
X		sz = 4;
X	
X	pos += prea(tc, pos, sz);
X	(void) putchar(',');
X	(void) prea(((tc >> 9) & 0x7) | ((tc >> 3) & 0x38), pos, sz);
X}
X
Xint	pcbch(te)
Xt_entry	*te;
X{
X	int	cc = ((te->t_contents >> 8) & 0xf) - 2;
X	char	*msg;
X	register  symbol  ts;
X	
X	if  (cc < 0)
X		msg = cc < -1? "ra": "sr";
X	else
X		msg = cclist[cc];
X	(void) printf("b%s", msg);
X/* this specifically requests that 8 bit addressing be used, 
X		but the unixpc assembler will do this automatically.	
X	if  (te->t_lng < 2) {
X		(void) putchar('.');
X		(void) putchar('b');
X	}
X*/
X	ts = te->t_relsymb;
X	if  (ts->s_lsymb != 0)
X		(void) printf("\tL%%%u", ts->s_lsymb);
X	else
X	{
X		(void) putchar('\t');
X		(void) fputs(ts->s_name, stdout);
X	}
X}
X
Xint	pdbcc(te)
Xt_entry	*te;
X{
X	unsigned  tc  =  te->t_contents;
X	int	cc = ((tc >> 8) & 0xf) - 2;
X	char	*msg;
X	register  symbol  ts;
X	
X	if  (cc < 0)
X		msg = cc < -1? "t": "f";
X	else
X		msg = cclist[cc];
X	ts = te->t_relsymb;
X	(void) printf("db%s\t%%d%d,", msg, tc & 0x7);
X	if  (ts->s_lsymb)
X		(void) printf("L%%%u", ts->s_lsymb);
X	else
X		(void) fputs(ts->s_name, stdout);
X}
X
Xint	pscc(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	unsigned  tc  =  te->t_contents;
X	int	cc = ((tc >> 8) & 0xf) - 2;
X	char	*msg;
X	
X	if  (cc < 0)
X		msg = cc < -1? "t": "f";
X	else
X		msg = cclist[cc];
X	(void) printf("s%s\t", msg);
X	(void) prea(tc, pos, 1);
X}
X
Xint	pcs(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	long	disp  =  gettw(&mainfile, pos+2, R_WORD);
X	
X	(void) fputs(optab[te->t_iindex].prarg, stdout);
X	if  ((te->t_contents & 0xc0) == 0){
X	 	(void) fputs(".b\t&", stdout);
X		(void) prind(disp);
X		(void) fputs(",%cc", stdout);
X	}
X	else {
X		(void) fputs(".w\t&", stdout);
X		(void) prind(disp);
X		(void) fputs(",%sr", stdout);
X	}
X}
X
Xint	pmovc(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	int	disp = gettw(&mainfile, pos+2, R_WORD);
X	int	ctrl = ((disp >> 10) & 2) | (disp & 1);
X
X	(void) fputs("movc\t", stdout);
X	if  ((te->t_contents & 1) == 0)
X		(void) fputs(creg[ctrl], stdout);
X	if  (disp & 0x8000)
X	{
X		(void) fputs(areg[(disp >> 12) & 7], stdout);
X		(void) putchar(',');
X	}
X	else
X		(void) printf("%%d%d,", disp >> 12);
X	if  (te->t_contents & 1)
X		(void) fputs(creg[ctrl], stdout);
X}
X
Xint	pimed(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	int	sz = findleng(te->t_contents);
X
X	/* we need to swith the operands to compare instrucions. */
X	if (strcmp (optab[te->t_iindex].prarg, "cmp")) {
X		(void) printf("%s.%c\t&", optab[te->t_iindex].prarg, sz);
X		if  (sz == 'l')  {
X			paddr(pos+2);
X			(void) putchar(',');
X			(void) prea(te->t_contents, pos+4, 4);
X		}
X		else  {
X			(void) prind(gettw(&mainfile, pos+2, R_WORD));
X			(void) putchar(',');
X			(void) prea(te->t_contents, pos+2, 2);
X		}
X	}
X	else {
X		(void) printf("%s.%c\t", optab[te->t_iindex].prarg, sz);
X		if  (sz == 'l')  {
X			(void) prea(te->t_contents, pos+4, 4);
X			(void) putchar(',');
X			(void) putchar('&');
X			paddr(pos+2);
X		}
X		else  {
X			(void) prea(te->t_contents, pos+2, 2);
X			(void) putchar(',');
X			(void) putchar('&');
X			(void) prind(gettw(&mainfile, pos+2, R_WORD));
X		}
X	}
X}
X
Xint	pmovp(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	unsigned  tc  =  te->t_contents;
X	long	disp  =  gettw(&mainfile, pos+2, R_WORD);
X	int	dreg = tc >> 9;
X	char	*ar = areg[tc & 0x7];
X	
X	(void) fputs("movp.", stdout);
X	if  (tc & (1 << 6))
X		(void) putchar('l');
X	else
X		(void) putchar('w');
X
X	if  (tc & (1 << 7)) {
X		(void) printf("\t%%d%d,", dreg);
X		(void) prind(disp);
X		(void) printf("(%s)", ar);
X	}
X	else {
X		(void) putchar('\t');
X		(void) prind(disp);
X		(void) printf("(%s),%%d%d", ar, dreg);
X	}
X}
X
Xint	psbit(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	unsigned  tc  =  te->t_contents;
X	
X	(void) printf("b%s\t&%d,", bittyp[(tc >> 6) & 0x3], gettw(&mainfile, pos+2, R_WORD));
X	(void) prea(tc, pos+2, 1);
X}
X
X/*ARGSUSED*/
Xint	pstop(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	(void) printf("stop\t&0x%x", gettw(&mainfile, pos+2, R_WORD));
X}
X
Xint	pdbit(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	unsigned  tc  =  te->t_contents;
X	
X	(void) printf("b%s\t%%d%d,", bittyp[(tc >> 6) & 0x3], (tc >> 9) & 0x7);
X	(void) prea(tc, pos, 1);
X}
X
Xint	pcs2(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	unsigned  tc  =  te->t_contents;
X	
X	(void) fputs("movw\t", stdout);
X	if  ((tc & 0xffc0) == 0x40c0)  {
X		(void) fputs("%sr,", stdout);
X		(void) prea(tc, pos, 2);
X	}
X	else  {
X		(void) prea(tc, pos, 2);
X		(void) putchar(',');
X		(void) fputs(optab[te->t_iindex].prarg, stdout);
X	}
X}
X
Xint	pone(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	unsigned  tc  =  te->t_contents;
X	int	sz = findleng(tc);
X	
X	(void) printf("%s.%c\t", optab[te->t_iindex].prarg, sz);
X	(void) prea(tc, pos, (unsigned)(sz == 'l'? 4: 2));
X}
X
Xint	ppea(te, pos)	/*  nbcd, pea, tas, jmp, jsr  */
Xt_entry	*te;
Xlong	pos;
X{
X	if (! strncmp(optab[te->t_iindex].prarg, "tas") && 
X	    (te->t_contents & 0x3f) == 0x3c) {
X		symbol symb;
X		t_entry tstr;
X		int counter = te->t_lng -2;
X		int offset = (pos += 4);
X		int dest;
X		char * sw_label;
X
X		(void) printf("swbeg\t&%d\n", counter);
X
X		symb = textlab(pos, pos);
X		printf("%s:\n", sw_label = symb->s_name);
X
X		while (counter--) {
X			gette(&mainfile, pos, &tstr);
X			dest = tstr.t_contents + offset;
X 			if (tstr.t_contents > 0 &&
X			    dest < 0x290000 && 
X			    ! (dest < mainfile.ef_tbase
X 			     || dest >= mainfile.ef_tbase+mainfile.ef_tsize
X 			     || (dest & 1) != 0 )) {
X				if (symb = textlab(dest,offset))
X					printf("\tshort\t%s-%s\n", 
X						symb->s_name,sw_label);
X				else
X					printf("\tshort\t0x%x\t# Can't label destination.\n", 
X							tstr.t_contents);
X			}
X			else 
X				printf("\tshort\t0x%x\t# Illegal address\n", 
X						tstr.t_contents);
X			pos += 2;
X		}
X	}
X	else {
X		(void) fputs(optab[te->t_iindex].prarg, stdout);
X		(void) putchar('\t');
X		(void) prea(te->t_contents, pos, (unsigned)(te->t_lng>2?4:2));
X	}
X}
X
X
Xint	plea(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	(void) fputs("lea\t", stdout);
X	(void) prea(te->t_contents, pos, 4);
X	(void) putchar(',');
X	(void) fputs(areg[(te->t_contents >> 9) & 0x7], stdout);
X}
X
Xint	pdreg(te)
Xt_entry	*te;
X{
X	(void) printf("%s\t%%d%d", optab[te->t_iindex].prarg, te->t_contents & 7);
X}
X
X
Xint	pmvml(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	unsigned  tc  =  te->t_contents;
X	register  unsigned  dw  =  gettw(&mainfile, pos+2, R_WORD);
X	unsigned  sz = 4;
X	int	sc = 'l';
X	register  int	i;
X	register  unsigned  bit;
X	
X	(void) fputs("movm.", stdout);
X	if  ((tc & 0x40) == 0)  {
X		sc = 'w';
X		sz = 2;
X	}
X
X	(void) putchar(sc);	
X	(void) putchar('\t');
X
X	if  (tc & 0x400)  {
X		(void) prea(tc, pos+2, sz);
X		(void) printf(",&0x%x", dw);
X	}
X	else  {
X		(void) printf("&0x%x,", dw);
X		(void) prea(tc, pos+2, sz);
X	}
X	
X	(void) printf("\t#\t");
X	
X	if  ((tc & 0x38) == 0x20)  {
X		bit = 0x8000;
X		for  (i = 0;  i < 8;  i++)  {
X			if  (dw & bit)
X				(void) printf(" %%d%d", i);
X			bit >>= 1;
X		}
X		for  (i = 0;  i < 8;  i++)  {
X			if  (dw & bit) {
X			        (void) putchar(' ');
X				(void) fputs(areg[i], stdout);
X			}
X			bit >>= 1;
X		}
X	}
X	else  {
X		bit = 1;
X		for  (i = 0;  i < 8;  i++)  {
X			if  (dw & bit)
X				(void) printf(" %%d%d", i);
X			bit <<= 1;
X		}
X		for  (i = 0;  i < 8;  i++)  {
X			if  (dw & bit) {
X				(void) putchar(' ');
X				(void) fputs(areg[i], stdout);
X			}
X			bit <<= 1;
X		}
X	}
X}
X
Xint	ptrap(te)
Xt_entry	*te;
X{
X	(void) printf("trap\t&%d", te->t_contents & 0xf);
X}
X
Xint	plink(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	(void) printf("link\t%s,&%d", areg[te->t_contents & 0x7],
X				gettw(&mainfile, pos+2, R_WORD));
X}
X
X
Xint	pareg(te)
Xt_entry	*te;
X{
X	(void) printf(optab[te->t_iindex].prarg, areg[te->t_contents & 0x7]);
X}
X
Xint	podreg(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	unsigned  tc  =  te->t_contents;
X	
X	(void) printf("%s\t", optab[te->t_iindex].prarg);
X	(void) prea(tc, pos, 2);
X	(void) printf(",%%d%d", (tc >> 9) & 0x7);
X}
X
Xint	pqu(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	unsigned  tc  =  te->t_contents;
X	int	sz  =  findleng(tc);
X	int	amt = (tc >> 9) & 0x7;
X	
X	if  (amt == 0)
X		amt = 8;
X	(void) printf("%s.%c\t&%d,", optab[te->t_iindex].prarg, sz, amt);
X	(void) prea(tc, pos, (unsigned)(sz == 'l'? 4: 2));
X}
X
Xint	pmqu(te)
Xt_entry	*te;
X{
X	unsigned  tc  =  te->t_contents;
X
X	(void) printf("mov.l\t&%d,%%d%d", (char)tc, (tc >> 9) & 0x7);
X}
X
Xint	ptreg(te)
Xt_entry	*te;
X{
X	register  unsigned  tc  =  te->t_contents;
X	int	rx = (tc >> 9) & 0x7;
X	int	ry = tc & 0x7;
X
X	(void) fputs(optab[te->t_iindex].prarg, stdout);
X	(void) putchar('\t');
X	if  (tc & 0x8)
X		(void) printf("-(%s),-(%s)", areg[ry], areg[rx]);
X	else
X		(void) printf("%%d%d,%%d%d", ry, rx);
X}
X
Xint	pcmpm(te)
Xt_entry	*te;
X{
X	register  unsigned  tc  =  te->t_contents;
X
X	(void) printf("%s\t(%s)+,(%s)+", optab[te->t_iindex].prarg,
X		areg[tc & 7], areg[(tc >> 9) & 7]);
X}
X
Xint	pomode(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	unsigned  tc  =  te->t_contents;
X	char	buf[5];
X	int	sz;
X	int	reg = (tc >> 9) & 7;
X
X	buf[0] = '\0';
X	
X	switch  ((tc >> 6) & 7)  {
X	case  0:
X		sz = 'b';
X		goto  toreg;
X	case  1:
X		sz = 'w';
X		goto  toreg;
X	case  2:
X		sz = 'l';
X	toreg:
X 		(void) sprintf(buf, "%%d%d", reg);
X		goto printaft;
X	case  3:
X		sz = 'w';
X		goto  toareg;
X	case  7:
X		sz = 'l';
X	toareg:
X		(void) sprintf(buf, "%s", areg[reg]);
X	printaft:
X		if (strcmp("cmp", optab[te->t_iindex].prarg)) {
X			(void) printf("%s.%c\t", optab[te->t_iindex].prarg,sz);
X			(void) prea(tc, pos, (unsigned)(sz == 'l'? 4: 2));
X			(void) putchar(',');
X			(void) fputs(buf, stdout);
X		}
X		else {
X			(void) printf("%s.%c\t%s,", optab[te->t_iindex].prarg,
X						    sz, buf);
X			(void) prea(tc, pos, (unsigned)(sz == 'l'? 4: 2));
X		}
X		break;
X	case  4:
X		sz = 'b';
X		goto  frreg;
X	case  5:
X		sz = 'w';
X		goto  frreg;
X	case  6:
X		sz = 'l';
X	frreg:
X		(void) sprintf(buf, "%%d%d", reg);
X		if (strcmp("cmp", optab[te->t_iindex].prarg)) {
X			(void) printf("%s.%c\t%s,", optab[te->t_iindex].prarg, 
X					sz, buf);
X			(void) prea(tc, pos, (unsigned)(sz == 'l'? 4: 2));
X		}
X		else {
X			(void) printf("%s.%c\t", optab[te->t_iindex].prarg,sz);
X			(void) prea(tc, pos, (unsigned)(sz == 'l'? 4: 2));
X			(void) putchar(',');
X			(void) fputs(buf, stdout);
X		}
X	}
X}
X
Xint	pexg(te)
Xt_entry	*te;
X{
X	unsigned  tc  =  te->t_contents;
X	int	r1 = (tc >> 9) & 7, r2 = tc & 7;
X
X	(void) printf("exg\t");
X	
X	if  ((tc & 0x00f8) == 0x0048)
X	{
X		(void) fputs(areg[r1], stdout);
X		(void) putchar(',');
X	}
X	else
X		(void) printf("%%d%d,", r1);
X	if  (tc & 0x8)
X		(void) fputs(areg[r2], stdout);
X	else
X		(void) printf("%%d%d", r2);
X}
X	
Xint	pmshf(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	unsigned  tc  =  te->t_contents;
X	
X	(void) printf("%s%c.w\t", shtype[(tc >> 9) & 3], tc & 0x100? 'l': 'r');
X	(void) prea(tc, pos, 2);
X}
X
Xint	pshf(te)
Xt_entry	*te;
X{
X	unsigned  tc  =  te->t_contents;
X	int	sz  =  findleng(tc);
X	int	disp = (tc >> 9) & 7;
X
X	(void) printf("%s%c.%c\t", shtype[(tc >> 3) & 3], tc & 0x100? 'l': 'r', sz);
X	if  (tc & 0x20)
X		(void) printf("%%d%d", disp);
X	else
X		(void) printf("&%d", disp == 0? 8: disp);
X	(void) printf(",%%d%d", tc & 7);
X}
X
X/*
X *	Find length etc of instruction.
X */
X
Xint	findinst(te, pos)
Xregister  t_entry  *te;
Xlong	pos;
X{
X	register  struct  opstr	*op;
X	unsigned  tc  =  te->t_contents;
X	int	lng = 0;
X	register  int	i;
X
X	te->t_type = T_BEGIN;
X	te->t_bchtyp = T_NOBR;
X	
X	for  (op = &optab[0];  op->mask;  op++)  {
X		if  ((tc & op->mask) == op->match)  {
X			te->t_iindex = op - optab;
X			lng = (op->opsize)(te, pos);
X			break;
X		}
X	}
X
X	for  (i = 1;  i < lng;  i++)  {
X		t_entry	ctent;
X		long	npos = pos+i+i;
X		
X		if  (npos >= endt)
X			goto  clearem;
X		gette(&mainfile, npos, &ctent);
X		if (swbegflg) {
X			ctent.t_type = T_UNKNOWN;
X			putte(&mainfile, npos, &ctent);
X		}
X		else {
X			if  (ctent.t_bdest || ctent.t_dref)  {
Xclearem:			for  (i--; i > 0; i--)  {
X					npos = pos + i + i;
X					gette(&mainfile, npos, &ctent);
X					ctent.t_type = T_UNKNOWN;
X					putte(&mainfile, npos, &ctent);
X				}
X				lng = 0;
X				goto  ginv;
X			}
X			ctent.t_type = T_CONT;
X			putte(&mainfile, npos, &ctent);
X		}
X	}
X	swbegflg = 0;
X
X	if  (lng <= 0)  {
Xginv:		te->t_vins = 0;
X		te->t_lng = 1;
X		te->t_type = T_UNKNOWN;
X		te->t_bchtyp = T_NOBR;
X	}
X	else
X		te->t_lng = lng;
X	return	lng;
X}
X
X/*
X *	Print instruction.
X */
X
Xvoid	prinst(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	putchar('\t');
X	(optab[te->t_iindex].opprin)(te, pos);
X	putchar('\n');
X}
SHAR_EOF
chmod 0644 iset.c || echo "restore of iset.c fails"
sed 's/^X//' << 'SHAR_EOF' > libmtch.c &&
X/*
X *	SCCS:	@(#)libmtch.c	1.2	11/2/84	14:18:55
X *	Read library files.
X *
X ***********************************************************************
X *	This software is copyright of
X *
X *		John M Collins
X *		47 Cedarwood Drive
X *		St Albans
X *		Herts, AL4 0DN
X *		England			+44 727 57267
X *
X *	and is released into the public domain on the following conditions:
X *
X *		1.  No free maintenance will be guaranteed.
X *		2.  Nothing may be based on this software without
X *		    acknowledgement, including incorporation of this
X *		    notice.
X *
X *	Notwithstanding the above, the author welcomes correspondence and bug
X *	fixes.
X ***********************************************************************
X */
X
X#include <stdio.h>
X#include <fcntl.h>
X#include <string.h>
X#include <a.out.h>
X#include <ar.h>
X#include <setjmp.h>
X#include <ldfcn.h>
X#include "unc.h"
X
Xlong	atol();
Xlong	lseek();
Xvoid	bfopen(), bfclose(), nomem();
Xvoid	rrell2(), markmatch();
Xchar	*malloc();
Xint	matchup();
Xlong	findstart();
X
Xchar	verbose;		/*  Tell the world what we are doing  */
Xchar	*tfnam;
Xchar	*cfile;
Xef_fids	mainfile;
Xstruct	commit	dreltab;
Xint	donedrel, donebrel;
Xlong	trelpos, drelpos, brelpos;
Xstatic	struct	libit	currlib = {NULL, NULL, ""};
X
Xvoid	lclash(str)
Xchar	*str;
X{
X	(void) fprintf(stderr, "Library scan failure - %s\n", str);
X	(void) fprintf(stderr, "Searching %s\n", cfile);
X	if  (currlib.lf_name[0])
X		(void) fprintf(stderr, "Member is %s\n", currlib.lf_name);
X	exit(255);
X}
X
X/*
X *	Find next member.
X */
X
Xlong	nextmemb(filename,lfd)
Xchar *filename;
Xregister  struct  libit	 *lfd;
X{
X	struct	ar_hdr	arbuf;
X	
X	ldaclose(lfd->ldptr2);
X	if (ldclose(lfd->ldptr != FAILURE))	/* end of archive */
X	    return -1;
X	lfd->ldptr = ldopen(filename,lfd->ldptr);
X	ldahread(lfd->ldptr, (char *)&arbuf);
X	(void) strncpy(lfd->lf_name, arbuf.ar_name, sizeof(lfd->lf_name));
X	return 1;
X}
X
X/*
X *	Decode a file name thus -
X *
X *	-lxxx decode as /lib/libxxx.a /usr/lib/libxxx.a etc
X *	-Lxxx forget "lib" ".a" bit thus -Lcrt0.o
X *	or read LDPATH environment var to give list of directories as sh
X *	(default /lib:/usr/lib).
X *
X *	Alternatively treat as normal pathname.
X *
X *	File names may be followed by (membername) if the file is an archive,
X *	thus
X *
X *		-lc(printf.o)
X *
X *	in which case the specified module is fetched.
X */
X
Xstruct	libit	*getfnam(str)
Xchar	*str;	/* will be expanded to full path name if necessary */
X{
X	char	*bp, *ep = NULL, *pathb, *pathe, *fullpath = NULL;
X	static	char	*pathn;
X	extern	char	*getenv();
X 	char	magic[8];
X	struct	ar_hdr	arhdr;
X	LDFILE *ldptr;
X
X 	if  ((bp = strrchr(str, '(')) != NULL &&
X 		 (ep = strrchr(str, ')')) != NULL)
X		*ep = *bp = '\0';
X
X	if  (str[0] == '-'  &&  (str[1] == 'l' || str[1] == 'L'))  {
X		if  (pathn == NULL)  {
X			if  ((pathn = getenv("LDPATH")) == NULL)
X				pathn = "/lib:/usr/lib";
X		}
X		fullpath = malloc((unsigned)(strlen(pathn) + strlen(str) + 1));
X		if  (fullpath == NULL)
X			nomem();
X		pathb = pathn;
X		do  {
X 			pathe = strchr(pathb, ':');
X			if  (*pathb == ':')
X				fullpath[0] = '\0';
X			else  {
X				if  (pathe != NULL)
X					*pathe = '\0';
X				(void) strcpy(fullpath, pathb);
X				(void) strcat(fullpath, "/");
X				if  (pathe != NULL)
X					*pathe = ':';
X			}
X			if  (str[1] == 'l')
X				(void) strcat(fullpath, "lib");
X			(void) strcat(fullpath, &str[2]);
X			if  (str[1] == 'l')
X				(void) strcat(fullpath, ".a");
X			if  ((ldptr = ldopen(fullpath, NULL)) != NULL)
X				goto  found;
X			pathb = pathe + 1;
X		}   while  (pathe != NULL);
X		
X		(void) fprintf(stderr, "Unable to locate lib%s.a in %s\n",
X			&str[2], pathn);
X		exit(101);
X	}
X	else  if  ((ldptr = ldopen(str, NULL)) == NULL)  {
X		(void) fprintf(stderr, "Cannot open %s\n", str);
X		exit(102);
X	}
X	
Xfound:
X
X	str = fullpath? fullpath: str;
X 	if  (FREAD(magic, sizeof(magic),1,ldptr) != 1  ||
X 		strcmp(magic, ARMAG) != 0)  {
X		if  (ep != NULL)  {
X			(void) fprintf(stderr, "%s is not library file\n", str);
X			exit(103);
X		}
X		currlib.ldptr = ldptr;
X		currlib.ldptr2 = ldaopen(str,ldptr);
X		currlib.lf_name[0] = '\0';
X		return  &currlib;
X	}
X	
X	/*
X	 *	It appears to be a library file - see if we want a specific
X	 *	one.
X	 */
X	
X	if  (ep != NULL)  {
X 		char *cp;
X 
X		for  (;;)  {
X			if  (ldahread(ldptr,&arhdr) == FAILURE)  {
X				(void) fprintf(stderr, "Cannot find member %s in %s\n",
X					bp+1, str);
X				exit(103);
X			}
X 			for ( cp = arhdr.ar_name + sizeof(arhdr.ar_name) - 1;
X 				*cp == ' ';
X 				cp -- ) ;
X 			if  (strncmp(bp+1, arhdr.ar_name, cp - arhdr.ar_name + 1) == 0)
X				break;
X
X			if (ldclose(ldptr) != FAILURE) {
X				(void) fprintf(stderr, "Cannot find member %s in %s\n",
X					bp+1, str);
X				exit(103);
X			}
X			ldptr = ldopen(str,ldptr);
X		}
X		currlib.ldptr = ldptr;
X		currlib.ldptr2 = ldaopen(str,ldptr);
X		currlib.lf_name[0] = '\0';
X		*bp = '(';
X		*ep = ')';
X		return	&currlib;
X	}
X	
X	/*
X	 *	Otherwise point to 1st member in library.
X	 */
X	
X	if  (ldahread(ldptr, &arhdr) == FAILURE)  {
X		(void) fprintf(stderr, "Library %s empty\n", str);
X		exit(104);
X	}
X	currlib.ldptr = ldptr;
X	currlib.ldptr2 = ldaopen(str,ldptr);
X	(void) strncpy(currlib.lf_name, arhdr.ar_name, sizeof(currlib.lf_name));
X	return	&currlib;
X}
X
X/*
X *	Process library files.
X */
X
X#define	MINTEXT	6
X
Xvoid	lscan(nfiles, fnames)
Xint	nfiles;
Xchar	**fnames;
X{
X	ef_fids	libfile;
X	register  ef_fid  ll = &libfile;
X	register  struct  libit	 *clf;
X	extern	symbol	dolsymb();
X	int	firstfile;
X	
X	for  (;  nfiles > 0;  fnames++, nfiles--)  {
X		clf = getfnam(*fnames);
X		cfile = *fnames;
X		firstfile = 1;
X		do  {
X			bfopen(tfnam, ll);
X
X			/*
X			 *	If file is garbled, silently forget it and go
X			 *	on to the next one.
X			 */
X
X			if  (!rtext(clf->ldptr, ll))
X				goto  closeit;
X				
X			if  (ll->ef_tsize < MINTEXT)
X				goto  closeit;
X				
X			if  (!rdata(clf->ldptr, ll))
X				goto  closeit;
X				
X			if  (rrell1(clf->ldptr, ll) < 0)
X				goto  closeit;
X				
X			/*
X			 *	If first file in library, find it from
X			 *	beginning of main file.
X			 */
X			
X			if  (firstfile)  {
X				if  ((trelpos = findstart(&mainfile, ll)) < 0)
X					goto  closeit;
X				firstfile = 0;
X			}
X			else   if  (!matchup(&mainfile, ll, trelpos))
X					goto  closeit;
X			
X			/*
X			 *	Found a match.
X			 */
X			
X			if  (!rsymb(clf->ldptr, dolsymb, ll))  {
X				(void) fprintf(stderr, "Corrupt file %s\n",
X							*fnames);
X				exit(150);
X			}
X			
X			donedrel = 0;
X			donebrel = 0;
X			rrell2(clf->ldptr, clf->ldptr2, ll);
X			if  (verbose)  {
X				(void) fprintf(stderr, "Found: ");
X				if  (clf->lf_name[0])
X					(void) fprintf(stderr, "%.14s in ",
X							clf->lf_name);
X				(void) fprintf(stderr, "%s\n", *fnames);
X			}
X			if  (libfile.ef_stvec != NULL)  {
X				free(libfile.ef_stvec);
X				libfile.ef_stvec = NULL;
X				libfile.ef_stcnt = 0;
X			}
X			dreltab.c_int = 0;
X				
X			/*
X			 *	Start looking next time round
X			 *	where last one left off.
X			 */
X			
X			markmatch(&mainfile, ll, trelpos);
X			trelpos += libfile.ef_tsize;
Xcloseit:
X			bfclose(ll);
X		}  while  (nextmemb(cfile,clf) >= 0);
X	}
X}
SHAR_EOF
chmod 0644 libmtch.c || echo "restore of libmtch.c fails"
sed 's/^X//' << 'SHAR_EOF' > robj.c &&
X/*
X *	SCCS:	@(#)robj.c	1.2	11/2/84	14:19:59
X *	Read object files.
X *
X ***********************************************************************
X *	This software is copyright of
X *
X *		John M Collins
X *		47 Cedarwood Drive
X *		St Albans
X *		Herts, AL4 0DN
X *		England			+44 727 57267
X *
X *	and is released into the public domain on the following conditions:
X *
X *		1.  No free maintenance will be guaranteed.
X *		2.  Nothing may be based on this software without
X *		    acknowledgement, including incorporation of this
X *		    notice.
X *
X *	Notwithstanding the above, the author welcomes correspondence and bug
X *	fixes.
X ***********************************************************************
X *
X *	This particular module will obviously have to be munged beyond
X *	recognition for another object format.
X */
X
X#include <stdio.h>
X#include <a.out.h>
X#include <ldfcn.h>
X#include <string.h>
X#include "unc.h"
X
Xvoid	gette(), getde(), setde(), putte(), putde();
Xlong	gettw(), getdw();
Xvoid	reallst(), lclash(), nomem(), unimpl();
Xvoid	addit();
Xchar	*malloc();
Xlong	lseek();
X
Xint	par_entry, par_round, nmods, donedrel, donebrel;
Xstruct	commit	abstab, comtab, dreltab;
Xlong	trelpos, drelpos, brelpos;
X
Xint *symord;	/* convert symbol index to symbol ordinal */
X
Xef_fids	mainfile;
X
Xsymbol	lookup(), inventsymb(), getnsymb();
X
X#define RWORD 1
X#define RLONG 2
X#define	DBSIZE	100
X#define	STINIT	20
X
X/*
X *	Read text segment.  Return 0 if not ok.
X */
X
Xint	rtext(ldptr, outf)
X  LDFILE *ldptr;		/*  a.out file (possibly in library)  */
X  ef_fid	outf;		/*  Output file descriptor  */
X{
X   t_entry		tstr;
X   struct	aouthdr	unixhdr;
X   struct  scnhdr  sect;
X   register  long	size;
X   register  int	i, l;
X   unsigned  short	inbuf[DBSIZE/2];
X   
X   /*
X    *	Initialise fields in structure.
X    */
X   
X   tstr.t_type = T_UNKNOWN;
X   tstr.t_vins = 1;		/*  For the moment  */
X   tstr.t_bdest = 0;
X   tstr.t_gbdest = 0;
X   tstr.t_lng = 1;
X   tstr.t_reloc = R_NONE;
X   tstr.t_rdisp = 0;
X   tstr.t_isrel = 0;
X   tstr.t_amap = 0;
X	tstr.t_dref = 0;
X	tstr.t_relsymb = NULL;
X	tstr.t_reldisp = 0;
X	tstr.t_lab = NULL;
X	tstr.t_lsymb = 0;
X	tstr.t_refhi = 0;
X	tstr.t_reflo = 0x7fffffff;
X	tstr.t_match = 0;
X	
X	/*
X	 *	Read a.out header.
X	 */
X
X	if (ldohseek(ldptr) == FAILURE) {	/* no optional header */
X
X	    outf->ef_entry = 0;
X	    ldshread(ldptr,1,&sect);		/* text header */
X	    outf->ef_tbase = sect.s_vaddr;
X	    outf->ef_tsize = sect.s_size;
X
X	    ldshread(ldptr,2,&sect);		/* data header */
X	    outf->ef_dbase = sect.s_vaddr;
X	    outf->ef_dsize = sect.s_size;
X
X	    ldshread(ldptr,3,&sect);		/* bss header */
X	    outf->ef_bbase = sect.s_vaddr;
X	    outf->ef_bsize = sect.s_size;
X	    outf->ef_end = sect.s_vaddr + sect.s_size;
X	} else {
X	    FREAD((char *)&unixhdr,sizeof(struct aouthdr),1,ldptr);
X	
X	    if ( N_BADMAG(unixhdr) )
X		return	0;
X
X	    outf->ef_entry = unixhdr.entry;
X	    outf->ef_tbase = unixhdr.text_start;
X	    outf->ef_dbase = unixhdr.data_start;
X	    outf->ef_bbase = outf->ef_dbase + unixhdr.dsize;
X	    outf->ef_end = outf->ef_bbase + unixhdr.bsize;
X
X	    outf->ef_tsize = unixhdr.tsize;
X	    outf->ef_dsize = unixhdr.dsize;
X	    outf->ef_bsize = unixhdr.bsize;
X	}
X	
X	ldsseek(ldptr,1);	/* seek to text section */
X	
X	size = outf->ef_tsize;
X	
X	while  (size > 1)  {
X		l = size > DBSIZE? DBSIZE: size;
X		if  (FREAD((char *)inbuf,1,l,ldptr) != l)
X			return	0;
X		l /= 2;
X		for  (i = 0;  i < l;  i++)  {
X			tstr.t_contents = inbuf[i];
X			(void) write(outf->ef_t, (char *)&tstr, sizeof(tstr));
X		}
X		size -= l + l;
X	}
X	
X	/*
X	 *	Extra one to cope with "etext".
X	 */
X	
X	(void) write(outf->ef_t, (char *)&tstr, sizeof(tstr));
X	return	1;
X}
X/*
X *	Same sort of thing for the data segment.
X */
X
Xint	rdata(ldptr, outf)
XLDFILE *ldptr;		/*  a.out file (possibly in library)  */
Xef_fid	outf;		/*  Output file descriptor  */
X{
X	d_entry		dstr;
X	register  long	size;
X	register  int	i, l;
X	unsigned  char	inbuf[DBSIZE];
X
X	/*
X	 *	Initialise fields in structure.
X	 */
X	
X	dstr.d_type = D_BYTE;
X	dstr.d_reloc = R_NONE;
X	dstr.d_lng = 1;
X	dstr.d_relsymb = NULL;
X	dstr.d_reldisp = 0;
X	dstr.d_lab = NULL;
X	
X	ldsseek(ldptr,2);	/* seek to data section */
X	
X	size = outf->ef_dsize;
X	
X	while  (size > 0)  {
X		l = size > DBSIZE? DBSIZE: size;
X		if  (FREAD((char *)inbuf,1,l,ldptr) != l)
X			return	0;
X		for  (i = 0;  i < l;  i++)  {
X			dstr.d_contents = inbuf[i];
X			(void) write(outf->ef_d, (char *)&dstr, sizeof(dstr));
X		}
X		size -= l;
X	}
X	
X	/*
X	 *	Repeat for BSS segment.
X	 */
X
X	dstr.d_contents = 0;
X	for  (size = outf->ef_bsize;  size > 0;  size--)
X		(void) write(outf->ef_d, (char *)&dstr, sizeof(dstr));
X	
X	/*
X	 *	Extra one to cope with "end".
X	 */
X	
X	(void) write(outf->ef_d, (char *)&dstr, sizeof(dstr));
X	return	1;
X}
X
X/*
X *	Process symbol table segment.
X */
X
Xint	rsymb(ldptr, dproc, outf)
XLDFILE *ldptr;		/*  a.out file (possibly in library)  */
Xsymbol	(*dproc)();
Xregister  ef_fid  outf;	/*  Output file descriptor  */
X{
X#define SYMLENGTH 256
X	register  symbol  csym;
X 	struct	syment	isym;
X	register  int   nsyms,symindex;
X	unsigned long   stroff;
X 	char	inbuf[SYMLENGTH+1], *cp;
X	int ord;
X
X	nsyms = HEADER(ldptr).f_nsyms;
X	stroff = HEADER(ldptr).f_symptr + nsyms*sizeof(struct syment);
X
X	if  (nsyms <= 0)
X		nsyms = STINIT;
X
X	outf->ef_stvec = (symbol *) malloc(nsyms * sizeof(symbol));
X	symord = (int *) malloc(nsyms * sizeof(int));
X	if  (outf->ef_stvec == NULL)
X		nomem();
X
X	outf->ef_stcnt = 0;
X	outf->ef_stmax = nsyms;
X	ord = 0;
X	
X 	for  (symindex=0; symindex<nsyms; symindex++)  {
X		ldtbread(ldptr,symindex,&isym);
X		if (isym.n_zeroes == 0) {	/* get from string table */
X		    FSEEK(ldptr,stroff + isym.n_offset,0);
X		    cp = inbuf;
X		    do {
X 			if (FREAD(cp,1,1,ldptr) != 1)/* Read symbol chars 1-by-1 */
X 				return 0;
X 			if ( cp - inbuf >= SYMLENGTH )/* Check against buffer overflow */
X 				return 0;
X		    } while (*cp++ != '\0');/* Terminate on null byte */
X		} else {			/* get from symbol field */
X		    strncpy(inbuf,isym.n_name,8);
X		    inbuf[8] = '\0';
X		}
X 		csym = (*dproc)(lookup(inbuf), convtosun(&isym),
X				isym.n_value, outf);
X 		if (outf->ef_stcnt >= outf->ef_stmax)
X			reallst(outf);
X		outf->ef_stvec[outf->ef_stcnt++] = csym;
X		symord[symindex] = ord++;		/* record ordinal */
X		symindex += isym.n_numaux;		/* skip aux entries */
X	}
X	return	1;
X}
X
X/*
X *	Process relocation stuff.  -1 error, 0 no relocation, 1 relocation.
X */
X
Xint	rrel(ldptr, ldptr2, outf)
XLDFILE *ldptr,*ldptr2;	/*  a.out file (possibly in library)  */
Xef_fid	outf;		/*  Output file descriptor  */
X{
X 	struct	reloc	crel;
X	struct scnhdr tsect,dsect;
X	struct syment isym;
X	t_entry	tstr;
X	d_entry	dstr;
X	register  int	nreloc;
X	long	cont, pos;
X
X	ldshread(ldptr,1,&tsect);
X	ldshread(ldptr,2,&dsect);
X 	if  (tsect.s_nreloc <= 0  &&  dsect.s_nreloc <= 0)
X		return	0;
X
X	nreloc = tsect.s_nreloc;
X
X	ldrseek(ldptr,1);
X 	while  (nreloc-- > 0)  {
X		if  (FREAD((char *)&crel, sizeof(crel),1,ldptr) != 1)
X			return	-1;
X
X 		pos = crel.r_vaddr;
X		gette(outf, pos, &tstr);
X		if (crel.r_type == R_ABS)
X		    tstr.t_reloc = R_NONE;
X		else
X		    tstr.t_reloc = R_LONG;	/* what about PC-relative? */
X		ldtbread(ldptr2,crel.r_symndx,&isym);
X		if (isym.n_sclass == C_EXT) {
X 			tstr.t_relsymb = outf->ef_stvec[symord[crel.r_symndx]];
X 			tstr.t_reldisp = gettw(outf, pos, (int)tstr.t_reloc);
X		}
X		else  {
X 			cont = gettw(outf, pos, (int)tstr.t_reloc);
X 			tstr.t_relsymb = getnsymb(outf, convtosun(&isym), cont);
X		}
X		tstr.t_relsymb->s_used++;
X		putte(outf, pos, &tstr);
X	}
X	
X	/*
X	 *	And now repeat all that for data relocations.
X	 */
X	
X	nreloc = dsect.s_nreloc;
X	
X	ldrseek(ldptr,2);
X 	while  (nreloc-- > 0)  {
X		if (FREAD((char *)&crel, sizeof(crel),1,ldptr) != 1)
X			return	-1;
X
X 		pos = crel.r_vaddr;
X		getde(outf, pos, &dstr);
X		if (crel.r_type == R_ABS)
X		    dstr.d_reloc = R_NONE;
X		else
X		    dstr.d_reloc = R_LONG;	/* what about PC-relative? */
X
X		ldtbread(ldptr2,crel.r_symndx,&isym);
X		if (isym.n_sclass == C_EXT) {
X 			dstr.d_relsymb = outf->ef_stvec[symord[crel.r_symndx]];
X 			dstr.d_reldisp = getdw(outf, pos, (int)dstr.d_reloc);
X		}
X		else  {
X 			cont = getdw(outf, pos, (int)dstr.d_reloc);
X 			dstr.d_relsymb = getnsymb(outf, convtosun(&isym), cont);
X 			if  (dstr.d_relsymb->s_type == S_TEXT)  {
X				gette(outf, cont, &tstr);
X				tstr.t_dref = 1;
X				putte(outf, cont, &tstr);
X			}
X		}
X 		switch  (dstr.d_reloc)  {
X		default:
X			unimpl("Data byte relocation");
X			break;
X		case  R_WORD:
X			unimpl("data word reloc");
X			dstr.d_type = D_WORD;
X			dstr.d_lng = 2;
X			setde(outf, pos+1, D_CONT, 1);
X			break;
X		case  R_LONG:
X			dstr.d_type = D_ADDR;
X			dstr.d_lng = 4;
X			setde(outf, pos+1, D_CONT, 1);
X			setde(outf, pos+2, D_CONT, 1);
X			setde(outf, pos+3, D_CONT, 1);
X			break;
X		}
X		dstr.d_relsymb->s_used++;
X		putde(outf, pos, &dstr);
X	}
X	return 1;
X}
X
X/*
X *	Process a symbol.
X */
X
Xsymbol	dosymb(sy, type, val, fid)
Xregister  symbol  sy;
Xint	type;
Xlong	val;
Xef_fid	fid;
X{
X	t_entry	tstr;
X	d_entry	dstr;
X	
X	if  (!sy->s_newsym)  {
X 		if  (type & S_EXT)  {
X			(void) fprintf(stderr, "Duplicate symbol %s\n", sy->s_name);
X			/* exit(10);  temporary? */
X		}
X		if  (++sy->s_defs > nmods)
X			nmods = sy->s_defs;
X		sy = inventsymb("DUP");
X	}
X
X	sy->s_value = val;
X	
X	switch  (type)  {
X	default:
X		return	NULL;
X		
X 	case  S_EXT|S_UNDF:
X		if  (val != 0)  {
X 			sy->s_type = S_COMM;
X			addit(&comtab, sy);
X		}
X		else
X			sy->s_type = S_UNDF;
X		sy->s_glob = 1;
X		break;
X		
X 	case  S_EXT|S_ABS:
X		sy->s_type = S_ABS;
X		sy->s_glob = 1;
X		addit(&abstab, sy);
X		break;
X		
X 	case  S_ABS:
X		sy->s_type = S_ABS;
X		addit(&abstab, sy);
X		break;
X		
X 	case  S_EXT|S_TEXT:
X 	case  S_TEXT:
X		sy->s_type = S_TEXT;
X		gette(fid, val, &tstr);
X		tstr.t_bdest = 1;
X 		if  (type & S_EXT)  {
X			tstr.t_gbdest = 1;
X			sy->s_glob = 1;
X		}
X		sy->s_link = tstr.t_lab;
X		tstr.t_lab = sy;
X		putte(fid, val, &tstr);
X		break;
X		
X 	case  S_BSS:
X 	case  S_EXT|S_BSS:
X		sy->s_type = S_BSS;
X		goto	datrest;
X 	case  S_DATA:
X 	case  S_EXT|S_DATA:
X		sy->s_type = S_DATA;
X	datrest:
X		getde(fid, val, &dstr);
X 		if  (type & S_EXT)
X			sy->s_glob = 1;
X		sy->s_link = dstr.d_lab;
X		dstr.d_lab = sy;
X		putde(fid, val, &dstr);
X		break;
X	}
X	
X	sy->s_newsym = 0;
X	return	sy;
X}
X
X
X/*
X *	Process relocation stuff in putative library modules.
X *	The main function of all this is to mark which bits of the text
X *	not to look at as I compare the stuff.
X *
X *	As with "rrel", return -1 error, 0 no relocation, 1 relocation.
X */
X
Xint	rrell1(ldptr, outf)
XLDFILE *ldptr;		/*  a.out file (possibly in library)  */
Xef_fid	outf;		/*  Output file descriptor  */
X{
X 	struct	reloc	crel;
X	struct scnhdr tsect,dsect;
X	t_entry	tstr;
X	register  int	nreloc;
X	long	pos;
X
X	ldshread(ldptr,1,&tsect);
X	ldshread(ldptr,2,&dsect);
X 	if  (tsect.s_nreloc <= 0  &&  dsect.s_nreloc <= 0)
X		return	0;
X
X	nreloc = tsect.s_nreloc;
X
X	ldrseek(ldptr,1);
X 	while  (nreloc-- > 0)  {
X		if  (FREAD((char *)&crel, sizeof(crel),1,ldptr) != 1)
X			return	-1;
X
X 		pos = crel.r_vaddr;
X		gette(outf, pos, &tstr);
X		if (crel.r_type == R_ABS)
X		    tstr.t_reloc = R_NONE;
X		else
X		    tstr.t_reloc = R_LONG;	/* what about PC-relative? */
X		tstr.t_isrel = 1;
X		putte(outf, pos, &tstr);
X 		if  (tstr.t_reloc == R_LONG)  {
X			gette(outf, pos+2, &tstr);
X			tstr.t_isrel = 1;
X			putte(outf, pos+2, &tstr);
X		}
X	}
X	
X	/*
X	 *	Dont bother with data relocation at this stage. We'll
X	 *	tie that up later.
X	 */
X	
X	return 1;
X}
X
X/*
X *	Process a symbol in library file.  The extern variable trelpos gives
X *	the place in the main file where the library module is relocated.
X *	We don't know the data position until we do the final merge, perhaps
X *	not even then.
X */
X/* trelpos ??? */
X
Xsymbol	dolsymb(sy, type, val, fid)
Xregister  symbol  sy;
Xint	type;
Xlong	val;
Xef_fid	fid;
X{
X	t_entry	tstr;
X	
X	switch  (type)  {
X	default:
X		return	NULL;
X		
X 	case  S_EXT|S_UNDF:
X		if  (!sy->s_newsym)
X			return	sy;
X		sy->s_value = val;
X		if  (val != 0)  {
X 			sy->s_type = S_COMM;
X			addit(&dreltab, sy);
X		}
X		else
X			sy->s_type = S_UNDF;
X		sy->s_glob = 1;
X		break;
X		
X 	case  S_EXT|S_ABS:
X		if  (!sy->s_newsym)  {
X			if  (sy->s_type != S_ABS || sy->s_value != val)
X				lclash("abs");
X		}
X		sy->s_type = S_ABS;
X		sy->s_value = val;
X		sy->s_glob = 1;
X		addit(&abstab, sy);
X		break;
X		
X 	case  S_EXT|S_TEXT:
X		sy->s_type = S_TEXT;
X		val += trelpos - fid->ef_tbase;
X		if  (!sy->s_newsym)  {
X			if  (val != sy->s_value)
X				lclash("tsym");
X			return	sy;
X		}
X		sy->s_value = val;
X		gette(&mainfile, val, &tstr);
X		tstr.t_bdest = 1;
X		tstr.t_gbdest = 1;
X		sy->s_glob = 1;
X		sy->s_link = tstr.t_lab;
X		tstr.t_lab = sy;
X		putte(&mainfile, val, &tstr);
X		break;
X
X 	case  S_EXT|S_BSS:
X		if  (!sy->s_newsym)
X			return	sy;
X		sy->s_type = S_BSS;
X		sy->s_value = val - fid->ef_bbase;
X		goto	datrest;
X
X 	case  S_EXT|S_DATA:
X		if  (!sy->s_newsym)
X			return	sy;
X		sy->s_type = S_DATA;
X		sy->s_value = val - fid->ef_dbase;
X	datrest:
X		sy->s_glob = 1;
X		addit(&dreltab, sy);
X		break;
X	}
X	
X	sy->s_newsym = 0;
X	return	sy;
X}
X
X/*
X *	Change definition of undefined symbol as we define it.
X */
X
Xvoid	reassign(sy, val)
Xregister  symbol  sy;
Xlong	val;
X{
X	sy->s_value = val;
X
X	if  (val < mainfile.ef_tbase)  {
X		sy->s_type = S_ABS;
X		addit(&abstab, sy);
X	}
X	else  if  (val < mainfile.ef_dbase)  {
X		t_entry	tstr;
X		
X		sy->s_type = S_TEXT;
X		gette(&mainfile, val, &tstr);
X		tstr.t_bdest = 1;
X		tstr.t_gbdest = 1;
X		sy->s_glob = 1;
X		sy->s_link = tstr.t_lab;
X		tstr.t_lab = sy;
X		putte(&mainfile, val, &tstr);
X	}
X	else  {
X		d_entry dstr;
X		
X		sy->s_type = val < mainfile.ef_bbase? S_DATA: S_BSS;
X		getde(&mainfile, val, &dstr);
X		sy->s_link = dstr.d_lab;
X		dstr.d_lab = sy;
X		putde(&mainfile, val, &dstr);
X	}
X}
X
X/*
X *	When we discover where bss or data come, reallocate the table.
X */
X
Xvoid	zapdat(seg, inc)
Xint	seg;
Xlong	inc;
X{
X	register  int	i;
X	register  symbol  csymb;
X	d_entry	dent;
X	
X	for  (i = 0;  i < dreltab.c_int;  i++) {
X		csymb = dreltab.c_symb[i];
X		if  (csymb->s_type != seg)
X			continue;
X		csymb->s_value += inc;
X		getde(&mainfile, csymb->s_value, &dent);
X		csymb->s_link = dent.d_lab;
X		dent.d_lab = csymb;
X		putde(&mainfile, csymb->s_value, &dent);
X	}
X}
X
X/*
X *	Process relocation stuff in library module which we are inserting.
X *	Horrors if something goes wrong.
X */
X/* trelpos, drelpos ??? */
X
Xrrell2(ldptr, ldptr2, outf)
XLDFILE *ldptr,*ldptr2;	/*  a.out file (possibly in library)  */
Xef_fid	outf;		/*  Output file descriptor  */
X{
X 	struct	reloc	crel;
X	t_entry	mtstr;
X	d_entry	mdstr;
X	struct scnhdr tsect,dsect;
X	struct syment isym;
X	int nreloc;
X	unsigned rtype;
X	register  long	size;
X	register  symbol  csymb;
X	long	pos, mpos, mval, lval;
X	int	dhere = 0;		/*  Mark whether bss done  */
X
X	ldshread(ldptr,1,&tsect);
X	ldshread(ldptr,2,&dsect);
X 	if  (tsect.s_nreloc <= 0  &&  dsect.s_nreloc <= 0)
X		return	0;
X
X	nreloc = tsect.s_nreloc;
X
X	ldrseek(ldptr,1);
X 	while  (nreloc-- > 0)  {
X		if  (FREAD((char *)&crel, sizeof(crel),1,ldptr) != 1)
X			lclash("rd trel");
X
X 		pos = crel.r_vaddr;
X 		mpos = crel.r_vaddr + trelpos;
X		gette(&mainfile, mpos, &mtstr);
X		if (crel.r_type == R_ABS)
X		    rtype = R_NONE;
X		else
X		    rtype = R_LONG;	/* what about PC-relative? */
X		ldtbread(ldptr2,crel.r_symndx,&isym);
X 		lval = gettw(outf, pos, (int)rtype);
X 		mval = gettw(&mainfile, mpos, (int)rtype);
X		
X		if ( isym.n_sclass != C_EXT ) {
X		switch (convtosun(&isym)) {
X 		case  S_TEXT:
X			if  (lval + trelpos - outf->ef_tbase != mval)
X				lclash("Trel");
X			continue;
X 		case  S_DATA:
X			if  (donedrel)  {
X				if  (lval + drelpos - outf->ef_dbase != mval)
X					lclash("Drel");
X			}
X			else  {
X				donedrel++;
X				drelpos = mval - lval + outf->ef_dbase;
X			}
X			continue;
X 		case  S_BSS:
X			if  (donebrel)  {
X				if  (lval + brelpos - outf->ef_bbase != mval)
X					lclash("brel");
X			}
X			else  {
X				donebrel++;
X				brelpos = mval - lval + outf->ef_bbase;
X			}
X			continue;
X 		      }
X 	      } else {
X 			if  (crel.r_symndx >= outf->ef_stcnt)
X				lclash("Bad sy no");
X 			csymb = outf->ef_stvec[symord[crel.r_symndx]];
X			if  (csymb == NULL)
X				continue;
X			switch  (csymb->s_type)  {
X			case  S_UNDF:
X				reassign(csymb, mval - lval);
X				break;
X			case  S_ABS:
X				if  (lval + csymb->s_value != mval)
X					lclash("abs rel");
X				break;
X			case  S_TEXT:
X				if  (lval + csymb->s_value != mval)
X					lclash("text rel");
X				break;
X			case  S_DATA:
X				if  (lval + csymb->s_value != mval)
X					lclash("data rel");
X				break;
X			case  S_BSS:
X				if  (lval + csymb->s_value != mval)
X					lclash("bss rel");
X				break;
X 			case  S_COMM:
X				reassign(csymb, mval - lval);
X				break;
X			}
X			mtstr.t_relsymb = csymb;
X			mtstr.t_reldisp = lval;
X		}
X	}
X	
X	/*
X	 *	Relocate data and bss if possible.
X	 */
X	
X	if  (donebrel)  {
X		zapdat(S_BSS, brelpos);
X		dhere++;
X	}
X	
X	if  (!donedrel)
X		return;
X		
X
X	zapdat(S_DATA, drelpos);
X	
X	/*
X	 *	And now repeat all that for data relocations if possible
X	 */
X	
X	nreloc = tsect.s_nreloc;
X
X	ldrseek(ldptr,2);
X	
X	while (nreloc-- > 0) {
X		if  (FREAD((char *)&crel, sizeof(crel),1,ldptr) != 1)
X			lclash("Rd drel");
X
X 		if  (crel.r_type == R_ABS)
X			continue;
X
X 		pos = crel.r_vaddr;
X 		mpos = crel.r_vaddr + drelpos;
X		getde(&mainfile, mpos, &mdstr);
X		rtype = R_LONG;		/* what about PC-relative? */
X		ldtbread(ldptr2,crel.r_symndx,&isym);
X
X 		lval = getdw(outf, pos, (int)rtype);
X 		mval = getdw(&mainfile, mpos, (int)rtype);
X		if ( isym.n_sclass != C_EXT ) {
X		switch (convtosun(&isym)) {
X 		case  S_TEXT:
X			if  (lval + trelpos - outf->ef_tbase != mval)
X				lclash("Trel-d");
X			continue;
X 		case  S_DATA:
X			if  (lval + drelpos - outf->ef_dbase != mval)
X				lclash("Drel-d");
X			continue;
X 		case  S_BSS:
X			if  (donebrel)  {
X				if  (lval + brelpos - outf->ef_bbase != mval)
X					lclash("brel");
X			}
X			else  {
X				donebrel++;
X				brelpos = mval - lval + outf->ef_bbase;
X			}
X			continue;
X 		      }
X 	      } else { 
X 			if  (crel.r_symndx >= outf->ef_stcnt)
X				lclash("Bad sy no");
X 			csymb = outf->ef_stvec[symord[crel.r_symndx]];
X			if  (csymb == NULL)
X				continue;
X			switch  (csymb->s_type)  {
X			case  S_UNDF:
X				reassign(csymb, mval - lval);
X				break;
X			case  S_ABS:
X				if  (lval + csymb->s_value != mval)
X					lclash("abs rel");
X				break;
X			case  S_TEXT:
X				if  (lval + csymb->s_value != mval)
X					lclash("text rel");
X				break;
X			case  S_DATA:
X				if  (lval + csymb->s_value != mval)
X					lclash("data rel");
X				break;
X			case  S_BSS:
X				if  (lval + csymb->s_value != mval)
X					lclash("bss rel");
X				break;
X 			case  S_COMM:
X				reassign(csymb, mval - lval);
X				break;
X			}
X			mtstr.t_relsymb = csymb;
X			mtstr.t_reldisp = lval;
X		}
X	}
X
X	if  (dhere || !donebrel)
X		return;
X
X	zapdat(S_BSS, brelpos);
X}
SHAR_EOF
chmod 0644 robj.c || echo "restore of robj.c fails"
exit 0