/*
 * init the symbol table
 */

#include "defs.h"
#include "sym.h"
#include "a.out.h"
#include <sys/types.h>

#define	NSYMS	300
#define	BIGBUF	(4*4096)

extern struct sym *symtab;
long		A6base;

syminit(h)
struct exec *h;
{
	register Sym *q;
	register n, m;
	Sym space[BIGBUF/sizeof(Sym)];
	struct sym *sbuf;
	register struct sym *cur;
	struct sym *curgbl;
	register int type, ltype;
	off_t off;
	char *malloc();
	char *savename();

	symtab = NULL;
	if (h->a_syms == 0)
		return;		/* stripped */
	off = swal(h->a_text) + swal(h->a_data);
#if NOTDEF
	if ((swal(h->a_flag) & 01) == 0)
		off += off;	/* space for reloc data */
#endif
	lseek(fsym, off + sizeof(*h), 0);
	curgbl = sbuf = cur = NULL;
	for (n = swal(h->a_syms); n > 0 ;) {
		m = read(fsym, (char *)space, min(n, sizeof(space)));
		if (m <= 0)
			break;
		n -= m;
		for (q = space; m > 0; q++, m-= sizeof(space[0])) {
			switch (q->type) {
			case 'T':
			case 't':
				type = S_TEXT;
				break;

			case 'D':
			case 'd':
			case 'B':
			case 'b':
				type = S_DATA;
				break;

			default:
				continue;
			}
			if (sbuf == NULL || ++cur >= sbuf + NSYMS) {
				if ((sbuf = (struct sym *)malloc(sizeof(struct sym) * NSYMS)) == NULL) {
					printf("out of mem for syms\n");
					return;
				}
				cur = sbuf;
			}
			cur->y_type = type;
			cur->y_ltype = ltype;
			cur->y_value = swal(q->value);
			cur->y_name = savename(q->name, sizeof(q->name));
			if (strcmp(cur->y_name, "a6base") == 0)
				A6base = swal(q->value);
			cur->y_locals = NULL;
			if (cur->y_type == S_TEXT && q->name[0] == '~') {
				cur->y_next = curgbl;
				curgbl = cur;
			}
			else if (cur->y_type == S_STAB) {
				if (curgbl == NULL)
					continue;
				cur->y_next = curgbl->y_locals;
				curgbl->y_locals = cur;
			}
			else {
				cur->y_next = symtab;
				symtab = cur;
			}
		}
	}
	for (; curgbl; curgbl = curgbl->y_next) {
		if (curgbl->y_locals == NULL)
			continue;
		for (cur = symtab; cur; cur = cur->y_next) {
			if (cur->y_type != S_TEXT)
				continue;
			if (cur->y_value == curgbl->y_value) {
				cur->y_locals = curgbl->y_locals;
				break;
			}
		}
	}
}

static char *
savename(n, sz)
char *n;
register int sz;
{
	char *p;
	char *malloc();

	if ((p = malloc(sz+1)) == NULL)
		return ("");
	strncpy(p, n, sz);
	p[sz] = 0;
	return (p);
}

eqsym(sp, n)
struct sym *sp;
char *n;
{

	return (strncmp(sp->y_name, n, NNAME) == 0);
}

min(a, b)
{
	if (a < b)
		return (a);
	else
		return (b);
}
