changeset 564:87f904e2b304

Add offset and length operands (optional) to includebin This addition is based on a patch from Tim Lindner <tlindner@macmess.org>. While the original logic of the patch was not quite correct, the basic idea is. So with some edits to the logic, the feature goes in.
author William Astle <lost@l-w.ca>
date Thu, 21 Dec 2023 22:14:25 -0700
parents 8c6c3363e18e
children fc072f6cde09
files lwasm/instab.c lwasm/lwasm.c lwasm/lwasm.h lwasm/pseudo.c
diffstat 4 files changed, 94 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/lwasm/instab.c	Fri Dec 01 21:16:54 2023 -0700
+++ b/lwasm/instab.c	Thu Dec 21 22:14:25 2023 -0700
@@ -317,7 +317,7 @@
 #define pseudo_emit_export NULL
 
 PARSEFUNC(pseudo_parse_includebin);
-#define pseudo_resolve_includebin NULL
+RESOLVEFUNC(pseudo_resolve_includebin);
 EMITFUNC(pseudo_emit_includebin);
 
 PARSEFUNC(pseudo_parse_includestr);
--- a/lwasm/lwasm.c	Fri Dec 01 21:16:54 2023 -0700
+++ b/lwasm/lwasm.c	Thu Dec 21 22:14:25 2023 -0700
@@ -284,6 +284,8 @@
 		case E_COMPLEX_INCOMPLETE:      return "Incomplete expression too complex";
 		case E_USER_SPECIFIED:			return "User Specified:";
 		case E_ILL5:					return "Illegal 5 bit offset";
+		case E_INCLUDEBIN_ILL_START: 	return "Start value out of range";
+		case E_INCLUDEBIN_ILL_LENGTH:	return "Length value out of range";
 
 		case W_ENDSTRUCT_WITHOUT:		return "ENDSTRUCT without STRUCT";
 		case W_DUPLICATE_SECTION:		return "Section flags can only be specified the first time; ignoring duplicate definition";
--- a/lwasm/lwasm.h	Fri Dec 01 21:16:54 2023 -0700
+++ b/lwasm/lwasm.h	Thu Dec 21 22:14:25 2023 -0700
@@ -216,6 +216,8 @@
 	E_ORG_NOT_FOUND				= 57,
 	E_COMPLEX_INCOMPLETE        = 58,
 	E_ILL5						= 59,
+	E_INCLUDEBIN_ILL_START      = 60,
+	E_INCLUDEBIN_ILL_LENGTH     = 61,
 	
 	/* warnings must be 1000 or greater */
 
--- a/lwasm/pseudo.c	Fri Dec 01 21:16:54 2023 -0700
+++ b/lwasm/pseudo.c	Thu Dec 21 22:14:25 2023 -0700
@@ -1482,7 +1482,8 @@
 	FILE *fp;
 	long flen;
 	char *rfn;
-	
+	lw_expr_t e, e1;
+
 	if (!**p)
 	{
 		lwasm_register_error(as, l, E_FILENAME_MISSING);
@@ -1522,12 +1523,94 @@
 	fclose(fp);
 
 	l -> len = flen;
+
+	if (**p == ',')
+	{
+		(*p)++;
+		e = lwasm_parse_expr(as, p);
+
+		if (e)
+			lwasm_save_expr(l, 0, e);
+
+		if (**p == ',')
+		{
+			(*p)++;
+			e1 = lwasm_parse_expr(as, p);
+
+			if (e1)
+				lwasm_save_expr(l, 1, e1);
+		}
+	}
+}
+
+RESOLVEFUNC(pseudo_resolve_includebin)
+{
+	lw_expr_t e, e1, n;
+	int i = 0, i1;
+
+	e = lwasm_fetch_expr(l, 0);
+	e1 = lwasm_fetch_expr(l, 1);
+	
+	// if offset and/or length specified, make sure they've resolved
+	// before we do anything
+	if (e && !lw_expr_istype(e, lw_expr_type_int))
+		return;
+	if (e1 && !lwexpr_istype(e, lw_expr_type_int))
+		return;
+	if (e != NULL)
+	{
+		i = lw_expr_intval(e);
+
+		if (i < 0)
+			i = l -> len + i;
+	}
+	
+	i1 = l -> len - i;
+
+	e1 = lwasm_fetch_expr(l, 1);
+
+	if (e1 != NULL)
+	{
+		i1 = lw_expr_intval(e1);
+	}
+
+	if( i < 0 )
+	{
+		/* starting before file */
+		lwasm_register_error(as, l, E_INCLUDEBIN_ILL_START);
+		return;
+	}
+
+	if (i > l -> len)
+	{
+		/* starts past end of file */
+		lwasm_register_error(as, l, E_INCLUDEBIN_ILL_START);
+		return;
+	}
+
+	if (i1 < 0)
+	{
+		/* length is negative */
+		lwasm_register_error(as, l, E_INCLUDEBIN_ILL_LENGTH);
+		return;
+	}
+
+	if (i + i1 > l -> len)
+	{
+		/* read past end of file */
+		lwasm_register_error(as, l, E_INCLUDEBIN_ILL_LENGTH);
+		return;
+	}
+
+
+	l -> lint = i; // pass forward offset
+	l -> len = i1;
 }
 
 EMITFUNC(pseudo_emit_includebin)
 {
 	FILE *fp;
-	int c;
+	int c, i;
 	
 	fp = fopen(l -> lstr, "rb");
 	if (!fp)
@@ -1536,7 +1619,10 @@
 		return;
 	}
 	
-	for (;;)
+	// apply the specified offset
+	fseek(fp, l -> lint, SEEK_SET);
+
+	for (i=0; i < l -> len; i++)
 	{
 		c = fgetc(fp);
 		if (c == EOF)