shithub: rgbds

Download patch

ref: 0649e6d65f5cca368f86986ca970fd3557db167c
parent: 072c965ba5fef4c4f431b5fb7b520ec0ca807555
author: ISSOtm <[email protected]>
date: Sun Nov 3 17:11:04 EST 2019

Add long options

--- a/Makefile
+++ b/Makefile
@@ -67,6 +67,7 @@
 	src/asm/symbol.o \
 	src/asm/util.o \
 	src/extern/err.o \
+	src/extern/getopt.o \
 	src/extern/utf8decoder.o \
 	src/version.o
 
@@ -82,6 +83,7 @@
 	src/link/section.o \
 	src/link/symbol.o \
 	src/extern/err.o \
+	src/extern/getopt.o \
 	src/hashmap.o \
 	src/version.o
 
@@ -88,6 +90,7 @@
 rgbfix_obj := \
 	src/fix/main.o \
 	src/extern/err.o \
+	src/extern/getopt.o \
 	src/version.o
 
 rgbgfx_obj := \
@@ -95,6 +98,7 @@
 	src/gfx/main.o \
 	src/gfx/makepng.o \
 	src/extern/err.o \
+	src/extern/getopt.o \
 	src/version.o
 
 rgbasm: ${rgbasm_obj}
--- 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 @@
 	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
--- a/src/asm/main.c
+++ b/src/asm/main.c
@@ -14,7 +14,6 @@
 #include <stdlib.h>
 #include <string.h>
 #include <time.h>
-#include <unistd.h>
 
 #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 @@
 	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 @@
 
 	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) {
--- a/src/extern/getopt.c
+++ b/src/extern/getopt.c
@@ -1,14 +1,47 @@
-#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 <stddef.h>
 #include <stdlib.h>
 #include <limits.h>
-#include <getopt.h>
+#include <unistd.h>
 #include <stdio.h>
 #include <string.h>
-#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)
 {
 	char **av = (char **)argv;
@@ -135,11 +168,6 @@
 		}
 	}
 	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)
--- a/src/fix/main.c
+++ b/src/fix/main.c
@@ -11,12 +11,44 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <unistd.h>
 
 #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 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;
--- a/src/gfx/main.c
+++ b/src/gfx/main.c
@@ -9,12 +9,47 @@
 #include <png.h>
 #include <stdlib.h>
 #include <string.h>
-#include <unistd.h>
 
 #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 @@
 
 	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;
--- a/src/link/main.c
+++ b/src/link/main.c
@@ -8,7 +8,6 @@
 
 #include <sys/types.h>
 #include <sys/stat.h>
-#include <unistd.h>
 #include <stdio.h>
 #include <stdbool.h>
 #include <stdint.h>
@@ -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 @@
 	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 @@
 	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;