shithub: rgbds

Download patch

ref: 61b2fd98160f3aa9f7f66f00273090412623002b
parent: 5ad7a9375076f1d352a9825379e0abee43c2fdfc
author: ISSOtm <[email protected]>
date: Tue Jul 28 20:39:18 EDT 2020

Add string expansion reporting

And fix line counting with expansion-made newlines.
This has the same bug as the old lexer (equs-newline's output does not
print the second warning as being part of the expansion).
Additionally, we regress equs-recursion, as we are no longer able to
catch this specific EQUS recursion. Simply enough, the new expansion
begins **after** the old one ends! I have found no way to handle that.

--- a/src/asm/lexer.c
+++ b/src/asm/lexer.c
@@ -25,6 +25,7 @@
 
 #include "asm/asm.h"
 #include "asm/lexer.h"
+#include "asm/fstack.h"
 #include "asm/macro.h"
 #include "asm/main.h"
 #include "asm/rpn.h"
@@ -230,6 +231,7 @@
 struct Expansion {
 	struct Expansion *firstChild;
 	struct Expansion *next;
+	char *name;
 	char const *contents;
 	size_t len;
 	uint8_t distance; /* Distance between the beginning of this expansion and of its parent */
@@ -461,6 +463,7 @@
 {
 	struct Expansion *expansion = lexerState->expansions;
 	struct Expansion *prevLevel = NULL; /* Top level has no "previous" level */
+	unsigned int depth = 0;
 
 	for (;;) {
 		/* Find the closest expansion whose end is after the target */
@@ -481,10 +484,14 @@
 		/* Otherwise, register this expansion and repeat the process */
 		prevLevel = expansion;
 		expansion = expansion->firstChild;
+
+		if (depth++ > nMaxRecursionDepth)
+			fatalerror("Recursion limit (%u) exceeded", nMaxRecursionDepth);
 	}
 }
 
-static void beginExpansion(size_t distance, uint8_t skip, char const *str, size_t size)
+static void beginExpansion(size_t distance, uint8_t skip,
+			   char const *str, size_t size, char const *name)
 {
 	struct Expansion *parent = getExpansionAtDistance(&distance);
 	struct Expansion **insertPoint = parent ? &parent->firstChild : &lexerState->expansions;
@@ -498,6 +505,7 @@
 		fatalerror("Unable to allocate new expansion: %s", strerror(errno));
 	(*insertPoint)->firstChild = NULL;
 	(*insertPoint)->next = NULL; /* Expansions are always performed left to right */
+	(*insertPoint)->name = strdup(name);
 	(*insertPoint)->contents = str;
 	(*insertPoint)->len = size;
 	(*insertPoint)->distance = distance;
@@ -513,6 +521,7 @@
 	do {
 		struct Expansion *next = expansion->next;
 
+		free(expansion->name);
 		free(expansion);
 		expansion = next;
 	} while (expansion);
@@ -654,6 +663,8 @@
 		}
 	}
 
+	/* FIXME: this may not be too great, as only the top level is considered... */
+
 	/*
 	 * The logic is as follows:
 	 * - Any characters up to the expansion need to be consumed in the file
@@ -732,7 +743,37 @@
 
 void lexer_DumpStringExpansions(void)
 {
-	/* TODO */
+	if (!lexerState)
+		return;
+	/* This is essentially a modified copy-paste of `getExpansionAtDistance(0)` */
+	struct Expansion *stack[nMaxRecursionDepth];
+
+	struct Expansion *expansion = lexerState->expansions;
+	unsigned int depth = 0;
+	size_t distance = lexerState->expansionOfs;
+
+	for (;;) {
+		/* Find the closest expansion whose end is after the target */
+		while (expansion && expansion->len - expansion->distance <= distance) {
+			distance -= expansion->skip;
+			expansion = expansion->next;
+		}
+
+		/* If there is none, or it begins after the target, return the previous level */
+		if (!expansion || expansion->distance > distance)
+			break;
+
+		/* We know we are inside of that expansion */
+		distance -= expansion->distance; /* Distances are relative to their parent */
+
+		stack[depth++] = expansion;
+		if (!expansion->firstChild)
+			break;
+		expansion = expansion->firstChild;
+	}
+
+	while (depth--)
+		fprintf(stderr, "while expanding symbol \"%s\"\n", stack[depth]->name);
 }
 
 /* Function to discard all of a line's comments */
@@ -1379,7 +1420,7 @@
 					if (sym && sym->type == SYM_EQUS) {
 						char const *s = sym_GetStringValue(sym);
 
-						beginExpansion(0, 0, s, strlen(s));
+						beginExpansion(0, 0, s, strlen(s), sym->name);
 						continue; /* Restart, reading from the new buffer */
 					}
 				}
@@ -1457,7 +1498,9 @@
 
 int yylex(void)
 {
-	if (lexerState->atLineStart) {
+	if (lexerState->atLineStart
+	/* Newlines read within an expansion should not increase the line count */
+	 && (!lexerState->expansions || lexerState->expansions->distance)) {
 		lexerState->lineNo++;
 		lexerState->colNo = 0;
 	}
--- /dev/null
+++ b/test/asm/equs-newline.asm
@@ -1,0 +1,4 @@
+
+ACT equs "WARN \"First\"\nWARN \"Second\""
+	ACT
+	WARN "Third"
--- /dev/null
+++ b/test/asm/equs-newline.err
@@ -1,0 +1,8 @@
+warning: test/asm/equs-newline.asm(2): [-Wuser]
+    First
+while expanding symbol "ACT"
+warning: test/asm/equs-newline.asm(3): [-Wuser]
+    Second
+while expanding symbol "ACT"
+warning: test/asm/equs-newline.asm(4): [-Wuser]
+    Third
--- /dev/null
+++ b/test/asm/equs-purge.asm
@@ -1,0 +1,2 @@
+BYE equs "PURGE BYE\nWARN \"Crash?\"\n    \n"
+BYE
--- /dev/null
+++ b/test/asm/equs-purge.err
@@ -1,0 +1,3 @@
+warning: test/asm/equs-purge.asm(0): [-Wuser]
+    Crash?
+while expanding symbol "BYE"