/***** spin: sym.c *****/

/* Copyright (c) 1991 by AT&T Bell Telephone Laboratories, Inc.
 * All Rights Reserved. This software is for educational purposes only.
 * No part of this source code may be reproduced in any form
 * without explicit written permission from the copyright owner.
 * This software was written by Gerard J. Holzmann, as part of the book
 * ``Design and Validation of Computer Protocols,'' ISBN 0-13-539925-4,
 * Prentice Hall, Englewood Cliffs, NJ, 07632.
 * Send bug-reports to: gerard@research.att.com
 */

#include "spin.h"
#include "y.tab.h"

Symbol	*symtab[Nhash+1];
Symbol	*context = (Symbol *) 0;

hash(s)
	char *s;
{
	int h=0;

	while (*s)
	{	h += *s++;
		h <<= 1;
		if (h&(Nhash+1))
			h |= 1;
	}
	return h&Nhash;
}

Symbol *
lookup(s)
	char *s;
{
	Symbol *sp;
	int h=hash(s);

	for (sp = symtab[h]; sp; sp = sp->next)
		if (strcmp(sp->name, s) == 0 && sp->context == context)
			return sp;			/* found */
	sp = (Symbol *) emalloc(sizeof(Symbol));	/* add */
	sp->name = (char *) emalloc(strlen(s) + 1);
	strcpy(sp->name, s);
	sp->nel = 1;
	sp->context = context;
	sp->next = symtab[h];
	symtab[h] = sp;

	return sp;
}

void
settype(n, t)
	Node *n;
{
	while (n)
	{	if (n->nsym->type)
		  yyerror("redeclaration of `%s'", n->nsym->name);
		n->nsym->type = t;
		if (n->nsym->nel <= 0)
		  yyerror("bad array size for `%s'", n->nsym->name);
		n = n->rgt;
	}
}

Node *Mtype = (Node *) 0;

void
setmtype(m)
	Node *m;
{
	Node *n = m;
	if (Mtype)
		yyerror("mtype redeclared", (char *)0);

	Mtype = n;
	while (n)	/* syntax check */
	{	if (!n->lft || !n->lft->nsym
		||  (n->lft->ntyp != NAME)
		||   n->lft->lft)	/* indexed variable */
			fatal("bad mtype definition", (char *)0);
		n = n->rgt;
	}
}

ismtype(str)
	char *str;
{
	Node *n;
	int cnt = 1;

	for (n = Mtype; n; n = n->rgt)
	{	if (strcmp(str, n->lft->nsym->name) == 0)
			return cnt;
		cnt++;
	}
	return 0;
}
