From 0649e6d65f5cca368f86986ca970fd3557db167c Mon Sep 17 00:00:00 2001 From: ISSOtm Date: Sun, 3 Nov 2019 22:11:04 +0100 Subject: [PATCH] Add long options --- Makefile | 4 ++++ include/extern/getopt.h | 35 ++++++++++++++++++++++--------- src/asm/main.c | 36 ++++++++++++++++++++++++++++++-- src/extern/getopt.c | 46 +++++++++++++++++++++++++++++++++-------- src/fix/main.c | 37 +++++++++++++++++++++++++++++++-- src/gfx/main.c | 40 +++++++++++++++++++++++++++++++++-- src/link/main.c | 34 ++++++++++++++++++++++++++++-- 7 files changed, 205 insertions(+), 27 deletions(-) diff --git a/Makefile b/Makefile index 0188e92b..39b061bb 100644 --- a/Makefile +++ b/Makefile @@ -67,6 +67,7 @@ rgbasm_obj := \ src/asm/symbol.o \ src/asm/util.o \ src/extern/err.o \ + src/extern/getopt.o \ src/extern/utf8decoder.o \ src/version.o @@ -82,12 +83,14 @@ rgblink_obj := \ src/link/section.o \ src/link/symbol.o \ src/extern/err.o \ + src/extern/getopt.o \ src/hashmap.o \ src/version.o rgbfix_obj := \ src/fix/main.o \ src/extern/err.o \ + src/extern/getopt.o \ src/version.o rgbgfx_obj := \ @@ -95,6 +98,7 @@ rgbgfx_obj := \ src/gfx/main.o \ src/gfx/makepng.o \ src/extern/err.o \ + src/extern/getopt.o \ src/version.o rgbasm: ${rgbasm_obj} diff --git a/include/extern/getopt.h b/include/extern/getopt.h index 35cbd358..33066d1e 100644 --- a/include/extern/getopt.h +++ b/include/extern/getopt.h @@ -1,11 +1,31 @@ +/* + * Copyright © 2005-2019 Rich Felker, et al. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* This implementation was taken from musl and modified for RGBDS */ + #ifndef _GETOPT_H #define _GETOPT_H -#ifdef __cplusplus -extern "C" { -#endif - -int getopt(int, char * const [], const char *); extern char *optarg; extern int optind, opterr, optopt, optreset; @@ -16,15 +36,10 @@ struct option { int val; }; -int getopt_long(int, char *const *, const char *, const struct option *, int *); int getopt_long_only(int, char *const *, const char *, const struct option *, int *); #define no_argument 0 #define required_argument 1 #define optional_argument 2 -#ifdef __cplusplus -} -#endif - #endif diff --git a/src/asm/main.c b/src/asm/main.c index ef24b3d6..ba07468b 100644 --- a/src/asm/main.c +++ b/src/asm/main.c @@ -14,7 +14,6 @@ #include #include #include -#include #include "asm/symbol.h" #include "asm/fstack.h" @@ -24,6 +23,7 @@ #include "asm/charmap.h" #include "extern/err.h" +#include "extern/getopt.h" #include "helpers.h" #include "version.h" @@ -287,6 +287,37 @@ void warning(const char *fmt, ...) va_end(args); } +/* Short options */ +static char const *optstring = "b:D:Eg:hi:LM:o:p:r:Vvw"; + +/* + * Equivalent long options + * Please keep in the same order as short opts + * + * Also, make sure long opts don't create ambiguity: + * A long opt's name should start with the same letter as its short opt, + * except if it doesn't create any ambiguity (`verbose` versus `version`). + * This is because long opt matching, even to a single char, is prioritized + * over short opt matching + */ +static struct option const longopts[] = { + { "binary-digits", required_argument, NULL, 'b' }, + { "define", required_argument, NULL, 'D' }, + { "export-all", no_argument, NULL, 'E' }, + { "gfx-chars", required_argument, NULL, 'g' }, + { "halt-without-nop", no_argument, NULL, 'h' }, + { "include", required_argument, NULL, 'i' }, + { "preserve-ld", no_argument, NULL, 'L' }, + { "dependfile", required_argument, NULL, 'M' }, + { "output", required_argument, NULL, 'o' }, + { "pad-value", required_argument, NULL, 'p' }, + { "recursion-depth", required_argument, NULL, 'r' }, + { "version", no_argument, NULL, 'V' }, + { "verbose", no_argument, NULL, 'v' }, + { "warning", no_argument, NULL, 'w' }, + { NULL, no_argument, NULL, 0 } +}; + static void print_usage(void) { printf( @@ -338,7 +369,8 @@ int main(int argc, char *argv[]) newopt = CurrentOptions; - while ((ch = getopt(argc, argv, "b:D:Eg:hi:LM:o:p:r:Vvw")) != -1) { + while ((ch = getopt_long_only(argc, argv, optstring, longopts, + NULL)) != -1) { switch (ch) { case 'b': if (strlen(optarg) == 2) { diff --git a/src/extern/getopt.c b/src/extern/getopt.c index 6949ab1c..473839f7 100644 --- a/src/extern/getopt.c +++ b/src/extern/getopt.c @@ -1,13 +1,46 @@ -#define _GNU_SOURCE +/* + * Copyright © 2005-2019 Rich Felker, et al. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* This implementation was taken from musl and modified for RGBDS */ + #include #include #include -#include +#include #include #include -#include "stdio_impl.h" +#include "extern/getopt.h" -extern int __optpos, __optreset; +int __optpos, __optreset; + +void __getopt_msg(const char *a, const char *b, const char *c, size_t l) +{ + FILE *f = stderr; + (void)(fputs(a, f)>=0 + && fwrite(b, strlen(b), 1, f) + && fwrite(c, 1, l, f)==l + && putc('\n', f)); +} static void permute(char *const *argv, int dest, int src) { @@ -137,11 +170,6 @@ static int __getopt_long_core(int argc, char *const *argv, const char *optstring return getopt(argc, argv, optstring); } -int getopt_long(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx) -{ - return __getopt_long(argc, argv, optstring, longopts, idx, 0); -} - int getopt_long_only(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx) { return __getopt_long(argc, argv, optstring, longopts, idx, 1); diff --git a/src/fix/main.c b/src/fix/main.c index 780a5388..addc0718 100644 --- a/src/fix/main.c +++ b/src/fix/main.c @@ -11,12 +11,44 @@ #include #include #include -#include #include "extern/err.h" +#include "extern/getopt.h" #include "version.h" +/* Shoft options */ +static char const *optstring = "Ccf:i:jk:l:m:n:p:sr:t:Vv"; + +/* + * Equivalent long options + * Please keep in the same order as short opts + * + * Also, make sure long opts don't create ambiguity: + * A long opt's name should start with the same letter as its short opt, + * except if it doesn't create any ambiguity (`verbose` versus `version`). + * This is because long opt matching, even to a single char, is prioritized + * over short opt matching + */ +static struct option const longopts[] = { + { "color-only", no_argument, NULL, 'C' }, + { "color-compatible", no_argument, NULL, 'c' }, + { "fix-spec", required_argument, NULL, 'f' }, + { "game-id", required_argument, NULL, 'i' }, + { "non-japanese", no_argument, NULL, 'j' }, + { "new-licensee", required_argument, NULL, 'k' }, + { "old-licensee", required_argument, NULL, 'l' }, + { "mbc-type", required_argument, NULL, 'm' }, + { "rom-version", required_argument, NULL, 'n' }, + { "pad-value", required_argument, NULL, 'p' }, + { "ram-size", required_argument, NULL, 'r' }, + { "sgb-compatible", no_argument, NULL, 's' }, + { "title", required_argument, NULL, 't' }, + { "version", no_argument, NULL, 'V' }, + { "verbose", no_argument, NULL, 'v' }, + { NULL, no_argument, NULL, 0 } +}; + static void print_usage(void) { printf( @@ -66,7 +98,8 @@ int main(int argc, char *argv[]) int version = 0; /* mask ROM version number */ int padvalue = 0; /* to pad the rom with if it changes size */ - while ((ch = getopt(argc, argv, "Ccf:i:jk:l:m:n:p:sr:t:Vv")) != -1) { + while ((ch = getopt_long_only(argc, argv, optstring, longopts, + NULL)) != -1) { switch (ch) { case 'C': coloronly = true; diff --git a/src/gfx/main.c b/src/gfx/main.c index 06ba0eac..5238c911 100644 --- a/src/gfx/main.c +++ b/src/gfx/main.c @@ -9,12 +9,47 @@ #include #include #include -#include #include "gfx/main.h" +#include "extern/getopt.h" #include "version.h" +/* Short options */ +static char const *optstring = "Aa:CDd:Ffhmo:Pp:Tt:uVvx:"; + +/* + * Equivalent long options + * Please keep in the same order as short opts + * + * Also, make sure long opts don't create ambiguity: + * A long opt's name should start with the same letter as its short opt, + * except if it doesn't create any ambiguity (`verbose` versus `version`). + * This is because long opt matching, even to a single char, is prioritized + * over short opt matching + */ +static struct option const longopts[] = { + { "output-attr-map", no_argument, NULL, 'A' }, + { "attr-map", required_argument, NULL, 'a' }, + { "color-curve", no_argument, NULL, 'C' }, + { "debug", no_argument, NULL, 'D' }, + { "depth", required_argument, NULL, 'd' }, + { "fix", no_argument, NULL, 'f' }, + { "fix-and-save", no_argument, NULL, 'F' }, + { "horizontal", no_argument, NULL, 'h' }, + { "mirror-tiles", no_argument, NULL, 'm' }, + { "output", required_argument, NULL, 'o' }, + { "output-palette", no_argument, NULL, 'P' }, + { "palette", required_argument, NULL, 'p' }, + { "output-tilemap", no_argument, NULL, 'T' }, + { "tilemap", required_argument, NULL, 't' }, + { "unique-tiles", no_argument, NULL, 'u' }, + { "version", no_argument, NULL, 'V' }, + { "verbose", no_argument, NULL, 'v' }, + { "trim-end", required_argument, NULL, 'x' }, + { NULL, no_argument, NULL, 0 } +}; + static void print_usage(void) { printf( @@ -45,7 +80,8 @@ int main(int argc, char *argv[]) depth = 2; - while ((ch = getopt(argc, argv, "Aa:CDd:Ffhmo:Tt:uPp:Vvx:")) != -1) { + while ((ch = getopt_long_only(argc, argv, optstring, longopts, + NULL)) != -1) { switch (ch) { case 'A': opts.attrmapout = true; diff --git a/src/link/main.c b/src/link/main.c index 3649f90c..d94710e3 100644 --- a/src/link/main.c +++ b/src/link/main.c @@ -8,7 +8,6 @@ #include #include -#include #include #include #include @@ -22,6 +21,7 @@ #include "link/output.h" #include "extern/err.h" +#include "extern/getopt.h" #include "version.h" bool isDmgMode; /* -d */ @@ -48,6 +48,35 @@ FILE *openFile(char const *fileName, char const *mode) return file; } +/* Short options */ +static char const *optstring = "dl:m:n:O:o:p:s:tVvw"; + +/* + * Equivalent long options + * Please keep in the same order as short opts + * + * Also, make sure long opts don't create ambiguity: + * A long opt's name should start with the same letter as its short opt, + * except if it doesn't create any ambiguity (`verbose` versus `version`). + * This is because long opt matching, even to a single char, is prioritized + * over short opt matching + */ +static struct option const longopts[] = { + { "dmg", no_argument, NULL, 'd' }, + { "linkerscript", required_argument, NULL, 'l' }, + { "map", required_argument, NULL, 'm' }, + { "sym", required_argument, NULL, 'n' }, + { "overlay", required_argument, NULL, 'O' }, + { "output", required_argument, NULL, 'o' }, + { "pad", required_argument, NULL, 'p' }, + { "smart", required_argument, NULL, 's' }, + { "tiny", no_argument, NULL, 't' }, + { "version", no_argument, NULL, 'V' }, + { "verbose", no_argument, NULL, 'v' }, + { "wramx", no_argument, NULL, 'w' }, + { NULL, no_argument, NULL, 0 } +}; + /** * Prints the program's usage to stdout. */ @@ -73,7 +102,8 @@ int main(int argc, char *argv[]) unsigned long value; /* For storing `strtoul`'s return value */ /* Parse options */ - while ((optionChar = getopt(argc, argv, "dl:m:n:O:o:p:s:tVvw")) != -1) { + while ((optionChar = getopt_long_only(argc, argv, optstring, longopts, + NULL)) != -1) { switch (optionChar) { case 'd': isDmgMode = true;