:: commit 7c8ea4628622f56e514a09bc8a730d3e4a6ac3fa

Kamila Szewczyk <kspalaiologos@gmail.com> — 2022-09-01 11:47

parents: 0fa8b3334a

getopt shim, make format

diff --git a/Makefile.am b/Makefile.am
index 2de8237..866246a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -14,6 +14,7 @@ noinst_HEADERS = include/cm.h \
 						 include/libsais.h \
 						 include/lzp.h \
 						 include/rle.h
+						 include/getopt-shim.h
 
 lib_LTLIBRARIES = libbzip3.la
 libbzip3_la_SOURCES = src/cm.c \
diff --git a/configure.ac b/configure.ac
index ca050bc..9d77c00 100644
--- a/configure.ac
+++ b/configure.ac
@@ -16,6 +16,9 @@ LT_INIT
 PKG_PROG_PKG_CONFIG
 PKG_INSTALLDIR
 
+AC_CHECK_HEADERS([getopt.h])
+AC_CHECK_FUNCS([getopt_long])
+
 AC_ARG_WITH([pthread],
 			  AS_HELP_STRING([--without-pthread], [Disable use of pthread library]))
 AM_CONDITIONAL([WITH_PTHREAD], [test x"$with_pthread" != xno])
diff --git a/include/getopt-shim.h b/include/getopt-shim.h
new file mode 100644
index 0000000..fde2108
--- /dev/null
+++ b/include/getopt-shim.h
@@ -0,0 +1,253 @@
+/*
+  Copyright 2005-2014 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.
+*/
+
+#ifndef _GETOPT_H
+#define _GETOPT_H
+
+int getopt(int, char * const [], const char *);
+extern char *optarg;
+extern int optind, opterr, optopt, optreset;
+
+struct option {
+	const char *name;
+	int has_arg;
+	int *flag;
+	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
+
+char *optarg;
+int optind=1, opterr=1, optopt, __optpos, optreset=0;
+
+#define optpos __optpos
+
+static void __getopt_msg(const char *a, const char *b, const char *c, size_t l)
+{
+	FILE *f = stderr;
+	flockfile(f);
+	fputs(a, f)>=0
+	&& fwrite(b, strlen(b), 1, f)
+	&& fwrite(c, 1, l, f)==l
+	&& putc('\n', f);
+	funlockfile(f);
+}
+
+int getopt(int argc, char * const argv[], const char *optstring)
+{
+	int i, c, d;
+	int k, l;
+	char *optchar;
+
+	if (!optind || optreset) {
+		optreset = 0;
+		__optpos = 0;
+		optind = 1;
+	}
+
+	if (optind >= argc || !argv[optind])
+		return -1;
+
+	if (argv[optind][0] != '-') {
+		if (optstring[0] == '-') {
+			optarg = argv[optind++];
+			return 1;
+		}
+		return -1;
+	}
+
+	if (!argv[optind][1])
+		return -1;
+
+	if (argv[optind][1] == '-' && !argv[optind][2])
+		return optind++, -1;
+
+	if (!optpos) optpos++;
+	c = argv[optind][optpos], k = 1;
+	optchar = argv[optind]+optpos;
+	optopt = c;
+	optpos += k;
+
+	if (!argv[optind][optpos]) {
+		optind++;
+		optpos = 0;
+	}
+
+	if (optstring[0] == '-' || optstring[0] == '+')
+		optstring++;
+
+	i = 0;
+	d = 0;
+	do {
+		d = optstring[i], l = 1;
+		if (l>0) i+=l; else i++;
+	} while (l && d != c);
+
+	if (d != c) {
+		if (optstring[0] != ':' && opterr)
+			__getopt_msg(argv[0], ": unrecognized option: ", optchar, k);
+		return '?';
+	}
+	if (optstring[i] == ':') {
+		if (optstring[i+1] == ':') optarg = 0;
+		else if (optind >= argc) {
+			if (optstring[0] == ':') return ':';
+			if (opterr) __getopt_msg(argv[0],
+				": option requires an argument: ",
+				optchar, k);
+			return '?';
+		}
+		if (optstring[i+1] != ':' || optpos) {
+			optarg = argv[optind++] + optpos;
+			optpos = 0;
+		}
+	}
+	return c;
+}
+
+static void permute(char *const *argv, int dest, int src)
+{
+	char **av = (char **)argv;
+	char *tmp = av[src];
+	int i;
+	for (i=src; i>dest; i--)
+		av[i] = av[i-1];
+	av[dest] = tmp;
+}
+
+static int __getopt_long_core(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx, int longonly)
+{
+	optarg = 0;
+	if (longopts && argv[optind][0] == '-' &&
+		((longonly && argv[optind][1] && argv[optind][1] != '-') ||
+		 (argv[optind][1] == '-' && argv[optind][2])))
+	{
+		int colon = optstring[optstring[0]=='+'||optstring[0]=='-']==':';
+		int i, cnt, match;
+		char *opt;
+		for (cnt=i=0; longopts[i].name; i++) {
+			const char *name = longopts[i].name;
+			opt = argv[optind]+1;
+			if (*opt == '-') opt++;
+			for (; *name && *name == *opt; name++, opt++);
+			if (*opt && *opt != '=') continue;
+			match = i;
+			if (!*name) {
+				cnt = 1;
+				break;
+			}
+			cnt++;
+		}
+		if (cnt==1) {
+			i = match;
+			optind++;
+			optopt = longopts[i].val;
+			if (*opt == '=') {
+				if (!longopts[i].has_arg) {
+					if (colon || !opterr)
+						return '?';
+					__getopt_msg(argv[0],
+						": option does not take an argument: ",
+						longopts[i].name,
+						strlen(longopts[i].name));
+					return '?';
+				}
+				optarg = opt+1;
+			} else if (longopts[i].has_arg == required_argument) {
+				if (!(optarg = argv[optind])) {
+					if (colon) return ':';
+					if (!opterr) return '?';
+					__getopt_msg(argv[0],
+						": option requires an argument: ",
+						longopts[i].name,
+						strlen(longopts[i].name));
+					return '?';
+				}
+				optind++;
+			}
+			if (idx) *idx = i;
+			if (longopts[i].flag) {
+				*longopts[i].flag = longopts[i].val;
+				return 0;
+			}
+			return longopts[i].val;
+		}
+		if (argv[optind][1] == '-') {
+			if (!colon && opterr)
+				__getopt_msg(argv[0], cnt ?
+					": option is ambiguous: " :
+					": unrecognized option: ",
+					argv[optind]+2,
+					strlen(argv[optind]+2));
+			optind++;
+			return '?';
+		}
+	}
+	return getopt(argc, argv, optstring);
+}
+
+static int __getopt_long(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx, int longonly)
+{
+	int ret, skipped, resumed;
+	if (!optind || optreset) {
+		optreset = 0;
+		__optpos = 0;
+		optind = 1;
+	}
+	if (optind >= argc || !argv[optind]) return -1;
+	skipped = optind;
+	if (optstring[0] != '+' && optstring[0] != '-') {
+		int i;
+		for (i=optind; ; i++) {
+			if (i >= argc || !argv[i]) return -1;
+			if (argv[i][0] == '-' && argv[i][1]) break;
+		}
+		optind = i;
+	}
+	resumed = optind;
+	ret = __getopt_long_core(argc, argv, optstring, longopts, idx, longonly);
+	if (resumed > skipped) {
+		int i, cnt = optind-resumed;
+		for (i=0; i<cnt; i++)
+			permute(argv, skipped, optind-1);
+		optind = skipped + cnt;
+	}
+	return ret;
+}
+
+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);
+}
+
+#endif
diff --git a/src/cm.c b/src/cm.c
index d669922..8a30874 100644
--- a/src/cm.c
+++ b/src/cm.c
@@ -1,5 +1,6 @@
 
 #include "cm.h"
+
 #include "common.h"
 
 #if defined(__has_builtin)
diff --git a/src/crc32.c b/src/crc32.c
index d455a44..851cd6c 100644
--- a/src/crc32.c
+++ b/src/crc32.c
@@ -18,6 +18,7 @@
  */
 
 #include "crc32.h"
+
 #include "common.h"
 
 static const u32 crc32Table[256] = {
diff --git a/src/libsais.c b/src/libsais.c
index 04d45e8..5587f28 100644
--- a/src/libsais.c
+++ b/src/libsais.c
@@ -22,7 +22,6 @@ Please see the file LICENSE for full copyright information.
 --*/
 
 #include "libsais.h"
-#include "common.h"
 
 #include <limits.h>
 #include <stddef.h>
@@ -30,6 +29,8 @@ Please see the file LICENSE for full copyright information.
 #include <stdlib.h>
 #include <string.h>
 
+#include "common.h"
+
 #define UNUSED(_x) (void)(_x)
 
 typedef s32 sa_sint_t;
diff --git a/src/main.c b/src/main.c
index 6b5bf32..82d7a82 100644
--- a/src/main.c
+++ b/src/main.c
@@ -25,7 +25,13 @@
 #include <string.h>
 #include <sys/stat.h>
 #include <unistd.h>
-#include <getopt.h>
+
+#ifdef HAVE_GETOPT_LONG
+    #include <getopt.h>
+#else
+    #include "getopt-shim.h"
+#endif
+
 #if defined __MSVCRT__
     #include <fcntl.h>
     #include <io.h>
@@ -39,11 +45,11 @@
 #define MODE_TEST 2
 
 static void version() {
-    fprintf(stdout,
-            "bzip3 "VERSION"\n"
-            "Copyright (C) by Kamila Szewczyk, 2022.\n"
-            "License: GNU Lesser GPL version 3 <https://www.gnu.org/licenses/lgpl-3.0.en.html>\n");
-    }
+    fprintf(stdout, "bzip3 " VERSION
+                    "\n"
+                    "Copyright (C) by Kamila Szewczyk, 2022.\n"
+                    "License: GNU Lesser GPL version 3 <https://www.gnu.org/licenses/lgpl-3.0.en.html>\n");
+}
 
 static void help() {
     fprintf(stdout,
@@ -99,27 +105,25 @@ int main(int argc, char * argv[]) {
     const char * short_options = "b:cdefhtV";
 #endif
 
-    static struct option long_options[] = {
-        {"encode",  no_argument,       0, 'e'},
-        {"decode",  no_argument,       0, 'd'},
-        {"test",    no_argument,       0, 't'},
-        {"stdout",  no_argument,       0, 'c'},
-        {"force",   no_argument,       0, 'f'},
-        {"help",    no_argument,       0, 'h'},
-        {"version", no_argument,       0, 'V'},
-        {"block",   required_argument, 0, 'b'},
+    static struct option long_options[] = { { "encode", no_argument, 0, 'e' },
+                                            { "decode", no_argument, 0, 'd' },
+                                            { "test", no_argument, 0, 't' },
+                                            { "stdout", no_argument, 0, 'c' },
+                                            { "force", no_argument, 0, 'f' },
+                                            { "help", no_argument, 0, 'h' },
+                                            { "version", no_argument, 0, 'V' },
+                                            { "block", required_argument, 0, 'b' },
 #ifdef PTHREAD
-        {"jobs",    required_argument, 0, 'j'},
+                                            { "jobs", required_argument, 0, 'j' },
 #endif
-        {0,         0,                 0,  0 }
-    };
+                                            { 0, 0, 0, 0 } };
 
-    while(1) {
+    while (1) {
         int option_index = 0;
         int c = getopt_long(argc, argv, short_options, long_options, &option_index);
         if (c == -1) break;
 
-        switch(c) {
+        switch (c) {
             case '?':
                 fprintf(stderr, "Try 'bzip3 --help' for more information.\n");
                 return 1;
@@ -192,10 +196,10 @@ int main(int argc, char * argv[]) {
         input = f1;
     else {
         if (mode == MODE_ENCODE) {
-            if(f2 == NULL) {
+            if (f2 == NULL) {
                 // encode from f1?
                 input = f1;
-                if(force_stdstreams)
+                if (force_stdstreams)
                     output = NULL;
                 else {
                     output = (char *)malloc(strlen(f1) + 5);
@@ -204,18 +208,19 @@ int main(int argc, char * argv[]) {
                 }
             } else {
                 // encode from f1 to f2.
-                input = f1; output = f2;
+                input = f1;
+                output = f2;
             }
-        } else if(mode == MODE_DECODE) {
-            if(f2 == NULL) {
+        } else if (mode == MODE_DECODE) {
+            if (f2 == NULL) {
                 // decode from f1 to stdout.
                 input = f1;
-                if(force_stdstreams)
+                if (force_stdstreams)
                     output = NULL;
                 else {
                     output = (char *)malloc(strlen(f1) + 1);
                     strcpy(output, f1);
-                    if(strlen(output) > 4 && !strcmp(output + strlen(output) - 4, ".bz3"))
+                    if (strlen(output) > 4 && !strcmp(output + strlen(output) - 4, ".bz3"))
                         output[strlen(output) - 4] = 0;
                     else {
                         fprintf(stderr, "Warning: file %s has an unknown extension, skipping.\n", f1);
@@ -224,11 +229,12 @@ int main(int argc, char * argv[]) {
                 }
             } else {
                 // decode from f1 to f2.
-                input = f1; output = f2;
+                input = f1;
+                output = f2;
             }
         }
     }
-    
+
     FILE *input_des = NULL, *output_des = NULL;
 
     if (input != NULL) {
diff --git a/src/rle.c b/src/rle.c
index ea1cfd1..87271fc 100644
--- a/src/rle.c
+++ b/src/rle.c
@@ -18,6 +18,7 @@
  */
 
 #include "rle.h"
+
 #include "common.h"
 
 s32 mrlec(u8 * in, s32 inlen, u8 * out) {
tab: 248 wrap: offon