shithub: rgbds

Download patch

ref: b3312886fb4b40ac4cb806d1a1410da35980c870
parent: 7fc8a65d0a428f8ee6978619ad4bd5b0acb64749
author: Rangi <remy.oukaour+rangi42@gmail.com>
date: Wed Apr 7 14:57:33 EDT 2021

Use a `lookupExpansion`, but not as an X macro

Instead of defining `LOOKUP_PRE_NEST` and `LOOKUP_POST_NEST`,
pass a variable name and a block to `lookupExpansion`; it
will assign successive looked-up expansions to the variable
and use them in the block.

The technique of using `__VA_ARGS__` to allow commas within a
block passed to a macro is not original, and should be stable.

--- a/src/asm/lexer.c
+++ b/src/asm/lexer.c
@@ -671,27 +671,37 @@
 		fatalerror("realloc error while resizing capture buffer: %s\n", strerror(errno));
 }
 
+/*
+ * A single { code block } is expected to be passed after `dist` and `exp`.
+ * This macro uses `__VA_ARGS__` so that the block can contain commas.
+ *
+ * `dist` is INTENDED to be mutable, since `getExpansionAtDistance` passes
+ * a dereferenced pointer to it.
+ */
+#define lookupExpansion(dist, exp, ...) do { \
+	for (struct Expansion *exp = lexerState->expansions; exp; exp = exp->firstChild) { \
+		/* Find the closest expansion whose end is after the target */ \
+		while (exp && exp->totalLen + exp->distance <= (dist)) { \
+			(dist) -= exp->totalLen + exp->skip; \
+			exp = exp->next; \
+		} \
+		/* If there is none, or it begins after the target, stop at the previous level */ \
+		if (!exp || exp->distance > (dist)) \
+			break; \
+		/* We know we are inside of that expansion */ \
+		(dist) -= exp->distance; /* Distances are relative to their parent */ \
+		/* Otherwise, do something with this expansion and repeat the process */ \
+		__VA_ARGS__ \
+	} \
+} while (0)
+
 static struct Expansion *getExpansionAtDistance(size_t *distance)
 {
 	struct Expansion *expansion = NULL; /* Top level has no "previous" level */
 
-	for (struct Expansion *exp = lexerState->expansions; exp; exp = exp->firstChild) {
-		/* Find the closest expansion whose end is after the target */
-		while (exp && exp->totalLen + exp->distance <= *distance) {
-			*distance -= exp->totalLen - exp->skip;
-			exp = exp->next;
-		}
-
-		/* If there is none, or it begins after the target, stop at previous level */
-		if (!exp || exp->distance > *distance)
-			break;
-
-		/* We know we are inside of that expansion */
-		*distance -= exp->distance; /* Distances are relative to their parent */
-
-		/* Otherwise, register this expansion and repeat the process */
+	lookupExpansion(*distance, exp, {
 		expansion = exp;
-	}
+	});
 
 	return expansion;
 }
@@ -711,21 +721,7 @@
 	struct Expansion *parent = NULL;
 	unsigned int depth = 0;
 
-	for (struct Expansion *exp = lexerState->expansions; exp; exp = exp->firstChild) {
-		/* Find the closest expansion whose end is after the target */
-		while (exp && exp->totalLen + exp->distance <= distance) {
-			distance -= exp->totalLen + exp->skip;
-			exp = exp->next;
-		}
-
-		/* If there is none, or it begins after the target, stop at the previous level */
-		if (!exp || exp->distance > distance)
-			break;
-
-		/* We know we are inside of that expansion */
-		distance -= exp->distance; /* Distances are relative to their parent */
-
-		/* Otherwise, register this expansion and repeat the process */
+	lookupExpansion(distance, exp, {
 		assert(exp->totalLen <= SIZE_MAX - (size - skip));
 		exp->totalLen += size - skip;
 		parent = exp;
@@ -732,7 +728,7 @@
 
 		if (name && depth++ >= nMaxRecursionDepth)
 			fatalerror("Recursion limit (%zu) exceeded\n", nMaxRecursionDepth);
-	}
+	});
 
 	struct Expansion **insertPoint = parent ? &parent->firstChild : &lexerState->expansions;
 
@@ -1037,24 +1033,11 @@
 	if (!stack)
 		fatalerror("Failed to alloc string expansion stack: %s\n", strerror(errno));
 
-	for (struct Expansion *exp = lexerState->expansions; exp; exp = exp->firstChild) {
-		/* Find the closest expansion whose end is after the target */
-		while (exp && exp->totalLen + exp->distance <= distance) {
-			distance -= exp->totalLen + exp->skip;
-			exp = exp->next;
-		}
-
-		/* If there is none, or it begins after the target, stop at the previous level */
-		if (!exp || exp->distance > distance)
-			break;
-
-		/* We know we are inside of that expansion */
-		distance -= exp->distance; /* Distances are relative to their parent */
-
+	lookupExpansion(distance, exp, {
 		/* Only register EQUS expansions, not string args */
 		if (exp->name)
 			stack[depth++] = exp;
-	}
+	});
 
 	while (depth--)
 		fprintf(stderr, "while expanding symbol \"%s\"\n", stack[depth]->name);