Consistent behavior with missing or incorrect parameters (#1179)

This commit is contained in:
Rangi
2023-11-02 12:40:40 -04:00
committed by GitHub
parent a64f28de5c
commit 0d72ba886b
8 changed files with 61 additions and 43 deletions

View File

@@ -34,6 +34,9 @@
The The
.Nm .Nm
program creates an RGB object file from an assembly source file. program creates an RGB object file from an assembly source file.
The object file format is documented in
.Xr rgbds 5 .
.Pp
The input The input
.Ar asmfile .Ar asmfile
can be a path to a file, or can be a path to a file, or

View File

@@ -41,6 +41,12 @@ Developers are advised to fill those fields with 0x00 bytes in their source code
and to have already populated whichever fields they don't specify using and to have already populated whichever fields they don't specify using
.Nm . .Nm .
.Pp .Pp
The input
.Ar asmfile
can be a path to a file, or
.Cm \-
to read from standard input.
.Pp
Note that options can be abbreviated as long as the abbreviation is unambiguous: Note that options can be abbreviated as long as the abbreviation is unambiguous:
.Fl Fl color-o .Fl Fl color-o
is is

View File

@@ -29,7 +29,7 @@ The
program links RGB object files, typically created by program links RGB object files, typically created by
.Xr rgbasm 1 , .Xr rgbasm 1 ,
into a single Game Boy ROM file. into a single Game Boy ROM file.
The format is documented in The object file format is documented in
.Xr rgbds 5 . .Xr rgbds 5 .
.Pp .Pp
ROM0 sections are placed in the first 16 KiB of the output ROM, and ROMX sections are placed in any 16 KiB ROM0 sections are placed in the first 16 KiB of the output ROM, and ROMX sections are placed in any 16 KiB
@@ -52,6 +52,12 @@ option, which implies
.Fl w .Fl w
but also prohibits the use of banked VRAM. but also prohibits the use of banked VRAM.
.Pp .Pp
The input
.Ar asmfile
can be a path to a file, or
.Cm \-
to read from standard input.
.Pp
Note that options can be abbreviated as long as the abbreviation is unambiguous: Note that options can be abbreviated as long as the abbreviation is unambiguous:
.Fl Fl verb .Fl Fl verb
is is

View File

@@ -126,7 +126,7 @@ static struct option const longopts[] = {
{ NULL, no_argument, NULL, 0 } { NULL, no_argument, NULL, 0 }
}; };
static void print_usage(void) static void printUsage(void)
{ {
fputs( fputs(
"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"
@@ -143,7 +143,6 @@ static void print_usage(void)
"\n" "\n"
"For help, use `man rgbasm' or go to https://rgbds.gbdev.io/docs/\n", "For help, use `man rgbasm' or go to https://rgbds.gbdev.io/docs/\n",
stderr); stderr);
exit(1);
} }
int main(int argc, char *argv[]) int main(int argc, char *argv[])
@@ -176,10 +175,10 @@ int main(int argc, char *argv[])
char *dependFileName = NULL; char *dependFileName = NULL;
size_t targetFileNameLen = 0; size_t targetFileNameLen = 0;
int ch; for (int ch; (ch = musl_getopt_long_only(argc, argv, optstring, longopts, NULL)) != -1;) {
char *ep;
while ((ch = musl_getopt_long_only(argc, argv, optstring, longopts, NULL)) != -1) {
switch (ch) { switch (ch) {
char *endptr;
case 'b': case 'b':
if (strlen(musl_optarg) == 2) if (strlen(musl_optarg) == 2)
opt_B(musl_optarg); opt_B(musl_optarg);
@@ -263,9 +262,9 @@ int main(int argc, char *argv[])
unsigned long padByte; unsigned long padByte;
case 'p': case 'p':
padByte = strtoul(musl_optarg, &ep, 0); padByte = strtoul(musl_optarg, &endptr, 0);
if (musl_optarg[0] == '\0' || *ep != '\0') if (musl_optarg[0] == '\0' || *endptr != '\0')
errx("Invalid argument for option 'p'"); errx("Invalid argument for option 'p'");
if (padByte > 0xFF) if (padByte > 0xFF)
@@ -280,9 +279,9 @@ int main(int argc, char *argv[])
precisionArg = musl_optarg; precisionArg = musl_optarg;
if (precisionArg[0] == '.') if (precisionArg[0] == '.')
precisionArg++; precisionArg++;
precision = strtoul(precisionArg, &ep, 0); precision = strtoul(precisionArg, &endptr, 0);
if (musl_optarg[0] == '\0' || *ep != '\0') if (musl_optarg[0] == '\0' || *endptr != '\0')
errx("Invalid argument for option 'Q'"); errx("Invalid argument for option 'Q'");
if (precision < 1 || precision > 31) if (precision < 1 || precision > 31)
@@ -292,9 +291,9 @@ int main(int argc, char *argv[])
break; break;
case 'r': case 'r':
maxDepth = strtoul(musl_optarg, &ep, 0); maxDepth = strtoul(musl_optarg, &endptr, 0);
if (musl_optarg[0] == '\0' || *ep != '\0') if (musl_optarg[0] == '\0' || *endptr != '\0')
errx("Invalid argument for option 'r'"); errx("Invalid argument for option 'r'");
break; break;
@@ -348,8 +347,9 @@ int main(int argc, char *argv[])
// Unrecognized options // Unrecognized options
default: default:
print_usage(); fprintf(stderr, "FATAL: unknown option '%c'\n", ch);
// NOTREACHED printUsage();
exit(1);
} }
} }
@@ -360,10 +360,12 @@ int main(int argc, char *argv[])
if (argc == musl_optind) { if (argc == musl_optind) {
fputs("FATAL: Please specify an input file (pass `-` to read from standard input)\n", stderr); fputs("FATAL: Please specify an input file (pass `-` to read from standard input)\n", stderr);
print_usage(); printUsage();
exit(1);
} else if (argc != musl_optind + 1) { } else if (argc != musl_optind + 1) {
fputs("FATAL: More than one input file specified\n", stderr); fputs("FATAL: More than one input file specified\n", stderr);
print_usage(); printUsage();
exit(1);
} }
char const *mainFileName = argv[musl_optind]; char const *mainFileName = argv[musl_optind];

View File

@@ -67,7 +67,7 @@ static void printUsage(void)
fputs( fputs(
"Usage: rgbfix [-jOsVv] [-C | -c] [-f <fix_spec>] [-i <game_id>] [-k <licensee>]\n" "Usage: rgbfix [-jOsVv] [-C | -c] [-f <fix_spec>] [-i <game_id>] [-k <licensee>]\n"
" [-l <licensee_byte>] [-m <mbc_type>] [-n <rom_version>]\n" " [-l <licensee_byte>] [-m <mbc_type>] [-n <rom_version>]\n"
" [-p <pad_value>] [-r <ram_size>] [-t <title_str>] [<file> ...]\n" " [-p <pad_value>] [-r <ram_size>] [-t <title_str>] <file> ...\n"
"Useful options:\n" "Useful options:\n"
" -m, --mbc-type <value> set the MBC type byte to this value; refer\n" " -m, --mbc-type <value> set the MBC type byte to this value; refer\n"
" to the man page for a list of values\n" " to the man page for a list of values\n"
@@ -1224,9 +1224,8 @@ finish:
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
nbErrors = 0; nbErrors = 0;
int ch;
while ((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) {
size_t len; size_t len;
#define parseByte(output, name) \ #define parseByte(output, name) \
@@ -1447,12 +1446,15 @@ do { \
bool failed = nbErrors; bool failed = nbErrors;
if (!*argv) { if (!*argv) {
failed |= processFilename("-"); fputs("FATAL: Please specify an input file (pass `-` to read from standard input)\n",
} else { stderr);
do { printUsage();
failed |= processFilename(*argv); exit(1);
} while (*++argv);
} }
do {
failed |= processFilename(*argv);
} while (*++argv);
return failed; return failed;
} }

View File

@@ -153,7 +153,6 @@ static void printUsage(void) {
"\n" "\n"
"For help, use `man rgbgfx' or go to https://rgbds.gbdev.io/docs/\n", "For help, use `man rgbgfx' or go to https://rgbds.gbdev.io/docs/\n",
stderr); stderr);
exit(1);
} }
/* /*
@@ -333,11 +332,9 @@ static std::vector<size_t> readAtFile(std::string const &path, std::vector<char>
*/ */
static char *parseArgv(int argc, char **argv, bool &autoAttrmap, bool &autoTilemap, static char *parseArgv(int argc, char **argv, bool &autoAttrmap, bool &autoTilemap,
bool &autoPalettes, bool &autoPalmap) { bool &autoPalettes, bool &autoPalmap) {
int opt; for (int ch; (ch = musl_getopt_long_only(argc, argv, optstring, longopts, nullptr)) != -1;) {
while ((opt = musl_getopt_long_only(argc, argv, optstring, longopts, nullptr)) != -1) {
char *arg = musl_optarg; // Make a copy for scanning char *arg = musl_optarg; // Make a copy for scanning
switch (opt) { switch (ch) {
case 'A': case 'A':
autoAttrmap = true; autoAttrmap = true;
break; break;
@@ -569,9 +566,10 @@ static char *parseArgv(int argc, char **argv, bool &autoAttrmap, bool &autoTilem
case 'D': case 'D':
case 'F': case 'F':
case 'f': case 'f':
warning("Ignoring retired option `-%c`", opt); warning("Ignoring retired option `-%c`", ch);
break; break;
default: default:
fprintf(stderr, "FATAL: unknown option '%c'\n", ch);
printUsage(); printUsage();
exit(1); exit(1);
} }
@@ -769,7 +767,9 @@ int main(int argc, char *argv[]) {
} }
if (options.input.empty()) { if (options.input.empty()) {
fatal("No input image specified"); fputs("FATAL: No input image specified\n", stderr);
printUsage();
exit(1);
} }
// Do not do anything if option parsing went wrong // Do not do anything if option parsing went wrong

View File

@@ -196,7 +196,6 @@ static struct option const longopts[] = {
{ NULL, no_argument, NULL, 0 } { NULL, no_argument, NULL, 0 }
}; };
// Prints the program's usage to stdout.
static void printUsage(void) static void printUsage(void)
{ {
fputs( fputs(
@@ -356,14 +355,9 @@ _Noreturn void reportErrors(void) {
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
int optionChar;
char *endptr; // For error checking with `strtoul`
unsigned long value; // For storing `strtoul`'s return value
// Parse options // Parse options
while ((optionChar = musl_getopt_long_only(argc, argv, optstring, for (int ch; (ch = musl_getopt_long_only(argc, argv, optstring, longopts, NULL)) != -1;) {
longopts, NULL)) != -1) { switch (ch) {
switch (optionChar) {
case 'd': case 'd':
isDmgMode = true; isDmgMode = true;
isWRA0Mode = true; isWRA0Mode = true;
@@ -396,8 +390,10 @@ int main(int argc, char *argv[])
warnx("Overriding output file %s", musl_optarg); warnx("Overriding output file %s", musl_optarg);
outputFileName = musl_optarg; outputFileName = musl_optarg;
break; break;
case 'p': case 'p': {
value = strtoul(musl_optarg, &endptr, 0); char *endptr;
unsigned long value = strtoul(musl_optarg, &endptr, 0);
if (musl_optarg[0] == '\0' || *endptr != '\0') { if (musl_optarg[0] == '\0' || *endptr != '\0') {
argErr('p', ""); argErr('p', "");
value = 0xFF; value = 0xFF;
@@ -408,6 +404,7 @@ int main(int argc, char *argv[])
} }
padValue = value; padValue = value;
break; break;
}
case 'S': case 'S':
parseScrambleSpec(musl_optarg); parseScrambleSpec(musl_optarg);
break; break;
@@ -434,6 +431,7 @@ int main(int argc, char *argv[])
is32kMode = true; is32kMode = true;
break; break;
default: default:
fprintf(stderr, "FATAL: unknown option '%c'\n", ch);
printUsage(); printUsage();
exit(1); exit(1);
} }
@@ -443,7 +441,8 @@ int main(int argc, char *argv[])
// If no input files were specified, the user must have screwed up // If no input files were specified, the user must have screwed up
if (curArgIndex == argc) { if (curArgIndex == argc) {
fputs("FATAL: no input files\n", stderr); fputs("FATAL: Please specify an input file (pass `-` to read from standard input)\n",
stderr);
printUsage(); printUsage();
exit(1); exit(1);
} }

View File

@@ -52,7 +52,7 @@ runTest () {
# Stop! This is not a Useless Use Of Cat. Using cat instead of # Stop! This is not a Useless Use Of Cat. Using cat instead of
# stdin redirection makes the input an unseekable pipe - a scenario # stdin redirection makes the input an unseekable pipe - a scenario
# that's harder to deal with. # that's harder to deal with.
cat "$2/$1.bin" | eval $RGBFIX "$flags" '>out.gb' '2>out.err' cat "$2/$1.bin" | eval $RGBFIX "$flags" - '>out.gb' '2>out.err'
subst='<stdin>' subst='<stdin>'
fi fi