rip out getopt and replace it with yarg.
yarg is a public domain argument parser written by the author of bzip3.
diff --git a/CMakeLists.txt b/CMakeLists.txt
index bd6d070..4ac224c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -88,10 +88,6 @@ install(
if(BZIP3_BUILD_APPS)
add_executable(bzip3)
target_sources(bzip3 PRIVATE src/main.c)
- check_symbol_exists(getopt_long "getopt.h" HAVE_GETOPT_LONG)
- if(HAVE_GETOPT_LONG)
- target_compile_definitions(bzip3 PRIVATE HAVE_GETOPT_LONG)
- endif()
if(BZIP3_ENABLE_STATIC_EXE)
if(BUILD_SHARED_LIBS)
message(
diff --git a/Makefile.am b/Makefile.am
index 26db061..f7ca2c9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -9,7 +9,7 @@ pkgconfig_DATA = bzip3.pc
include_HEADERS = include/libbz3.h
noinst_HEADERS = include/common.h \
include/libsais.h \
- include/getopt-shim.h
+ include/yarg.h
lib_LTLIBRARIES = libbzip3.la
libbzip3_la_SOURCES = src/libbz3.c
diff --git a/README.md b/README.md
index e77abed..f3934e7 100644
--- a/README.md
+++ b/README.md
@@ -133,7 +133,6 @@ A breakdown of components and their licenses follows:
- (compile-time) `build-aux/ax_check_compile_flag.m4`: Copyright 2008, Guido U. Draheim (guidod@gmx.de), 2011, Maarten Bosmans (mkbosmans@gmail.com); FSFAP
- (compile-time) `build-aux/git-version-gen`: Copyright 2007-2012, Free Software Foundation, Inc; GPLv3
- (runtime) `bz3grep`: Copyright 2003, Thomas Klausner; BSD-2-clause
-- (runtime) `include/getopt-shim.h`: Copyright 2005-2014, Rich Felker; Expat
`bzip3` as a whole is licensed under LGPLv3 only. It is not dual-licensed under LGPLv3 and Apache 2.0.
diff --git a/configure.ac b/configure.ac
index af7c136..b846095 100644
--- a/configure.ac
+++ b/configure.ac
@@ -16,9 +16,6 @@ LT_INIT
PKG_PROG_PKG_CONFIG
PKG_INSTALLDIR
-AC_CHECK_HEADERS([getopt.h])
-AC_CHECK_FUNCS([getopt_long])
-
AC_C_RESTRICT
AC_ARG_WITH([pthread],
diff --git a/include/getopt-shim.h b/include/getopt-shim.h
deleted file mode 100644
index 6a7a9db..0000000
--- a/include/getopt-shim.h
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- 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
-
-#ifdef WIN32
-static void flockfile(FILE * f) { _lock_file(f); }
-static void funlockfile(FILE * f) { _unlock_file(f); }
-#endif
-
-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/include/yarg.h b/include/yarg.h
new file mode 100644
index 0000000..8ce9028
--- /dev/null
+++ b/include/yarg.h
@@ -0,0 +1,297 @@
+/* Written by Kamila Szewczyk (kspalaiologos@gmail.com) */
+
+#ifndef _YARG_H
+#define _YARG_H
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+typedef enum {
+ no_argument,
+ required_argument,
+ optional_argument
+} yarg_arg_type;
+
+typedef struct {
+ int opt;
+ yarg_arg_type type;
+ const char * long_opt;
+} yarg_options;
+
+typedef enum {
+ YARG_STYLE_WINDOWS,
+ YARG_STYLE_UNIX,
+ YARG_STYLE_UNIX_SHORT
+} yarg_style;
+
+typedef struct {
+ bool dash_dash;
+ yarg_style style;
+} yarg_settings;
+
+typedef struct {
+ int opt;
+ const char * long_opt;
+ char * arg;
+} yarg_option;
+
+typedef struct {
+ yarg_option * args;
+ int argc;
+ char ** pos_args;
+ int pos_argc;
+ char * error;
+} yarg_result;
+
+static void * yarg_alloc(size_t size) {
+ void * ptr = calloc(size, 1);
+ if (!ptr) { perror("calloc"); exit(1); }
+ return ptr;
+}
+
+static int yarg_asprintf(char ** strp, const char * fmt, ...) {
+ va_list ap;
+ va_start(ap, fmt);
+ int len = vsnprintf(NULL, 0, fmt, ap);
+ va_end(ap);
+ if (len < 0) return -1;
+ *strp = (char *) malloc(len + 1);
+ if (!*strp) return -1;
+ va_start(ap, fmt);
+ len = vsnprintf(*strp, len + 1, fmt, ap);
+ va_end(ap);
+ return len;
+}
+
+static char * yarg_strdup(const char * str) {
+ char * new_str = (char *) yarg_alloc(strlen(str) + 1);
+ strcpy(new_str, str);
+ return new_str;
+}
+
+static void yarg_parse_unix(int argc, char * argv[], yarg_options opt[],
+ yarg_result * res, bool dash_dash) {
+ int no_args = 0, no_pos_args = 0;
+ for (int i = 1; i < argc; i++) {
+ if (argv[i][0] == '-') {
+ if (argv[i][1] == '-') {
+ if (dash_dash && argv[i][2] == '\0')
+ { no_pos_args += argc - i - 1; break; }
+ char * long_opt = argv[i] + 2; yarg_options * o = NULL;
+ int len = 0; while (long_opt[len] && long_opt[len] != '=') len++;
+ for (int j = 0; opt[j].opt; j++)
+ if (opt[j].long_opt && !strncmp(opt[j].long_opt, long_opt, len))
+ { o = &opt[j]; break; }
+ if (!o) {
+ asprintf(&res->error, "--%.*s -- unknown option\n", len, long_opt);
+ return;
+ }
+ if (o->type == required_argument) {
+ if (long_opt[len] == '=') {
+ // Ignore.
+ } else if (argv[i + 1] && argv[i + 1][0] != '-') {
+ i++;
+ } else {
+ asprintf(&res->error, "--%s -- missing argument\n", o->long_opt);
+ return;
+ }
+ } else if (o->type == optional_argument) {
+ if (long_opt[len] == '=') {
+ } else if (argv[i + 1] && argv[i + 1][0] != '-') {
+ i++;
+ }
+ }
+ no_args++;
+ } else {
+ for (int j = 1; argv[i][j]; j++) {
+ char c = argv[i][j]; yarg_options * o = NULL;
+ for (int k = 0; opt[k].opt; k++)
+ if (opt[k].opt == c)
+ { o = &opt[k]; break; }
+ if (!o) {
+ asprintf(&res->error, "-%c -- unknown option\n", c);
+ return;
+ }
+ if (o->type == required_argument) {
+ if (argv[i][j + 1]) {
+ // Ignore.
+ } else if (argv[i + 1] && argv[i + 1][0] != '-') {
+ i++;
+ } else {
+ asprintf(&res->error, "-%c -- missing argument\n", c);
+ return;
+ }
+ no_args++;
+ break;
+ } else if(o->type == optional_argument) {
+ if (argv[i][j + 1]) {
+ // Ignore.
+ no_args++;
+ break;
+ } else if (argv[i + 1] && argv[i + 1][0] != '-') {
+ i++;
+ no_args++;
+ break;
+ }
+ }
+ no_args++;
+ }
+ }
+ } else no_pos_args++;
+ }
+
+ res->args = (yarg_option *) yarg_alloc((no_args + 1) * sizeof(yarg_option));
+ res->pos_args = (char **) yarg_alloc((no_pos_args + 1) * sizeof(char *));
+
+ for (int i = 1; i < argc; i++) {
+ if (argv[i][0] == '-') {
+ if (argv[i][1] == '-') {
+ if (dash_dash && argv[i][2] == '\0') {
+ for (int j = i + 1; j < argc; j++)
+ res->pos_args[res->pos_argc++] = yarg_strdup(argv[j]);
+ break;
+ }
+ char * long_opt = argv[i] + 2; yarg_options * o = NULL;
+ int len = 0; while (long_opt[len] && long_opt[len] != '=') len++;
+ for (int j = 0; opt[j].opt; j++)
+ if (opt[j].long_opt && !strncmp(opt[j].long_opt, long_opt, len))
+ { o = &opt[j]; break; }
+ res->args[res->argc].opt = o->opt;
+ res->args[res->argc].long_opt = o->long_opt;
+ if (o->type == required_argument || o->type == optional_argument) {
+ if (long_opt[len] == '=') {
+ res->args[res->argc].arg = yarg_strdup(long_opt + len + 1);
+ } else if (argv[i + 1] && argv[i + 1][0] != '-') {
+ res->args[res->argc].arg = yarg_strdup(argv[++i]);
+ }
+ }
+ res->argc++;
+ } else {
+ for (int j = 1; argv[i][j]; j++) {
+ char c = argv[i][j]; yarg_options * o = NULL;
+ for (int k = 0; opt[k].opt; k++)
+ if (opt[k].opt == c)
+ { o = &opt[k]; break; }
+ if (!o) {
+ asprintf(&res->error, "-%c -- unknown option\n", c);
+ return;
+ }
+ res->args[res->argc].opt = c;
+ res->args[res->argc].long_opt = o->long_opt;
+ if (o->type == required_argument || o->type == optional_argument) {
+ if (argv[i][j + 1]) {
+ res->args[res->argc++].arg = yarg_strdup(argv[i] + j + 1);
+ break;
+ } else if (argv[i + 1] && argv[i + 1][0] != '-') {
+ res->args[res->argc++].arg = yarg_strdup(argv[++i]);
+ break;
+ }
+ }
+ res->argc++;
+ }
+ }
+ } else res->pos_args[res->pos_argc++] = yarg_strdup(argv[i]);
+ }
+}
+
+static void yarg_parse_unix_short(int argc, char * argv[], yarg_options opt[],
+ yarg_result * res, bool dash_dash, char opt_char) {
+ int no_args = 0, no_pos_args = 0;
+ for (int i = 1; i < argc; i++) {
+ if (argv[i][0] == opt_char) {
+ if (dash_dash && argv[i][1] == '\0') {
+ no_pos_args += argc - i - 1;
+ break;
+ }
+ char * long_opt = argv[i] + 1; yarg_options * o = NULL;
+ int len = 0; while (long_opt[len] && long_opt[len] != '=') len++;
+ for (int j = 0; opt[j].opt; j++)
+ if (opt[j].long_opt && !strncmp(opt[j].long_opt, long_opt, len))
+ { o = &opt[j]; break; }
+ if (!o) {
+ asprintf(&res->error, "%c%.*s -- unknown option\n", opt_char, len, long_opt);
+ return;
+ }
+ if (o->type == required_argument) {
+ if (long_opt[len] == '=') {
+ // Ignore.
+ } else if (argv[i + 1] && argv[i + 1][0] != opt_char) {
+ i++;
+ } else {
+ asprintf(&res->error, "%c%s -- missing argument\n", opt_char, o->long_opt);
+ return;
+ }
+ } else if (o->type == optional_argument) {
+ if (long_opt[len] == '=') {
+ // Ignore.
+ } else if (argv[i + 1] && argv[i + 1][0] != opt_char) {
+ i++;
+ }
+ }
+ no_args++;
+ } else no_pos_args++;
+ }
+
+ res->args = (yarg_option *) yarg_alloc((no_args + 1) * sizeof(yarg_option));
+ res->pos_args = (char **) yarg_alloc((no_pos_args + 1) * sizeof(char *));
+
+ for (int i = 1; i < argc; i++) {
+ if (argv[i][0] == opt_char) {
+ if (dash_dash && argv[i][1] == '\0') {
+ for (int j = i + 1; j < argc; j++)
+ res->pos_args[res->pos_argc++] = yarg_strdup(argv[j]);
+ break;
+ }
+ char * long_opt = argv[i] + 1; yarg_options * o = NULL;
+ int len = 0; while (long_opt[len] && long_opt[len] != '=') len++;
+ for (int j = 0; opt[j].opt; j++)
+ if (opt[j].long_opt && !strncmp(opt[j].long_opt, long_opt, len))
+ { o = &opt[j]; break; }
+ res->args[res->argc].opt = o->opt;
+ res->args[res->argc].long_opt = o->long_opt;
+ if (o->type == required_argument || o->type == optional_argument) {
+ if (long_opt[len] == '=') {
+ res->args[res->argc].arg = yarg_strdup(long_opt + len + 1);
+ } else if (argv[i + 1] && argv[i + 1][0] != opt_char) {
+ res->args[res->argc].arg = yarg_strdup(argv[++i]);
+ }
+ }
+ res->argc++;
+ } else res->pos_args[res->pos_argc++] = yarg_strdup(argv[i]);
+ }
+}
+
+void yarg_destroy(yarg_result * r) {
+ for (int i = 0; i < r->argc; i++) {
+ free(r->args[i].arg);
+ }
+ free(r->args);
+ for (int i = 0; i < r->pos_argc; i++) {
+ free(r->pos_args[i]);
+ }
+ free(r->pos_args);
+ free(r->error);
+ free(r);
+}
+
+yarg_result * yarg_parse(int argc, char * argv[], yarg_options opt[], yarg_settings settings) {
+ yarg_result * res = (yarg_result *) yarg_alloc(sizeof(yarg_result));
+ switch (settings.style) {
+ case YARG_STYLE_WINDOWS:
+ yarg_parse_unix_short(argc, argv, opt, res, false, '/');
+ break;
+ case YARG_STYLE_UNIX:
+ yarg_parse_unix(argc, argv, opt, res, settings.dash_dash);
+ break;
+ case YARG_STYLE_UNIX_SHORT:
+ yarg_parse_unix_short(argc, argv, opt, res, settings.dash_dash, '-');
+ break;
+ }
+ return res;
+}
+
+#endif
diff --git a/src/main.c b/src/main.c
index cb7108b..17116f3 100644
--- a/src/main.c
+++ b/src/main.c
@@ -27,12 +27,6 @@
#include <sys/stat.h>
#include <unistd.h>
-#ifdef HAVE_GETOPT_LONG
- #include <getopt.h>
-#else
- #include "getopt-shim.h"
-#endif
-
#if defined __MSVCRT__
#include <fcntl.h>
#include <io.h>
@@ -40,6 +34,7 @@
#include "common.h"
#include "libbz3.h"
+#include "yarg.h"
#define MODE_DECODE 0
#define MODE_ENCODE 1
@@ -561,91 +556,68 @@ int main(int argc, char * argv[]) {
// the block size
u32 block_size = MiB(16);
-#ifdef PTHREAD
- const char * short_options = "Bb:cdefhj:krtvVz";
-#else
- const char * short_options = "Bb:cdefhkrtvVz";
-#endif
-
enum { RM_OPTION = CHAR_MAX + 1 };
- 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' },
- { "recover", no_argument, 0, 'r' },
- { "help", no_argument, 0, 'h' },
- { "rm", no_argument, 0, RM_OPTION },
- { "keep", no_argument, 0, 'k' },
- { "version", no_argument, 0, 'V' },
- { "verbose", no_argument, 0, 'v' },
- { "block", required_argument, 0, 'b' },
- { "batch", no_argument, 0, 'B' },
+ yarg_options opt[] = {
+ { 'e', no_argument, "encode" },
+ { 'z', no_argument, "encode" }, /* alias */
+ { 'd', no_argument, "decode" },
+ { 't', no_argument, "test" },
+ { 'c', no_argument, "stdout" },
+ { 'f', no_argument, "force" },
+ { 'r', no_argument, "recover" },
+ { 'h', no_argument, "help" },
+ { RM_OPTION, no_argument, "rm" },
+ { 'k', no_argument, "keep" },
+ { 'V', no_argument, "version" },
+ { 'v', no_argument, "verbose" },
+ { 'b', required_argument, "block" },
+ { 'B', no_argument, "batch" },
#ifdef PTHREAD
- { "jobs", required_argument, 0, 'j' },
+ { 'j', required_argument, "jobs" },
#endif
- { 0, 0, 0, 0 } };
-
- while (1) {
- int option_index = 0;
- int c = getopt_long(argc, argv, short_options, long_options, &option_index);
- if (c == -1) break;
-
- switch (c) {
- case '?':
- fprintf(stderr, "Try 'bzip3 --help' for more information.\n");
- return 1;
- case 'e':
- case 'z':
- mode = MODE_ENCODE;
- break;
- case 'd':
- mode = MODE_DECODE;
- break;
- case 'r':
- mode = MODE_RECOVER;
- break;
- case 't':
- mode = MODE_TEST;
- break;
- case 'c':
- force_stdstreams = 1;
- break;
- case 'f':
- force = 1;
- break;
- case RM_OPTION:
- remove_input_file = 1;
- break;
- case 'k':
- break;
- case 'h':
- help();
- return 0;
- case 'V':
- version();
- return 0;
- case 'B':
- batch = 1;
- break;
- case 'v':
- verbose = 1;
- break;
+ { 0, no_argument, NULL }
+ };
+ yarg_settings settings = {
+ .dash_dash = true,
+ .style = YARG_STYLE_UNIX,
+ };
+ yarg_result * res = yarg_parse(argc, argv, opt, settings);
+ if (res->error) {
+ fputs(res->error, stderr);
+ fputs("Try 'bzip3 --help' for more information.\n", stderr);
+ return 1;
+ }
+ // `res' is not freed later on as it has the approximate lifetime
+ // equal to the lifetime of the program overall.
+ for (int i = 0; i < res->argc; i++) {
+ switch(res->args[i].opt) {
+ case 'e': case 'z': mode = MODE_ENCODE; break;
+ case 'd': mode = MODE_DECODE; break;
+ case 'r': mode = MODE_RECOVER; break;
+ case 't': mode = MODE_TEST; break;
+ case 'c': force_stdstreams = 1; break;
+ case 'f': force = 1; break;
+ case RM_OPTION: remove_input_file = 1; break;
+ case 'k': break;
+ case 'h': help(); return 0;
+ case 'V': version(); return 0;
+ case 'B': batch = 1; break;
+ case 'v': verbose = 1; break;
case 'b':
- if (!is_numeric(optarg)) {
- fprintf(stderr, "bzip3: invalid block size: %s\n", optarg);
+ if (!is_numeric(res->args[i].arg)) {
+ fprintf(stderr, "bzip3: invalid block size: %s\n", res->args[i].arg);
return 1;
}
- block_size = MiB(atoi(optarg));
+ block_size = MiB(atoi(res->args[i].arg));
break;
#ifdef PTHREAD
case 'j':
- if (!is_numeric(optarg)) {
- fprintf(stderr, "bzip3: invalid amount of jobs: %s\n", optarg);
+ if (!is_numeric(res->args[i].arg)) {
+ fprintf(stderr, "bzip3: invalid amount of jobs: %s\n", res->args[i].arg);
return 1;
}
- workers = atoi(optarg);
+ workers = atoi(res->args[i].arg);
break;
#endif
}
@@ -665,8 +637,8 @@ int main(int argc, char * argv[]) {
switch (mode) {
case MODE_ENCODE:
/* Encode each of the files. */
- while (optind < argc) {
- char * arg = argv[optind++];
+ for (int i = 0; i < res->pos_argc; i++) {
+ char * arg = res->pos_args[i];
FILE * input_des = open_input(arg);
char * output_name;
@@ -692,8 +664,8 @@ int main(int argc, char * argv[]) {
case MODE_RECOVER:
case MODE_DECODE:
/* Decode each of the files. */
- while (optind < argc) {
- char * arg = argv[optind++];
+ for (int i = 0; i < res->pos_argc; i++) {
+ char * arg = res->pos_args[i];
FILE * input_des = open_input(arg);
char * output_name;
@@ -723,8 +695,8 @@ int main(int argc, char * argv[]) {
break;
case MODE_TEST:
/* Test each of the files. */
- while (optind < argc) {
- char * arg = argv[optind++];
+ for (int i = 0; i < res->pos_argc; i++) {
+ char * arg = res->pos_args[i];
FILE * input_des = open_input(arg);
process(input_des, NULL, mode, block_size, workers, verbose, arg);
@@ -741,9 +713,8 @@ int main(int argc, char * argv[]) {
return 0;
}
- while (optind < argc) {
- // Positional argument. Likely a file name.
- char * arg = argv[optind++];
+ for (int i = 0; i < res->pos_argc; i++) {
+ char * arg = res->pos_args[i];
if (f1 != NULL && f2 != NULL) {
fprintf(stderr, "Error: too many files specified.\n");
@@ -819,6 +790,5 @@ int main(int argc, char * argv[]) {
if (remove_input_file) {
remove_in_file(input, output_des);
}
-
return r;
}
\ No newline at end of file
