changeset 143:0ee5f65bccf9

Added pragma to allow all undefined symbols to be considered external and also added a --pragma command line option
author lost
date Thu, 29 Jan 2009 01:32:11 +0000
parents 36ca3fa755e0
children 006d737756fd
files src/lwasm.c src/lwasm.h src/main.c src/pragma.c src/symbol.c
diffstat 5 files changed, 68 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/src/lwasm.c	Wed Jan 28 06:06:05 2009 +0000
+++ b/src/lwasm.c	Thu Jan 29 01:32:11 2009 +0000
@@ -40,6 +40,9 @@
 	char errbuff[1024];
 	int r;
 	
+	if (!l)
+		return;
+
 	if (as -> passnum != pass)
 		return;
 	
--- a/src/lwasm.h	Wed Jan 28 06:06:05 2009 +0000
+++ b/src/lwasm.h	Thu Jan 29 01:32:11 2009 +0000
@@ -178,7 +178,10 @@
 	sectiontab_t *csect;		// current section - NULL if not in one
 } asmstate_t;
 
+// do not rewrite XXX,r to ,r if XXX evaluates to 0
 #define PRAGMA_NOINDEX0TONONE	1
+// any undefined symbols are considered external
+#define PRAGMA_UNDEFEXTERN	2
 
 #ifndef __lwasm_c_seen__
 #define __lwasm_E__ extern
--- a/src/main.c	Wed Jan 28 06:06:05 2009 +0000
+++ b/src/main.c	Thu Jan 29 01:32:11 2009 +0000
@@ -38,6 +38,7 @@
 extern void lwasm_pass2(asmstate_t *as);
 extern void lwasm_list(asmstate_t *as);
 extern void lwasm_output(asmstate_t *as);
+extern void pseudo_pragma_real(asmstate_t *as, lwasm_line_t *cl, char **optr, int error);
 
 // command line option handling
 const char *argp_program_version = "LWASM from " PACKAGE_STRING;
@@ -46,6 +47,7 @@
 static error_t parse_opts(int key, char *arg, struct argp_state *state)
 {
 	asmstate_t *as = state -> input;
+	char *p;
 	
 	switch (key)
 	{
@@ -99,6 +101,18 @@
 			exit(1);
 		}
 		break;
+	
+	case 'p':
+		// pragmas
+		p = arg;
+		pseudo_pragma_real(as, NULL, &p, 2);
+		if (!p)
+		{
+			fprintf(stderr, "Invalid pragma string: %s\n", arg);
+			exit(1);
+		}
+		break;
+
 	case ARGP_KEY_END:
 		// done; sanity check
 		if (!as -> outfile)
@@ -134,6 +148,8 @@
 				"Generate raw binary format output, equivalent of --format=raw"},
 	{ "obj",		0x100,		0,		0,
 				"Generate proprietary object file format for later linking, equivalent of --format=obj" },
+	{ "pragma",		'p',	"PRAGMA",	0,
+				"Set an assembler pragma to any value understood by the \"pragma\" pseudo op"},
 	{ 0 }
 };
 
--- a/src/pragma.c	Wed Jan 28 06:06:05 2009 +0000
+++ b/src/pragma.c	Thu Jan 29 01:32:11 2009 +0000
@@ -76,6 +76,10 @@
 		{
 			register_error(as, cl, 1, "Unrecognized pragma");
 		}
+		if (error == 2)
+		{
+			*optr = NULL;
+		}
 		return;
 	}
 	pragma[c] = 0;
@@ -87,11 +91,23 @@
 	{
 		as -> pragmas &= ~PRAGMA_NOINDEX0TONONE;
 	}
+	else if (!strcmp(pragma, "undefextern"))
+	{
+		as -> pragmas |= PRAGMA_UNDEFEXTERN;
+	}
+	else if (!strcmp(pragma, "noundefextern"))
+	{
+		as -> pragmas &= ~PRAGMA_UNDEFEXTERN;
+	}
 	else
 	{
 		if (error)
 		{
 			register_error(as, cl, 1, "Unrecognized pragma");
+			if (error == 2)
+			{
+				*optr = NULL;
+			}
 		}
 	}
 }
--- a/src/symbol.c	Wed Jan 28 06:06:05 2009 +0000
+++ b/src/symbol.c	Thu Jan 29 01:32:11 2009 +0000
@@ -138,7 +138,12 @@
 		se -> expr = l -> exprs[0];
 	se -> sym = lwasm_strdup(sym);
 	se -> context = scontext;
-	se -> sect = as -> csect;
+
+	if (!(flags & SYMBOL_EXTERN))
+		se -> sect = as -> csect;
+	else
+		se -> sect = NULL;
+
 	se -> expr = NULL;
 	se -> flags = flags;
 	se -> externalname = NULL;
@@ -149,6 +154,7 @@
 lwasm_symbol_ent_t *lwasm_find_symbol(asmstate_t *as, char *sym, int scontext)
 {
 	lwasm_symbol_ent_t *se;
+	static int st = 0;
 	
 	for (se = as -> symhead; se; se = se -> next)
 	{
@@ -157,6 +163,29 @@
 			return se;
 		}
 	}
+	if (as -> passnum == 2 && st == 0 && scontext == -1 && as -> outformat == OUTPUT_OBJ && as -> pragmas & PRAGMA_UNDEFEXTERN)
+	{
+		// we want undefined symbols to be considered external
+		// we didn't find it on a lookup so register it as external
+		// but we only do so when looking up in global context
+		st = 1;
+		if (lwasm_register_symbol(as, NULL, sym, 0, SYMBOL_EXTERN))
+		{
+			st = 0;
+			return NULL;
+		}
+		st = 0;
+		
+		// find the newly registered symbol and return it
+		for (se = as -> symhead; se; se = se -> next)
+		{
+			if (scontext == se -> context && !strcmp(sym, se -> sym))
+			{
+				return se;
+			}
+		}
+	}
+		
 	return NULL;
 }