]> git.mdlowis.com Git - projs/opts.git/commitdiff
revised interface for parsing
authorMichael D. Lowis <mike.lowis@gentex.com>
Fri, 3 Oct 2014 19:31:02 +0000 (15:31 -0400)
committerMichael D. Lowis <mike.lowis@gentex.com>
Fri, 3 Oct 2014 19:31:02 +0000 (15:31 -0400)
Rakefile
source/opts.c [changed mode: 0644->0755]
source/opts.h [changed mode: 0644->0755]
tests/atf.c [new file with mode: 0755]
tests/atf.h [new file with mode: 0755]
tests/main.c
tests/test.c [deleted file]
tests/test.h [deleted file]
tests/test_opts.c [changed mode: 0644->0755]

index 5885867d49d5ea93745520bb2262c41b6dcc5b2b..3e07f2c448d74922b9a76d441d69b85f97289ccd 100644 (file)
--- a/Rakefile
+++ b/Rakefile
@@ -25,6 +25,8 @@ TestEnv = Env.clone  do |env|
   env.build_dir('source','build/obj/test_source')
   env.build_dir('tests','build/obj/tests/source')
   env['CPPPATH'] += Dir['tests/']
+  env["CFLAGS"]  += ['--coverage']
+  env["LDFLAGS"] += ['--coverage']
 end
 
 # Make sure the environment is processed before we quit
old mode 100644 (file)
new mode 100755 (executable)
index 42e74c1..a6e2079
 #include <string.h>
 #include "opts.h"
 
+typedef struct {
+    char* name;
+    char* tag;
+    char* value;
+} option_t;
+
+typedef struct entry_t {
+    void* value;
+    struct entry_t* next;
+} entry_t;
+
+static entry_t* Options   = NULL;
+static entry_t* Arguments = NULL;
+
+typedef enum { LONG, SHORT } OptionType_T;
+
+typedef struct {
+    unsigned int line_idx;
+    unsigned int col_idx;
+    unsigned int arg_count;
+    char** arg_vect;
+    int current;
+    OptionConfig_T* options;
+} StreamContext_T;
+
+static void opts_init_context( StreamContext_T* ctx, int argc, char** argv );
+static void opts_parse_short_option( StreamContext_T* ctx );
+static void opts_parse_long_option( StreamContext_T* ctx );
+static char* opts_parse_optarg(StreamContext_T* ctx, char* opt_name);
+static void opts_parse_argument( StreamContext_T* ctx );
+static void opts_parse_error(const char* msg, const char* opt_name);
+
+static OptionConfig_T* opts_get_option_config( OptionConfig_T* opts, OptionType_T typ, char* name );
+static char* opts_next_token( StreamContext_T* ctx );
+static void opts_consume_ws( StreamContext_T* ctx );
+static char opts_next_char( StreamContext_T* ctx );
+static char* opts_append_char( char* str, char ch );
 static char* strclone(const char* p_old);
 
-Result_T* OPTS_ParseOptions( OptionConfig_T* opts, int argc, char** argv )
-{
-    // Setup the stream
+static void opts_add_option(char* name, char* tag, char* arg);
+static void opts_add_argument(char* arg);
+
+void opts_parse( OptionConfig_T* opts, int argc, char** argv ) {
+    /* Setup the stream */
     StreamContext_T ctx;
     ctx.options = opts;
-    OPTS_InitContext( &ctx, argc, argv );
-
-    // Until we run out of characters
-    while( ctx.current != EOF )
-    {
-        OPTS_ConsumeWhitespace( &ctx );
-
-        // If we have an option
-        if ( '-' == ctx.current )
-        {
-            // And it's a long one
-            if( '-' == OPTS_NextCharacter( &ctx ) )
-            {
-                // Consume the second '-'
-                OPTS_NextCharacter( &ctx );
-
-                // Parse the option
-                OPTS_ParseLongOption( &ctx );
-            }
-            // Or a short one
-            else
-            {
-                // Parse the option
-                OPTS_ParseShortOption( &ctx );
+    opts_init_context( &ctx, argc, argv );
+
+    /* Until we run out of characters */
+    while (ctx.current != EOF) {
+        opts_consume_ws( &ctx );
+        /* If we have an option */
+        if ('-' == ctx.current) {
+            /* And it's a long one */
+            if ('-' == opts_next_char( &ctx )) {
+                /* Consume the second '-' */
+                opts_next_char( &ctx );
+                /* Parse the option */
+                opts_parse_long_option( &ctx );
+            } else {
+                /* Parse the option */
+                opts_parse_short_option( &ctx );
             }
-        }
-        // Or we have a floating argument
-        else
-        {
-            OPTS_ParseArgument( &ctx );
+        } else {
+            opts_parse_argument( &ctx );
         }
     }
+}
 
-    return ctx.results;
+void opts_reset(void) {
+    while (Options != NULL) {
+        entry_t* entry = Options;
+        option_t* opt  = (option_t*)entry->value;
+        Options = entry->next;
+        free(opt->name);
+        free(opt->tag);
+        if(opt->name != opt->value)
+            free(opt->value);
+        free(opt);
+        free(entry);
+    }
+
+    while (Arguments != NULL) {
+        entry_t* entry = Arguments;
+        char* arg  = (char*)entry->value;
+        Arguments = entry->next;
+        free(arg);
+        free(entry);
+    }
 }
 
-void OPTS_InitContext( StreamContext_T* ctx, int argc, char** argv )
-{
+static void opts_init_context( StreamContext_T* ctx, int argc, char** argv ) {
     // Setup the char stream
     ctx->line_idx  = 0;
     ctx->col_idx   = -1;
     ctx->arg_count = argc;
     ctx->arg_vect  = argv;
-    (void)OPTS_NextCharacter( ctx ); // Loads up the first char
-
-    // Setup the results object
-    ctx->results = (Result_T*)malloc( sizeof( Result_T ) );
-    ctx->results->options = (OptionList_T*)malloc( sizeof( OptionList_T ) );
-    ctx->results->options->head = NULL;
-    ctx->results->options->tail = NULL;
-    ctx->results->arguments = (ArgumentList_T*)malloc( sizeof( ArgumentList_T ) );
-    ctx->results->arguments->head = NULL;
-    ctx->results->arguments->tail = NULL;
+    (void)opts_next_char( ctx ); // Loads up the first char
 }
 
-void OPTS_ParseShortOption( StreamContext_T* ctx )
-{
+static void opts_parse_short_option( StreamContext_T* ctx ) {
     // Get Config
     char opt_name[2] = { ctx->current, '\0' };
-    OptionConfig_T* config = OPTS_GetOptConfig( ctx->options, SHORT, opt_name );
-    if( config != NULL )
-    {
+    OptionConfig_T* config = opts_get_option_config( ctx->options, SHORT, opt_name );
+    if (config != NULL) {
         char* opt_arg = NULL;
-        (void)OPTS_NextCharacter( ctx );
-        if( 1 == config->has_arg )
-        {
-            OPTS_ConsumeWhitespace( ctx );
-            if( ('-' == ctx->current) || (EOF  == ctx->current) )
-            {
-                printf("Expected an argument for option '%s'\n", opt_name);
-                exit(1);
-            }
-            opt_arg = OPTS_NextToken( ctx );
-        }
-        else if( (' ' != ctx->current) && (EOF != ctx->current) )
-        {
-            OPTS_ParseShortOption( ctx );
-        }
-        OPTS_AddOption( ctx->results, opt_name, opt_arg );
-    }
-    else
-    {
-        printf("Unknown Option '%s'\n", opt_name);
-        exit(1);
+        (void)opts_next_char( ctx );
+        if (config->has_arg)
+            opt_arg = opts_parse_optarg( ctx, opt_name );
+        else if ((' ' != ctx->current) && (EOF != ctx->current))
+            opts_parse_short_option( ctx );
+        opts_add_option( strclone(opt_name), config->tag, opt_arg );
+    } else {
+        opts_parse_error("Unknown Option", opt_name);
     }
 }
 
-void OPTS_ParseLongOption( StreamContext_T* ctx )
-{
-    char* opt_name = OPTS_NextToken( ctx );
-    OptionConfig_T* config = OPTS_GetOptConfig( ctx->options, LONG, opt_name );
-    if( config != NULL )
-    {
+static void opts_parse_long_option( StreamContext_T* ctx ) {
+    char* opt_name = opts_next_token( ctx );
+    OptionConfig_T* config = opts_get_option_config( ctx->options, LONG, opt_name );
+    if (config != NULL) {
         char* opt_arg = NULL;
-        if( 1 == config->has_arg )
-        {
-            OPTS_ConsumeWhitespace( ctx );
-            if( ('-' == ctx->current) || (EOF == ctx->current) )
-            {
-                printf("Expected an argument for option '%s'\n", opt_name);
-                exit(1);
-            }
-            opt_arg = OPTS_NextToken( ctx );
-        }
-        OPTS_AddOption( ctx->results, opt_name, opt_arg );
-    }
-    else
-    {
-        printf("Unknown Option '%s'\n", opt_name);
-        exit(1);
+        if (config->has_arg)
+            opt_arg = opts_parse_optarg( ctx, opt_name );
+        opts_add_option( opt_name, config->tag, opt_arg );
+    } else {
+        opts_parse_error("Unknown Option", opt_name);
     }
 }
 
-void OPTS_ParseArgument( StreamContext_T* ctx )
-{
-    char* arg_val = OPTS_NextToken( ctx );
-    if( NULL != arg_val )
-    {
-        Argument_T* arg = (Argument_T*)malloc( sizeof( Argument_T ) );
-        arg->val  = arg_val;
-        arg->next = NULL;
-        if( ctx->results->arguments->head == NULL )
-        {
-            ctx->results->arguments->head = arg;
-            ctx->results->arguments->tail = arg;
-        }
-        else
-        {
-            ctx->results->arguments->tail->next = arg;
-            ctx->results->arguments->tail = arg;
-        }
-    }
+static char* opts_parse_optarg(StreamContext_T* ctx, char* opt_name) {
+    opts_consume_ws( ctx );
+    if (('-' == ctx->current) || (EOF == ctx->current))
+        opts_parse_error("Expected an argument, none received", opt_name);
+    return opts_next_token( ctx );
 }
 
-OptionConfig_T* OPTS_GetOptConfig( OptionConfig_T* opts, OptionType_T typ, char* name )
-{
+static void opts_parse_error(const char* msg, const char* opt_name) {
+    fprintf(stderr, "Option '%s' : %s\n", opt_name, msg);
+    exit(1);
+}
+
+static void opts_parse_argument( StreamContext_T* ctx ) {
+    char* arg_val = opts_next_token( ctx );
+    if (NULL != arg_val)
+        opts_add_argument(arg_val);
+}
+
+
+
+static OptionConfig_T* opts_get_option_config( OptionConfig_T* opts, OptionType_T type, char* name ) {
     OptionConfig_T* cfg = NULL;
     int i = 0;
-    while( opts[i].type != END )
-    {
-        if( (opts[i].type == typ) && (0 == strcmp(opts[i].name, name)) )
-        {
+    while( opts[i].name != NULL ) {
+        OptionType_T curr_type = (strlen(opts[i].name) > 1) ? LONG : SHORT;
+        if ((curr_type == type) && (0 == strcmp(opts[i].name, name))) {
             cfg = &(opts[i]);
             break;
         }
@@ -160,90 +167,55 @@ OptionConfig_T* OPTS_GetOptConfig( OptionConfig_T* opts, OptionType_T typ, char*
     return cfg;
 }
 
-char* OPTS_NextToken( StreamContext_T* ctx )
-{
+static char* opts_next_token( StreamContext_T* ctx ) {
     char* tok = NULL;
 
-    OPTS_ConsumeWhitespace( ctx );
-    if ( EOF != ctx->current )
-    {
+    opts_consume_ws( ctx );
+    if (EOF != ctx->current) {
         // Setup the string
         tok = (char*)malloc(2);
         tok[0] = ctx->current;
         tok[1] = '\0';
 
-        (void)OPTS_NextCharacter( ctx );
-        while( (EOF != ctx->current) && (' ' != ctx->current) )
-        {
-            tok = OPTS_AppendCharacter( tok, ctx->current );
-            (void)OPTS_NextCharacter( ctx );
+        (void)opts_next_char( ctx );
+        while ((EOF != ctx->current) && (' ' != ctx->current)) {
+            tok = opts_append_char( tok, ctx->current );
+            (void)opts_next_char( ctx );
         }
     }
     return tok;
 }
 
-void OPTS_AddOption( Result_T* res, char* name, char* arg )
-{
-    if( (NULL != res) && (NULL != res->options) )
-    {
-        Option_T* opt = (Option_T*)malloc( sizeof( Option_T ) );
-        opt->key = strclone( name );
-        opt->val = arg;
-        opt->next = NULL;
-        if( res->options->head == NULL )
-        {
-            res->options->head = opt;
-            res->options->tail = opt;
-        }
-        else
-        {
-            res->options->tail->next = opt;
-            res->options->tail = opt;
-        }
-    }
-}
-
-void OPTS_ConsumeWhitespace( StreamContext_T* ctx )
-{
-    while( ' ' == ctx->current )
-    {
-        (void)OPTS_NextCharacter( ctx );
-    }
+static void opts_consume_ws( StreamContext_T* ctx ) {
+    while (' ' == ctx->current)
+        (void)opts_next_char( ctx );
 }
 
-#include <stdio.h>
-char OPTS_NextCharacter( StreamContext_T* ctx )
-{
+static char opts_next_char( StreamContext_T* ctx ) {
     char current = EOF;
     ctx->current = EOF;
 
-    if( ctx->line_idx < ctx->arg_count )
-    {
+    if (ctx->line_idx < ctx->arg_count) {
         ctx->col_idx++;
-
-        if( ctx->line_idx < ctx->arg_count )
-        {
+        if (ctx->line_idx < ctx->arg_count) {
             char temp = ctx->arg_vect[ ctx->line_idx ][ ctx->col_idx ];
-            if( temp == '\0' )
-            {
+            if (temp == '\0') {
                 ctx->col_idx = -1;
                 ctx->line_idx++;
                 current = ' ';
                 ctx->current = current;
-            }
-            else
-            {
+            } else {
                 temp = (temp == '=') ? ' ' : temp;
                 current = temp;
                 ctx->current = current;
             }
         }
     }
+
     return current;
 }
 
-char* OPTS_AppendCharacter( char* str, char ch )
-{
+static char* opts_append_char( char* str, char ch ) {
     unsigned int new_size = strlen( str ) + 2;
     str = (char*)realloc( str, new_size );
     str[ new_size - 2 ] = ch;
@@ -251,7 +223,6 @@ char* OPTS_AppendCharacter( char* str, char ch )
     return str;
 }
 
-
 static char* strclone(const char* p_old) {
     size_t length = strlen(p_old);
     char* p_str = (char*)malloc(length+1);
@@ -260,3 +231,61 @@ static char* strclone(const char* p_old) {
     return p_str;
 }
 
+/*****************************************************************************/
+
+static void opts_add_option(char* name, char* tag, char* arg) {
+    option_t* option = (option_t*)malloc(sizeof(option_t));
+    option->name     = name;
+    option->tag      = strclone(tag);
+    option->value    = (NULL == arg) ? name : arg;
+    entry_t* entry   = (entry_t*)malloc(sizeof(entry_t));
+    entry->value     = (void*)option;
+    entry->next      = Options;
+    Options          = entry;
+}
+
+static void opts_add_argument(char* arg_val) {
+    entry_t* entry = (entry_t*)malloc(sizeof(entry_t));
+    entry->value   = (void*)arg_val;
+    entry->next    = Arguments;
+    Arguments      = entry;
+}
+
+/*****************************************************************************/
+option_t* find_option(const char* name, const char* tag) {
+    option_t* p_opt = NULL;
+    entry_t* current = Options;
+    while (current != NULL) {
+        option_t* curr_opt = (option_t*)current->value;
+        if (((NULL == name) || (0 == strcmp(name, curr_opt->name))) &&
+            ((NULL == tag)  || (0 == strcmp(tag,  curr_opt->tag)))) {
+            p_opt = curr_opt;
+            break;
+        }
+        current = current->next;
+    }
+    return p_opt;
+}
+
+bool opts_is_set(const char* name, const char* tag)
+{
+    return (NULL != find_option(name,tag));
+}
+
+const char* opts_get_value(const char* name, const char* tag)
+{
+    option_t* p_opt = find_option(name,tag);
+    return (NULL == p_opt) ? NULL : p_opt->value;
+}
+
+size_t opts_num_args(void)
+{
+    return 0;
+}
+
+const char* opts_get_arg(size_t index)
+{
+    (void)index;
+    return NULL;
+}
+
old mode 100644 (file)
new mode 100755 (executable)
index 3f8571e..b2233d0
@@ -1,81 +1,31 @@
 #ifndef OPTS_H
 #define OPTS_H
 
-typedef struct Option_T {
-    char* key;
-    char* val;
-    struct Option_T* next;
-} Option_T;
-
-typedef struct OptionList {
-    Option_T* head;
-    Option_T* tail;
-} OptionList_T;
-
-typedef struct Argument_T {
-    char* val;
-    struct Argument_T* next;
-} Argument_T;
-
-typedef struct ArgumentList {
-    Argument_T* head;
-    Argument_T* tail;
-} ArgumentList_T;
-
-typedef struct Result_T {
-    ArgumentList_T* arguments;
-    OptionList_T* options;
-} Result_T;
+#ifdef __cplusplus
+extern "C" {
+#endif
 
-typedef enum {
-    LONG,
-    SHORT,
-    END
-} OptionType_T;
+#include <stdbool.h>
+#include <stddef.h>
 
 typedef struct OptionConfig_T {
-    unsigned int type;
     char* name;
-    char* dest;
-    int has_arg;
+    bool has_arg;
+    char* tag;
     char* desc;
 } OptionConfig_T;
 
-typedef struct {
-    unsigned int line_idx;
-    unsigned int col_idx;
-    unsigned int arg_count;
-    char** arg_vect;
-    char current;
-    OptionConfig_T* options;
-    Result_T* results;
-} StreamContext_T;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-Result_T* OPTS_ParseOptions( OptionConfig_T* opts, int argc, char** argv );
-
-void OPTS_InitContext( StreamContext_T* ctx, int argc, char** argv );
-
-void OPTS_ParseShortOption( StreamContext_T* ctx );
-
-void OPTS_ParseLongOption( StreamContext_T* ctx );
-
-void OPTS_ParseArgument( StreamContext_T* ctx );
-
-OptionConfig_T* OPTS_GetOptConfig( OptionConfig_T* opts, OptionType_T typ, char* name );
+void opts_parse( OptionConfig_T* opts, int argc, char** argv );
 
-char* OPTS_NextToken( StreamContext_T* ctx );
+void opts_reset(void);
 
-void OPTS_AddOption( Result_T* res, char* name, char* arg );
+bool opts_is_set(const char* name, const char* tag);
 
-void OPTS_ConsumeWhitespace( StreamContext_T* ctx );
+const char* opts_get_value(const char* name, const char* tag);
 
-char OPTS_NextCharacter( StreamContext_T* ctx );
+size_t opts_num_args(void);
 
-char* OPTS_AppendCharacter( char* str, char ch );
+const char* opts_get_arg(size_t index);
 
 #ifdef __cplusplus
 }
diff --git a/tests/atf.c b/tests/atf.c
new file mode 100755 (executable)
index 0000000..14a972a
--- /dev/null
@@ -0,0 +1,38 @@
+/**
+  @file atf.c
+  @brief See header for details
+  $Revision$
+  $HeadURL$
+  */
+#include "atf.h"
+
+char* Curr_Test = NULL;
+static unsigned int Total = 0;
+static unsigned int Failed = 0;
+
+void atf_run_suite(suite_t suite) {
+    suite();
+}
+
+void atf_test_start(char* p_test_name) {
+    Curr_Test = p_test_name;
+    Total++;
+}
+
+void atf_test_fail(char* expr, char* file, int line) {
+    Failed++;
+    printf("%s:%d:0:%s:FAIL\n\t%s\n", file, line, Curr_Test, expr); \
+}
+
+int atf_print_results(void) {
+    static const char* results_string =
+    "\nUnit Test Summary"
+    "\n-----------------"
+    "\nTotal:  %d"
+    "\nPassed: %d"
+    "\nFailed: %d"
+    "\n\n";
+    printf(results_string, Total, Total - Failed, Failed);
+    return Failed;
+}
+
diff --git a/tests/atf.h b/tests/atf.h
new file mode 100755 (executable)
index 0000000..dc156de
--- /dev/null
@@ -0,0 +1,40 @@
+/**
+  @file test.h
+  @brief TODO: Describe this file
+  $Revision$
+  $HeadURL$
+  */
+#ifndef TEST_H
+#define TEST_H
+
+#include <stdio.h>
+
+#define CHECK(expr) \
+    if (!(expr)) { atf_test_fail(#expr,__FILE__,__LINE__); break; }
+
+#define TEST_SUITE(name) void name(void)
+
+#define TEST(desc) \
+    for(atf_test_start(#desc); Curr_Test != NULL; Curr_Test = NULL)
+
+#define RUN_EXTERN_TEST_SUITE(name) \
+    do { extern TEST_SUITE(name); atf_run_suite(&name); } while(0)
+
+#define RUN_TEST_SUITE(name) \
+    do { atf_run_suite(&name) } while(0)
+
+#define PRINT_TEST_RESULTS atf_print_results
+
+typedef void (*suite_t)(void);
+
+extern char* Curr_Test;
+
+void atf_run_suite(suite_t suite);
+
+void atf_test_start(char* p_test_name);
+
+void atf_test_fail(char* expr, char* file, int line);
+
+int atf_print_results(void);
+
+#endif /* TEST_H */
index 98d6801116e98872617525dbc07f7171ca2751f2..c47450f3c2a689f4a0ded3d585e7138634512da3 100755 (executable)
@@ -1,9 +1,9 @@
-#include "test.h"
+#include "atf.h"
 
 int main(int argc, char** argv)
 {
     (void)argc;
     (void)argv;
-    RUN_TEST_SUITE(Opts);
+    RUN_EXTERN_TEST_SUITE(Opts);
     return PRINT_TEST_RESULTS();
 }
diff --git a/tests/test.c b/tests/test.c
deleted file mode 100755 (executable)
index d58c9d4..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/**
-  @file test.c
-  @brief See header for details
-  $Revision$
-  $HeadURL$
-  */
-#include "test.h"
-
-int Loop_Var;
-char* Curr_Test;
-test_results_t Test_Results = {0};
-
-static const char* Results_String =
-"\nUnit Test Summary"
-"\n-----------------"
-"\nTotal:  %d"
-"\nPassed: %d"
-"\nFailed: %d"
-"\n\n"
-;
-
-int test_print_results(void) {
-    (void)Loop_Var;
-    (void)Curr_Test;
-    printf(Results_String,
-           Test_Results.total,
-           Test_Results.total - Test_Results.failed,
-           Test_Results.failed);
-    return Test_Results.failed;
-}
-
-void test_fail(char* expr, char* file, int line) {
-    Test_Results.failed++;
-    printf("%s:%d:0:%s:FAIL\n\t%s\n", file, line, Curr_Test, expr); \
-}
-
diff --git a/tests/test.h b/tests/test.h
deleted file mode 100755 (executable)
index 4ddfc44..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/**
-  @file test.h
-  @brief TODO: Describe this file
-  $Revision$
-  $HeadURL$
-  */
-#ifndef TEST_H
-#define TEST_H
-
-#include <stdio.h>
-
-#define CHECK(expr) \
-    if (!(expr)) { \
-        test_fail(#expr,__FILE__,__LINE__-1); \
-        break; \
-    }
-
-#define TEST(desc)        \
-    Curr_Test = #desc;    \
-    Test_Results.total++; \
-    test_setup();         \
-    for(Loop_Var = 0; Loop_Var < 1; Loop_Var++)
-
-#define TEST_SUITE(name) void name(void)
-
-#define RUN_TEST_SUITE(name) \
-    extern TEST_SUITE(name); \
-    name();
-
-#define PRINT_TEST_RESULTS test_print_results
-
-typedef struct {
-    unsigned int total;
-    unsigned int passed;
-    unsigned int failed;
-} test_results_t;
-
-extern int Loop_Var;
-
-extern char* Curr_Test;
-
-extern test_results_t Test_Results;
-
-int test_print_results(void);
-void test_fail(char* expr, char* file, int line);
-
-#endif /* TEST_H */
old mode 100644 (file)
new mode 100755 (executable)
index 28ddb6c..4be03de
@@ -1,5 +1,5 @@
 // Unit Test Framework Includes
-#include "test.h"
+#include "atf.h"
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 // Sample Option Configuration
 //-----------------------------------------------------------------------------
 OptionConfig_T Options_Config[] = {
-    { SHORT, (char*)"a",   (char*)"test_a", 0, (char*)"A simple test option" },
-    { SHORT, (char*)"b",   (char*)"test_b", 1, (char*)"A simple test option" },
-    { LONG,  (char*)"foo", (char*)"test_d", 0, (char*)"A simple test option" },
-    { LONG,  (char*)"bar", (char*)"test_e", 1, (char*)"A simple test option" },
-    { END,   (char*)NULL,  (char*)NULL,     0, (char*)NULL }
+    { (char*)"a",   false, (char*)"test_a", (char*)"A simple test option" },
+    { (char*)"b",   true,  (char*)"test_b", (char*)"A simple test option" },
+    { (char*)"c",   false, (char*)"test_c", (char*)"A simple test option" },
+    { (char*)"foo", false, (char*)"test_d", (char*)"A simple test option" },
+    { (char*)"bar", true,  (char*)"test_e", (char*)"A simple test option" },
+    { (char*)NULL,  false, (char*)NULL,     (char*)NULL }
 };
 
 //-----------------------------------------------------------------------------
@@ -43,112 +44,18 @@ void test_setup(void) {}
 // Begin Unit Tests
 //-----------------------------------------------------------------------------
 TEST_SUITE(Opts) {
-    //-------------------------------------------------------------------------
-    // Test InitContext Function
-    //-------------------------------------------------------------------------
-    TEST(Verify_InitContext_Initializes_The_StreamContext)
-    {
-        StreamContext_T ctx;
-        char* args[] = { (char*)"-a", (char*)"b", (char*)"--foo", (char*)"--foo=bar" };
-        OPTS_InitContext( &ctx, 4, args );
-
-        CHECK( 0 == ctx.line_idx );
-        CHECK( 0 == ctx.col_idx );
-        CHECK( 4 == ctx.arg_count );
-        CHECK( args == ctx.arg_vect );
-        CHECK( '-' == ctx.current );
-        CHECK( NULL != ctx.results );
-        CHECK( NULL != ctx.results->options );
-        CHECK( NULL == ctx.results->options->head );
-        CHECK( NULL == ctx.results->options->tail );
-        CHECK( NULL != ctx.results->arguments );
-        CHECK( NULL == ctx.results->arguments->head );
-        CHECK( NULL == ctx.results->arguments->tail );
-    }
-
     //-------------------------------------------------------------------------
     // Test ParseOptions Function
     //-------------------------------------------------------------------------
-    TEST(Verify_ParseOptions_Parses_A_Short_Option_With_No_Param)
-    {
-        char* args[] = { (char*)"-a" };
-
-        CHECK_DOES_NOT_EXIT()
-        {
-            Result_T* results = OPTS_ParseOptions( Options_Config, 1, args );
-
-            OptionList_T* result = results->options;
-            CHECK( NULL != result );
-            CHECK( NULL != result->head );
-            CHECK( NULL != result->tail );
-            CHECK( result->head == result->tail );
-            CHECK( NULL != result->tail->key );
-            CHECK( 0 == strcmp( result->tail->key, "a" ) );
-            CHECK( NULL == result->tail->val );
-            CHECK( NULL == result->tail->next );
-        }
-    }
-
-    TEST(Verify_ParseOptions_Parses_A_Short_Option_With_A_Param_And_A_Space)
-    {
-        char* args[] = { (char*)"-b", (char*)"5" };
-
-        CHECK_DOES_NOT_EXIT()
-        {
-            Result_T* results = OPTS_ParseOptions( Options_Config, 2, args );
-
-            OptionList_T* result = results->options;
-            CHECK( NULL != result );
-            CHECK( NULL != result->head );
-            CHECK( NULL != result->tail );
-            CHECK( result->head == result->tail );
-            CHECK( NULL != result->tail->key );
-            CHECK( 0 == strcmp( result->tail->key, "b" ) );
-            CHECK( NULL != result->tail->val );
-            CHECK( 0 == strcmp( result->tail->val, "5" ) );
-            CHECK( NULL == result->tail->next );
-        }
-    }
-
-    TEST(Verify_ParseOptions_Parses_A_Short_Option_With_A_Param_And_No_Space)
-    {
-        char* args[] = { (char*)"-b5" };
-
-        CHECK_DOES_NOT_EXIT()
-        {
-            Result_T* results = OPTS_ParseOptions( Options_Config, 1, args );
-
-            OptionList_T* result = results->options;
-            CHECK( NULL != result );
-            CHECK( NULL != result->head );
-            CHECK( NULL != result->tail );
-            CHECK( result->head == result->tail );
-            CHECK( NULL != result->tail->key );
-            CHECK( 0 == strcmp( result->tail->key, "b" ) );
-            CHECK( NULL != result->tail->val );
-            CHECK( 0 == strcmp( result->tail->val, "5" ) );
-            CHECK( NULL == result->tail->next );
-        }
-    }
-
     TEST(Verify_ParseOptions_Parses_A_Long_Option_With_No_Param)
     {
         char* args[] = { (char*)"--foo" };
-
         CHECK_DOES_NOT_EXIT()
         {
-            Result_T* results = OPTS_ParseOptions( Options_Config, 1, args );
-
-            OptionList_T* result = results->options;
-            CHECK( NULL != result );
-            CHECK( NULL != result->head );
-            CHECK( NULL != result->tail );
-            CHECK( result->head == result->tail );
-            CHECK( NULL != result->tail->key );
-            CHECK( 0 == strcmp( result->tail->key, "foo" ) );
-            CHECK( NULL == result->tail->val );
-            CHECK( NULL == result->tail->next );
+            opts_parse( Options_Config, 1, args );
+            CHECK(opts_is_set("foo", NULL));
         }
+        opts_reset();
     }
 
     TEST(Verify_ParseOptions_Parses_A_Long_Option_With_A_Param_And_A_Space)
@@ -157,657 +64,370 @@ TEST_SUITE(Opts) {
 
         CHECK_DOES_NOT_EXIT()
         {
-            Result_T* results = OPTS_ParseOptions( Options_Config, 2, args );
-
-            OptionList_T* result = results->options;
-            CHECK( NULL != result );
-            CHECK( NULL != result->head );
-            CHECK( NULL != result->tail );
-            CHECK( result->head == result->tail );
-            CHECK( NULL != result->tail->key );
-            CHECK( 0 == strcmp( result->tail->key, "bar" ) );
-            CHECK( NULL != result->tail->val );
-            CHECK( 0 == strcmp( result->tail->val, "baz" ) );
-            CHECK( NULL == result->tail->next );
+            opts_parse( Options_Config, 2, args );
+            CHECK(opts_is_set("bar", NULL));
+            CHECK(0 == strcmp("baz", opts_get_value("bar", NULL)));
         }
+        opts_reset();
     }
 
     TEST(Verify_ParseOptions_Parses_A_Long_Option_With_A_Param_And_An_Equals_Sign)
     {
         char* args[] = { (char*)"--bar=baz" };
-
         CHECK_DOES_NOT_EXIT()
         {
-            Result_T* results = OPTS_ParseOptions( Options_Config, 1, args );
-
-            OptionList_T* result = results->options;
-            CHECK( NULL != result );
-            CHECK( NULL != result->head );
-            CHECK( NULL != result->tail );
-            CHECK( result->head == result->tail );
-            CHECK( NULL != result->tail->key );
-            CHECK( 0 == strcmp( result->tail->key, "bar" ) );
-            CHECK( NULL != result->tail->val );
-            CHECK( 0 == strcmp( result->tail->val, "baz" ) );
-            CHECK( NULL == result->tail->next );
+            opts_parse( Options_Config, 1, args );
+            CHECK(opts_is_set("bar", NULL));
+            CHECK(0 == strcmp("baz", opts_get_value("bar", NULL)));
         }
+        opts_reset();
     }
 
-    TEST(Verify_ParseOptions_Parses_A_Floating_Argument)
+    TEST(Verify_ParseOptions_Parses_a_long_option_with_a_missing_param)
     {
-        char* args[] = { (char*)"baz1" };
+        int exit_code = 0;
+        char* args[] = { (char*)"--bar" };
 
-        CHECK_DOES_NOT_EXIT()
-        {
-            Result_T* results = OPTS_ParseOptions( Options_Config, 1, args );
-
-            ArgumentList_T* result = results->arguments;
-            CHECK( NULL != result );
-            CHECK( NULL != result->head );
-            CHECK( NULL != result->tail );
-            CHECK( result->head == result->tail );
-            CHECK( 0 == strcmp( result->tail->val, (char*)"baz1" ) );
-            CHECK( NULL == result->tail->next );
+        exit_code = setjmp( Exit_Point );
+        if( 0 == exit_code ) {
+            opts_parse( Options_Config, 1, args );
+            // If we fail to call exit then this breaks our test
+            CHECK( false );
+        } else {
+            CHECK( 1 == exit_code );
         }
+        opts_reset();
     }
 
-    //-------------------------------------------------------------------------
-    // Test ParseShortOption Function
-    //-------------------------------------------------------------------------
-    TEST(Verify_ParseShortOption_Exits_With_Error_On_Invalid_Option)
+    TEST(Verify_ParseOptions_Parses_a_long_option_with_a_missing_param)
     {
         int exit_code = 0;
-        char* args[] = { (char*)"z" };
-        StreamContext_T ctx;
-        ctx.options = Options_Config;
-        OPTS_InitContext( &ctx, 1, args );
+        char* args[] = { (char*)"--bar-" };
 
         exit_code = setjmp( Exit_Point );
-        if( 0 == exit_code )
-        {
-            OPTS_ParseShortOption( &ctx );
+        if( 0 == exit_code ) {
+            opts_parse( Options_Config, 1, args );
             // If we fail to call exit then this breaks our test
             CHECK( false );
-        }
-        else
-        {
-            OptionList_T* result = ctx.results->options;
+        } else {
             CHECK( 1 == exit_code );
-            CHECK( NULL != result );
-            CHECK( NULL == result->head );
-            CHECK( NULL == result->tail );
         }
+        opts_reset();
     }
 
-    TEST(Verify_ParseShortOption_Parses_A_Single_Valid_Option_With_No_Arg)
+    TEST(Verify_ParseOptions_exits_when_invalid_long_option)
     {
-        char* args[] = { (char*)"a", (char*)"a" };
-        StreamContext_T ctx;
-        ctx.options = Options_Config;
-        OPTS_InitContext( &ctx, 2, args );
+        int exit_code = 0;
+        char* args[] = { (char*)"--baz-" };
 
-        CHECK_DOES_NOT_EXIT()
-        {
-            OPTS_ParseShortOption( &ctx );
-            OptionList_T* result = ctx.results->options;
-            CHECK( NULL != result );
-            CHECK( NULL != result->head );
-            CHECK( NULL != result->tail );
-            CHECK( result->head == result->tail );
-            CHECK( NULL != result->tail->key );
-            CHECK( 0 == strcmp( result->tail->key, "a" ) );
-            CHECK( NULL == result->tail->val );
-            CHECK( NULL == result->tail->next );
+        exit_code = setjmp( Exit_Point );
+        if( 0 == exit_code ) {
+            opts_parse( Options_Config, 1, args );
+            // If we fail to call exit then this breaks our test
+            CHECK( false );
+        } else {
+            CHECK( 1 == exit_code );
         }
+        opts_reset();
     }
 
-    TEST(Verify_ParseShortOption_Parses_A_Single_Valid_Option_With_Arg_And_No_Space)
+    TEST(Verify_ParseOptions_Parses_short_option_with_no_argument)
     {
-        char* args[] = { (char*)"b5" };
-        StreamContext_T ctx;
-        ctx.options = Options_Config;
-        OPTS_InitContext( &ctx, 1, args );
-
+        char* args[] = { (char*)"-a" };
         CHECK_DOES_NOT_EXIT()
         {
-            OPTS_ParseShortOption( &ctx );
-
-            OptionList_T* result = ctx.results->options;
-            CHECK( NULL != result );
-            CHECK( NULL != result->head );
-            CHECK( NULL != result->tail );
-            CHECK( result->head == result->tail );
-            CHECK( NULL != result->tail->key );
-            CHECK( 0 == strcmp( result->tail->key, "b" ) );
-            CHECK( NULL != result->tail->val );
-            CHECK( 0 == strcmp( result->tail->val, "5" ) );
-            CHECK( NULL == result->tail->next );
+            opts_parse( Options_Config, 1, args );
+            CHECK(opts_is_set("a", NULL));
         }
+        opts_reset();
     }
 
-    TEST(Verify_ParseShortOption_Parses_A_Single_Valid_Option_With_Arg_And_Space)
+    TEST(Verify_ParseOptions_Parses_short_option_list_with_no_args)
     {
-        char* args[] = { (char*)"b", (char*)"5" };
-        StreamContext_T ctx;
-        ctx.options = Options_Config;
-        OPTS_InitContext( &ctx, 2, args );
-
+        char* args[] = { (char*)"-ac" };
         CHECK_DOES_NOT_EXIT()
         {
-            OPTS_ParseShortOption( &ctx );
-
-            OptionList_T* result = ctx.results->options;
-            CHECK( NULL != result );
-            CHECK( NULL != result->head );
-            CHECK( NULL != result->tail );
-            CHECK( result->head == result->tail );
-            CHECK( NULL != result->tail->key );
-            CHECK( 0 == strcmp( result->tail->key, "b" ) );
-            CHECK( NULL != result->tail->val );
-            CHECK( 0 == strcmp( result->tail->val, "5" ) );
-            CHECK( NULL == result->tail->next );
+            opts_parse( Options_Config, 1, args );
+            CHECK(opts_is_set("a", NULL));
+            CHECK(opts_is_set("c", NULL));
         }
+        opts_reset();
     }
 
-    TEST(Verify_ParseShortOption_Exits_With_Error_When_No_Arg_Received_When_Expected)
+    TEST(Verify_ParseOptions_Parses_a_short_option_with_an_argument)
     {
-        int exit_code = 0;
-        char* args[] = { (char*)"b" };
-        StreamContext_T ctx;
-        ctx.options = Options_Config;
-        OPTS_InitContext( &ctx, 1, args );
-
-        exit_code = setjmp( Exit_Point );
-        if( 0 == exit_code )
-        {
-            OPTS_ParseShortOption( &ctx );
-            // If we fail to call exit then this breaks our test
-            CHECK( false );
-        }
-        else
+        char* args[] = { (char*)"-bbaz" };
+        CHECK_DOES_NOT_EXIT()
         {
-            OptionList_T* result = ctx.results->options;
-            CHECK( 1 == exit_code );
-            CHECK( NULL != result );
-            CHECK( NULL == result->head );
-            CHECK( NULL == result->tail );
+            opts_parse( Options_Config, 1, args );
+            CHECK(opts_is_set("b", NULL));
+            CHECK(0 == strcmp("baz", opts_get_value("b", NULL)));
         }
+        opts_reset();
     }
 
-    TEST(Verify_ParseShortOption_Parses_A_Group_Of_Valid_Options_With_No_Arg)
+    TEST(Verify_ParseOptions_Parses_a_short_option_with_an_argument_and_a_space)
     {
-        char* args[] = { (char*)"aa" };
-        StreamContext_T ctx;
-        ctx.options = Options_Config;
-        OPTS_InitContext( &ctx, 1, args );
-
+        char* args[] = { (char*)"-b", "baz" };
         CHECK_DOES_NOT_EXIT()
         {
-            OPTS_ParseShortOption( &ctx );
-
-            OptionList_T* result = ctx.results->options;
-            CHECK( NULL != result );
-            CHECK( NULL != result->head );
-            CHECK( NULL != result->tail );
-            CHECK( result->head != result->tail );
-            // First option
-            CHECK( NULL != result->head->key );
-            CHECK( 0 == strcmp( result->head->key, "a" ) );
-            CHECK( NULL == result->head->val );
-            CHECK( NULL != result->head->next );
-            // Second option
-            CHECK( NULL != result->tail->key );
-            CHECK( 0 == strcmp( result->tail->key, "a" ) );
-            CHECK( NULL == result->tail->val );
-            CHECK( NULL == result->tail->next );
+            opts_parse( Options_Config, 2, args );
+            CHECK(opts_is_set("b", NULL));
+            CHECK(0 == strcmp("baz", opts_get_value("b", NULL)));
         }
+        opts_reset();
     }
 
-    TEST(Verify_ParseShortOption_Parses_A_Group_Of_Valid_Options_With_The_Last_Having_An_Arg)
+    TEST(Verify_ParseOptions_Parses_a_short_option_with_an_argument_and_an_equals)
     {
-        char* args[] = { (char*)"ab5" };
-        StreamContext_T ctx;
-        ctx.options = Options_Config;
-        OPTS_InitContext( &ctx, 1, args );
-
+        char* args[] = { (char*)"-b=baz" };
         CHECK_DOES_NOT_EXIT()
         {
-            OPTS_ParseShortOption( &ctx );
-
-            OptionList_T* result = ctx.results->options;
-            CHECK( NULL != result );
-            CHECK( NULL != result->head );
-            CHECK( NULL != result->tail );
-            CHECK( result->head != result->tail );
-            // First option
-            CHECK( NULL != result->head->key );
-            CHECK( 0 == strcmp( result->head->key, "b" ) );
-            CHECK( NULL != result->head->val );
-            CHECK( 0 == strcmp( result->head->val, "5" ) );
-            CHECK( NULL != result->head->next );
-            // Second option
-            CHECK( NULL != result->tail->key );
-            CHECK( 0 == strcmp( result->tail->key, "a" ) );
-            CHECK( NULL == result->tail->val );
-            CHECK( NULL == result->tail->next );
+            opts_parse( Options_Config, 1, args );
+            CHECK(opts_is_set("b", NULL));
+            CHECK(0 == strcmp("baz", opts_get_value("b", NULL)));
         }
+        opts_reset();
     }
 
-    //-------------------------------------------------------------------------
-    // Test ParseLongOption Function
-    //-------------------------------------------------------------------------
-    TEST(Verify_ParseLongOption_Errors_And_Exits_On_Invalid_Option)
+
+    TEST(Verify_ParseOptions_Parses_a_short_option_with_a_missing_param)
     {
         int exit_code = 0;
-        char* args[] = { (char*)"baz" };
-        StreamContext_T ctx;
-        ctx.options = Options_Config;
-        OPTS_InitContext( &ctx, 1, args );
+        char* args[] = { (char*)"-b" };
 
         exit_code = setjmp( Exit_Point );
-        if( 0 == exit_code )
-        {
-            OPTS_ParseLongOption( &ctx );
+        if( 0 == exit_code ) {
+            opts_parse( Options_Config, 1, args );
             // If we fail to call exit then this breaks our test
             CHECK( false );
-        }
-        else
-        {
-            OptionList_T* result = ctx.results->options;
+        } else {
             CHECK( 1 == exit_code );
-            CHECK( NULL != result );
-            CHECK( NULL == result->head );
-            CHECK( NULL == result->tail );
         }
+        opts_reset();
     }
 
-    TEST(Verify_ParseLongOption_Errors_And_Exits_Next_Option_Instead_Of_Argument)
+    TEST(Verify_ParseOptions_Parses_a_short_option_with_a_missing_param)
     {
         int exit_code = 0;
-        char* args[] = { (char*)"bar", (char*)"--foo" };
-        StreamContext_T ctx;
-        ctx.options = Options_Config;
-        OPTS_InitContext( &ctx, 2, args );
+        char* args[] = { (char*)"-b-" };
 
         exit_code = setjmp( Exit_Point );
-        if( 0 == exit_code )
-        {
-            OPTS_ParseLongOption( &ctx );
+        if( 0 == exit_code ) {
+            opts_parse( Options_Config, 1, args );
             // If we fail to call exit then this breaks our test
             CHECK( false );
-        }
-        else
-        {
-            OptionList_T* result = ctx.results->options;
+        } else {
             CHECK( 1 == exit_code );
-            CHECK( NULL != result );
-            CHECK( NULL == result->head );
-            CHECK( NULL == result->tail );
         }
+        opts_reset();
     }
 
-    TEST(Verify_ParseLongOption_Errors_And_Exits_EOF_Instead_Of_Argument)
+    TEST(Verify_ParseOptions_exits_when_invalid_short_option)
     {
         int exit_code = 0;
-        char* args[] = { (char*)"bar" };
-        StreamContext_T ctx;
-        ctx.options = Options_Config;
-        OPTS_InitContext( &ctx, 1, args );
+        char* args[] = { (char*)"-d" };
 
         exit_code = setjmp( Exit_Point );
-        if( 0 == exit_code )
-        {
-            OPTS_ParseLongOption( &ctx );
+        if( 0 == exit_code ) {
+            opts_parse( Options_Config, 1, args );
             // If we fail to call exit then this breaks our test
             CHECK( false );
-        }
-        else
-        {
-            OptionList_T* result = ctx.results->options;
+        } else {
             CHECK( 1 == exit_code );
-            CHECK( NULL != result );
-            CHECK( NULL == result->head );
-            CHECK( NULL == result->tail );
-        }
-    }
-
-    TEST(Verify_ParseLongOption_Parses_Option_With_No_Arg)
-    {
-        char* args[] = { (char*)"foo" };
-        StreamContext_T ctx;
-        ctx.options = Options_Config;
-        OPTS_InitContext( &ctx, 1, args );
-
-        CHECK_DOES_NOT_EXIT()
-        {
-            OPTS_ParseLongOption( &ctx );
-
-            OptionList_T* result = ctx.results->options;
-            CHECK( NULL != result );
-            CHECK( NULL != result->head );
-            CHECK( NULL != result->tail );
-            CHECK( result->head == result->tail );
-            CHECK( 0 == strcmp( result->head->key, (char*)"foo") );
-            CHECK( NULL == result->tail->val );
-        }
-    }
-
-    TEST(Verify_ParseLongOption_Parses_Option_With_Arg_Using_Equals_Sign)
-    {
-        char* args[] = { (char*)"bar=baz" };
-        StreamContext_T ctx;
-        ctx.options = Options_Config;
-        OPTS_InitContext( &ctx, 1, args );
-
-        CHECK_DOES_NOT_EXIT()
-        {
-            OPTS_ParseLongOption( &ctx );
-
-            OptionList_T* result = ctx.results->options;
-            CHECK( NULL != result );
-            CHECK( NULL != result->head );
-            CHECK( NULL != result->tail );
-            CHECK( result->head == result->tail );
-            CHECK( 0 == strcmp( result->head->key, (char*)"bar") );
-            CHECK( 0 == strcmp( result->head->val, (char*)"baz") );
         }
+        opts_reset();
     }
 
-    TEST(Verify_ParseLongOption_Parses_Option_With_Arg_Not_Using_Equals_Sign)
+    TEST(Verify_ParseOptions_Parses_A_Floating_Argument)
     {
-        char* args[] = { (char*)"bar", (char*)"baz" };
-        StreamContext_T ctx;
-        ctx.options = Options_Config;
-        OPTS_InitContext( &ctx, 2, args );
+        char* args[] = { (char*)"baz1" };
 
         CHECK_DOES_NOT_EXIT()
         {
-            OPTS_ParseLongOption( &ctx );
-
-            OptionList_T* result = ctx.results->options;
-            CHECK( NULL != result );
-            CHECK( NULL != result->head );
-            CHECK( NULL != result->tail );
-            CHECK( result->head == result->tail );
-            CHECK( 0 == strcmp( result->head->key, (char*)"bar") );
-            CHECK( 0 == strcmp( result->head->val, (char*)"baz") );
+            opts_parse( Options_Config, 1, args );
         }
-    }
-
-    //-------------------------------------------------------------------------
-    // Test ParseArgument Function
-    //-------------------------------------------------------------------------
-    TEST(Verify_ParseArgument_Does_Nothing_If_No_Tokens_Left)
-    {
-        char* args[] = { (char*)"" };
-        StreamContext_T ctx;
-        ctx.options = Options_Config;
-        OPTS_InitContext( &ctx, 1, args );
-
-        OPTS_ParseArgument( &ctx );
-
-        ArgumentList_T* result = ctx.results->arguments;
-        CHECK( NULL != result );
-        CHECK( NULL == result->head );
-        CHECK( NULL == result->tail );
-    }
-
-    TEST(Verify_ParseArgument_Adds_Argument_To_Empty_List)
-    {
-        char* args[] = { (char*)"baz1" };
-        StreamContext_T ctx;
-        ctx.options = Options_Config;
-        OPTS_InitContext( &ctx, 1, args );
-
-        OPTS_ParseArgument( &ctx );
-
-        ArgumentList_T* result = ctx.results->arguments;
-        CHECK( NULL != result );
-        CHECK( NULL != result->head );
-        CHECK( NULL != result->tail );
-        CHECK( result->head == result->tail );
-        CHECK( 0 == strcmp( result->tail->val, (char*)"baz1" ) );
-        CHECK( NULL == result->tail->next );
-    }
-
-    TEST(Verify_ParseArgument_Appends_Argument_To_End_Of_List)
-    {
-        char* args[] = { (char*)"baz1" };
-        StreamContext_T ctx;
-        ctx.options = Options_Config;
-        OPTS_InitContext( &ctx, 1, args );
-        ArgumentList_T* result = ctx.results->arguments;
-        Argument_T arg = { 0 };
-        result->head = &arg;
-        result->tail = &arg;
-
-        OPTS_ParseArgument( &ctx );
-
-        CHECK( NULL != result );
-        CHECK( NULL != result->head );
-        CHECK( NULL != result->tail );
-        CHECK( result->head != result->tail );
-        CHECK( 0 == strcmp( result->tail->val, (char*)"baz1" ) );
-        CHECK( NULL == result->tail->next );
-    }
-
-    //-------------------------------------------------------------------------
-    // Test GetOptConfig Function
-    //-------------------------------------------------------------------------
-    TEST(Verify_GetOptConfig_Can_Retrieve_A_Short_Config_By_Name_And_Type)
-    {
-        OptionConfig_T* result = NULL;
-        result = OPTS_GetOptConfig( Options_Config, SHORT, (char*)"a" );
-        CHECK( result == &(Options_Config[0]) );
-    }
-
-    TEST(Verify_GetOptConfig_Can_Retrieve_A_Long_Config_By_Name_And_Type)
-    {
-        OptionConfig_T* result = NULL;
-        result = OPTS_GetOptConfig( Options_Config, LONG, (char*)"foo" );
-        CHECK( result == &(Options_Config[2]) );
-    }
-
-    TEST(Verify_GetOptConfig_Returns_Null_If_No_Config_Found)
-    {
-        OptionConfig_T* result = NULL;
-        result = OPTS_GetOptConfig( Options_Config, LONG, (char*)"baz" );
-        CHECK( result == NULL );
-    }
-
-    TEST(Verify_GetOptConfig_Returns_Null_If_Config_List_Empty)
-    {
-        OptionConfig_T config[] = {
-            { END,   NULL,  NULL,     0, NULL }
-        };
-        OptionConfig_T* result = NULL;
-        result = OPTS_GetOptConfig( config, LONG, (char*)"foo" );
-        CHECK( result == NULL );
-    }
-
-    //-------------------------------------------------------------------------
-    // Test AddOption Function
-    //-------------------------------------------------------------------------
-    TEST(Verify_AddOption_Ignores_NULL_Result_Set)
-    {
-        Result_T results;
-        results.options = NULL;
-
-        // If we don't segfault here I call it a win
-        OPTS_AddOption( NULL, NULL, NULL );
-        OPTS_AddOption( &results, NULL, NULL );
-    }
-
-    TEST(Verify_AddOption_Adds_Result_To_Empty_List)
-    {
-        Result_T results;
-        char name[] = "foo";
-        char arg[]  = "bar";
-        results.options = (OptionList_T*)malloc( sizeof( OptionList_T ) );
-        results.options->head = NULL;
-        results.options->tail = NULL;
-        OPTS_AddOption( &results, name, arg );
-
-        CHECK( NULL != results.options->head );
-        CHECK( NULL != results.options->tail );
-        CHECK( NULL != results.options->head->key );
-        CHECK( name != results.options->head->key );
-        CHECK( 0 == strcmp( name, results.options->head->key ) );
-        CHECK( NULL != results.options->head->val );
-        CHECK( arg == results.options->head->val );
-        CHECK( NULL == results.options->head->next );
-        CHECK( results.options->head == results.options->tail );
-
-        free(results.options->head->key);
-        free(results.options->head);
-        free(results.options);
-    }
-
-    TEST(Verify_AddOption_Appends_Result_To_Tail_Of_List)
-    {
-        Result_T results;
-        Option_T option = {0};
-        char name[] = "foo";
-        char arg[]  = "bar";
-        results.options = (OptionList_T*)malloc( sizeof( OptionList_T ) );
-        results.options->head = &option;
-        results.options->tail = &option;
-        OPTS_AddOption( &results, name, arg );
-
-        CHECK( NULL != results.options->head );
-        CHECK( NULL != results.options->tail );
-        CHECK( results.options->head != results.options->tail );
-        CHECK( NULL != results.options->tail->key );
-        CHECK( name != results.options->tail->key );
-        CHECK( 0 == strcmp( name, results.options->tail->key ) );
-        CHECK( NULL != results.options->tail->val );
-        CHECK( arg == results.options->tail->val );
-        CHECK( NULL == results.options->tail->next );
-
-        free(results.options->tail->key);
-        free(results.options->tail);
-        free(results.options);
-    }
-
-    //-------------------------------------------------------------------------
-    // Test ConsumeWhitespaace Function
-    //-------------------------------------------------------------------------
-    TEST(Verify_ConsumeWhitespace_Removes_Whitespace_From_The_Stream_Till_The_Next_Token)
-    {
-        char* args[] = { (char*)"    " };
-        StreamContext_T ctx;
-        ctx.line_idx  = 0;
-        ctx.col_idx   = -1;
-        ctx.arg_count = 1;
-        ctx.arg_vect  = args;
-        (void)OPTS_NextCharacter( &ctx );
-
-        OPTS_ConsumeWhitespace( &ctx );
-        CHECK( EOF == OPTS_NextCharacter( &ctx ) );
-    }
-
-    //-------------------------------------------------------------------------
-    // Test NextToken Function
-    //-------------------------------------------------------------------------
-    TEST(Verify_NextToken_Properly_Tokenizes_Stream)
-    {
-        char* token = NULL;
-        char* args[] = { (char*)"-a", (char*)"b", (char*)"--foo", (char*)"--foo=bar" };
-        StreamContext_T ctx;
-        ctx.line_idx  = 0;
-        ctx.col_idx   = -1;
-        ctx.arg_count = 4;
-        ctx.arg_vect  = args;
-
-        (void)OPTS_NextCharacter( &ctx );
-        token = OPTS_NextToken( &ctx );
-        CHECK( 0 == strcmp( token, (char*)"-a" ) );
-        free( token );
-
-        (void)OPTS_NextCharacter( &ctx );
-        token = OPTS_NextToken( &ctx );
-        CHECK( 0 == strcmp( token, (char*)"b" ) );
-        free( token );
-
-        (void)OPTS_NextCharacter( &ctx );
-        token = OPTS_NextToken( &ctx );
-        CHECK( 0 == strcmp( token, (char*)"--foo" ) );
-        free( token );
-
-        (void)OPTS_NextCharacter( &ctx );
-        token = OPTS_NextToken( &ctx );
-        CHECK( 0 == strcmp( token, (char*)"--foo" ) );
-        free( token );
-
-        (void)OPTS_NextCharacter( &ctx );
-        token = OPTS_NextToken( &ctx );
-        CHECK( 0 == strcmp( token, (char*)"bar" ) );
-        free( token );
-    }
-
-    //-------------------------------------------------------------------------
-    // Test NextCharacter Function
-    //-------------------------------------------------------------------------
-    TEST(Verify_NextCharacter_Can_Loop_Through_Characters)
-    {
-        char* args[] = { (char*)"abc", (char*)"123=4" };
-        StreamContext_T ctx;
-        ctx.line_idx  = 0;
-        ctx.col_idx   = -1;
-        ctx.arg_count = 2;
-        ctx.arg_vect  = args;
-
-        CHECK( 'a' == OPTS_NextCharacter( &ctx ) );
-        CHECK( 'a' == ctx.current );
-        CHECK( 'b' == OPTS_NextCharacter( &ctx ) );
-        CHECK( 'b' == ctx.current );
-        CHECK( 'c' == OPTS_NextCharacter( &ctx ) );
-        CHECK( 'c' == ctx.current );
-        CHECK( ' ' == OPTS_NextCharacter( &ctx ) );
-        CHECK( ' ' == ctx.current );
-        CHECK( '1' == OPTS_NextCharacter( &ctx ) );
-        CHECK( '1' == ctx.current );
-        CHECK( '2' == OPTS_NextCharacter( &ctx ) );
-        CHECK( '2' == ctx.current );
-        CHECK( '3' == OPTS_NextCharacter( &ctx ) );
-        CHECK( '3' == ctx.current );
-        CHECK( ' ' == OPTS_NextCharacter( &ctx ) );
-        CHECK( ' ' == ctx.current );
-        CHECK( '4' == OPTS_NextCharacter( &ctx ) );
-        CHECK( '4' == ctx.current );
-        CHECK( ' ' == OPTS_NextCharacter( &ctx ) );
-        CHECK( ' ' == ctx.current );
-        CHECK( EOF == OPTS_NextCharacter( &ctx ) );
-        CHECK( EOF == ctx.current );
-        CHECK( EOF == OPTS_NextCharacter( &ctx ) );
-        CHECK( EOF == ctx.current );
-    }
-
-    TEST(Verify_NextCharacter_Can_Handle_Empty_Input)
-    {
-        char* args[] = {};
-        StreamContext_T ctx;
-        ctx.line_idx  = 0;
-        ctx.col_idx   = -1;
-        ctx.arg_count = 0;
-        ctx.arg_vect  = args;
-
-        CHECK( EOF == OPTS_NextCharacter( &ctx ) );
-        CHECK( EOF == ctx.current );
-        CHECK( EOF == OPTS_NextCharacter( &ctx ) );
-        CHECK( EOF == ctx.current );
-    }
-
-    //-------------------------------------------------------------------------
-    // Test AppendCharacter Function
-    //-------------------------------------------------------------------------
-    TEST(Verify_AppendCharacter_Dynamically_Resizes_and_Appends_Char)
-    {
-        char* str = (char*)malloc(2);
-        str[0] = 'a';
-        str[1] = '\0';
-        str = OPTS_AppendCharacter( str, 'b' );
-
-        CHECK( 0 == strcmp( str, (char*)"ab" ) );
-    }
+        opts_reset();
+    }
+
+
+
+
+
+
+
+
+
+
+
+
+//    TEST(Verify_ParseOptions_exits_when_a_short_option_lacks_the_required_option)
+//    {
+//        Result_T* results;
+//        int exit_code = 0;
+//        char* args[] = { (char*)"-b-" };
+//
+//        exit_code = setjmp( Exit_Point );
+//        if( 0 == exit_code ) {
+//            results = opts_parse( Options_Config, 1, args );
+//            // If we fail to call exit then this breaks our test
+//            CHECK( false );
+//        } else {
+//            CHECK( 1 == exit_code );
+//        }
+//    }
+//
+//    TEST(Verify_ParseOptions_exits_when_a_short_option_with_no_accompanying_option)
+//    {
+//        Result_T* results;
+//        int exit_code = 0;
+//        char* args[] = { (char*)"-b" };
+//
+//        exit_code = setjmp( Exit_Point );
+//        if( 0 == exit_code ) {
+//            results = opts_parse( Options_Config, 1, args );
+//            // If we fail to call exit then this breaks our test
+//            CHECK( false );
+//        } else {
+//            CHECK( 1 == exit_code );
+//        }
+//    }
+//
+//    TEST(Verify_ParseOptions_errors_on_unknown_option)
+//    {
+//        Result_T* results;
+//        int exit_code = 0;
+//        char* args[] = { (char*)"-z" };
+//
+//        exit_code = setjmp( Exit_Point );
+//        if( 0 == exit_code ) {
+//            results = opts_parse( Options_Config, 1, args );
+//            // If we fail to call exit then this breaks our test
+//            CHECK( false );
+//        } else {
+//            CHECK( 1 == exit_code );
+//        }
+//    }
+//
+//    TEST(Verify_ParseOptions_Parses_short_option_group)
+//    {
+//        char* args[] = { (char*)"-aa" };
+//
+//        CHECK_DOES_NOT_EXIT()
+//        {
+//            Result_T* results = opts_parse( Options_Config, 1, args );
+//
+//            OptionList_T* result = results->options;
+//            CHECK( NULL != result );
+//            CHECK( NULL != result->head );
+//            CHECK( NULL != result->tail );
+//            CHECK( result->head != result->tail );
+//            CHECK( NULL != result->head->key );
+//            CHECK( 0 == strcmp( result->head->key, "a" ) );
+//            CHECK( NULL == result->head->val );
+//            CHECK( NULL != result->tail->key );
+//            CHECK( 0 == strcmp( result->tail->key, "a" ) );
+//            CHECK( NULL == result->tail->val );
+//        }
+//    }
+//
+//    TEST(Verify_ParseOptions_Parses_short_option_group_with_more_than_2_options)
+//    {
+//        char* args[] = { (char*)"-aaaa" };
+//
+//        CHECK_DOES_NOT_EXIT()
+//        {
+//            Result_T* results = opts_parse( Options_Config, 1, args );
+//
+//            OptionList_T* result = results->options;
+//            CHECK( NULL != result );
+//            CHECK( NULL != result->head );
+//            CHECK( NULL != result->tail );
+//            CHECK( result->head != result->tail );
+//        }
+//    }
+//
+//    TEST(Verify_ParseOptions_Parses_short_option_group_with_the_last_having_an_arg)
+//    {
+//        char* args[] = { (char*)"-ab5" };
+//
+//        CHECK_DOES_NOT_EXIT()
+//        {
+//            Result_T* results = opts_parse( Options_Config, 1, args );
+//            OptionList_T* result = results->options;
+//            CHECK( NULL != result );
+//            CHECK( NULL != result->head );
+//            CHECK( NULL != result->tail );
+//            CHECK( result->head != result->tail );
+//            CHECK( NULL != result->head->key );
+//            CHECK( 0 == strcmp( result->head->key, "b" ) );
+//            CHECK( NULL != result->head->val );
+//            CHECK( 0 == strcmp( result->head->val, "5" ) );
+//            CHECK( NULL != result->tail->key );
+//            CHECK( 0 == strcmp( result->tail->key, "a" ) );
+//            CHECK( NULL == result->tail->val );
+//        }
+//    }
+//
+//    TEST(Verify_ParseOptions_Parses_A_Short_Option_With_No_Param)
+//    {
+//        char* args[] = { (char*)"-a" };
+//
+//        CHECK_DOES_NOT_EXIT()
+//        {
+//            Result_T* results = opts_parse( Options_Config, 1, args );
+//
+//            OptionList_T* result = results->options;
+//            CHECK( NULL != result );
+//            CHECK( NULL != result->head );
+//            CHECK( NULL != result->tail );
+//            CHECK( result->head == result->tail );
+//            CHECK( NULL != result->tail->key );
+//            CHECK( 0 == strcmp( result->tail->key, "a" ) );
+//            CHECK( NULL == result->tail->val );
+//            CHECK( NULL == result->tail->next );
+//        }
+//    }
+//
+//    TEST(Verify_ParseOptions_Parses_A_Short_Option_With_A_Param_And_A_Space)
+//    {
+//        char* args[] = { (char*)"-b", (char*)"5" };
+//
+//        CHECK_DOES_NOT_EXIT()
+//        {
+//            Result_T* results = opts_parse( Options_Config, 2, args );
+//
+//            OptionList_T* result = results->options;
+//            CHECK( NULL != result );
+//            CHECK( NULL != result->head );
+//            CHECK( NULL != result->tail );
+//            CHECK( result->head == result->tail );
+//            CHECK( NULL != result->tail->key );
+//            CHECK( 0 == strcmp( result->tail->key, "b" ) );
+//            CHECK( NULL != result->tail->val );
+//            CHECK( 0 == strcmp( result->tail->val, "5" ) );
+//            CHECK( NULL == result->tail->next );
+//        }
+//    }
+//
+//    TEST(Verify_ParseOptions_Parses_A_Short_Option_With_A_Param_And_No_Space)
+//    {
+//        char* args[] = { (char*)"-b5" };
+//
+//        CHECK_DOES_NOT_EXIT()
+//        {
+//            Result_T* results = opts_parse( Options_Config, 1, args );
+//
+//            OptionList_T* result = results->options;
+//            CHECK( NULL != result );
+//            CHECK( NULL != result->head );
+//            CHECK( NULL != result->tail );
+//            CHECK( result->head == result->tail );
+//            CHECK( NULL != result->tail->key );
+//            CHECK( 0 == strcmp( result->tail->key, "b" ) );
+//            CHECK( NULL != result->tail->val );
+//            CHECK( 0 == strcmp( result->tail->val, "5" ) );
+//            CHECK( NULL == result->tail->next );
+//        }
+//    }
 }