From 249b17332a82ffc0161596cd82e69da225e7fe13 Mon Sep 17 00:00:00 2001 From: Kamila Szewczyk Date: Mon, 16 Dec 2024 15:53:44 +0100 Subject: [PATCH] rip out getopt and replace it with yarg. yarg is a public domain argument parser written by the author of bzip3. --- CMakeLists.txt | 4 - Makefile.am | 2 +- README.md | 1 - configure.ac | 3 - include/getopt-shim.h | 236 --------------------------------- include/yarg.h | 297 ++++++++++++++++++++++++++++++++++++++++++ src/main.c | 148 +++++++++------------ 7 files changed, 357 insertions(+), 334 deletions(-) delete mode 100644 include/getopt-shim.h create mode 100644 include/yarg.h 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 +#include +#include +#include +#include +#include + +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 #include -#ifdef HAVE_GETOPT_LONG - #include -#else - #include "getopt-shim.h" -#endif - #if defined __MSVCRT__ #include #include @@ -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