diff lwasm/pseudo.c @ 356:7166254491ed

Finished pseudo ops
author lost@starbug
date Wed, 31 Mar 2010 18:46:32 -0600
parents 60568b123281
children d96c30e60ddf
line wrap: on
line diff
--- a/lwasm/pseudo.c	Tue Mar 30 23:12:41 2010 -0600
+++ b/lwasm/pseudo.c	Wed Mar 31 18:46:32 2010 -0600
@@ -21,8 +21,11 @@
 
 #include <config.h>
 
+#include <stdio.h>
+
 #include "lwasm.h"
 #include "instab.h"
+#include "input.h"
 
 #include "lw_string.h"
 
@@ -912,3 +915,188 @@
 	lwasm_register_error(as, l, "User error: %s", *p);
 	skip_operand(p);
 }
+
+PARSEFUNC(pseudo_parse_includebin)
+{
+	char *fn, *p2;
+	int delim = 0;
+	FILE *fp;
+	long flen;
+	
+	if (!**p)
+	{
+		lwasm_register_error(as, l, "Missing filename");
+		return;
+	}
+	
+	if (**p == '"' || **p == '\'')
+	{
+		delim = **p;
+		(*p)++;
+
+		for (p2 = *p; *p2 && *p2 != delim; p2++)
+			/* do nothing */ ;
+	}
+	else
+	{
+		for (p2 = *p; *p2 && !isspace(*p2); p2++)
+			/* do nothing */ ;
+	}
+	fn = lw_strndup(*p, p2 - *p);
+	
+	if (delim && **p)
+		(*p)++;
+	
+	fp = input_open_standalone(as, fn);
+	if (!fp)
+	{
+		lwasm_register_error(as, l, "Cannot open file");
+		lw_free(fn);
+		return;
+	}
+	
+	l -> lstr = fn;
+	
+	fseek(fp, 0, SEEK_END);
+	flen = ftell(fp);
+	fclose(fp);
+
+	l -> len = flen;
+}
+
+EMITFUNC(pseudo_emit_includebin)
+{
+	FILE *fp;
+	int c;
+	
+	fp = input_open_standalone(as, l -> lstr);
+	if (!fp)
+	{
+		lwasm_register_error(as, l, "Cannot open file (emit)!");
+		return;
+	}
+	
+	for (;;)
+	{
+		c = fgetc(fp);
+		if (c == EOF)
+		{
+			fclose(fp);
+			return;
+		}
+		lwasm_emit(l, c);
+	}
+}
+
+PARSEFUNC(pseudo_parse_include)
+{
+	char *fn, *p2;
+	int delim = 0;
+	
+	if (!**p)
+	{
+		lwasm_register_error(as, l, "Missing filename");
+		return;
+	}
+	
+	if (**p == '"' || **p == '\'')
+	{
+		delim = **p;
+		(*p)++;
+
+		for (p2 = *p; *p2 && *p2 != delim; p2++)
+			/* do nothing */ ;
+	}
+	else
+	{
+		for (p2 = *p; *p2 && !isspace(*p2); p2++)
+			/* do nothing */ ;
+	}
+	fn = lw_strndup(*p, p2 - *p);
+	
+	if (delim && **p)
+		(*p)++;
+	
+	input_open(as, fn);
+
+	l -> len = 0;
+}
+
+PARSEFUNC(pseudo_parse_align)
+{
+	lw_expr_t e;
+	
+	if (!**p)
+	{
+		lwasm_register_error(as, l, "Bad operand");
+		return;
+	}
+	
+	e = lwasm_parse_expr(as, p);
+	if (!e)
+	{
+		lwasm_register_error(as, l, "Bad operand");
+		return;
+	}
+	
+	lwasm_save_expr(l, 0, e);
+	
+	if (**p == ',')
+	{
+		e = lwasm_parse_expr(as, p);
+	}
+	else
+	{
+		e = lw_expr_build(lw_expr_type_int, 0);
+	}
+	if (!e)
+	{
+		lwasm_register_error(as, l, "Bad padding");
+		return;
+	}
+	
+	lwasm_save_expr(l, 1, e);
+}
+
+RESOLVEFUNC(pseudo_resolve_align)
+{
+	lw_expr_t e;
+	int align;
+
+	e = lwasm_fetch_expr(l, 0);
+	
+	if (lw_expr_istype(e, lw_expr_type_int))
+	{
+		align = lw_expr_intval(e);
+		if (align < 1)
+		{
+			lwasm_register_error(as, l, "Invalid alignment");
+			return;
+		}
+	}
+	
+	if (lw_expr_istype(l -> addr, lw_expr_type_int))
+	{
+		int a;
+		a = lw_expr_intval(l -> addr);
+		if (a % align == 0)
+		{
+			l -> len = 0;
+			return;
+		}
+		l -> len = align - (a % align);
+		return;
+	}
+}
+
+EMITFUNC(pseudo_emit_align)
+{
+	lw_expr_t e;
+	int i;
+	
+	e = lwasm_fetch_expr(l, 1);
+	for (i = 0; i < l -> len; i++)
+	{
+		lwasm_emitexpr(l, e, 1);
+	}
+}