[Forensics-changes] [yara] 228/407: Replace argparse with my own argument parsing code

Hilko Bengen bengen at moszumanska.debian.org
Sat Jul 1 10:28:29 UTC 2017


This is an automated email from the git hooks/post-receive script.

bengen pushed a commit to annotated tag v3.3.0
in repository yara.

commit 116b5e1b3bdfa4e787f722f91de08f0dc26ccc3c
Author: Victor Manuel Alvarez <vmalvarez at virustotal.com>
Date:   Sat Nov 22 23:38:48 2014 +0100

    Replace argparse with my own argument parsing code
---
 Makefile.am              |  12 +-
 argparse/.gitignore      |   5 -
 argparse/.travis.yml     |   5 -
 argparse/LICENSE         |  21 ---
 argparse/README.md       |  89 ----------
 argparse/argparse.c      | 366 --------------------------------------
 argparse/argparse.h      | 165 ------------------
 argparse/tap-functions   | 445 -----------------------------------------------
 argparse/test.sh         |  46 -----
 argparse/test_argparse.c |  57 ------
 args.c                   | 278 +++++++++++++++++++++++++++++
 args.h                   |  92 ++++++++++
 yara.c                   |  64 ++++---
 yarac.c                  |  50 ++++--
 14 files changed, 456 insertions(+), 1239 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index 6c237a4..74dd4e1 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,18 +1,18 @@
 AM_CFLAGS=-O3 -std=gnu99 -Wall -I$(srcdir)/libyara/include
 
 # Build the library in the hand subdirectory first.
-SUBDIRS = libyara argparse
-DIST_SUBDIRS = libyara argparse
+SUBDIRS = libyara
+DIST_SUBDIRS = libyara
 
 ACLOCAL_AMFLAGS=-I m4
 
 bin_PROGRAMS = yara yarac
 
-yara_SOURCES = threading.c threading.h yara.c
-yara_LDADD = libyara/.libs/libyara.a argparse/libargparse.a
+yara_SOURCES = args.c args.h threading.c threading.h yara.c
+yara_LDADD = libyara/.libs/libyara.a
 
-yarac_SOURCES = yarac.c
-yarac_LDADD = libyara/.libs/libyara.a argparse/libargparse.a
+yarac_SOURCES = args.c args.h yarac.c
+yarac_LDADD = libyara/.libs/libyara.a
 
 # man pages
 man1_MANS = yara.man yarac.man
diff --git a/argparse/.gitignore b/argparse/.gitignore
deleted file mode 100755
index fb716d2..0000000
--- a/argparse/.gitignore
+++ /dev/null
@@ -1,5 +0,0 @@
-tags
-test_argparse
-*.[ao]
-*.dylib
-*.so
diff --git a/argparse/.travis.yml b/argparse/.travis.yml
deleted file mode 100755
index 41bac87..0000000
--- a/argparse/.travis.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-language: c
-compiler:
-  - gcc
-  - clang
-script: make test
diff --git a/argparse/LICENSE b/argparse/LICENSE
deleted file mode 100755
index 3c77749..0000000
--- a/argparse/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2012-2013 Yecheng Fu <cofyc.jackson at gmail.com>
-
-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.
diff --git a/argparse/README.md b/argparse/README.md
deleted file mode 100755
index 6d2ee87..0000000
--- a/argparse/README.md
+++ /dev/null
@@ -1,89 +0,0 @@
-NAME
-====
-
-argparse - A command line arguments parsing library.
-
-[![Build Status](https://travis-ci.org/Cofyc/argparse.png)](https://travis-ci.org/Cofyc/argparse)
-
-DESCRIPTION
-===========
-
-This module is inspired by parse-options.c (git) and python's argparse
-module.
-
-Arguments parsing is common task in cli program, but traditional `getopt`
-libraries are not easy to use. This library provides high-level arguments
-parsing solutions.
-
-The program defines what arguments it requires, and `argparse` will figure
-out how to parse those out of `argc` and `argv`, it also automatically
-generates help and usage messages and issues errors when users give the
-program invalid arguments.
-
-Features
-========
-
- - handles both optional and positional arguments
- - produces highly informative usage messages
- - issures errors when given invalid arguments
-
-There are basically three types of options:
-
- - boolean options
- - options with mandatory argument
- - options with optional argument
-
-There are basically two forms of options:
-
- - short option consist of one dash (`-`) and one alphanumeric character.
- - long option begin with two dashes (`--`) and some alphanumeric characters.
-
-Short options may be bundled, e.g. `-a -b` can be specified as `-ab`.
-
-Options are case-sensitive.
-
-Options and non-option arguments can clearly be separated using the `--` option.
-
-Examples
-========
-
-```c
-#include "argparse.h"
-
-static const char *const usage[] = {
-   "test_argparse [options] [[--] args]",
-   NULL,
-};
-
-int
-main(int argc, const char **argv)
-{
-   int force = 0;
-   int num = 0;
-   const char *path = NULL;
-   struct argparse_option options[] = {
-       OPT_HELP(),
-       OPT_BOOLEAN('f', "force", &force, "force to do", NULL),
-       OPT_STRING('p', "path", &path, "path to read", NULL),
-       OPT_INTEGER('n', "num", &num, "selected num", NULL),
-       OPT_END(),
-   };
-   struct argparse argparse;
-   argparse_init(&argparse, options, usage, 0);
-   argc = argparse_parse(&argparse, argc, argv);
-   if (force != 0)
-       printf("force: %d\n", force);
-   if (path != NULL)
-       printf("path: %s\n", path);
-   if (num != 0)
-       printf("num: %d\n", num);
-   if (argc != 0) {
-       printf("argc: %d\n", argc);
-       int i;
-       for (i = 0; i < argc; i++) {
-           printf("argv[%d]: %s\n", i, *(argv + i));
-       }
-   }
-   return 0;
-}
-```
diff --git a/argparse/argparse.c b/argparse/argparse.c
deleted file mode 100755
index e60b76c..0000000
--- a/argparse/argparse.c
+++ /dev/null
@@ -1,366 +0,0 @@
-#include "argparse.h"
-
-#define OPT_UNSET 1
-
-static const char *
-prefix_skip(const char *str, const char *prefix)
-{
-    size_t len = strlen(prefix);
-    return strncmp(str, prefix, len) ? NULL : str + len;
-}
-
-int
-prefix_cmp(const char *str, const char *prefix)
-{
-    for (;; str++, prefix++)
-        if (!*prefix)
-            return 0;
-        else if (*str != *prefix)
-            return (unsigned char)*prefix - (unsigned char)*str;
-}
-
-static void
-argparse_error(struct argparse *self, struct argparse_option *opt,
-               const char *reason)
-{
-    if (!strncmp(self->argv[0], "--", 2)) {
-        fprintf(stderr, "error: option `%s` %s\n", opt->long_name, reason);
-        exit(1);
-    } else {
-        fprintf(stderr, "error: option `%c` %s\n", opt->short_name, reason);
-        exit(1);
-    }
-}
-
-static int
-argparse_getvalue(struct argparse *self, struct argparse_option *opt,
-                  int flags)
-{
-    const char *s = NULL;
-
-    if (opt->count == opt->max_count)
-        argparse_error(self, opt, "repeated too many times");
-
-    if (!opt->value)
-        goto skipped;
-
-    switch (opt->type) {
-    case ARGPARSE_OPT_BOOLEAN:
-        if (flags & OPT_UNSET) {
-            *(int *)opt->value = *(int *)opt->value - 1;
-        } else {
-            *(int *)opt->value = *(int *)opt->value + 1;
-        }
-        if (*(int *)opt->value < 0) {
-            *(int *)opt->value = 0;
-        }
-        break;
-    case ARGPARSE_OPT_BIT:
-        if (flags & OPT_UNSET) {
-            *(int *)opt->value &= ~opt->data;
-        } else {
-            *(int *)opt->value |= opt->data;
-        }
-        break;
-    case ARGPARSE_OPT_STRING:
-        if (self->optvalue) {
-            *(const char **)opt->value = self->optvalue;
-            self->optvalue = NULL;
-        } else if (self->argc > 1) {
-            self->argc--;
-            if (opt->max_count > 1) {
-                ((const char**)opt->value)[opt->count] = *++self->argv;
-            }
-            else {
-                *(const char **)opt->value = *++self->argv;
-            }
-        } else {
-            argparse_error(self, opt, "requires a value");
-        }
-        break;
-    case ARGPARSE_OPT_INTEGER:
-        if (self->optvalue) {
-            *(int *)opt->value = strtol(self->optvalue, (char **)&s, 0);
-            self->optvalue = NULL;
-        } else if (self->argc > 1) {
-            self->argc--;
-            if (opt->max_count > 1) {
-                ((int*)opt->value)[opt->count] = strtol(*++self->argv, (char **)&s, 0);
-            }
-            else {
-                *(int *)opt->value = strtol(*++self->argv, (char **)&s, 0);
-            }
-        } else {
-            argparse_error(self, opt, "requires a value");
-        }
-        if (s[0] != '\0')
-            argparse_error(self, opt, "expects a numerical value");
-        break;
-    default:
-        assert(0);
-    }
-
-    opt->count++;
-
-skipped:
-    if (opt->callback) {
-        return opt->callback(self, opt);
-    }
-
-    return 0;
-}
-
-static void
-argparse_options_check(struct argparse_option *options)
-{
-    for (; options->type != ARGPARSE_OPT_END; options++) {
-        switch (options->type) {
-        case ARGPARSE_OPT_END:
-        case ARGPARSE_OPT_BOOLEAN:
-        case ARGPARSE_OPT_BIT:
-        case ARGPARSE_OPT_INTEGER:
-        case ARGPARSE_OPT_STRING:
-        case ARGPARSE_OPT_GROUP:
-            continue;
-        default:
-            fprintf(stderr, "wrong option type: %d", options->type);
-            break;
-        }
-    }
-}
-
-static int
-argparse_short_opt(struct argparse *self, struct argparse_option *options)
-{
-    for (; options->type != ARGPARSE_OPT_END; options++) {
-        if (options->short_name == *self->optvalue) {
-            self->optvalue = self->optvalue[1] ? self->optvalue + 1 : NULL;
-            return argparse_getvalue(self, options, 0);
-        }
-    }
-    return -2;
-}
-
-static int
-argparse_long_opt(struct argparse *self, struct argparse_option *options)
-{
-    for (; options->type != ARGPARSE_OPT_END; options++) {
-        const char *rest;
-        int opt_flags = 0;
-        if (!options->long_name)
-            continue;
-
-        rest = prefix_skip(self->argv[0] + 2, options->long_name);
-        if (!rest) {
-            // Negation allowed?
-            if (options->flags & OPT_NONEG) {
-                continue;
-            }
-            // Only boolean/bit allow negation.
-            if (options->type != ARGPARSE_OPT_BOOLEAN && options->type != ARGPARSE_OPT_BIT) {
-                continue;
-            }
-
-            if (!prefix_cmp(self->argv[0] + 2, "no-")) {
-                rest = prefix_skip(self->argv[0] + 2 + 3, options->long_name);
-                if (!rest)
-                    continue;
-                opt_flags |= OPT_UNSET;
-            } else {
-                continue;
-            }
-        }
-        if (*rest) {
-            if (*rest != '=')
-                continue;
-            self->optvalue = rest + 1;
-        }
-        return argparse_getvalue(self, options, opt_flags);
-    }
-    return -2;
-}
-
-int
-argparse_init(struct argparse *self, struct argparse_option *options,
-              const char *const *usage, int flags)
-{
-    memset(self, 0, sizeof(*self));
-    self->options = options;
-    self->usage = usage;
-    self->flags = flags;
-
-    for (; options->type != ARGPARSE_OPT_END; options++)
-        options->count = 0;
-
-    return 0;
-}
-
-int
-argparse_parse(struct argparse *self, int argc, const char **argv)
-{
-    self->argc = argc - 1;
-    self->argv = argv + 1;
-    self->out = argv;
-
-    argparse_options_check(self->options);
-
-    for (; self->argc; self->argc--, self->argv++) {
-        const char *arg = self->argv[0];
-        if (arg[0] != '-' || !arg[1]) {
-            if (self->flags & ARGPARSE_STOP_AT_NON_OPTION) {
-                goto end;
-            }
-            // if it's not option or is a single char '-', copy verbatimly
-            self->out[self->cpidx++] = self->argv[0];
-            continue;
-        }
-        // short option
-        if (arg[1] != '-') {
-            self->optvalue = arg + 1;
-            switch (argparse_short_opt(self, self->options)) {
-            case -1:
-                break;
-            case -2:
-                goto unknown;
-            }
-            while (self->optvalue) {
-                switch (argparse_short_opt(self, self->options)) {
-                case -1:
-                    break;
-                case -2:
-                    goto unknown;
-                }
-            }
-            continue;
-        }
-        // if '--' presents
-        if (!arg[2]) {
-            self->argc--;
-            self->argv++;
-            break;
-        }
-        // long option
-        switch (argparse_long_opt(self, self->options)) {
-        case -1:
-            break;
-        case -2:
-            goto unknown;
-        }
-        continue;
-
-unknown:
-        fprintf(stderr, "error: unknown option `%s`\n", self->argv[0]);
-        argparse_usage(self);
-        exit(1);
-    }
-
-end:
-    memmove(self->out + self->cpidx, self->argv,
-            self->argc * sizeof(*self->out));
-    self->out[self->cpidx + self->argc] = NULL;
-
-    return self->cpidx + self->argc;
-}
-
-void
-argparse_usage(struct argparse *self)
-{
-    fprintf(stdout, "Usage: %s\n", *self->usage++);
-    while (*self->usage && **self->usage)
-        fprintf(stdout, "   or: %s\n", *self->usage++);
-    fputc('\n', stdout);
-
-    struct argparse_option *options;
-
-    // figure out best width
-    size_t usage_opts_width = 0;
-    size_t len;
-    options = self->options;
-    for (; options->type != ARGPARSE_OPT_END; options++) {
-        len = 0;
-        if ((options)->short_name) {
-            len += 2;
-        }
-        if ((options)->short_name && (options)->long_name) {
-            len += 2;           // separator ", "
-        }
-        if ((options)->long_name) {
-            len += strlen((options)->long_name) + 2;
-        }
-        if (options->type == ARGPARSE_OPT_INTEGER) {
-            len++; // equal sign "=" or space
-            if (options->type_help != NULL)
-                len += strlen(options->type_help);
-            else
-                len += strlen("<int>");
-        } else if (options->type == ARGPARSE_OPT_STRING) {
-            len++; // equal sign "=" or space
-            if (options->type_help != NULL)
-                len += strlen(options->type_help);
-            else
-                len += strlen("<str>");
-        }
-        len = (len / 4) * 4 + 4;
-        if (usage_opts_width < len) {
-            usage_opts_width = len;
-        }
-    }
-    usage_opts_width += 4;      // 4 spaces prefix
-
-    options = self->options;
-    for (; options->type != ARGPARSE_OPT_END; options++) {
-        size_t pos = 0;
-        size_t pad = 0;
-        if (options->type == ARGPARSE_OPT_GROUP) {
-            fputc('\n', stdout);
-            fprintf(stdout, "%s", options->help);
-            fputc('\n', stdout);
-            continue;
-        }
-        pos = fprintf(stdout, "    ");
-        if (options->short_name) {
-            pos += fprintf(stdout, "-%c", options->short_name);
-        }
-        if (options->long_name && options->short_name) {
-            pos += fprintf(stdout, ", ");
-        }
-        if (options->long_name) {
-            pos += fprintf(stdout, "--%s", options->long_name);
-        }
-        if (options->type == ARGPARSE_OPT_INTEGER) {
-            if (options->long_name)
-                pos += fprintf(stdout, "=");
-            else
-                pos += fprintf(stdout, " ");
-            if (options->type_help != NULL)
-                pos += fprintf(stdout, "%s", options->type_help);
-            else
-                pos += fprintf(stdout, "<int>");
-        } else if (options->type == ARGPARSE_OPT_STRING) {
-            if (options->long_name)
-                pos += fprintf(stdout, "=");
-            else
-                pos += fprintf(stdout, " ");
-            if (options->type_help != NULL)
-                pos += fprintf(stdout, "%s", options->type_help);
-            else
-                pos += fprintf(stdout, "<str>");
-        }
-        if (pos <= usage_opts_width) {
-            pad = usage_opts_width - pos;
-        } else {
-            fputc('\n', stdout);
-            pad = usage_opts_width;
-        }
-        fprintf(stdout, "%*s%s\n", pad + 2, "", options->help);
-    }
-}
-
-int
-argparse_help_cb(struct argparse *self, const struct argparse_option *option)
-{
-    (void)option;
-    argparse_usage(self);
-    exit(0);
-    return 0;
-}
diff --git a/argparse/argparse.h b/argparse/argparse.h
deleted file mode 100755
index 183be46..0000000
--- a/argparse/argparse.h
+++ /dev/null
@@ -1,165 +0,0 @@
-#ifndef ARGPARSE_H
-#define ARGPARSE_H
-/**
- * Command-line arguments parsing library.
- *
- * This module is inspired by parse-options.c (git) and python's argparse
- * module.
- *
- * Arguments parsing is common task in cli program, but traditional `getopt`
- * libraries are not easy to use. This library provides high-level arguments
- * parsing solutions.
- *
- * The program defines what arguments it requires, and `argparse` will figure
- * out how to parse those out of `argc` and `argv`, it also automatically
- * generates help and usage messages and issues errors when users give the
- * program invalid arguments.
- *
- * Reserved namespaces:
- *  argparse
- *  OPT
- * Author: Yecheng Fu <cofyc.jackson at gmail.com>
- */
-
-#include <assert.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct argparse;
-struct argparse_option;
-
-typedef int argparse_callback(struct argparse *self,
-                              const struct argparse_option *option);
-
-enum argparse_flag {
-    ARGPARSE_STOP_AT_NON_OPTION = 1,
-};
-
-enum argparse_option_type {
-    /* special */
-    ARGPARSE_OPT_END,
-    ARGPARSE_OPT_GROUP,
-    /* options with no arguments */
-    ARGPARSE_OPT_BOOLEAN,
-    ARGPARSE_OPT_BIT,
-    /* options with arguments (optional or required) */
-    ARGPARSE_OPT_INTEGER,
-    ARGPARSE_OPT_STRING,
-    /* repetable options */
-    ARGPARSE_OPT_INTEGER_MULTI,
-    ARGPARSE_OPT_STRING_MULTI,
-};
-
-enum argparse_option_flags {
-    OPT_NONEG = 1,              /* Negation disabled. */
-};
-
-/*
- *  Argparse option struct.
- *
- *  `type`:
- *    holds the type of the option, you must have an ARGPARSE_OPT_END last in your
- *    array.
- *
- *  `short_name`:
- *    the character to use as a short option name, '\0' if none.
- *
- *  `long_name`:
- *    the long option name, without the leading dash, NULL if none.
- *
- *  `value`:
- *    stores pointer to the value to be filled.
- *
- *  `max_count`:
- *
- *    maximum number of times self option can appear in the command line.
- *
- *  `help`:
- *    the short help message associated to what the option does.
- *    Must never be NULL (except for ARGPARSE_OPT_END).
- *
- *  `callback`:
- *    function is called when corresponding argument is parsed.
- *
- *  `data`:
- *    associated data. Callbacks can use it like they want.
- *
- *  `flags`:
- *    option flags.
- *
- *
- *
- */
-struct argparse_option {
-    enum argparse_option_type type;
-    const char short_name;
-    const char *long_name;
-    void *value;
-    int max_count;
-    const char *help;
-    const char *type_help;
-    argparse_callback *callback;
-    intptr_t data;
-    int flags;
-    int count;
-};
-
-/*
- * argpparse
- */
-struct argparse {
-    // user supplied
-    struct argparse_option *options;
-    const char *const *usage;
-    int flags;
-    // internal context
-    int argc;
-    const char **argv;
-    const char **out;
-    int cpidx;
-    const char *optvalue;       // current option value
-};
-
-// builtin callbacks
-int argparse_help_cb(struct argparse *self,
-                     const struct argparse_option *option);
-
-// builtin option macros
-#define OPT_BIT(short_name, long_name, value, ...) \
-    { ARGPARSE_OPT_BIT, short_name, long_name, value, 1, __VA_ARGS__ }
-
-#define OPT_BOOLEAN(short_name, long_name, value, ...) \
-    { ARGPARSE_OPT_BOOLEAN, short_name, long_name, value, 1, __VA_ARGS__ }
-
-#define OPT_INTEGER(short_name, long_name, value, ...) \
-    { ARGPARSE_OPT_INTEGER, short_name, long_name, value, 1, __VA_ARGS__ }
-
-#define OPT_STRING_MULTI(short_name, long_name, value, max_count, ...) \
-    { ARGPARSE_OPT_STRING, short_name, long_name, value, max_count, __VA_ARGS__ }
-
-#define OPT_STRING(short_name, long_name, value, ...) \
-    OPT_STRING_MULTI(short_name, long_name, value, 1, __VA_ARGS__)
-
-
-#define OPT_GROUP(h)   { ARGPARSE_OPT_GROUP, 0, NULL, NULL, h }
-#define OPT_END()      { ARGPARSE_OPT_END, 0 }
-
-#define OPT_HELP()     OPT_BOOLEAN('h', "help", NULL, "show self help message and exit", NULL, argparse_help_cb)
-
-
-int argparse_init(struct argparse *self, struct argparse_option *options,
-                  const char *const *usage, int flags);
-int argparse_parse(struct argparse *self, int argc, const char **argv);
-void argparse_usage(struct argparse *self);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/argparse/tap-functions b/argparse/tap-functions
deleted file mode 100755
index 84f700e..0000000
--- a/argparse/tap-functions
+++ /dev/null
@@ -1,445 +0,0 @@
-#!/bin/bash 
-
-
-_version='1.02'
-	
-_plan_set=0
-_no_plan=0
-_skip_all=0
-_test_died=0
-_expected_tests=0 
-_executed_tests=0 
-_failed_tests=0
-TODO=
-
-
-usage(){
-	cat <<'USAGE'
-tap-functions: A TAP-producing BASH library
-
-PLAN:
-  plan_no_plan
-  plan_skip_all [REASON]
-  plan_tests NB_TESTS
-
-TEST:
-  ok RESULT [NAME]
-  okx COMMAND
-  is RESULT EXPECTED [NAME]
-  isnt RESULT EXPECTED [NAME]
-  like RESULT PATTERN [NAME]
-  unlike RESULT PATTERN [NAME]
-  pass [NAME]
-  fail [NAME]
-
-SKIP:
-  skip [CONDITION] [REASON] [NB_TESTS=1]
-
-  skip $feature_not_present "feature not present" 2 || {
-      is $a "a"
-      is $b "b"
-  }
-
-TODO:
-  Specify TODO mode by setting $TODO:
-    TODO="not implemented yet"
-    ok $result "some not implemented test"
-    unset TODO
-
-OTHER:
-  diag MSG
-
-EXAMPLE:
-  #!/bin/bash
-
-  . tap-functions
-
-  plan_tests 7
-
-  me=$USER
-  is $USER $me "I am myself"
-  like $HOME $me "My home is mine"
-  like "`id`" $me "My id matches myself"
-
-  /bin/ls $HOME 1>&2
-  ok $? "/bin/ls $HOME"
-  # Same thing using okx shortcut
-  okx /bin/ls $HOME
-
-  [[ "`id -u`" != "0" ]]
-  i_am_not_root=$?
-  skip $i_am_not_root "Must be root" || {
-    okx ls /root
-  }
-
-  TODO="figure out how to become root..."
-  okx [ "$HOME" == "/root" ]
-  unset TODO
-USAGE
-	exit
-}
-
-opt=
-set_u=
-while getopts ":sx" opt ; do
-	case $_opt in
-        u) set_u=1 ;;
-        *) usage ;;
-    esac
-done
-shift $(( OPTIND - 1 ))
-# Don't allow uninitialized variables if requested
-[[ -n "$set_u" ]] && set -u
-unset opt set_u
-
-# Used to call _cleanup on shell exit
-trap _exit EXIT
-
-
-
-plan_no_plan(){
-	(( _plan_set != 0 )) && "You tried to plan twice!"
-
-	_plan_set=1
-	_no_plan=1
-
-	return 0
-}
-
-
-plan_skip_all(){
-	local reason=${1:-''}
-
-	(( _plan_set != 0 )) && _die "You tried to plan twice!"
-
-	_print_plan 0 "Skip $reason"
-
-	_skip_all=1
-	_plan_set=1
-	_exit 0
-
-	return 0
-}
-
-
-plan_tests(){
-	local tests=${1:?}
-
-	(( _plan_set != 0 )) && _die "You tried to plan twice!"
-	(( tests == 0 )) && _die "You said to run 0 tests!  You've got to run something."
-
-	_print_plan $tests
-	_expected_tests=$tests
-	_plan_set=1
-
-	return $tests
-}
-
-
-_print_plan(){
-	local tests=${1:?}
-	local directive=${2:-''}
-
-	echo -n "1..$tests"
-	[[ -n "$directive" ]] && echo -n " # $directive"
-	echo
-}
-
-
-pass(){
-	local name=$1
-	ok 0 "$name"
-}
-
-
-fail(){
-	local name=$1
-	ok 1 "$name"
-}
-
-
-# This is the workhorse method that actually
-# prints the tests result.
-ok(){
-	local result=${1:?}
-	local name=${2:-''}
-
-	(( _plan_set == 0 )) && _die "You tried to run a test without a plan!  Gotta have a plan."
-
-	_executed_tests=$(( $_executed_tests + 1 ))
-
-	if [[ -n "$name" ]] ; then
-		if _matches "$name" "^[0-9]+$" ; then
-			diag "    You named your test '$name'.  You shouldn't use numbers for your test names."
-			diag "    Very confusing."
-		fi
-	fi
-
-	if (( result != 0 )) ; then
-		echo -n "not "
-		_failed_tests=$(( _failed_tests + 1 ))
-	fi
-	echo -n "ok $_executed_tests"
-
-	if [[ -n "$name" ]] ; then
-		local ename=${name//\#/\\#}
-		echo -n " - $ename"
-	fi
-
-	if [[ -n "$TODO" ]] ; then
-		echo -n " # TODO $TODO" ;
-		if (( result != 0 )) ; then
-			_failed_tests=$(( _failed_tests - 1 ))
-		fi
-	fi
-
-	echo
-	if (( result != 0 )) ; then
-		local file='tap-functions'
-		local func=
-		local line=
-
-		local i=0
-		local bt=$(caller $i)
-		while _matches "$bt" "tap-functions$" ; do
-			i=$(( $i + 1 ))
-			bt=$(caller $i)
-		done
-		local backtrace=
-		eval $(caller $i | (read line func file ; echo "backtrace=\"$file:$func() at line $line.\""))
-			
-		local t=
-		[[ -n "$TODO" ]] && t="(TODO) "
-
-		if [[ -n "$name" ]] ; then
-			diag "  Failed ${t}test '$name'"
-			diag "  in $backtrace"
-		else
-			diag "  Failed ${t}test in $backtrace"
-		fi
-	fi
-
-	return $result
-}
-
-
-okx(){
-	local command="$@"
-
-	local line=
-	diag "Output of '$command':"
-	$command | while read line ; do
-		diag "$line"
-	done
-	ok ${PIPESTATUS[0]} "$command"
-}
-
-
-_equals(){
-	local result=${1:?}
-	local expected=${2:?}
-
-	if [[ "$result" == "$expected" ]] ; then
-		return 0
-	else 
-		return 1
-	fi
-}
-
-
-# Thanks to Aaron Kangas for the patch to allow regexp matching
-# under bash < 3.
- _bash_major_version=${BASH_VERSION%%.*}
-_matches(){
-	local result=${1:?}
-	local pattern=${2:?}
-
-	if [[ -z "$result" || -z "$pattern" ]] ; then
-		return 1
-	else
-		if (( _bash_major_version >= 3 )) ; then
-			eval '[[ "$result" =~ "$pattern" ]]'
-		else
-			echo "$result" | egrep -q "$pattern"
-		fi
-	fi
-}
-
-
-_is_diag(){
-	local result=${1:?}
-	local expected=${2:?}
-
-	diag "         got: '$result'" 
-	diag "    expected: '$expected'"
-}
-
-
-is(){
-	local result=${1:?}
-	local expected=${2:?}
-	local name=${3:-''}
-
-	_equals "$result" "$expected"
-	(( $? == 0 ))
-	ok $? "$name"
-	local r=$?
-	(( r != 0 )) && _is_diag "$result" "$expected"
-	return $r 
-}
-
-
-isnt(){
-	local result=${1:?}
-	local expected=${2:?}
-	local name=${3:-''}
-
-	_equals "$result" "$expected"
-	(( $? != 0 ))
-	ok $? "$name"
-	local r=$?
-	(( r != 0 )) && _is_diag "$result" "$expected"
-	return $r 
-}
-
-
-like(){
-	local result=${1:?}
-	local pattern=${2:?}
-	local name=${3:-''}
-
-	_matches "$result" "$pattern"
-	(( $? == 0 ))
-	ok $? "$name"
-	local r=$?
-	(( r != 0 )) && diag "    '$result' doesn't match '$pattern'"
-	return $r
-}
-
-
-unlike(){
-	local result=${1:?}
-	local pattern=${2:?}
-	local name=${3:-''}
-
-	_matches "$result" "$pattern"
-	(( $? != 0 ))
-	ok $? "$name"
-	local r=$?
-	(( r != 0 )) && diag "    '$result' matches '$pattern'"
-	return $r
-}
-
-
-skip(){
-	local condition=${1:?}
-	local reason=${2:-''}
-	local n=${3:-1}
-
-	if (( condition == 0 )) ; then
-		local i=
-		for (( i=0 ; i<$n ; i++ )) ; do
-			_executed_tests=$(( _executed_tests + 1 ))
-			echo "ok $_executed_tests # skip: $reason" 
-		done
-		return 0
-	else
-		return
-	fi
-}
-
-
-diag(){
-	local msg=${1:?}
-
-	if [[ -n "$msg" ]] ; then
-		echo "# $msg"
-	fi
-	
-	return 1
-}
-
-	
-_die(){
-	local reason=${1:-'<unspecified error>'}
-
-	echo "$reason" >&2
-	_test_died=1
-	_exit 255
-}
-
-
-BAIL_OUT(){
-	local reason=${1:-''}
-
-	echo "Bail out! $reason" >&2
-	_exit 255
-}
-
-
-_cleanup(){
-	local rc=0
-
-	if (( _plan_set == 0 )) ; then
-		diag "Looks like your test died before it could output anything."
-		return $rc
-	fi
-
-	if (( _test_died != 0 )) ; then
-		diag "Looks like your test died just after $_executed_tests."
-		return $rc
-	fi
-
-	if (( _skip_all == 0 && _no_plan != 0 )) ; then
-		_print_plan $_executed_tests
-	fi
-
-	local s=
-	if (( _no_plan == 0 && _expected_tests < _executed_tests )) ; then
-		s= ; (( _expected_tests > 1 )) && s=s
-		local extra=$(( _executed_tests - _expected_tests ))
-		diag "Looks like you planned $_expected_tests test$s but ran $extra extra."
-		rc=-1 ;
-	fi
-
-	if (( _no_plan == 0 && _expected_tests > _executed_tests )) ; then
-		s= ; (( _expected_tests > 1 )) && s=s
-		diag "Looks like you planned $_expected_tests test$s but only ran $_executed_tests."
-	fi
-
-	if (( _failed_tests > 0 )) ; then
-		s= ; (( _failed_tests > 1 )) && s=s
-		diag "Looks like you failed $_failed_tests test$s of $_executed_tests."
-	fi
-
-	return $rc
-}
-
-
-_exit_status(){
-	if (( _no_plan != 0 || _plan_set == 0 )) ; then
-		return $_failed_tests
-	fi
-
-	if (( _expected_tests < _executed_tests )) ; then
-		return $(( _executed_tests - _expected_tests  ))
-	fi
-
-	return $(( _failed_tests + ( _expected_tests - _executed_tests )))
-}
-
-
-_exit(){
-	local rc=${1:-''}
-	if [[ -z "$rc" ]] ; then
-		_exit_status
-		rc=$?
-	fi
-
-	_cleanup
-	local alt_rc=$?
-	(( alt_rc != 0 )) && rc=$alt_rc
-	trap - EXIT
-	exit $rc
-}
-
diff --git a/argparse/test.sh b/argparse/test.sh
deleted file mode 100755
index fdb430a..0000000
--- a/argparse/test.sh
+++ /dev/null
@@ -1,46 +0,0 @@
-#!/bin/bash
-
-. tap-functions
-plan_no_plan
-
-is "$(./test_argparse -f --path=/path/to/file a 2>&1)" 'force: 1
-path: /path/to/file
-argc: 1
-argv[0]: a'
-
-is "$(./test_argparse -f -f --force --no-force 2>&1)" 'force: 2'
-
-is "$(./test_argparse -n 2>&1)" 'error: option `n` requires a value'
-
-is "$(./test_argparse -n 2 2>&1)" 'num: 2'
-
-is "$(./test_argparse -n2 2>&1)" 'num: 2'
-
-is "$(./test_argparse -na 2>&1)" 'error: option `n` expects a numerical value'
-
-is "$(./test_argparse -f -- do -f -h 2>&1)" 'force: 1
-argc: 3
-argv[0]: do
-argv[1]: -f
-argv[2]: -h'
-
-is "$(./test_argparse -tf 2>&1)" 'force: 1
-test: 1'
-
-is "$(./test_argparse --read --write 2>&1)" 'perms: 3'
-
-is "$(./test_argparse -h)" 'Usage: test_argparse [options] [[--] args]
-   or: test_argparse [options]
-
-    -h, --help        show this help message and exit
-
-OPTIONS
-    -f, --force       force to do
-    -t, --test        test only
-    -p, --path=<str>  path to read
-    -n, --num=<int>   selected num
-
-BITS
-    --read            read perm
-    --write           write perm
-    --exec            exec perm'
diff --git a/argparse/test_argparse.c b/argparse/test_argparse.c
deleted file mode 100755
index 6d95d35..0000000
--- a/argparse/test_argparse.c
+++ /dev/null
@@ -1,57 +0,0 @@
-#include "argparse.h"
-
-static const char *const usage[] = {
-    "test_argparse [options] [[--] args]",
-    "test_argparse [options]",
-    NULL,
-};
-
-#define PERM_READ  (1<<0)
-#define PERM_WRITE (1<<1)
-#define PERM_EXEC  (1<<2)
-
-int
-main(int argc, const char **argv)
-{
-    int force = 0;
-    int test = 0;
-    int num = 0;
-    const char *path = NULL;
-    int perms = 0;
-    struct argparse_option options[] = {
-        OPT_HELP(),
-        OPT_GROUP("OPTIONS"),
-        OPT_BOOLEAN('f', "force", &force, "force to do"),
-        OPT_BOOLEAN('t', "test", &test, "test only"),
-        OPT_STRING('p', "path", &path, "path to read"),
-        OPT_INTEGER('n', "num", &num, "selected num"),
-        OPT_GROUP("BITS"),
-        OPT_BIT(0, "read", &perms, "read perm", NULL, PERM_READ, OPT_NONEG),
-        OPT_BIT(0, "write", &perms, "write perm", NULL, PERM_WRITE),
-        OPT_BIT(0, "exec", &perms, "exec perm", NULL, PERM_EXEC),
-        OPT_END(),
-    };
-
-    struct argparse argparse;
-    argparse_init(&argparse, options, usage, 0);
-    argc = argparse_parse(&argparse, argc, argv);
-    if (force != 0)
-        printf("force: %d\n", force);
-    if (test != 0)
-        printf("test: %d\n", test);
-    if (path != NULL)
-        printf("path: %s\n", path);
-    if (num != 0)
-        printf("num: %d\n", num);
-    if (argc != 0) {
-        printf("argc: %d\n", argc);
-        int i;
-        for (i = 0; i < argc; i++) {
-            printf("argv[%d]: %s\n", i, *(argv + i));
-        }
-    }
-    if (perms) {
-        printf("perms: %d\n", perms);
-    }
-    return 0;
-}
diff --git a/args.c b/args.c
new file mode 100755
index 0000000..45f11ec
--- /dev/null
+++ b/args.c
@@ -0,0 +1,278 @@
+/*
+Copyright (c) 2014. The YARA Authors. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "args.h"
+
+#define args_is_long_arg(arg)  \
+    (arg[0] == '-' && arg[1] == '-' && arg[2] != '\0')
+
+
+#define args_is_short_arg(arg)  \
+    (arg[0] == '-' && arg[1] != '-' && arg[1] != '\0')
+
+
+args_option_t* args_get_short_option(
+    args_option_t *options,
+    const char opt)
+{
+  while (options->type != ARGS_OPT_END)
+  {
+    if (opt == options->short_name)
+      return options;
+
+    options++;
+  }
+
+  return NULL;
+}
+
+
+args_option_t* args_get_long_option(
+    args_option_t *options,
+    const char* arg)
+{
+  arg += 2; // skip starting --
+
+  while (options->type != ARGS_OPT_END)
+  {
+    if (options->long_name != NULL)
+    {
+      int l = strlen(options->long_name);
+
+      if ((arg[l] == '\0' || arg[l] == '=') &&
+          strstr(arg, options->long_name) == arg)
+      {
+        return options;
+      }
+    }
+
+    options++;
+  }
+
+  return NULL;
+}
+
+
+args_error_type_t args_parse_option(
+    args_option_t* opt,
+    const char* opt_arg,
+    int* opt_arg_was_used)
+{
+  char *endptr = NULL;
+
+  if (opt_arg_was_used != NULL)
+      *opt_arg_was_used = 0;
+
+  if (opt->count == opt->max_count)
+    return ARGS_ERROR_TOO_MANY;
+
+  switch (opt->type)
+  {
+    case ARGS_OPT_BOOLEAN:
+      *(int*) opt->value = 1;
+      break;
+
+    case ARGS_OPT_INTEGER:
+
+      if (opt_arg == NULL)
+        return ARGS_ERROR_REQUIRED_INTEGER_ARG;
+
+      *(int*) opt->value = strtol(opt_arg, &endptr, 0);
+
+      if (*endptr != '\0')
+        return ARGS_ERROR_REQUIRED_INTEGER_ARG;
+
+      if (opt_arg_was_used != NULL)
+        *opt_arg_was_used = 1;
+
+      break;
+
+    case ARGS_OPT_STRING:
+
+      if (opt_arg == NULL)
+        return ARGS_ERROR_REQUIRED_STRING_ARG;
+
+      if (opt->max_count > 1)
+        ((const char**)opt->value)[opt->count] = opt_arg;
+      else
+        *(const char**) opt->value = opt_arg;
+
+      if (opt_arg_was_used != NULL)
+        *opt_arg_was_used = 1;
+
+      break;
+
+    default:
+      assert(0);
+  }
+
+  opt->count++;
+
+  return ARGS_ERROR_OK;
+}
+
+
+void args_print_error(
+    args_error_type_t error,
+    const char* option)
+{
+  switch(error)
+  {
+    case ARGS_ERROR_UKNOWN_OPT:
+      fprintf(stderr, "unknown option `%s`\n", option);
+      break;
+    case ARGS_ERROR_TOO_MANY:
+      fprintf(stderr, "too many `%s` options\n", option);
+      break;
+    case ARGS_ERROR_REQUIRED_INTEGER_ARG:
+      fprintf(stderr, "option `%s` requieres an integer argument\n", option);
+      break;
+    case ARGS_ERROR_REQUIRED_STRING_ARG:
+      fprintf(stderr, "option `%s` requieres a string argument\n", option);
+      break;
+    case ARGS_ERROR_UNEXPECTED_ARG:
+      fprintf(stderr, "option `%s` doesn't expect an argument\n", option);
+      break;
+    default:
+      return;
+  }
+}
+
+
+int args_parse(
+    args_option_t *options,
+    int argc,
+    const char **argv)
+{
+  args_error_type_t error = ARGS_ERROR_OK;
+
+  int i = 1;  // start with i = 1, argv[0] is the program name
+  int o = 0;
+
+  while (i < argc)
+  {
+    const char* arg = argv[i];
+
+    if (args_is_long_arg(arg))
+    {
+      args_option_t* opt = args_get_long_option(options, arg);
+
+      if (opt != NULL)
+      {
+        const char* equal = strchr(arg, '=');
+
+        if (equal)
+          error = args_parse_option(opt, equal + 1, NULL);
+        else
+          error = args_parse_option(opt, NULL, NULL);
+      }
+      else
+      {
+        error = ARGS_ERROR_UKNOWN_OPT;
+      }
+    }
+    else if (args_is_short_arg(arg))
+    {
+      for (int j = 1; arg[j] != '\0'; j++)
+      {
+        args_option_t* opt = args_get_short_option(options, arg[j]);
+
+        if (opt != NULL)
+        {
+          if (arg[j + 1] == '\0')
+          {
+            int arg_used;
+
+            // short option followed by a space, argv[i + 1] could be
+            // an argument for the option (i.e: -a <arg>)
+            error = args_parse_option(opt, argv[i + 1], &arg_used);
+
+            // argv[i + 1] was actually an argument to the option, skip it.
+            if (arg_used)
+              i++;
+          }
+          else
+          {
+            // short option followed by another option (i.e: -ab), no
+            // argument for this option
+            error = args_parse_option(opt, NULL, NULL);
+          }
+        }
+        else
+        {
+          error = ARGS_ERROR_UKNOWN_OPT;
+        }
+
+        if (error != ARGS_ERROR_OK)
+          break;
+      }
+    }
+    else
+    {
+      argv[o++] = arg;
+    }
+
+    if (error != ARGS_ERROR_OK)
+    {
+      args_print_error(error, arg);
+      exit(1);
+    }
+
+    i++;
+  }
+
+  return o;
+}
+
+
+void args_print_usage(
+    args_option_t *options,
+    int help_alignment)
+{
+  char buffer[128];
+
+  for (; options->type != ARGS_OPT_END; options++)
+  {
+    int len = sprintf(buffer, "  ");
+
+    if (options->short_name != '\0')
+      len += sprintf(buffer + len, "-%c", options->short_name);
+    else
+      len += sprintf(buffer + len, "     ");
+
+    if (options->short_name != '\0' && options->long_name != NULL)
+      len += sprintf(buffer + len, ",  ");
+
+    if (options->long_name != NULL)
+      len += sprintf(buffer + len, "--%s", options->long_name);
+
+    if (options->type == ARGS_OPT_STRING ||
+       options->type == ARGS_OPT_INTEGER)
+    {
+      len += sprintf(
+          buffer + len,
+          "%s%s",
+          (options->long_name != NULL) ? "=" : " ",
+          options->type_help);
+    }
+
+    printf("%-*s%s\n", help_alignment, buffer, options->help);
+  }
+}
diff --git a/args.h b/args.h
new file mode 100755
index 0000000..eec36a3
--- /dev/null
+++ b/args.h
@@ -0,0 +1,92 @@
+/*
+Copyright (c) 2014. The YARA Authors. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#ifndef ARGPARSE_H
+#define ARGPARSE_H
+
+#include <stdio.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+typedef enum _args_error_type {
+  ARGS_ERROR_OK,
+  ARGS_ERROR_UKNOWN_OPT,
+  ARGS_ERROR_TOO_MANY,
+  ARGS_ERROR_REQUIRED_INTEGER_ARG,
+  ARGS_ERROR_REQUIRED_STRING_ARG,
+  ARGS_ERROR_UNEXPECTED_ARG,
+} args_error_type_t;
+
+
+typedef enum _args_option_type {
+  // special
+  ARGS_OPT_END,
+  ARGS_OPT_GROUP,
+  // options with no arguments
+  ARGS_OPT_BOOLEAN,
+  // options with arguments (optional or required)
+  ARGS_OPT_INTEGER,
+  ARGS_OPT_STRING,
+} args_option_type_t;
+
+
+typedef struct _args_option {
+  args_option_type_t type;
+  const char short_name;
+  const char *long_name;
+  void *value;
+  int max_count;
+  const char *help;
+  const char *type_help;
+  int count;
+} args_option_t;
+
+
+#define OPT_BOOLEAN(short_name, long_name, value, ...) \
+    { ARGS_OPT_BOOLEAN, short_name, long_name, value, 1, __VA_ARGS__ }
+
+#define OPT_INTEGER(short_name, long_name, value, ...) \
+    { ARGS_OPT_INTEGER, short_name, long_name, value, 1, __VA_ARGS__ }
+
+#define OPT_STRING_MULTI(short_name, long_name, value, max_count, ...) \
+    { ARGS_OPT_STRING, short_name, long_name, value, max_count, __VA_ARGS__ }
+
+#define OPT_STRING(short_name, long_name, value, ...) \
+    OPT_STRING_MULTI(short_name, long_name, value, 1, __VA_ARGS__)
+
+#define OPT_END() { ARGS_OPT_END, 0 }
+
+
+int args_parse(
+    args_option_t *options,
+    int argc,
+    const char **argv);
+
+
+void args_print_usage(
+    args_option_t *options,
+    int aligment);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/yara.c b/yara.c
index f34a3cf..e28b538 100644
--- a/yara.c
+++ b/yara.c
@@ -35,9 +35,9 @@ limitations under the License.
 #include <string.h>
 #include <ctype.h>
 
-#include <argparse/argparse.h>
 #include <yara.h>
 
+#include "args.h"
 #include "threading.h"
 #include "config.h"
 
@@ -93,6 +93,8 @@ int show_specified_rules = FALSE;
 int show_strings = FALSE;
 int show_meta = FALSE;
 int show_namespace = FALSE;
+int show_version = FALSE;
+int show_help = FALSE;
 int ignore_warnings = FALSE;
 int fast_scan = FALSE;
 int negate = FALSE;
@@ -102,22 +104,20 @@ int timeout = 0;
 int threads = 8;
 
 
-static const char *const usage[] = {
-   "yara [OPTION]... RULES_FILE FILE | DIRECTORY | PID",
-   NULL,
-};
+#define USAGE_STRING \
+    "Usage: yara [OPTION]... RULES_FILE FILE | DIR | PID"
 
 
-struct argparse_option options[] =
+args_option_t options[] =
 {
   OPT_STRING_MULTI('t', "tag", &tags, MAX_ARGS_TAG,
-      "only print rules tagged as <tag>.", "<tag>"),
+      "print only rules tagged as TAG", "TAG"),
 
   OPT_STRING_MULTI('i', "identifier", &identifiers, MAX_ARGS_IDENTIFIER,
-      "only print rules named <identifier>.", "<identifier>"),
+      "print only rules named IDENTIFIER", "IDENTIFIER"),
 
   OPT_BOOLEAN('n', "negate", &negate,
-      "only print not satisfied rules (negate)", NULL),
+      "print only not satisfied rules (negate)", NULL),
 
   OPT_BOOLEAN('g', "print-tags", &show_tags,
       "print tags"),
@@ -132,19 +132,19 @@ struct argparse_option options[] =
       "print rules' namespace"),
 
   OPT_INTEGER('p', "threads", &threads,
-      "use the specified number of threads to scan a directory", "<number>"),
+      "use the specified NUMBER of threads to scan a directory", "NUMBER"),
 
   OPT_INTEGER('l', "max-rules", &limit,
-      "abort scanning after matching a number rules", "<number>"),
+      "abort scanning after matching a NUMBER of rules", "NUMBER"),
 
   OPT_STRING_MULTI('d', NULL, &ext_vars, MAX_ARGS_EXT_VAR,
-      "define external variable", "<identifier>=<value>"),
+      "define external variable", "VAR=VALUE"),
 
   OPT_STRING_MULTI('x', NULL, &modules_data, MAX_ARGS_MODULE_DATA,
-      "pass file's content as extra data to module", "<module>=<file>"),
+      "pass FILE's content as extra data to MODULE", "MODULE=FILE"),
 
   OPT_INTEGER('a', "timeout", &timeout,
-      "abort scanning after matching a number of  rules", "<number>"),
+      "abort scanning after the given number of SECONDS", "SECONDS"),
 
   OPT_BOOLEAN('r', "recursive", &recursive_search,
       "recursively search directories"),
@@ -155,7 +155,12 @@ struct argparse_option options[] =
   OPT_BOOLEAN('w', "no-warnings", &ignore_warnings,
       "disable warnings"),
 
-  OPT_HELP(),
+  OPT_BOOLEAN('v', "version", &show_version,
+      "show version information"),
+
+  OPT_BOOLEAN('h', "help", &show_help,
+      "show this help and exit"),
+
   OPT_END()
 };
 
@@ -800,12 +805,29 @@ int main(
   YR_COMPILER* compiler = NULL;
   YR_RULES* rules = NULL;
 
-  struct argparse argparse;
   int result;
 
-  argparse_init(&argparse, options, usage, 0);
+  argc = args_parse(options, argc, argv);
 
-  argc = argparse_parse(&argparse, argc, argv);
+  if (show_version)
+  {
+    printf("%s\n", PACKAGE_STRING);
+    return EXIT_FAILURE;
+  }
+
+  if (show_help)
+  {
+    printf(
+      "YARA %s, the pattern matching swiss army knife.\n"
+      "%s\n\n"
+      "Mandatory arguments to long options are mandatory for "
+      "short options too.\n\n", PACKAGE_VERSION, USAGE_STRING);
+
+    args_print_usage(options, 35);
+    printf("\nSend bug reports and suggestions to: %s.\n", PACKAGE_BUGREPORT);
+
+    return EXIT_FAILURE;
+  }
 
   if (argc != 2)
   {
@@ -813,8 +835,10 @@ int main(
     // arguments, the rules file and the target file, directory or pid to
     // be scanned.
 
-    fprintf(stderr, "error: wrong number of arguments\n");
-    argparse_usage(&argparse);
+    fprintf(stderr, "yara: wrong number of arguments\n");
+    fprintf(stderr, "%s\n\n", USAGE_STRING);
+    fprintf(stderr, "Try `--help` for more options\n");
+
     return EXIT_FAILURE;
   }
 
diff --git a/yarac.c b/yarac.c
index 4402c48..e0eb000 100644
--- a/yarac.c
+++ b/yarac.c
@@ -31,9 +31,9 @@ limitations under the License.
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
-#include <argparse/argparse.h>
 #include <yara.h>
 
+#include "args.h"
 #include "config.h"
 
 #ifndef MAX_PATH
@@ -45,23 +45,27 @@ limitations under the License.
 
 char* ext_vars[MAX_ARGS_EXT_VAR + 1];
 int ignore_warnings = FALSE;
+int show_version = FALSE;
+int show_help = FALSE;
 
 
-static const char *const usage[] = {
-   "yarac [option]... [namespace:]rules_file... output_file",
-   NULL,
-};
-
+#define USAGE_STRING \
+    "Usage: yarac [OPTION]... [NAMESPACE:]SOURCE_FILE... OUTPUT_FILE"
 
-struct argparse_option options[] =
+args_option_t options[] =
 {
   OPT_STRING_MULTI('d', NULL, &ext_vars, MAX_ARGS_EXT_VAR,
-      "define external variable"),
+      "define external variable", "VAR=VALUE"),
 
   OPT_BOOLEAN('w', "no-warnings", &ignore_warnings,
-      "disable warnings", NULL),
+      "disable warnings"),
+
+  OPT_BOOLEAN('v', "version", &show_version,
+      "show version information"),
+
+  OPT_BOOLEAN('h', "help", &show_help,
+      "show this help and exit"),
 
-  OPT_HELP(),
   OPT_END()
 };
 
@@ -156,16 +160,34 @@ int main(
   YR_COMPILER* compiler = NULL;
   YR_RULES* rules = NULL;
 
-  struct argparse argparse;
   int result;
 
-  argparse_init(&argparse, options, usage, 0);
+  argc = args_parse(options, argc, argv);
 
-  argc = argparse_parse(&argparse, argc, argv);
+  if (show_version)
+  {
+    printf("%s\n", PACKAGE_STRING);
+    printf("\nSend bug reports and suggestions to: %s.\n", PACKAGE_BUGREPORT);
+
+    return EXIT_FAILURE;
+  }
+
+  if (show_help)
+  {
+    printf("%s\n\n", USAGE_STRING);
+
+    args_print_usage(options, 25);
+    printf("\nSend bug reports and suggestions to: %s.\n", PACKAGE_BUGREPORT);
+
+    return EXIT_FAILURE;
+  }
 
   if (argc < 2)
   {
-    fprintf(stderr, "error: wrong number of arguments\n");
+    fprintf(stderr, "yarac: wrong number of arguments\n");
+    fprintf(stderr, "%s\n\n", USAGE_STRING);
+    fprintf(stderr, "Try `--help` for more options\n");
+
     exit_with_code(EXIT_FAILURE);
   }
 

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/forensics/yara.git



More information about the forensics-changes mailing list