diff src/macro.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/macro.c	Fri Oct 03 02:44:20 2008 +0000
@@ -0,0 +1,215 @@
+/*
+ * macro.c
+ *
+ * stuff associated with macro processing
+ */
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include "lwasm.h"
+
+extern void resolve_insn(asmstate_t *as, sourceline_t *cl);
+
+void pseudo_macro(asmstate_t *as, sourceline_t *cl, char **optr)
+{
+	macrotab_t *m;
+
+	if (as -> inmacro)
+	{
+		errorp1(ERR_MACRO);
+		return;
+	}
+	as -> inmacro = 1;
+	if (as -> passnum != 1)
+		return;
+	
+	for (m = as -> macros; m; m = m -> next)
+	{
+		if (!strcmp(m -> name, cl -> symstr))
+			break;
+	}
+	if (m)
+	{
+		errorp1(ERR_DUPSYM);
+		return;
+	}
+	m = calloc(sizeof(macrotab_t), 1);
+	m -> name = strdup(cl -> symstr);
+	m -> next = as -> macros;
+	as -> macros = m;
+	cl -> hassym = 0;
+	while (**optr && !isspace(**optr))
+		(*optr)++;
+	cl -> macrodef = 1;
+}
+
+void pseudo_endm(asmstate_t *as, sourceline_t *cl, char **optr)
+{
+	if (!as -> inmacro)
+	{
+		errorp1(ERR_ENDM);
+		return;
+	}
+	
+	as -> inmacro = 0;
+	cl -> macrodef = 1;
+}
+
+int add_macro_line(asmstate_t *as, sourceline_t *cl, char *optr)
+{
+	macroline_t *l;
+	
+	if (!as -> inmacro)
+		return 0;
+	
+	if (as -> passnum == 2)
+		return 1;
+
+	l = calloc(sizeof(macroline_t), 1);
+	l -> linetext = strdup(optr);
+	if (as -> macros -> linetail)
+		as -> macros -> linetail -> next = l;
+	as -> macros -> linetail = l;
+	if (!(as -> macros -> linehead))
+		as -> macros -> linehead = l;
+	return 1;
+}
+
+void macro_add_to_buff(char **buff, int *loc, int *len, char c)
+{
+	if (*loc == *len)
+	{
+		*buff = realloc(*buff, *len + 32);
+		*len += 32;
+	}
+	(*buff)[(*loc)++] = c;
+}
+
+// this is just like a regular operation function
+/*
+macro args are references by "\n" where 1 <= n <= 9
+or by "\{n}"; a \ can be included by writing \\
+*/
+void expand_macro(asmstate_t *as, sourceline_t *cl, char **optr)
+{
+	char **args = NULL;
+	int nargs = 0;
+	int c;
+	sourceline_t *nl;
+	int nline = 1;
+	macrotab_t *m;
+	macroline_t *ml;
+	char *buff = NULL;
+	int bufflen = 0, buffloc;
+	
+	m = cl -> macro;
+	
+	// step the first: parse arguments
+	while (**optr && !isspace(**optr))
+	{
+		c = 0;
+		while ((*optr)[c] && !isspace((*optr)[c]) && (*optr)[c] != ',')
+		{
+			c++;
+		}
+		args = realloc(args, sizeof(char *) * (nargs + 1));
+		args[nargs] = malloc(c + 1);
+		strncpy(args[nargs], *optr, c);
+		args[nargs][c] = '\0';
+		nargs++;
+		*optr += c;
+		if (**optr == ',')
+			(*optr)++;
+	}
+	
+	// step the second: iterate over the lines and expand arguments and add
+	// them after "cl"
+	for (ml = m -> linehead; ml; ml = ml -> next)
+	{
+		nl = calloc(sizeof(sourceline_t), 1);
+		
+		nl -> lineno = nline++;
+		nl -> sourcefile = m -> name;
+		nl -> opcode = -1;
+		nl -> addrmode = -1;
+		nl -> addr = as -> addr;
+		nl -> dpval = as -> dpval;
+		nl -> prev = cl;
+		if (!(cl -> next))
+			as -> source_tail = nl;
+		nl -> next = cl -> next;
+		cl -> next = nl;
+
+		buffloc = 0;
+		c = 0;
+		while (ml -> linetext[c])
+		{
+			int ch;
+			ch = ml -> linetext[c++];
+			if (ch == '{')
+			{
+				int v = 0;
+			again:
+				ch = ml -> linetext[c++];
+				if (!ch)
+				{
+					c--;
+					continue;
+				}
+				if (ch >= '0' && ch <= '9')
+				{
+					v = v * 10 + (ch - '0');
+					goto again;
+				}
+				if (ch == '}')
+				{
+					v--;
+					if (v < nargs)
+					{
+						char *t;
+						for (t = args[v]; *t; t++)
+						{
+							macro_add_to_buff(&buff, &buffloc, &bufflen, *t);
+						}
+					}
+					continue;
+				}
+				else
+					continue;
+			}
+			else if (ch == '\\' && ml -> linetext[c])
+			{
+				ch = ml -> linetext[c++];
+				if (ch >= '1' && ch <= '9')
+				{
+					ch -= '1';
+					if (ch < nargs)
+					{
+						char *t;
+						for (t = args[ch]; *t; t++)
+						{
+							macro_add_to_buff(&buff, &buffloc, &bufflen, *t);
+						}
+					}
+				}
+				else
+				{
+					c--;
+					macro_add_to_buff(&buff, &buffloc, &bufflen, '\\');
+				}
+			}
+			else
+			{
+				macro_add_to_buff(&buff, &buffloc, &bufflen, ch);
+			}
+		}
+		macro_add_to_buff(&buff, &buffloc, &bufflen, 0);
+		nl -> line = strdup(buff);
+
+		resolve_insn(as, nl);
+		cl = nl;
+	}
+	if (buff)
+		free(buff);
+}