changeset 55:bad2ee25acdd

Added string comparison pseudo ops
author lost@l-w.ca
date Tue, 05 Apr 2011 23:59:41 -0600
parents 2077b755b8b4
children 337301ddf74a
files lwasm/instab.c lwasm/pseudo.c
diffstat 2 files changed, 459 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/lwasm/instab.c	Tue Apr 05 21:50:23 2011 -0600
+++ b/lwasm/instab.c	Tue Apr 05 23:59:41 2011 -0600
@@ -219,6 +219,10 @@
 #define pseudo_resolve_ifndef NULL
 #define pseudo_emit_ifndef NULL
 
+extern PARSEFUNC(pseudo_parse_ifstr);
+#define pseudo_resolve_ifstr NULL
+#define pseudo_emit_ifstr NULL
+
 extern PARSEFUNC(pseudo_parse_endc);
 #define pseudo_resolve_endc NULL
 #define pseudo_emit_endc NULL
@@ -608,6 +612,9 @@
 	{ "ifdef",		{	-1, 	-1, 	-1, 	-1},	pseudo_parse_ifdef,		pseudo_resolve_ifdef,			pseudo_emit_ifdef,			lwasm_insn_cond},
 	{ "ifndef",		{	-1, 	-1, 	-1, 	-1},	pseudo_parse_ifndef,	pseudo_resolve_ifndef,			pseudo_emit_ifndef,			lwasm_insn_cond},
 
+	// string operations, mostly useful in macros
+	{ "ifstr",		{	-1,		-1,		-1,		-1},	pseudo_parse_ifstr,		pseudo_resolve_ifstr,			pseudo_emit_ifstr,			lwasm_insn_cond},
+
 	{ "macro",		{	-1, 	-1, 	-1, 	-1}, 	pseudo_parse_macro,		pseudo_resolve_macro,			pseudo_emit_macro,			lwasm_insn_cond | lwasm_insn_setsym},
 	{ "endm",		{	-1, 	-1, 	-1, 	-1},	pseudo_parse_endm,		pseudo_resolve_endm,			pseudo_emit_endm,			lwasm_insn_cond | lwasm_insn_setsym | lwasm_insn_endm},
 
--- a/lwasm/pseudo.c	Tue Apr 05 21:50:23 2011 -0600
+++ b/lwasm/pseudo.c	Tue Apr 05 23:59:41 2011 -0600
@@ -22,6 +22,7 @@
 #include <stdio.h>
 #include <ctype.h>
 #include <string.h>
+#include <stdlib.h>
 
 #include <lw_alloc.h>
 
@@ -1161,3 +1162,454 @@
 		lwasm_emitexpr(l, e, 1);
 	}
 }
+
+/* string conditional argument parser */
+/*
+argument syntax:
+
+a bare word ended by whitespace, comma, or NUL
+a double quote delimited string containing arbitrary printable characters
+a single quote delimited string containing arbitrary printable characters
+
+In a double quoted string, a double quote cannot be represented.
+In a single quoted string, a single quote cannot be represented.
+
+*/
+char *strcond_parsearg(char **p)
+{
+	char *arg;
+	char *tstr;
+	int i;
+	tstr = *p;
+
+	if (!**p || isspace(**p))
+	{
+		return lw_strdup("");
+	}
+	
+	if (*tstr == '"')
+	{
+		// double quote delim
+		tstr++;
+		for (i = 0; tstr[i] && tstr[i] != '"'; i++)
+			/* do nothing */ ;
+		
+		arg = lw_alloc(i + 1);
+		strncpy(arg, tstr, i);
+		arg[i] = 0;
+		
+		if (tstr[i])
+			i++;
+		
+		*p += i;
+		return arg;
+	}
+	else if (*tstr == '\'')
+	{
+		// single quote delim
+		tstr++;
+		for (i = 0; tstr[i] && tstr[i] != '\''; i++)
+			/* do nothing */ ;
+		
+		arg = lw_alloc(i + 1);
+		strncpy(arg, tstr, i);
+		arg[i] = 0;
+		
+		if (tstr[i])
+			i++;
+		
+		*p += i;
+		return arg;
+	}
+	else
+	{
+		// bare word - whitespace or comma delim
+		for (i = 0; tstr[i] && !isspace(tstr[i]) && tstr[i] != ','; i++)
+			/* do nothing */ ;
+		
+		arg = lw_alloc(i + 1);
+		strncpy(arg, tstr, i);
+		arg[i] = 0;
+		if (tstr[i] == ',')
+			i++;
+		
+		*p += i;
+		return arg;
+	}
+}
+
+/* string conditional helpers */
+/* return "1" for true, "0" for false */
+int strcond_eq(char **p)
+{
+	char *arg1;
+	char *arg2;
+	int c = 0;
+		
+	arg1 = strcond_parsearg(p);
+	arg2 = strcond_parsearg(p);
+	
+	if (strcmp(arg1, arg2) == 0)
+		c = 1;
+	lw_free(arg1);
+	lw_free(arg2);
+	return c;
+}
+
+int strcond_ieq(char **p)
+{
+	char *arg1;
+	char *arg2;
+	int c = 0;
+		
+	arg1 = strcond_parsearg(p);
+	arg2 = strcond_parsearg(p);
+	
+	if (strcasecmp(arg1, arg2) == 0)
+		c = 1;
+	lw_free(arg1);
+	lw_free(arg2);
+	return c;
+}
+
+int strcond_ne(char **p)
+{
+	char *arg1;
+	char *arg2;
+	int c = 0;
+		
+	arg1 = strcond_parsearg(p);
+	arg2 = strcond_parsearg(p);
+	
+	if (strcmp(arg1, arg2) != 0)
+		c = 1;
+	lw_free(arg1);
+	lw_free(arg2);
+	return c;
+}
+
+int strcond_ine(char **p)
+{
+	char *arg1;
+	char *arg2;
+	int c = 0;
+		
+	arg1 = strcond_parsearg(p);
+	arg2 = strcond_parsearg(p);
+	
+	if (strcasecmp(arg1, arg2) != 0)
+		c = 1;
+	lw_free(arg1);
+	lw_free(arg2);
+	return c;
+}
+
+int strcond_peq(char **p)
+{
+	char *arg0;
+	char *arg1;
+	char *arg2;
+	int plen;
+	int c = 0;
+	
+	arg0 = strcond_parsearg(p);
+	arg1 = strcond_parsearg(p);
+	arg2 = strcond_parsearg(p);
+	
+	plen = strtol(arg0, NULL, 10);
+	if (strlen(arg1) > plen)
+		arg1[plen] = 0;
+	if (strlen(arg2) > plen)
+		arg2[plen] = 0;
+
+	if (strcmp(arg1, arg2) == 0)
+		c = 1;
+	lw_free(arg0);
+	lw_free(arg1);
+	lw_free(arg2);
+	return c;
+}
+
+int strcond_ipeq(char **p)
+{
+	char *arg0;
+	char *arg1;
+	char *arg2;
+	int plen;
+	int c = 0;
+	
+	arg0 = strcond_parsearg(p);
+	arg1 = strcond_parsearg(p);
+	arg2 = strcond_parsearg(p);
+	
+	plen = strtol(arg0, NULL, 10);
+	if (strlen(arg1) > plen)
+		arg1[plen] = 0;
+	if (strlen(arg2) > plen)
+		arg2[plen] = 0;
+
+	if (strcasecmp(arg1, arg2) == 0)
+		c = 1;
+	lw_free(arg0);
+	lw_free(arg1);
+	lw_free(arg2);
+	return c;
+}
+
+int strcond_pne(char **p)
+{
+	char *arg0;
+	char *arg1;
+	char *arg2;
+	int plen;
+	int c = 0;
+	
+	arg0 = strcond_parsearg(p);
+	arg1 = strcond_parsearg(p);
+	arg2 = strcond_parsearg(p);
+	
+	plen = strtol(arg0, NULL, 10);
+	if (strlen(arg1) > plen)
+		arg1[plen] = 0;
+	if (strlen(arg2) > plen)
+		arg2[plen] = 0;
+
+	if (strcmp(arg1, arg2) != 0)
+		c = 1;
+	lw_free(arg0);
+	lw_free(arg1);
+	lw_free(arg2);
+	return c;
+}
+
+int strcond_ipne(char **p)
+{
+	char *arg0;
+	char *arg1;
+	char *arg2;
+	int plen;
+	int c = 0;
+	
+	arg0 = strcond_parsearg(p);
+	arg1 = strcond_parsearg(p);
+	arg2 = strcond_parsearg(p);
+
+	plen = strtol(arg0, NULL, 10);
+	if (strlen(arg1) > plen)
+		arg1[plen] = 0;
+	if (strlen(arg2) > plen)
+		arg2[plen] = 0;
+
+	if (strcasecmp(arg1, arg2) != 0)
+		c = 1;
+	lw_free(arg0);
+	lw_free(arg1);
+	lw_free(arg2);
+	return c;
+}
+
+int strcond_seq(char **p)
+{
+	char *arg0;
+	char *arg1;
+	char *arg2;
+	char *rarg1;
+	char *rarg2;
+	
+	int plen;
+	int c = 0;
+	
+	arg0 = strcond_parsearg(p);
+	arg1 = strcond_parsearg(p);
+	arg2 = strcond_parsearg(p);
+	
+	rarg1 = arg1;
+	rarg2 = arg2;
+
+	plen = strtol(arg0, NULL, 10);
+	if (strlen(arg1) > plen)
+	{
+		rarg1 += strlen(arg1) - plen;
+	}
+	if (strlen(arg2) > plen)
+	{
+		rarg2 += strlen(arg2) - plen;
+	}
+	if (strcmp(rarg1, rarg2) == 0)
+		c = 1;
+	lw_free(arg0);
+	lw_free(arg1);
+	lw_free(arg2);
+	return c;
+}
+
+int strcond_iseq(char **p)
+{
+	char *arg0;
+	char *arg1;
+	char *arg2;
+	char *rarg1;
+	char *rarg2;
+	
+	int plen;
+	int c = 0;
+	
+	arg0 = strcond_parsearg(p);
+	arg1 = strcond_parsearg(p);
+	arg2 = strcond_parsearg(p);
+	
+	rarg1 = arg1;
+	rarg2 = arg2;
+		
+	plen = strtol(arg0, NULL, 10);
+	if (strlen(arg1) > plen)
+	{
+		rarg1 += strlen(arg1) - plen;
+	}
+	if (strlen(arg2) > plen)
+	{
+		rarg2 += strlen(arg2) - plen;
+	}
+	
+	if (strcasecmp(rarg1, rarg2) == 0)
+		c = 1;
+	lw_free(arg0);
+	lw_free(arg1);
+	lw_free(arg2);
+	return c;
+}
+
+
+int strcond_sne(char **p)
+{
+	char *arg0;
+	char *arg1;
+	char *arg2;
+	char *rarg1;
+	char *rarg2;
+	
+	int plen;
+	int c = 0;
+	
+	arg0 = strcond_parsearg(p);
+	arg1 = strcond_parsearg(p);
+	arg2 = strcond_parsearg(p);
+	
+	rarg1 = arg1;
+	rarg2 = arg2;
+		
+	plen = strtol(arg0, NULL, 10);
+	if (strlen(arg1) > plen)
+	{
+		rarg1 += strlen(arg1) - plen;
+	}
+	if (strlen(arg2) > plen)
+	{
+		rarg2 += strlen(arg2) - plen;
+	}
+	
+	if (strcmp(rarg1, rarg2) != 0)
+		c = 1;
+	lw_free(arg0);
+	lw_free(arg1);
+	lw_free(arg2);
+	return c;
+}
+
+int strcond_isne(char **p)
+{
+	char *arg0;
+	char *arg1;
+	char *arg2;
+	char *rarg1;
+	char *rarg2;
+	
+	int plen;
+	int c = 0;
+	
+	arg0 = strcond_parsearg(p);
+	arg1 = strcond_parsearg(p);
+	arg2 = strcond_parsearg(p);
+	
+	rarg1 = arg1;
+	rarg2 = arg2;
+		
+	plen = strtol(arg0, NULL, 10);
+	if (strlen(arg1) > plen)
+	{
+		rarg1 += strlen(arg1) - plen;
+	}
+	if (strlen(arg2) > plen)
+	{
+		rarg2 += strlen(arg2) - plen;
+	}
+	
+	if (strcasecmp(rarg1, rarg2) != 0)
+		c = 1;
+	lw_free(arg0);
+	lw_free(arg1);
+	lw_free(arg2);
+	return c;
+}
+
+/* string conditionals */
+PARSEFUNC(pseudo_parse_ifstr)
+{
+	static struct strconds
+	{
+		char *str;
+		int (*fn)(char **ptr);
+	} strops[] = {
+		{ "eq", strcond_eq },
+		{ "ieq", strcond_ieq },
+		{ "ne", strcond_ne },
+		{ "ine", strcond_ine },
+		{ "peq", strcond_peq },
+		{ "ipeq", strcond_ipeq },
+		{ "pne", strcond_pne },
+		{ "ipne", strcond_ipne },
+		{ "seq", strcond_seq },
+		{ "iseq", strcond_iseq },
+		{ "sne", strcond_sne },
+		{ "isne", strcond_isne },
+		{ NULL, 0 }
+	};
+	int tv = 0;
+	char *tstr;
+	int i, strop;
+	
+	l -> len = 0;
+	
+	if (as -> skipcond && !(as -> skipmacro))
+	{
+		as -> skipcount++;
+		skip_operand(p);
+		return;
+	}
+
+	tstr = strcond_parsearg(p);
+	if (!**p || isspace(**p))	
+	{
+		lwasm_register_error(as, l, "Bad string condition");
+		return;
+	}
+		
+	for (strop = 0; strops[strop].str != NULL; strop++)
+		if (strcasecmp(strops[strop].str, tstr) == 0)
+			break;
+	
+	lw_free(tstr);
+	
+	if (strops[strop].str == NULL)
+	{
+		lwasm_register_error(as, l, "Bad string condition");
+	}
+
+	tv = (*(strops[strop].fn))(p);
+	
+	if (!tv)
+	{
+		as -> skipcond = 1;
+		as -> skipcount = 1;
+	}
+}