mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 18:22:07 +00:00
Implement -X/--max-errors for RGBASM (#1262)
Co-authored-by: Eldred Habert <me@eldred.fr>
This commit is contained in:
@@ -43,6 +43,7 @@ _rgbasm_completions() {
|
|||||||
[Q]="q-precision:unk"
|
[Q]="q-precision:unk"
|
||||||
[r]="recursion-depth:unk"
|
[r]="recursion-depth:unk"
|
||||||
[W]="warning:warning"
|
[W]="warning:warning"
|
||||||
|
[X]="max-errors:unk"
|
||||||
)
|
)
|
||||||
# Parse command-line up to current word
|
# Parse command-line up to current word
|
||||||
local opt_ena=true
|
local opt_ena=true
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ local args=(
|
|||||||
'(-Q --q-precision)'{-Q,--q-precision}'+[Set fixed-point precision]:precision:'
|
'(-Q --q-precision)'{-Q,--q-precision}'+[Set fixed-point precision]:precision:'
|
||||||
'(-r --recursion-depth)'{-r,--recursion-depth}'+[Set maximum recursion depth]:depth:'
|
'(-r --recursion-depth)'{-r,--recursion-depth}'+[Set maximum recursion depth]:depth:'
|
||||||
'(-W --warning)'{-W,--warning}'+[Toggle warning flags]:warning flag:_rgbasm_warnings'
|
'(-W --warning)'{-W,--warning}'+[Toggle warning flags]:warning flag:_rgbasm_warnings'
|
||||||
|
'(-X --max-errors)'{-X,--max-errors}'+[Set maximum errors before aborting]:maximum errors:'
|
||||||
|
|
||||||
":assembly sources:_files -g '*.asm'"
|
":assembly sources:_files -g '*.asm'"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
#include "helpers.hpp"
|
#include "helpers.hpp"
|
||||||
|
|
||||||
extern unsigned int nbErrors;
|
extern unsigned int nbErrors, maxErrors;
|
||||||
|
|
||||||
enum WarningState {
|
enum WarningState {
|
||||||
WARNING_DEFAULT,
|
WARNING_DEFAULT,
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
.Op Fl Q Ar fix_precision
|
.Op Fl Q Ar fix_precision
|
||||||
.Op Fl r Ar recursion_depth
|
.Op Fl r Ar recursion_depth
|
||||||
.Op Fl W Ar warning
|
.Op Fl W Ar warning
|
||||||
|
.Op Fl X Ar max_errors
|
||||||
.Ar asmfile
|
.Ar asmfile
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
The
|
The
|
||||||
@@ -176,6 +177,13 @@ See the
|
|||||||
section for a list of warnings.
|
section for a list of warnings.
|
||||||
.It Fl w
|
.It Fl w
|
||||||
Disable all warning output, even when turned into errors.
|
Disable all warning output, even when turned into errors.
|
||||||
|
.It Fl X Ar max_errors , Fl \-max-errors Ar max_errors
|
||||||
|
If more than this number of errors (not warnings) occur, then abort the assembly process;
|
||||||
|
.Fl X 0
|
||||||
|
disables this behavior.
|
||||||
|
The default is 100 if
|
||||||
|
.Nm
|
||||||
|
is printing errors to a terminal, and 0 otherwise.
|
||||||
.El
|
.El
|
||||||
.Sh DIAGNOSTICS
|
.Sh DIAGNOSTICS
|
||||||
Warnings are diagnostic messages that indicate possibly erroneous behavior that does not necessarily compromise the assembling process.
|
Warnings are diagnostic messages that indicate possibly erroneous behavior that does not necessarily compromise the assembling process.
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
#include <limits.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -83,7 +84,7 @@ static char *make_escape(char const *str)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Short options
|
// Short options
|
||||||
static const char *optstring = "b:D:Eg:Hhi:I:LlM:o:P:p:Q:r:VvW:w";
|
static const char *optstring = "b:D:Eg:Hhi:I:LlM:o:P:p:Q:r:VvW:wX:";
|
||||||
|
|
||||||
// Variables for the long-only options
|
// Variables for the long-only options
|
||||||
static int depType; // Variants of `-M`
|
static int depType; // Variants of `-M`
|
||||||
@@ -110,6 +111,7 @@ static struct option const longopts[] = {
|
|||||||
{ "MG", no_argument, &depType, 'G' },
|
{ "MG", no_argument, &depType, 'G' },
|
||||||
{ "MP", no_argument, &depType, 'P' },
|
{ "MP", no_argument, &depType, 'P' },
|
||||||
{ "MT", required_argument, &depType, 'T' },
|
{ "MT", required_argument, &depType, 'T' },
|
||||||
|
{ "warning", required_argument, NULL, 'W' },
|
||||||
{ "MQ", required_argument, &depType, 'Q' },
|
{ "MQ", required_argument, &depType, 'Q' },
|
||||||
{ "output", required_argument, NULL, 'o' },
|
{ "output", required_argument, NULL, 'o' },
|
||||||
{ "preinclude", required_argument, NULL, 'P' },
|
{ "preinclude", required_argument, NULL, 'P' },
|
||||||
@@ -119,6 +121,7 @@ static struct option const longopts[] = {
|
|||||||
{ "version", no_argument, NULL, 'V' },
|
{ "version", no_argument, NULL, 'V' },
|
||||||
{ "verbose", no_argument, NULL, 'v' },
|
{ "verbose", no_argument, NULL, 'v' },
|
||||||
{ "warning", required_argument, NULL, 'W' },
|
{ "warning", required_argument, NULL, 'W' },
|
||||||
|
{ "max-errors", required_argument, NULL, 'X' },
|
||||||
{ NULL, no_argument, NULL, 0 }
|
{ NULL, no_argument, NULL, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -128,7 +131,7 @@ static void printUsage(void)
|
|||||||
"Usage: rgbasm [-EHhLlVvw] [-b chars] [-D name[=value]] [-g chars] [-I path]\n"
|
"Usage: rgbasm [-EHhLlVvw] [-b chars] [-D name[=value]] [-g chars] [-I path]\n"
|
||||||
" [-M depend_file] [-MG] [-MP] [-MT target_file] [-MQ target_file]\n"
|
" [-M depend_file] [-MG] [-MP] [-MT target_file] [-MQ target_file]\n"
|
||||||
" [-o out_file] [-P include_file] [-p pad_value] [-Q precision]\n"
|
" [-o out_file] [-P include_file] [-p pad_value] [-Q precision]\n"
|
||||||
" [-r depth] [-W warning] <file>\n"
|
" [-r depth] [-W warning] [-X max_errors] <file>\n"
|
||||||
"Useful options:\n"
|
"Useful options:\n"
|
||||||
" -E, --export-all export all labels\n"
|
" -E, --export-all export all labels\n"
|
||||||
" -M, --dependfile <path> set the output dependency file\n"
|
" -M, --dependfile <path> set the output dependency file\n"
|
||||||
@@ -171,6 +174,10 @@ int main(int argc, char *argv[])
|
|||||||
char const *dependFileName = NULL;
|
char const *dependFileName = NULL;
|
||||||
size_t targetFileNameLen = 0;
|
size_t targetFileNameLen = 0;
|
||||||
|
|
||||||
|
// Maximum of 100 errors only applies if rgbasm is printing errors to a terminal.
|
||||||
|
if (isatty(STDERR_FILENO))
|
||||||
|
maxErrors = 100;
|
||||||
|
|
||||||
for (int ch; (ch = musl_getopt_long_only(argc, argv, optstring, longopts, NULL)) != -1;) {
|
for (int ch; (ch = musl_getopt_long_only(argc, argv, optstring, longopts, NULL)) != -1;) {
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
char *endptr;
|
char *endptr;
|
||||||
@@ -316,6 +323,19 @@ int main(int argc, char *argv[])
|
|||||||
warnings = false;
|
warnings = false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
unsigned int maxValue;
|
||||||
|
case 'X':
|
||||||
|
maxValue = strtoul(musl_optarg, &endptr, 0);
|
||||||
|
|
||||||
|
if (musl_optarg[0] == '\0' || *endptr != '\0')
|
||||||
|
errx("Invalid argument for option 'X'");
|
||||||
|
|
||||||
|
if (maxValue > UINT_MAX)
|
||||||
|
errx("Argument for option 'X' must be between 0 and %u", UINT_MAX);
|
||||||
|
|
||||||
|
maxErrors = maxValue;
|
||||||
|
break;
|
||||||
|
|
||||||
// Long-only options
|
// Long-only options
|
||||||
case 0:
|
case 0:
|
||||||
switch (depType) {
|
switch (depType) {
|
||||||
@@ -399,8 +419,7 @@ int main(int argc, char *argv[])
|
|||||||
sect_CheckUnionClosed();
|
sect_CheckUnionClosed();
|
||||||
|
|
||||||
if (nbErrors != 0)
|
if (nbErrors != 0)
|
||||||
errx("Assembly aborted (%u error%s)!", nbErrors,
|
errx("Assembly aborted (%u error%s)!", nbErrors, nbErrors == 1 ? "" : "s");
|
||||||
nbErrors == 1 ? "" : "s");
|
|
||||||
|
|
||||||
// If parse aborted due to missing an include, and `-MG` was given, exit normally
|
// If parse aborted due to missing an include, and `-MG` was given, exit normally
|
||||||
if (failedOnMissingInclude)
|
if (failedOnMissingInclude)
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
#include "itertools.hpp"
|
#include "itertools.hpp"
|
||||||
|
|
||||||
unsigned int nbErrors = 0;
|
unsigned int nbErrors = 0;
|
||||||
|
unsigned int maxErrors = 0;
|
||||||
|
|
||||||
static const enum WarningState defaultWarnings[ARRAY_SIZE(warningStates)] = {
|
static const enum WarningState defaultWarnings[ARRAY_SIZE(warningStates)] = {
|
||||||
AT(WARNING_ASSERT) WARNING_ENABLED,
|
AT(WARNING_ASSERT) WARNING_ENABLED,
|
||||||
@@ -343,7 +344,12 @@ void error(char const *fmt, ...)
|
|||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
printDiag(fmt, args, "error: ", ":\n ", NULL);
|
printDiag(fmt, args, "error: ", ":\n ", NULL);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
|
// This intentionally makes 0 act as "unlimited" (or at least "limited to sizeof(unsigned)")
|
||||||
nbErrors++;
|
nbErrors++;
|
||||||
|
if (nbErrors == maxErrors)
|
||||||
|
errx("The maximum of %u error%s was reached (configure with \"-X/--max-errors\"); assembly aborted!",
|
||||||
|
maxErrors, maxErrors == 1 ? "" : "s");
|
||||||
}
|
}
|
||||||
|
|
||||||
[[noreturn]] void fatalerror(char const *fmt, ...)
|
[[noreturn]] void fatalerror(char const *fmt, ...)
|
||||||
|
|||||||
3
test/asm/max-errors.asm
Normal file
3
test/asm/max-errors.asm
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
section "s", rom0
|
||||||
|
db 42
|
||||||
|
println @ ; causes an error before println occurs
|
||||||
3
test/asm/max-errors.err
Normal file
3
test/asm/max-errors.err
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
error: max-errors.asm(3):
|
||||||
|
Expected constant expression: PC is not constant at assembly time
|
||||||
|
error: The maximum of 1 error was reached (configure with "-X/--max-errors"); assembly aborted!
|
||||||
1
test/asm/max-errors.flags
Normal file
1
test/asm/max-errors.flags
Normal file
@@ -0,0 +1 @@
|
|||||||
|
-Weverything -X 1
|
||||||
Reference in New Issue
Block a user