h03568
s 00519/00000/00000
d D 1.1 80/05/15 14:27:21 lcd 1 0
e
u
sunix
lcd
U
t
T
I 1
#

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

/*
 *	symb.c: KER.out symbol table manager
 */

TYPE	struct symentry {
			char	sname[ 8 ];
			integer	stype;
			integer	svalue;
			};

	struct symtab {
			struct symtab	*left;
			struct symtab	*right;
			struct symentry	symbl;
			integer		leftw;
			integer		rghtw;
		      };
	
CONST	char	*_S_symb	"%W%";

#define	HEADERSIZE	020
#define NIL		0

#define	SLESS	0
#define	SGREATR	1
#define	SEQUAL	2

VAR	struct symtab	*root;

	unsigned integer	header[ HEADERSIZE/2 ];

	long			dtsiz;
	long			txtsiz;

/*
 *	scmpre: compare two strings
 */


PROCEDURE integer scmpre( s1, s2 )

VAR	char	s1[8];
	char	s2[8];

BEGIN	VAR	integer	index;
		integer result;

	index = 0;
	LOOP	WHEN s1[ index ] > s2[ index ] 
		DO	result = SGREATR;
		EXIT;

		WHEN s1[ index ] < s2[ index ]
		DO	result = SLESS;
		EXIT;

		WHEN ( index == 7 ) OR
		     ( ( s1[ index ] == eos ) AND ( s2[ index ] == eos ) )
		DO	result = SEQUAL;
		EXIT;

		inc( index );
	END;

	return( result );
END

/*
 *	balance: balance binary tree
 */

PROCEDURE balance( rt )

VAR	struct symtab	**rt;

BEGIN	VAR	struct symtab	*desn;

	IF *rt != NIL
	THEN	WHILE abs( (*rt)->rghtw - (*rt)->leftw ) > 1
		DO	IF ( (*rt)->rghtw - (*rt)->leftw ) > 0
			THEN	desn = (*rt)->right;
				desn->left = *rt;
				(*rt)->right = NIL;
				desn->leftw = (*rt)->leftw+1;
				(*rt)->rghtw = 0;

			ELSE	desn = (*rt)->left;
				desn->right = *rt;
				(*rt)->left = NIL;
				desn->rghtw = (*rt)->rghtw+1;
				(*rt)->leftw = 0;
			END;

			*rt = desn;
		END;

		balance( &((*rt)->right) );
		balance( &((*rt)->left) );
	END
END



/*
 *	insert: inserts element into symbol table
 */

PROCEDURE insert( symb )

VAR     struct symtab *symb;

BEGIN	VAR	boolean		lesstn;
		struct symtab	*find;
		struct symtab	*foll;

	symb->leftw = 0;
	symb->rghtw = 0;
	symb->left = NIL;
	symb->right = NIL;

	IF root == NIL
	THEN	root = symb;
	ELSE	find = root;
		foll = root;

		LOOP	WHEN scmpre( symb->symbl.sname, 
				     find->symbl.sname ) == SLESS
			DO EXIT;

			inc( find->rghtw );
			foll = find;
			find = find->right;

			WHEN find == NIL DO EXIT;
		END;

		IF find == root
		THEN	root = symb;
		ELSE	foll->right = symb;
		END;

		symb->right = find;

		IF find != NIL
		THEN	symb->rghtw = find->rghtw+1;
		END;
	END;
END


VAR	long	saddr;

	
PROCEDURE printtree( rt, depth )

VAR	struct symtab	*rt;
	int		depth;

BEGIN	VAR	char	word[9];
		int	count;	

	IF rt != NIL
	THEN	printtree( rt->left, depth+1 );
		
		count = depth;

		WHILE count != 0
		DO	putchar(' ');
			dec( count );
		END;

		word[8] = eos;
		move( rt->symbl.sname, word, 8 );
		printf("%s l%d r%d\n", word, rt->leftw, rt->rghtw );

		printtree( rt->right, depth+1 );
	END;
END


/*
 *	syminit: symbol table initialization
 */

PROCEDURE syminit()

BEGIN	VAR	struct symtab	*symb;
		integer		symcnt;

	fseek( o_aout, 0L, 0 );

	fread( header, HEADERSIZE, 1, o_aout );

	dtsiz = header[2];
	txtsiz = header[1];

	dtsiz = dtsiz&0177777L;
	txtsiz = txtsiz&0177777L;

	saddr = dtsiz + txtsiz;

	IF header[7]				/* relocation bits? */
	THEN	saddr = saddr + 020L;
	ELSE	saddr = 020L + 2L*( saddr );
	END;

	fseek( o_aout,  saddr, 0 );

	symcnt = header[4]/12;
	root = NIL;

	WHILE symcnt > 0
	DO	symb = alloc( sizeof( *symb ) );
		fread( &(symb->symbl), sizeof( symb->symbl ), 1, o_aout );
		insert( symb );
		dec( symcnt );
	END;

	balance( &root );
	/*	printtree( root, 0 );		*/
END


/*
 *	rlookup: recursive look up
 */

PROCEDURE struct symtab *rlookup( word, rt )

CONST	char		word[8];
	struct symtab	*rt;

BEGIN	VAR	integer		comp;
		struct symtab	*result;

	IF rt == NIL
	THEN	result = NIL;
	ELSE	comp = scmpre( word, rt->symbl.sname );

		IF comp == SEQUAL
		THEN	result = rt;
		ELSE	IF comp == SLESS
			THEN	result = rlookup( word, rt->left );
			ELSE	result = rlookup( word, rt->right );
			END;
		END;
	END;

	return( result );
END

/*
 *	lookup: look up symbol in symbol table
 */

PROCEDURE struct symtab *lookup( word )

CONST	char	word[8];

BEGIN	return( rlookup( word, root ) );
END

CONST

#define	UNDEF	0
#define ABS	1
#define TXT	02
#define DTA	03
#define FLNM	037
#define BSS	04
#define UNEX	040
#define ABSEX	041
#define TXTEX	042
#define DTAEX	043
#define BSSEX	044


/*
 *	convert: convert symbol table entry into physical address
 */

PROCEDURE boolean convert( symb, address )

VAR	struct symtab	*symb;
	long		*address;

BEGIN	VAR	boolean	b;
		integer type;
		long	sval;	

	b = true;

	type = symb->symbl.stype & FLNM;

	sval = symb->symbl.svalue;
	sval = sval&0177777L;

	IF type > BSS
	THEN	type = ABS;
	END;

	CASE type OF
	case ABS	:
	case TXTEX	:
	case TXT	: BEGIN	*address = sval;
			  ENDCASE;
	case DTA	:
	case DTAEX	: BEGIN	*address = sval+txtsiz;
			  ENDCASE;
	case BSS	:
	case BSSEX	: BEGIN	*address = sval+dtsiz+txtsiz;
			  ENDCASE;
	default		: BEGIN	printf("Symbol not address.\n");
				b = false;
			  ENDCASE;
	END;

	return( b );
END

/*
 *	text: set addr to text address
 */

PROCEDURE text()

BEGIN	VAR	long	addr1;
		long	addr2;

	getnum( &addr1 );

	IF addr1 == -1L
	THEN	printf("?\n");
	ELSE	getnum( &addr2 );
		
		IF addr2 == -1L
		THEN	addr2 = 0L;
		END;

		addr2 = addr2+addr1;

		display( addr1, addr2 );
		addr = addr2;
	END;
END

/*
 *	data: display data addresses
 */

PROCEDURE data()

BEGIN	VAR	long	addr1;
		long	addr2;
		integer	par;
		integer pdr;

	getnum( &addr1 );

	IF addr1 == -1L
	THEN	printf("?\n");
	ELSE	getnum( &addr2 );

		IF addr2 == -1L
		THEN	addr2 = 0L;
		END;

		IF ( addr1 >= 0140000L ) AND
		   ( addr1 <  0160000L ) 
		THEN	regpr( &par, &pdr );
			paradr( par, pdr, &addr1 );

		ELSE	addr1 = addr1+txtsiz;
		END;

		addr2 = addr2+addr1;

		display( addr1, addr2 );
		addr = addr2;
	END
END

/*
 *	xtcto: get minus part from "g-" label
 */

PROCEDURE xtcto( word, bmp )

CONST	char	*word;
	long	*bmp;

BEGIN	integer	index;
	integer	tmp;

	index = 0;
	*bmp = 0L;

	LOOP	WHEN word[ index ] == eos DO EXIT;

		tmp = word[ index ] - '0';
		*bmp = *bmp*8L + tmp;

		inc( index );
	END;
END


/*
 *	getaddr: lookup and get address
 */

PROCEDURE getaddr( word, addrs )

CONST	char	*word;
VAR	long	*addrs;

BEGIN	VAR	struct symtab *symb;
		long		bump;
		boolean		minus;

	minus = false;

	IF ( word[0] == 'G' ) OR
	   ( word[0] == 'g' )
	THEN	word[0] = 'g';
		IF word[1] == '-'
		THEN	word[1] = eos;
			minus = true;
		END;
	END;

	symb = lookup( word );

	IF symb == NIL
	THEN	printf("Symbol not found.\n");
		*addrs = 0L;

     	ELSE	IF convert( symb, addrs )
		THEN	IF minus
			THEN	xtcto( &word[2], &bump );
				*addrs = *addrs - bump;
			END;
		END;
	END;

	return( symb != NIL );
END


/*
 *	dislabel: display data at label
 */

PROCEDURE dislabel( word )

CONST	char	*word;

BEGIN	VAR	long		addr1;
		long		addr2;

	IF getaddr( word, &addr1 )
     	THEN	getnum( &addr2 );

		IF addr2 == -1L
		THEN	addr2 = 0L;
		END;

		addr2 = addr2 + addr1;

		display( addr1, addr2 );
		addr = addr2;
	END;
END

/*
 *	label: look up label in symbol table
 */

PROCEDURE label()

BEGIN	char		word[ MAXLINELENGTH ];

	getword( word );

	dislabel( word );
END


/*
 *	dadjust: adjust address of d-space
 */

PROCEDURE dadjust( addrs )

VAR	long	*addrs;

BEGIN	*addrs = *addrs + txtsiz;
END

/*
 *	prtdot: print out dot
 */

PROCEDURE prtdot()

BEGIN	printf("%lo", addr );

	IF ( addr >= txtsiz ) AND
	   ( addr <  txtsiz+dtsiz )
	THEN	printf(": %loD", addr-txtsiz );
	END;

	putchar( eoln );
END;
E 1
