diff lwasm/pass1.c @ 345:7416c3f9c321

Basic macro processor ported forward; added context break handling for local symbols
author lost@starbug
date Thu, 25 Mar 2010 23:17:54 -0600
parents 0215a0fbf61b
children a82c55070624
line wrap: on
line diff
--- a/lwasm/pass1.c	Thu Mar 25 22:06:50 2010 -0600
+++ b/lwasm/pass1.c	Thu Mar 25 23:17:54 2010 -0600
@@ -59,6 +59,22 @@
 		line = input_readline(as);
 		if (!line)
 			break;
+		if (line[0] == 1 && line[1] == 1)
+		{
+			// special internal directive
+			// these DO NOT appear in the output anywhere
+			// they are generated by the parser to pass information
+			// forward
+			for (p1 = line + 2; *p1 && !isspace(*p1); p1++)
+				/* do nothing */ ;
+			*p1++ = '\0';
+			if (!strcmp(line + 2, "SETCONTEXT"))
+			{
+				as -> context = strtol(p1, NULL, 10);
+			}
+			lw_free(line);
+			continue;
+		}
 		printf("%s\n", line);
 		
 		cl = lw_alloc(sizeof(line_t));
@@ -84,12 +100,15 @@
 		as -> line_tail = cl;
 
 		// blank lines don't count for anything
+		// except a local symbol context break
 		if (!*line)
 		{
+			as -> context = lwasm_next_context(as);
 			goto nextline;
 		}
 	
 		// skip comments
+		// commends do not create a context break
 		if (*line == '*' || *line == ';' || *line == '#')
 			goto nextline;
 
@@ -105,9 +124,14 @@
 				p1++;
 		}
 
+		// blank line - context break
 		if (!*p1)
+		{
+			as -> context = lwasm_next_context(as);
 			goto nextline;
+		}
 
+		// comment - no context break
 		if (*p1 == '*' || *p1 == ';' || *p1 == '#')
 			goto nextline;
 
@@ -120,8 +144,14 @@
 		else
 			stspace = 0;
 
-		if (*p1 == '*' || *p1 == ';' || *p1 == '#' || !*p1)
+		if (*p1 == '*' || *p1 == ';' || *p1 == '#')
 			goto nextline;
+		if (!*p1)
+		{
+			// nothing but whitespace - context break
+			as -> context = lwasm_next_context(as);
+			goto nextline;
+		}
 
 		// find the end of the first token
 		for (tok = p1; *p1 && !isspace(*p1) && *p1 != ':'; p1++)
@@ -156,50 +186,77 @@
 				if (!strcasecmp(instab[opnum].opcode, sym))
 					break;
 			}
-			lw_free(sym);
 			
 			// p1 points to the start of the operand
 			
+			// if we're inside a macro definition and not at ENDM,
+			// add the line to the macro definition and continue
+			if (as -> inmacro && !(instab[opnum].flags & lwasm_insn_endm))
+			{
+				add_macro_line(as, line);
+				goto linedone;
+			}
+			
+			// if skipping a condition and the operation code doesn't
+			// operate within a condition (not a conditional)
+			// do nothing
+			if (as -> skipcond && !(instab[opnum].flags & lwasm_insn_cond))
+				goto linedone;
+        			
 			if (instab[opnum].opcode == NULL)
 			{
 				cl -> insn = -1;
 				if (*tok != ';' && *tok != '*')
 				{
 					// bad opcode; check for macro here
-					lwasm_register_error(as, cl, "Bad opcode");
+					if (expand_macro(as, cl, &p1, sym) != 0)
+					{
+						// macro expansion failed
+						lwasm_register_error(as, cl, "Bad opcode");
+					}
 				}
 			}
 			else
 			{
 				cl -> insn = opnum;
-				// call parse function
-				
-				if (*p1 && !isspace(*p1))
+				// no parse func means operand doesn't matter
+				if (instab[opnum].parse)
 				{
-					// flag bad operand error
-					lwasm_register_error(as, cl, "Bad operand (%s)", p1);
+					// call parse function
+					(instab[opnum].parse)(as, cl, &p1);
+					
+					if (*p1 && !isspace(*p1))
+					{
+						// flag bad operand error
+						lwasm_register_error(as, cl, "Bad operand (%s)", p1);
+					}
 				}
 			}
 		}
+	
+	linedone:
+		lw_free(sym);
 		
-		if (cl -> sym && cl -> symset == 0)
+		if (!as -> skipcond && !as -> inmacro)
 		{
-			printf("Register symbol %s:", sym);
+			if (cl -> sym && cl -> symset == 0)
+			{
+				printf("Register symbol %s:", sym);
+				lw_expr_print(cl -> addr);
+				printf("\n");
+	
+				// register symbol at line address
+				if (!register_symbol(as, cl, cl -> sym, cl -> addr, symbol_flag_none))
+				{
+					// symbol error
+					lwasm_register_error(as, cl, "Bad symbol '%s'", cl -> sym);
+				}
+			}
+		
 			lw_expr_print(cl -> addr);
 			printf("\n");
-
-			// register symbol at line address
-			if (!register_symbol(as, cl, cl -> sym, cl -> addr, symbol_flag_none))
-			{
-				// symbol error
-				lwasm_register_error(as, cl, "Bad symbol '%s'", cl -> sym);
-			}
 		}
 		
-		lw_expr_print(cl -> addr);
-		printf("\n");
-		// now parse the line
-		
 	nextline:
 		lw_free(line);
 	}