#include <sys/types.h>
#include "ansi.h"
#include "host.h"
#include "hash.h"
#include "files.h"
#include "il.h"
#include "allocate.h"
#include "config.h"

#undef NULL
#define NULL			0L

#undef HASH_MAX
#define HASH_MAX		512

#ifndef MAX_SCOPE
#define MAX_SCOPE		64
#endif

extern file_pos_t yypos;

static symbol_t *hash_table[HASH_MAX];

typedef struct {
	int	nparams;
	symbol_t *scope_thread;
} scope_info_t;

static scope_info_t scope_info[MAX_SCOPE];
static int scope = 0;

symbol_t*
new_sym()
{
	static symbol_t *free = NULL;
	static int free_index;

	symbol_t *decl;

	if (free == NULL || free_index > 63) {
		free = (symbol_t*) allocate(sizeof(symbol_t) * 64);
		free_index = 0;
	}

	decl = &free[free_index++];

	decl->sym_def = yypos;
	decl->sym_scope = scope;
	decl->traversal_unit = -1;

	return decl;
}

symbol_t*
find_sym(name)
	char *name;
{
	hash_t hash;
	int index;
	symbol_t *decl;

	assert(name != NULL);

	hash = common_hash(name);
	index = hash & (HASH_MAX-1);

	for (decl = hash_table[index]; decl; decl = decl->sym_hash_list) {
		assert(decl->sym_hash_list != decl);
		if (decl->sym_hash == hash && !strcmp(name,decl->sym_ident->node.id.name)) {
			return decl;
		}
	}

	return NULL;
}

void
store_sym(decl)
	symbol_t *decl;
{
	hash_t hash;
	int index;

	assert(decl != NULL);
	assert(decl->sym_ident != NULL);
	assert(decl->sym_ident->node_kind == _Ident);
	assert(decl->sym_ident->node.id.name != NULL);

	if (decl->stored) return;
	decl->stored = 1;

	decl->sym_hash = common_hash(decl->sym_ident->node.id.name);
	index = decl->sym_hash & (HASH_MAX-1);

	decl->sym_hash_list = hash_table[index];
	hash_table[index] = decl;
	decl->sym_scope_list = scope_info[scope].scope_thread;
	scope_info[scope].scope_thread = decl;
}

void
scope_push()
{
	if (++scope >= MAX_SCOPE) {
		fatal(__FILE__,__LINE__,"Maximum scope depth exceeded");
	}

	scope_info[scope].nparams = 0;
	scope_info[scope].scope_thread = NULL;
}

static void
pop_scope_thread()
{
	symbol_t *thread, *sym, *last, *next;
	int index;

	for (thread = scope_info[scope].scope_thread; thread; thread = next) {
		next = thread->sym_scope_list;
		thread->sym_scope_list = NULL;

		/*
		 * Do we really want to pull this symbol out
		 * of the symbol table?
		 */
		switch (thread->sym_kind) {
		  case type_symbol:
		  case enum_literal:
			continue;
		}

		last = NULL;
		index = thread->sym_hash & (HASH_MAX-1);

		for (sym = hash_table[index]; sym && sym != thread; sym = sym->sym_hash_list) {
			last = sym;
		}

		if (sym != NULL) {
			if (last != NULL) {
				last->sym_hash_list = sym->sym_hash_list;
			}
			else {
				hash_table[index] = sym->sym_hash_list;
			}
		}
	}
}

void
scope_pop()
{
/*
	pop_scope_thread();
*/
	if (--scope < 0) {
		fatal(__FILE__,__LINE__,"Scope stack underflow");
	}
}

int
next_param()
{
	return ++scope_info[scope].nparams;
}


syntax highlighted by Code2HTML, v. 0.9.1