OpenCores
URL https://opencores.org/ocsvn/jtag_stapl_player/jtag_stapl_player/trunk

Subversion Repositories jtag_stapl_player

[/] [jtag_stapl_player/] [trunk/] [jamsym.c] - Rev 2

Compare with Previous | Blame | View Log

/****************************************************************************/
/*																			*/
/*	Module:			jamsym.c												*/
/*																			*/
/*					Copyright (C) Altera Corporation 1997					*/
/*																			*/
/*	Description:	Functions for maintaining symbol table, including		*/
/*					adding a synbol, searching for a symbol, and			*/
/*					modifying the value associated with a symbol			*/
/*																			*/
/*	Revisions:		1.1 added support for dynamic memory allocation, made	*/
/*					jam_symbol_table a pointer table instead of a table of	*/
/*					structures.  Actual symbols now live at the top of the	*/
/*					workspace, and grow dynamically downwards in memory.	*/
/*																			*/
/****************************************************************************/
 
/****************************************************************************/
/*																			*/
/*	Actel version 1.1             May 2003									*/
/*																			*/
/****************************************************************************/
 
#include "jamexprt.h"
#include "jamdefs.h"
#include "jamsym.h"
#include "jamheap.h"
#include "jamutil.h"
 
/****************************************************************************/
/*																			*/
/*	Global variables														*/
/*																			*/
/****************************************************************************/
 
JAMS_SYMBOL_RECORD **jam_symbol_table = NULL;
 
void *jam_symbol_bottom = NULL;
 
extern BOOL jam_checking_uses_list;
 
/****************************************************************************/
/*																			*/
 
JAM_RETURN_TYPE jam_init_symbol_table()
 
/*																			*/
/*	Description:	Initializes the symbol table.  The symbol table is		*/
/*					located at the beginning of the workspace buffer.		*/
/*																			*/
/*	Returns:		JAMC_SUCCESS for success, or JAMC_OUT_OF_MEMORY if the	*/
/*					size of the workspace buffer is too small to hold the	*/
/*					desired number of symbol records.						*/
/*																			*/
/****************************************************************************/
{
	int index = 0;
	JAM_RETURN_TYPE status = JAMC_SUCCESS;
 
	if (jam_workspace != NULL)
	{
		jam_symbol_table = (JAMS_SYMBOL_RECORD **) jam_workspace;
 
		jam_symbol_bottom = (void *) (((long)jam_workspace) +
			((long)jam_workspace_size));
 
		if (jam_workspace_size <
			(JAMC_MAX_SYMBOL_COUNT * sizeof(void *)))
		{
			status = JAMC_OUT_OF_MEMORY;
		}
	}
	else
	{
		jam_symbol_table = (JAMS_SYMBOL_RECORD **) jam_malloc(
			(JAMC_MAX_SYMBOL_COUNT * sizeof(void *)));
 
		if (jam_symbol_table == NULL)
		{
			status = JAMC_OUT_OF_MEMORY;
		}
	}
 
	if (status == JAMC_SUCCESS)
	{
		for (index = 0; index < JAMC_MAX_SYMBOL_COUNT; ++index)
		{
			jam_symbol_table[index] = NULL;
		}
	}
 
	return (status);
}
 
void jam_free_symbol_table()
{
	int hash = 0;
	JAMS_SYMBOL_RECORD *symbol_record = NULL;
	JAMS_SYMBOL_RECORD *next = NULL;
 
	if ((jam_symbol_table != NULL) && (jam_workspace == NULL))
	{
		for (hash = 0; hash < JAMC_MAX_SYMBOL_COUNT; ++hash)
		{
			symbol_record = jam_symbol_table[hash];
			while (symbol_record != NULL)
			{
				next = symbol_record->next;
				jam_free(symbol_record);
				symbol_record = next;
			}
		}
 
		jam_free(jam_symbol_table);
	}
}
 
/****************************************************************************/
/*																			*/
 
BOOL jam_check_init_list
(
	char *name,
	long *value
)
 
/*																			*/
/*	Description:	Compares variable name to names in initialization list	*/
/*					and, if name is found, returns the corresponding		*/
/*					initialization value for the variable.					*/
/*																			*/
/*	Returns:		TRUE if variable was found, else FALSE					*/
/*																			*/
/****************************************************************************/
{
	char r, l;
	int ch_index = 0;
	int init_entry = 0;
	char *init_string = NULL;
	long val;
	BOOL match = FALSE;
	BOOL negate = FALSE;
	BOOL status = FALSE;
 
	if (jam_init_list != NULL)
	{
		while ((!match) && (jam_init_list[init_entry] != NULL))
		{
			init_string = jam_init_list[init_entry];
			match = TRUE;
			ch_index = 0;
			do
			{
				r = jam_toupper(init_string[ch_index]);
				if (!jam_is_name_char(r)) r = '\0';
				l = name[ch_index];
				match = (r == l);
				++ch_index;
			}
			while (match && (r != '\0') && (l != '\0'));
 
			if (match)
			{
				--ch_index;
				while (jam_isspace(init_string[ch_index])) ++ch_index;
				if (init_string[ch_index] == JAMC_EQUAL_CHAR)
				{
					++ch_index;
					while (jam_isspace(init_string[ch_index])) ++ch_index;
 
					if (init_string[ch_index] == JAMC_MINUS_CHAR)
					{
						++ch_index;
						negate = TRUE;
					}
 
					if (jam_isdigit(init_string[ch_index]))
					{
						val = jam_atol(&init_string[ch_index]);
 
						if (negate) val = 0L - val;
 
						if (value != NULL) *value = val;
 
						status = TRUE;
					}
				}
			}
			else
			{
				++init_entry;
			}
		}
	}
 
	return (status);
}
 
/****************************************************************************/
/*																			*/
 
int jam_hash
(
	char *name
)
 
/*																			*/
/*	Description:	Calcluates 'hash value' for a symbolic name.  This is	*/
/*					a pseudo-random number which is used as an offset into	*/
/*					the symbol table, as the initial position for the		*/
/*					symbol record.											*/
/*																			*/
/*	Returns:		An integer between 0 and JAMC_MAX_SYMBOL_COUNT-1		*/
/*																			*/
/****************************************************************************/
{
	int ch_index = 0;
	int hash = 0;
 
	while ((ch_index < JAMC_MAX_NAME_LENGTH) && (name[ch_index] != '\0'))
	{
		hash <<= 1;
		hash += (name[ch_index] & 0x1f);
		++ch_index;
	}
	if (hash < 0) hash = 0 - hash;
 
	return (hash % JAMC_MAX_SYMBOL_COUNT);
}
 
/****************************************************************************/
/*																			*/
 
JAM_RETURN_TYPE jam_add_symbol
(
	JAME_SYMBOL_TYPE type,
	char *name,
	long value,
	long position
)
 
/*																			*/
/*	Description:	Adds a new symbol to the symbol table.  If the symbol	*/
/*					name already exists in the symbol table, it is an error	*/
/*					unless the symbol type and the position in the file		*/
/*					where the symbol was declared are identical.  This is	*/
/*					necessary to allow labels and variable declarations		*/
/*					inside loops and subroutines where they may be			*/
/*					encountered multiple times.								*/
/*																			*/
/*	Returns:		JAMC_SUCCESS for success, or JAMC_REDEFINED_SYMBOL		*/
/*					if symbol was already declared elsewhere, or			*/
/*					JAMC_OUT_OF_MEMORY if symbol table is full.				*/
/*																			*/
/****************************************************************************/
{
	char r, l;
	int ch_index = 0;
	int hash = 0;
	long init_list_value = 0L;
	BOOL match = FALSE;
	BOOL identical_redeclaration = FALSE;
	JAM_RETURN_TYPE status = JAMC_SUCCESS;
	JAMS_SYMBOL_RECORD *symbol_record = NULL;
	JAMS_SYMBOL_RECORD *prev_symbol_record = NULL;
 
	/*
	*	Check for legal characters in name, and legal name length
	*/
	while (name[ch_index] != JAMC_NULL_CHAR)
	{
		if (!jam_is_name_char(name[ch_index++])) status = JAMC_ILLEGAL_SYMBOL;
	}
 
	if ((ch_index == 0) || (ch_index > JAMC_MAX_NAME_LENGTH))
	{
		status = JAMC_ILLEGAL_SYMBOL;
	}
 
	/*
	*	Get hash key for this name
	*/
	hash = jam_hash(name);
 
	/*
	*	Get pointer to first symbol record corresponding to this hash key
	*/
	symbol_record = jam_symbol_table[hash];
 
	/*
	*	Then check for duplicate entry in symbol table
	*/
	while ((status == JAMC_SUCCESS) && (symbol_record != NULL) &&
		(!identical_redeclaration))
	{
		match = TRUE;
		ch_index = 0;
		do
		{
			r = symbol_record->name[ch_index];
			l = name[ch_index];
			match = (r == l);
			++ch_index;
		}
		while (match && (r != '\0') && (l != '\0'));
 
		if (match)
		{
			/*
			*	Check if symbol was already declared identically
			*	(same name, type, and source position)
			*/
			if ((symbol_record->position == position) &&
				(jam_phase == JAM_DATA_PHASE))
			{
				if ((type == JAM_INTEGER_ARRAY_WRITABLE) &&
					(symbol_record->type == JAM_INTEGER_ARRAY_INITIALIZED))
				{
					type = JAM_INTEGER_ARRAY_INITIALIZED;
				}
 
				if ((type == JAM_BOOLEAN_ARRAY_WRITABLE) &&
					(symbol_record->type == JAM_BOOLEAN_ARRAY_INITIALIZED))
				{
					type = JAM_BOOLEAN_ARRAY_INITIALIZED;
				}
			}
 
			if ((symbol_record->type == type) &&
				(symbol_record->position == position))
			{
				/*
				*	For identical redeclaration, simply assign the value
				*/
				identical_redeclaration = TRUE;
 
				if (jam_version != 2)
				{
					symbol_record->value = value;
				}
				else
				{
					if ((type != JAM_PROCEDURE_BLOCK) &&
						(type != JAM_DATA_BLOCK) &&
						(jam_current_block != NULL) &&
						(jam_current_block->type == JAM_PROCEDURE_BLOCK))
					{
						symbol_record->value = value;
					}
				}
			}
			else
			{
				status = JAMC_REDEFINED_SYMBOL;
			}
		}
 
		prev_symbol_record = symbol_record;
		symbol_record = symbol_record->next;
	}
 
	/*
	*	If no duplicate entry found, add the symbol
	*/
	if ((status == JAMC_SUCCESS) && (symbol_record == NULL) &&
		(!identical_redeclaration))
	{
		/*
		*	Check initialization list -- if matching name is found,
		*	override the initialization value with the new value
		*/
		if (((type == JAM_INTEGER_SYMBOL) || (type == JAM_BOOLEAN_SYMBOL)) &&
			(jam_init_list != NULL))
		{
			if ((jam_version != 2) &&
				jam_check_init_list(name, &init_list_value))
			{
				/* value was found -- override old value */
				value = init_list_value;
			}
		}
 
		/*
		*	Add the symbol
		*/
		if (jam_workspace != NULL)
		{
			jam_symbol_bottom = (void *)
				(((long)jam_symbol_bottom) - sizeof(JAMS_SYMBOL_RECORD));
 
			symbol_record = (JAMS_SYMBOL_RECORD *) jam_symbol_bottom;
 
			if ((long)jam_heap_top > (long)jam_symbol_bottom)
			{
				status = JAMC_OUT_OF_MEMORY;
			}
		}
		else
		{
			symbol_record = (JAMS_SYMBOL_RECORD *)
				jam_malloc(sizeof(JAMS_SYMBOL_RECORD));
 
			if (symbol_record == NULL)
			{
				status = JAMC_OUT_OF_MEMORY;
			}
		}
 
		if (status == JAMC_SUCCESS)
		{
			symbol_record->type = type;
			symbol_record->value = value;
			symbol_record->position = position;
			symbol_record->parent = jam_current_block;
			symbol_record->next = NULL;
 
			if (prev_symbol_record == NULL)
			{
				jam_symbol_table[hash] = symbol_record;
			}
			else
			{
				prev_symbol_record->next = symbol_record;
			}
 
			ch_index = 0;
			while ((ch_index < JAMC_MAX_NAME_LENGTH) &&
				(name[ch_index] != '\0'))
			{
				symbol_record->name[ch_index] = name[ch_index];
				++ch_index;
			}
			symbol_record->name[ch_index] = '\0';
		}
	}
 
	return (status);
}
 
/****************************************************************************/
/*																			*/
 
JAM_RETURN_TYPE jam_get_symbol_record
(
	char *name,
	JAMS_SYMBOL_RECORD **symbol_record
)
 
/*																			*/
/*	Description:	Searches in symbol table for a symbol record with		*/
/*					matching name.											*/
/*																			*/
/*	Return:			Pointer to symbol record, or NULL if symbol not found	*/
/*																			*/
/****************************************************************************/
{
	char r, l;
	char save_ch = 0;
	int ch_index = 0;
	int hash = 0;
	int name_begin = 0;
	int name_end = 0;
	BOOL match = FALSE;
	JAMS_SYMBOL_RECORD *tmp_symbol_record = NULL;
	JAM_RETURN_TYPE status = JAMC_UNDEFINED_SYMBOL;
 
	/*
	*	Get hash key for this name
	*/
	hash = jam_hash(name);
 
	/*
	*	Get pointer to first symbol record corresponding to this hash key
	*/
	tmp_symbol_record = jam_symbol_table[hash];
 
	/*
	*	Search for name in symbol table
	*/
	while ((!match) && (tmp_symbol_record != NULL))
	{
		match = TRUE;
		ch_index = 0;
		do
		{
			r = tmp_symbol_record->name[ch_index];
			l = name[ch_index];
			match = (r == l);
			++ch_index;
		}
		while (match && (r != '\0') && (l != '\0'));
 
		if (match)
		{
			status = JAMC_SUCCESS;
		}
		else
		{
			tmp_symbol_record = tmp_symbol_record->next;
		}
	}
 
	/*
	*	For Jam version 2, check that symbol is in scope
	*/
	if ((status == JAMC_SUCCESS) && (jam_version == 2))
	{
		if (jam_checking_uses_list &&
			((tmp_symbol_record->type == JAM_PROCEDURE_BLOCK) ||
			(tmp_symbol_record->type == JAM_DATA_BLOCK)))
		{
			/* ignore scope rules when validating USES list */
			status = JAMC_SUCCESS;
		}
		else
		if ((tmp_symbol_record->parent != NULL) &&
			(tmp_symbol_record->parent != jam_current_block) &&
			(tmp_symbol_record != jam_current_block))
		{
			JAMS_SYMBOL_RECORD *parent = tmp_symbol_record->parent;
			JAMS_HEAP_RECORD *heap_record = NULL;
			char *parent_name = NULL;
			char *uses_list = NULL;
 
			status = JAMC_SCOPE_ERROR;
 
			/*
			*	If the symbol in question is a procedure name, check that IT
			*	itself is in the uses list, instead of looking for its parent
			*/
			if (tmp_symbol_record->type == JAM_PROCEDURE_BLOCK)
			{
				parent = tmp_symbol_record;
			}
 
			if (parent != NULL)
			{
				parent_name = parent->name;
			}
 
			if ((jam_current_block != NULL) &&
				(jam_current_block->type == JAM_PROCEDURE_BLOCK))
			{
				heap_record = (JAMS_HEAP_RECORD *) jam_current_block->value;
 
				if (heap_record != NULL)
				{
					uses_list = (char *) heap_record->data;
				}
			}
 
			if ((uses_list != NULL) && (parent_name != NULL))
			{
				name_begin = 0;
				ch_index = 0;
				while ((uses_list[ch_index] != JAMC_NULL_CHAR) &&
					(status != JAMC_SUCCESS))
				{
					name_end = 0;
					while ((uses_list[ch_index] != JAMC_NULL_CHAR) &&
						(!jam_is_name_char(uses_list[ch_index])))
					{
						++ch_index;
					}
					if (jam_is_name_char(uses_list[ch_index]))
					{
						name_begin = ch_index;
					}
					while ((uses_list[ch_index] != JAMC_NULL_CHAR) &&
						(jam_is_name_char(uses_list[ch_index])))
					{
						++ch_index;
					}
					name_end = ch_index;
 
					if (name_end > name_begin)
					{
						save_ch = uses_list[name_end];
						uses_list[name_end] = JAMC_NULL_CHAR;
						if (jam_strcmp(&uses_list[name_begin],
							parent_name) == 0)
						{
							/* symbol is in scope */
							status = JAMC_SUCCESS;
						}
						uses_list[name_end] = save_ch;
					}
				}
			}
		}
	}
 
	if (status == JAMC_SUCCESS)
	{
		if (symbol_record == NULL)
		{
			status = JAMC_INTERNAL_ERROR;
		}
		else
		{
			*symbol_record = tmp_symbol_record;
		}
	}
	return (status);
}
 
/****************************************************************************/
/*																			*/
 
JAM_RETURN_TYPE jam_get_symbol_value
(
	JAME_SYMBOL_TYPE type,
	char *name,
	long *value
)
 
/*																			*/
/*	Description:	Gets the value of a symbol based on the name and		*/
/*					symbol type.											*/
/*																			*/
/*	Returns:		JAMC_SUCCESS for success, else JAMC_UNDEFINED_SYMBOL	*/
/*					if symbol is not found									*/
/*																			*/
/****************************************************************************/
{
	JAM_RETURN_TYPE status = JAMC_UNDEFINED_SYMBOL;
	JAMS_SYMBOL_RECORD *symbol_record = NULL;
 
	status = jam_get_symbol_record(name, &symbol_record);
 
	if ((status == JAMC_SUCCESS) && (symbol_record != NULL))
	{
		/*
		*	If type and name match, return the value
		*/
		if (symbol_record->type == type)
		{
			if (value != NULL)
			{
				*value = symbol_record->value;
			}
			else
			{
				status = JAMC_INTERNAL_ERROR;
			}
		}
		else
		{
			status = JAMC_TYPE_MISMATCH;
		}
	}
 
	return (status);
}
 
/****************************************************************************/
/*																			*/
 
JAM_RETURN_TYPE jam_set_symbol_value
(
	JAME_SYMBOL_TYPE type,
	char *name,
	long value
)
 
/*																			*/
/*	Description:	Assigns the value corresponding to a symbol, based on	*/
/*					the name and symbol type								*/
/*																			*/
/*	Returns:		JAMC_SUCCESS for success, else JAMC_UNDEFINED_SYMBOL	*/
/*					if symbol is not found									*/
/*																			*/
/****************************************************************************/
{
	JAM_RETURN_TYPE status = JAMC_UNDEFINED_SYMBOL;
	JAMS_SYMBOL_RECORD *symbol_record = NULL;
 
	status = jam_get_symbol_record(name, &symbol_record);
 
	if ((status == JAMC_SUCCESS) && (symbol_record != NULL))
	{
		/* check for matching type... */
		if (symbol_record->type == type)
		{
			symbol_record->value = value;
		}
		else
		{
			status = JAMC_TYPE_MISMATCH;
		}
	}
 
	return (status);
}
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.