ref: 7dd8ba37f11d38fa6a45737922e6af1dbcc9b468
parent: 6842c831fdedec5deff3f1dc7fcca1465a4a9bd7
author: ISSOtm <eldredhabert0@gmail.com>
date: Sat Feb 5 07:15:32 EST 2022
Allow changing recursion depth limit at runtime
--- a/include/asm/fstack.h
+++ b/include/asm/fstack.h
@@ -77,6 +77,7 @@
void fstk_StopRept(void);
bool fstk_Break(void);
+void fstk_NewRecursionDepth(size_t newDepth);
void fstk_Init(char const *mainPath, size_t maxDepth);
#endif /* RGBDS_ASM_FSTACK_H */
--- a/include/asm/lexer.h
+++ b/include/asm/lexer.h
@@ -83,6 +83,7 @@
size_t size;
};
+void lexer_CheckRecursionDepth(void);
char const *lexer_GetFileName(void);
uint32_t lexer_GetLineNo(void);
uint32_t lexer_GetColNo(void);
--- a/src/asm/fstack.c
+++ b/src/asm/fstack.c
@@ -284,8 +284,9 @@
*/
static void newContext(struct FileStackNode *fileInfo)
{
- if (++contextDepth >= maxRecursionDepth)
- fatalerror("Recursion limit (%zu) exceeded\n", maxRecursionDepth);
+ ++contextDepth;
+ fstk_NewRecursionDepth(maxRecursionDepth); // Only checks if the max depth was exceeded
+
struct Context *context = malloc(sizeof(*context));
if (!context)
@@ -505,6 +506,13 @@
fstk_StopRept();
return true;
+}
+
+void fstk_NewRecursionDepth(size_t newDepth)
+{
+ if (contextDepth >= newDepth)
+ fatalerror("Recursion limit (%zu) exceeded\n", newDepth);
+ maxRecursionDepth = newDepth;
}
void fstk_Init(char const *mainPath, size_t maxDepth)
--- a/src/asm/lexer.c
+++ b/src/asm/lexer.c
@@ -668,15 +668,9 @@
if (!size)
return;
- if (name) {
- size_t depth = 0;
+ if (name)
+ lexer_CheckRecursionDepth();
- for (struct Expansion *exp = lexerState->expansions; exp; exp = exp->parent) {
- if (depth++ >= maxRecursionDepth)
- fatalerror("Recursion limit (%zu) exceeded\n", maxRecursionDepth);
- }
- }
-
struct Expansion *exp = malloc(sizeof(*exp));
if (!exp)
@@ -690,6 +684,16 @@
exp->owned = owned;
lexerState->expansions = exp;
+}
+
+void lexer_CheckRecursionDepth(void)
+{
+ size_t depth = 0;
+
+ for (struct Expansion *exp = lexerState->expansions; exp; exp = exp->parent) {
+ if (depth++ >= maxRecursionDepth)
+ fatalerror("Recursion limit (%zu) exceeded\n", maxRecursionDepth);
+ }
}
static void freeExpansion(struct Expansion *expansion)
--- a/src/asm/opt.c
+++ b/src/asm/opt.c
@@ -1,3 +1,4 @@
+#include <ctype.h>
#include <errno.h>
#include <stdbool.h>
#include <stdint.h>
@@ -5,6 +6,7 @@
#include <stdlib.h>
#include <string.h>
+#include "asm/fstack.h"
#include "asm/lexer.h"
#include "asm/main.h"
#include "asm/section.h"
@@ -17,6 +19,7 @@
bool haltnop;
bool optimizeLoads;
bool warningsAreErrors;
+ size_t maxRecursionDepth;
// Don't be confused: we use the size of the **global variable** `warningStates`!
enum WarningState warningStates[sizeof(warningStates)];
struct OptStackEntry *next;
@@ -39,6 +42,12 @@
fillByte = fill;
}
+void opt_R(size_t newDepth)
+{
+ fstk_NewRecursionDepth(newDepth);
+ lexer_CheckRecursionDepth();
+}
+
void opt_h(bool halt)
{
haltnop = halt;
@@ -85,6 +94,29 @@
error("Invalid argument for option 'p'\n");
}
break;
+
+ case 'r': {
+ ++s; // Skip 'r'
+ while (isblank(*s))
+ ++s; // Skip leading whitespace
+
+ if (s[0] == '\0') {
+ error("Missing argument to option 'r'\n");
+ break;
+ }
+
+ char *endptr;
+ unsigned long newDepth = strtoul(s, &endptr, 10);
+
+ if (*endptr != '\0') {
+ error("Invalid argument to option 'r' (\"%s\")\n", s);
+ } else if (errno == ERANGE) {
+ error("Argument to 'r' is out of range (\"%s\")\n", s);
+ } else {
+ opt_R(newDepth);
+ }
+ break;
+ }
case 'h':
if (s[1] == '\0')
--- a/src/asm/rgbasm.5
+++ b/src/asm/rgbasm.5
@@ -1993,6 +1993,7 @@
.Ss Changing options while assembling
.Ic OPT
can be used to change some of the options during assembling from within the source, instead of defining them on the command-line.
+.Pq See Xr rgbasm 1 .
.Pp
.Ic OPT
takes a comma-separated list of options as its argument:
@@ -2008,8 +2009,10 @@
LD [$FF88], A ; optimized to use LDH by default
.Ed
.Pp
-The options that OPT can modify are currently:
-.Cm b , g , p , h , L ,
+The options that
+.Ic OPT
+can modify are currently:
+.Cm b , g , p , r , h , L ,
and
.Cm W .
The Boolean flag options
--- /dev/null
+++ b/test/asm/opt-r.asm
@@ -1,0 +1,13 @@
+OPT r34 ; :3
+OPT r 360
+
+; Invalid
+OPT r ; Missing arg
+OPT r 2a ; Bad decimal
+
+; Check that it has an effect
+OPT r 1
+MACRO m
+ m
+ENDM
+ m
--- /dev/null
+++ b/test/asm/opt-r.err
@@ -1,0 +1,6 @@
+error: opt-r.asm(5):
+ Missing argument to option 'r'
+error: opt-r.asm(6):
+ Invalid argument to option 'r' ("2a")
+FATAL: opt-r.asm(13):
+ Recursion limit (1) exceeded