diff src/symtab.c @ 0:57495da01900

Initial checking of LWASM
author lost
date Fri, 03 Oct 2008 02:44:20 +0000
parents
children 34568fab6058
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/symtab.c	Fri Oct 03 02:44:20 2008 +0000
@@ -0,0 +1,97 @@
+/*
+ * symtab.c
+ *
+ * main code for lwasm
+ */
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#define __symtab_c_seen__
+#include "lwasm.h"
+
+void register_symbol(asmstate_t *as, sourceline_t *cl, char *symstr, int val, int flags)
+{
+	symtab_t *st;
+	symtab_t *prev;
+	int cv = -2;
+	
+	for (prev = NULL, st = as -> symbol_table; st; st = st -> next)
+	{
+		cv = strcasecmp(st -> symbol, symstr);
+		if (cv == 0)
+		{
+			cv = strcmp(st -> symbol, symstr);
+		}
+		if (cv >= 0)
+			break;
+		prev = st;
+	}
+	// cv is 0 if we found the symbol, > 0 if we didn't and found one
+	// later in order, or -2 if we never did a comparison
+	// if st is NULL, the value of cv is irrelevant as it means
+	// we fell off the end of the list
+	// if st is NULL and prev is not, then prev is the tail of the list
+	// if both are NULL, the list is empty
+	
+	// handle adding the symbol if needed
+	if (!st || cv != 0)
+	{
+		symtab_t *st2;
+		// register the symbol
+		st2 = malloc(sizeof(symtab_t));
+		st2 -> symbol = strdup(symstr);
+		st2 -> addr = val;
+		st2 -> flags = 0;
+		if (flags & SYMFLAG_SET)
+			st2 -> flags |= SYMFLAG_SET;
+
+		if (prev)
+			prev -> next = st2;
+		else
+			as -> symbol_table = st2;
+		
+		st2 -> next = st;
+		return;
+	}
+	
+	// st is NOT NULL here and cv IS 0
+	if ((flags & SYMFLAG_SET) && ((st -> flags) & SYMFLAG_SET))
+	{
+		// symbol already exists but it is a "SET" symbol so reset the value
+		st -> addr = val;
+		return;
+	}
+	if (st && as -> passnum == 1)
+	{
+		// duplicate symbol, flag error
+		errorp1(ERR_DUPSYM);
+	}
+	if (st -> addr != val)
+		errorp2(ERR_PHASE);
+}
+
+int lookup_symbol(asmstate_t *as, char *symstr)
+{
+	symtab_t *st;
+
+	for (st = as -> symbol_table; st; st = st -> next)
+	{
+		if (!strcmp(symstr, st -> symbol))
+			break;
+	}
+	if (st)
+		return st -> addr;
+	return -1;
+}
+
+void list_symbols(asmstate_t *as, FILE *f)
+{
+	symtab_t *st;
+	for (st = as -> symbol_table; st; st = st -> next)
+	{
+		fprintf(f, "%04X %s%s\n", st -> addr, st -> symbol, (st -> flags & SYMFLAG_SET) ? "(S)" : "");
+	}
+}