mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 10:12:06 +00:00
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.
This commit is contained in:
@@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#include "asm/asm.h"
|
#include "asm/asm.h"
|
||||||
#include "asm/lexer.h"
|
#include "asm/lexer.h"
|
||||||
|
#include "asm/fstack.h"
|
||||||
#include "asm/macro.h"
|
#include "asm/macro.h"
|
||||||
#include "asm/main.h"
|
#include "asm/main.h"
|
||||||
#include "asm/rpn.h"
|
#include "asm/rpn.h"
|
||||||
@@ -230,6 +231,7 @@ static_assert(LEXER_BUF_SIZE <= SSIZE_MAX);
|
|||||||
struct Expansion {
|
struct Expansion {
|
||||||
struct Expansion *firstChild;
|
struct Expansion *firstChild;
|
||||||
struct Expansion *next;
|
struct Expansion *next;
|
||||||
|
char *name;
|
||||||
char const *contents;
|
char const *contents;
|
||||||
size_t len;
|
size_t len;
|
||||||
uint8_t distance; /* Distance between the beginning of this expansion and of its parent */
|
uint8_t distance; /* Distance between the beginning of this expansion and of its parent */
|
||||||
@@ -461,6 +463,7 @@ static struct Expansion *getExpansionAtDistance(size_t *distance)
|
|||||||
{
|
{
|
||||||
struct Expansion *expansion = lexerState->expansions;
|
struct Expansion *expansion = lexerState->expansions;
|
||||||
struct Expansion *prevLevel = NULL; /* Top level has no "previous" level */
|
struct Expansion *prevLevel = NULL; /* Top level has no "previous" level */
|
||||||
|
unsigned int depth = 0;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
/* Find the closest expansion whose end is after the target */
|
/* Find the closest expansion whose end is after the target */
|
||||||
@@ -481,10 +484,14 @@ static struct Expansion *getExpansionAtDistance(size_t *distance)
|
|||||||
/* Otherwise, register this expansion and repeat the process */
|
/* Otherwise, register this expansion and repeat the process */
|
||||||
prevLevel = expansion;
|
prevLevel = expansion;
|
||||||
expansion = expansion->firstChild;
|
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 *parent = getExpansionAtDistance(&distance);
|
||||||
struct Expansion **insertPoint = parent ? &parent->firstChild : &lexerState->expansions;
|
struct Expansion **insertPoint = parent ? &parent->firstChild : &lexerState->expansions;
|
||||||
@@ -498,6 +505,7 @@ static void beginExpansion(size_t distance, uint8_t skip, char const *str, size_
|
|||||||
fatalerror("Unable to allocate new expansion: %s", strerror(errno));
|
fatalerror("Unable to allocate new expansion: %s", strerror(errno));
|
||||||
(*insertPoint)->firstChild = NULL;
|
(*insertPoint)->firstChild = NULL;
|
||||||
(*insertPoint)->next = NULL; /* Expansions are always performed left to right */
|
(*insertPoint)->next = NULL; /* Expansions are always performed left to right */
|
||||||
|
(*insertPoint)->name = strdup(name);
|
||||||
(*insertPoint)->contents = str;
|
(*insertPoint)->contents = str;
|
||||||
(*insertPoint)->len = size;
|
(*insertPoint)->len = size;
|
||||||
(*insertPoint)->distance = distance;
|
(*insertPoint)->distance = distance;
|
||||||
@@ -513,6 +521,7 @@ static void freeExpansion(struct Expansion *expansion)
|
|||||||
do {
|
do {
|
||||||
struct Expansion *next = expansion->next;
|
struct Expansion *next = expansion->next;
|
||||||
|
|
||||||
|
free(expansion->name);
|
||||||
free(expansion);
|
free(expansion);
|
||||||
expansion = next;
|
expansion = next;
|
||||||
} while (expansion);
|
} while (expansion);
|
||||||
@@ -654,6 +663,8 @@ static void shiftChars(uint8_t distance)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* FIXME: this may not be too great, as only the top level is considered... */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The logic is as follows:
|
* The logic is as follows:
|
||||||
* - Any characters up to the expansion need to be consumed in the file
|
* - Any characters up to the expansion need to be consumed in the file
|
||||||
@@ -732,7 +743,37 @@ uint32_t lexer_GetColNo(void)
|
|||||||
|
|
||||||
void lexer_DumpStringExpansions(void)
|
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 */
|
/* Function to discard all of a line's comments */
|
||||||
@@ -1379,7 +1420,7 @@ static int yylex_NORMAL(void)
|
|||||||
if (sym && sym->type == SYM_EQUS) {
|
if (sym && sym->type == SYM_EQUS) {
|
||||||
char const *s = sym_GetStringValue(sym);
|
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 */
|
continue; /* Restart, reading from the new buffer */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1457,7 +1498,9 @@ static int yylex_SKIP_TO_ENDC(void)
|
|||||||
|
|
||||||
int yylex(void)
|
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->lineNo++;
|
||||||
lexerState->colNo = 0;
|
lexerState->colNo = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
4
test/asm/equs-newline.asm
Normal file
4
test/asm/equs-newline.asm
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
ACT equs "WARN \"First\"\nWARN \"Second\""
|
||||||
|
ACT
|
||||||
|
WARN "Third"
|
||||||
8
test/asm/equs-newline.err
Normal file
8
test/asm/equs-newline.err
Normal file
@@ -0,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
|
||||||
0
test/asm/equs-newline.out
Normal file
0
test/asm/equs-newline.out
Normal file
2
test/asm/equs-purge.asm
Normal file
2
test/asm/equs-purge.asm
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
BYE equs "PURGE BYE\nWARN \"Crash?\"\n \n"
|
||||||
|
BYE
|
||||||
3
test/asm/equs-purge.err
Normal file
3
test/asm/equs-purge.err
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
warning: test/asm/equs-purge.asm(0): [-Wuser]
|
||||||
|
Crash?
|
||||||
|
while expanding symbol "BYE"
|
||||||
0
test/asm/equs-purge.out
Normal file
0
test/asm/equs-purge.out
Normal file
Reference in New Issue
Block a user