mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 10:12:06 +00:00
Allow changing recursion depth limit at runtime
This commit is contained in:
@@ -77,6 +77,7 @@ void fstk_RunFor(char const *symName, int32_t start, int32_t stop, int32_t step,
|
|||||||
void fstk_StopRept(void);
|
void fstk_StopRept(void);
|
||||||
bool fstk_Break(void);
|
bool fstk_Break(void);
|
||||||
|
|
||||||
|
void fstk_NewRecursionDepth(size_t newDepth);
|
||||||
void fstk_Init(char const *mainPath, size_t maxDepth);
|
void fstk_Init(char const *mainPath, size_t maxDepth);
|
||||||
|
|
||||||
#endif /* RGBDS_ASM_FSTACK_H */
|
#endif /* RGBDS_ASM_FSTACK_H */
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ struct CaptureBody {
|
|||||||
size_t size;
|
size_t size;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void lexer_CheckRecursionDepth(void);
|
||||||
char const *lexer_GetFileName(void);
|
char const *lexer_GetFileName(void);
|
||||||
uint32_t lexer_GetLineNo(void);
|
uint32_t lexer_GetLineNo(void);
|
||||||
uint32_t lexer_GetColNo(void);
|
uint32_t lexer_GetColNo(void);
|
||||||
|
|||||||
@@ -284,8 +284,9 @@ bool yywrap(void)
|
|||||||
*/
|
*/
|
||||||
static void newContext(struct FileStackNode *fileInfo)
|
static void newContext(struct FileStackNode *fileInfo)
|
||||||
{
|
{
|
||||||
if (++contextDepth >= maxRecursionDepth)
|
++contextDepth;
|
||||||
fatalerror("Recursion limit (%zu) exceeded\n", maxRecursionDepth);
|
fstk_NewRecursionDepth(maxRecursionDepth); // Only checks if the max depth was exceeded
|
||||||
|
|
||||||
struct Context *context = malloc(sizeof(*context));
|
struct Context *context = malloc(sizeof(*context));
|
||||||
|
|
||||||
if (!context)
|
if (!context)
|
||||||
@@ -507,6 +508,13 @@ bool fstk_Break(void)
|
|||||||
return true;
|
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)
|
void fstk_Init(char const *mainPath, size_t maxDepth)
|
||||||
{
|
{
|
||||||
struct LexerState *state = lexer_OpenFile(mainPath);
|
struct LexerState *state = lexer_OpenFile(mainPath);
|
||||||
|
|||||||
@@ -668,14 +668,8 @@ static void beginExpansion(char const *str, bool owned, char const *name)
|
|||||||
if (!size)
|
if (!size)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (name) {
|
if (name)
|
||||||
size_t depth = 0;
|
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));
|
struct Expansion *exp = malloc(sizeof(*exp));
|
||||||
|
|
||||||
@@ -692,6 +686,16 @@ static void beginExpansion(char const *str, bool owned, char const *name)
|
|||||||
lexerState->expansions = exp;
|
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)
|
static void freeExpansion(struct Expansion *expansion)
|
||||||
{
|
{
|
||||||
free(expansion->name);
|
free(expansion->name);
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@@ -5,6 +6,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "asm/fstack.h"
|
||||||
#include "asm/lexer.h"
|
#include "asm/lexer.h"
|
||||||
#include "asm/main.h"
|
#include "asm/main.h"
|
||||||
#include "asm/section.h"
|
#include "asm/section.h"
|
||||||
@@ -17,6 +19,7 @@ struct OptStackEntry {
|
|||||||
bool haltnop;
|
bool haltnop;
|
||||||
bool optimizeLoads;
|
bool optimizeLoads;
|
||||||
bool warningsAreErrors;
|
bool warningsAreErrors;
|
||||||
|
size_t maxRecursionDepth;
|
||||||
// Don't be confused: we use the size of the **global variable** `warningStates`!
|
// Don't be confused: we use the size of the **global variable** `warningStates`!
|
||||||
enum WarningState warningStates[sizeof(warningStates)];
|
enum WarningState warningStates[sizeof(warningStates)];
|
||||||
struct OptStackEntry *next;
|
struct OptStackEntry *next;
|
||||||
@@ -39,6 +42,12 @@ void opt_P(uint8_t fill)
|
|||||||
fillByte = fill;
|
fillByte = fill;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void opt_R(size_t newDepth)
|
||||||
|
{
|
||||||
|
fstk_NewRecursionDepth(newDepth);
|
||||||
|
lexer_CheckRecursionDepth();
|
||||||
|
}
|
||||||
|
|
||||||
void opt_h(bool halt)
|
void opt_h(bool halt)
|
||||||
{
|
{
|
||||||
haltnop = halt;
|
haltnop = halt;
|
||||||
@@ -86,6 +95,29 @@ void opt_Parse(char *s)
|
|||||||
}
|
}
|
||||||
break;
|
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':
|
case 'h':
|
||||||
if (s[1] == '\0')
|
if (s[1] == '\0')
|
||||||
opt_h(false);
|
opt_h(false);
|
||||||
|
|||||||
@@ -1993,6 +1993,7 @@ block, all of them but the first one are ignored.
|
|||||||
.Ss Changing options while assembling
|
.Ss Changing options while assembling
|
||||||
.Ic OPT
|
.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.
|
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
|
.Pp
|
||||||
.Ic OPT
|
.Ic OPT
|
||||||
takes a comma-separated list of options as its argument:
|
takes a comma-separated list of options as its argument:
|
||||||
@@ -2008,8 +2009,10 @@ POPO
|
|||||||
LD [$FF88], A ; optimized to use LDH by default
|
LD [$FF88], A ; optimized to use LDH by default
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
The options that OPT can modify are currently:
|
The options that
|
||||||
.Cm b , g , p , h , L ,
|
.Ic OPT
|
||||||
|
can modify are currently:
|
||||||
|
.Cm b , g , p , r , h , L ,
|
||||||
and
|
and
|
||||||
.Cm W .
|
.Cm W .
|
||||||
The Boolean flag options
|
The Boolean flag options
|
||||||
|
|||||||
13
test/asm/opt-r.asm
Normal file
13
test/asm/opt-r.asm
Normal file
@@ -0,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
|
||||||
6
test/asm/opt-r.err
Normal file
6
test/asm/opt-r.err
Normal file
@@ -0,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
|
||||||
0
test/asm/opt-r.out
Normal file
0
test/asm/opt-r.out
Normal file
Reference in New Issue
Block a user