aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLion Kortlepel <[email protected]>2026-02-01 15:35:37 +0000
committerLion Kortlepel <[email protected]>2026-02-01 15:35:37 +0000
commite933171609b676556f70834cbf48b441c7ed8060 (patch)
tree0612d3313f5ab791c854dec5ee2f19d1d60ecfae
parentb13f5c7b5a21ac3ad03fd980f085a86531d37f27 (diff)
downloadargs-2.3.tar.zst
args-2.3.zip
feat: add readme, refactor error handlingv2.3
we now handle the allocation failure case in error branches too
-rw-r--r--README.md62
-rw-r--r--ls_args.h191
-rw-r--r--tests/tests.c252
3 files changed, 417 insertions, 88 deletions
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..bff5cc6
--- /dev/null
+++ b/README.md
@@ -0,0 +1,62 @@
+# LS Args
+
+Minimal, single-header command-line argument parser for C.
+
+- ANSI C / C89
+- Header-only
+- No macros or code generation
+- Extensively unit-tested (90%+ line- and branch coverage)
+- Supports short/long options, booleans, strings, and positional arguments
+- Supports short options as `-abc` equivalent to `-a -b -c`
+- Optional/required argument modes
+- Auto-generated help text
+- Supports `--` to indicate that all following arguments should be treated as positional, even if they start with `-`
+
+## Quick Start
+1. Copy `ls_args.h` to your project.
+2. Define and initialize an argument parser:
+ ```c
+ ls_args args;
+ ls_args_init(&args);
+ args.help_description = "My program description.";
+ ```
+3. Register arguments:
+ ```c
+ int verbose = 0;
+ ls_args_bool(&args, &verbose, "v", "verbose", "Enable verbose output", 0);
+
+ const char* output = NULL;
+ ls_args_string(&args, &output, "o", "output", "Output file", 0);
+
+ const char* input;
+ ls_args_pos_string(&args, &input, "Input file", LS_ARGS_REQUIRED);
+ ```
+4. Parse arguments:
+ ```c
+ if (!ls_args_parse(&args, argc, argv)) {
+ fprintf(stderr, "%s\n", args.last_error);
+ exit(1);
+ }
+ ```
+5. Use parsed values. Free resources when done:
+ ```c
+ ls_args_free(&args);
+ ```
+6. Use `ls_args_help()` to generate a help string from provided arguments:
+ ```c
+ puts(ls_args_help(&args));
+ ```
+ Example output:
+ ```
+ Usage: ./my_example [OPTION] <Input file>
+
+ Options:
+ -v --verbose Enable verbose output
+ -o --output Output file
+ ```
+
+See [`ls_args.h`](ls_args.h) for detailed documentation and usage patterns.
+
+## License
+
+MIT.
diff --git a/ls_args.h b/ls_args.h
index f27b491..36e951c 100644
--- a/ls_args.h
+++ b/ls_args.h
@@ -1,7 +1,7 @@
/* Lion's Standard (LS) ANSI C commandline argument parser with included help
* renderer.
*
- * Version: 2.2
+ * Version: 2.3
* Website: https://libls.org
* Repo: https://github.com/libls/args
* SPDX-License-Identifier: MIT
@@ -244,11 +244,36 @@ void ls_args_free(ls_args*);
* separately with -DLS_ARGS_IMPLEMENTATION. */
#ifdef LS_ARGS_IMPLEMENTATION
+#define _lsa_ALLOC_FAIL_STR "Allocation failure"
+
#include <assert.h>
+#include <stdarg.h>
#include <stdint.h>
#include <stdio.h> /* for sprintf */
#include <string.h>
+static int _lsa_set_error_va(
+ ls_args* a, size_t len, const char* fmt, va_list ap) {
+ a->_allocated_error = LS_REALLOC(a->_allocated_error, len);
+ if (a->_allocated_error == NULL) {
+ a->last_error = _lsa_ALLOC_FAIL_STR;
+ return 0;
+ }
+ memset(a->_allocated_error, 0, len);
+ vsprintf(a->_allocated_error, fmt, ap);
+ a->last_error = a->_allocated_error;
+ return 1;
+}
+
+static int _lsa_set_error(ls_args* a, size_t len, const char* fmt, ...) {
+ int ret;
+ va_list ap;
+ va_start(ap, fmt);
+ ret = _lsa_set_error_va(a, len, fmt, ap);
+ va_end(ap);
+ return ret;
+}
+
/* 0 on failure, 1 on success */
static int _lsa_add(ls_args* a, ls_args_arg** arg) {
/* a is already checked when this is called */
@@ -300,7 +325,7 @@ int _lsa_register(ls_args* a, void* val, ls_args_type type,
assert(short_opt == NULL || strlen(short_opt) == 1);
ret = _lsa_add(a, &arg);
if (ret == 0) {
- a->last_error = "Allocation failure";
+ a->last_error = _lsa_ALLOC_FAIL_STR;
return 0;
}
/* TODO: sanity check that there are no dashes in there, because that would
@@ -339,7 +364,7 @@ int ls_args_pos_string(
assert(val != NULL);
ret = _lsa_add(a, &arg);
if (ret == 0) {
- a->last_error = "Allocation failure";
+ a->last_error = _lsa_ALLOC_FAIL_STR;
return 0;
}
arg->type = LS_ARGS_TYPE_STRING;
@@ -441,11 +466,10 @@ static int _lsa_parse_long(
}
if (!found) {
const size_t len = 32 + strlen(parsed->as.erroneous);
- a->_allocated_error = LS_REALLOC(a->_allocated_error, len);
- memset(a->_allocated_error, 0, len);
- sprintf(a->_allocated_error, "Invalid argument '--%s'",
- parsed->as.erroneous);
- a->last_error = a->_allocated_error;
+ if (!_lsa_set_error(
+ a, len, "Invalid argument '--%s'", parsed->as.erroneous)) {
+ return 0;
+ }
return 0;
}
return 1;
@@ -461,13 +485,12 @@ static int _lsa_parse_short(
if (*prev_arg) {
struct _lsa_spec named = (*prev_arg)->match.name;
const size_t len = 128 + strlen(named.short_opt);
- a->_allocated_error = LS_REALLOC(a->_allocated_error, len);
- memset(a->_allocated_error, 0, len);
- sprintf(a->_allocated_error,
- "Expected argument following '-%s', instead got another "
- "argument '-%c'",
- named.short_opt, arg);
- a->last_error = a->_allocated_error;
+ if (!_lsa_set_error(a, len,
+ "Expected argument following '-%s', instead got another "
+ "argument '-%c'",
+ named.short_opt, arg)) {
+ return 0;
+ }
return 0;
}
for (k = 0; k < a->args_len; ++k) {
@@ -484,10 +507,9 @@ static int _lsa_parse_short(
}
if (!found) {
const size_t len = 32;
- a->_allocated_error = LS_REALLOC(a->_allocated_error, len);
- memset(a->_allocated_error, 0, len);
- sprintf(a->_allocated_error, "Invalid argument '-%c'", arg);
- a->last_error = a->_allocated_error;
+ if (!_lsa_set_error(a, len, "Invalid argument '-%c'", arg)) {
+ return 0;
+ }
return 0;
}
}
@@ -506,11 +528,10 @@ static int _lsa_parse_positional(
return 1;
}
}
- a->_allocated_error = LS_REALLOC(a->_allocated_error, len);
- memset(a->_allocated_error, 0, len);
- sprintf(
- a->_allocated_error, "Unexpected argument '%s'", parsed->as.positional);
- a->last_error = a->_allocated_error;
+ if (!_lsa_set_error(
+ a, len, "Unexpected argument '%s'", parsed->as.positional)) {
+ return 0;
+ }
return 0;
}
@@ -532,12 +553,11 @@ int ls_args_parse(ls_args* a, int argc, char** argv) {
if (parsed.type != LS_ARGS_PARSED_POSITIONAL) {
/* argument for the previous param expected, but none given */
const size_t len = 64 + strlen(prev_arg->match.name.long_opt);
- a->_allocated_error = LS_REALLOC(a->_allocated_error, len);
- memset(a->_allocated_error, 0, len);
- sprintf(a->_allocated_error,
- "Expected argument following '--%s'",
- prev_arg->match.name.long_opt);
- a->last_error = a->_allocated_error;
+ if (!_lsa_set_error(a, len,
+ "Expected argument following '--%s'",
+ prev_arg->match.name.long_opt)) {
+ return 0;
+ }
return 0;
}
if (prev_arg->type == LS_ARGS_TYPE_STRING) {
@@ -549,11 +569,10 @@ int ls_args_parse(ls_args* a, int argc, char** argv) {
switch (parsed.type) {
case LS_ARGS_PARSED_ERROR: {
const size_t len = 32 + strlen(parsed.as.erroneous);
- a->_allocated_error = LS_REALLOC(a->_allocated_error, len);
- memset(a->_allocated_error, 0, len);
- sprintf(a->_allocated_error, "Invalid argument '%s'",
- parsed.as.erroneous);
- a->last_error = a->_allocated_error;
+ if (!_lsa_set_error(
+ a, len, "Invalid argument '%s'", parsed.as.erroneous)) {
+ return 0;
+ }
return 0;
}
case LS_ARGS_PARSED_LONG: {
@@ -599,11 +618,10 @@ int ls_args_parse(ls_args* a, int argc, char** argv) {
* case with -/--... arguments */
assert(!prev_arg->is_pos);
len = 64 + strlen(prev_arg->match.name.long_opt);
- a->_allocated_error = LS_REALLOC(a->_allocated_error, len);
- memset(a->_allocated_error, 0, len);
- sprintf(a->_allocated_error, "Expected argument following '--%s'",
- prev_arg->match.name.long_opt);
- a->last_error = a->_allocated_error;
+ if (!_lsa_set_error(a, len, "Expected argument following '--%s'",
+ prev_arg->match.name.long_opt)) {
+ return 0;
+ }
return 0;
}
@@ -612,20 +630,19 @@ int ls_args_parse(ls_args* a, int argc, char** argv) {
size_t len;
if (a->args[i].is_pos) {
len = 64;
- a->_allocated_error = LS_REALLOC(a->_allocated_error, len);
- memset(a->_allocated_error, 0, len);
- sprintf(a->_allocated_error,
- "Required argument '%s' not provided", a->args[i].help);
+ if (!_lsa_set_error(a, len,
+ "Required argument '%s' not provided",
+ a->args[i].help)) {
+ return 0;
+ }
} else {
len = 64 + strlen(a->args[i].match.name.long_opt);
- a->_allocated_error = LS_REALLOC(a->_allocated_error, len);
- memset(a->_allocated_error, 0, len);
- sprintf(a->_allocated_error,
- "Required argument '--%s' not found",
- a->args[i].match.name.long_opt);
+ if (!_lsa_set_error(a, len,
+ "Required argument '--%s' not found",
+ a->args[i].match.name.long_opt)) {
+ return 0;
+ }
}
-
- a->last_error = a->_allocated_error;
return 0;
}
}
@@ -701,18 +718,19 @@ char* ls_args_help(ls_args* a) {
}
}
for (i = 0; i < a->args_len; ++i) {
- if (a->args[i].is_pos) {
- const char* open
- = a->args[i].mode == LS_ARGS_REQUIRED ? " <" : " [";
- const char* close
- = a->args[i].mode == LS_ARGS_REQUIRED ? ">" : "]";
- if (!_lsa_buffer_append_cstr(&help, open))
- goto alloc_fail;
- if (!_lsa_buffer_append_cstr(&help, a->args[i].help))
- goto alloc_fail;
- if (!_lsa_buffer_append_cstr(&help, close))
- goto alloc_fail;
+ const char* open, *close;
+ if (!a->args[i].is_pos) {
+ continue;
}
+
+ open = a->args[i].mode == LS_ARGS_REQUIRED ? " <" : " [";
+ close = a->args[i].mode == LS_ARGS_REQUIRED ? ">" : "]";
+ if (!_lsa_buffer_append_cstr(&help, open))
+ goto alloc_fail;
+ if (!_lsa_buffer_append_cstr(&help, a->args[i].help))
+ goto alloc_fail;
+ if (!_lsa_buffer_append_cstr(&help, close))
+ goto alloc_fail;
}
if (a->help_description) {
if (!_lsa_buffer_append_cstr(&help, "\n\n"))
@@ -720,24 +738,37 @@ char* ls_args_help(ls_args* a) {
if (!_lsa_buffer_append_cstr(&help, a->help_description))
goto alloc_fail;
}
- if (!_lsa_buffer_append_cstr(&help, "\n\nOptions:"))
- goto alloc_fail;
- for (i = 0; i < a->args_len; ++i) {
- if (!a->args[i].is_pos) {
- if (!_lsa_buffer_append_cstr(&help, "\n -"))
- goto alloc_fail;
- if (!_lsa_buffer_append_cstr(
- &help, a->args[i].match.name.short_opt))
- goto alloc_fail;
- if (!_lsa_buffer_append_cstr(&help, " \t--"))
- goto alloc_fail;
- if (!_lsa_buffer_append_cstr(
- &help, a->args[i].match.name.long_opt))
- goto alloc_fail;
- if (!_lsa_buffer_append_cstr(&help, " \t\t"))
- goto alloc_fail;
- if (!_lsa_buffer_append_cstr(&help, a->args[i].help))
+
+ /* Only print "Options:" if there are non-positional options */
+ {
+ int has_nonpositional = 0;
+ for (i = 0; i < a->args_len; ++i) {
+ if (!a->args[i].is_pos) {
+ has_nonpositional = 1;
+ break;
+ }
+ }
+ if (has_nonpositional) {
+ if (!_lsa_buffer_append_cstr(&help, "\n\nOptions:"))
goto alloc_fail;
+ for (i = 0; i < a->args_len; ++i) {
+ if (!a->args[i].is_pos) {
+ if (!_lsa_buffer_append_cstr(&help, "\n -"))
+ goto alloc_fail;
+ if (!_lsa_buffer_append_cstr(
+ &help, a->args[i].match.name.short_opt))
+ goto alloc_fail;
+ if (!_lsa_buffer_append_cstr(&help, " \t--"))
+ goto alloc_fail;
+ if (!_lsa_buffer_append_cstr(
+ &help, a->args[i].match.name.long_opt))
+ goto alloc_fail;
+ if (!_lsa_buffer_append_cstr(&help, " \t\t"))
+ goto alloc_fail;
+ if (!_lsa_buffer_append_cstr(&help, a->args[i].help))
+ goto alloc_fail;
+ }
+ }
}
}
}
@@ -747,7 +778,7 @@ char* ls_args_help(ls_args* a) {
return a->_allocated_help;
alloc_fail:
a->_allocated_help = help.data;
- a->last_error = "Allocation failure";
+ a->last_error = _lsa_ALLOC_FAIL_STR;
return "Not enough memory available to generate help text.";
}
diff --git a/tests/tests.c b/tests/tests.c
index 6a7b4b7..9b9007e 100644
--- a/tests/tests.c
+++ b/tests/tests.c
@@ -3,10 +3,15 @@
#define LS_TEST_IMPLEMENTATION
#include "ls_test.h"
-int fail_alloc = 0;
+int fail_alloc_once = 0;
+int alloc_limit = -1;
void* test_realloc(void* p, size_t size) {
- if (fail_alloc) {
+ if (fail_alloc_once) {
+ fail_alloc_once = 0;
+ return NULL;
+ }
+ if (alloc_limit != -1 && (int)size > alloc_limit) {
return NULL;
}
return realloc(p, size);
@@ -70,15 +75,246 @@ TEST_CASE(basic_args_with_unused_positionals) {
return 0;
}
+TEST_CASE(help_output_no_options) {
+ ls_args args;
+ const char* infile = NULL;
+ char* help_str;
+
+ ls_args_init(&args);
+ ls_args_pos_string(&args, &infile, "Input file", 0);
+
+ help_str = ls_args_help(&args);
+ ASSERT(help_str != NULL);
+ ASSERT_STR_EQ(args.last_error, "Success");
+
+ /* [OPTION] should NOT be present */
+ ASSERT(!strstr(help_str, "[OPTION]"));
+
+ /* "Options:" should NOT be present */
+ ASSERT(!strstr(help_str, "Options:"));
+
+ /* The positional argument should be present */
+ ASSERT(strstr(help_str, "[Input file]") || strstr(help_str, "<Input file>"));
+
+ ls_args_free(&args);
+ return 0;
+}
+
+TEST_CASE(huge_description) {
+ int help = 0;
+ ls_args args;
+ int i;
+ char* help_str;
+ /* Create a very large description string */
+ enum { DESC_SIZE = 8192 };
+ char* huge_desc = (char*)LS_REALLOC(NULL, DESC_SIZE + 1);
+ ASSERT(huge_desc != NULL);
+ for (i = 0; i < DESC_SIZE; ++i) {
+ huge_desc[i] = 'A' + (i % 26);
+ }
+ huge_desc[DESC_SIZE] = '\0';
+
+ ls_args_init(&args);
+ ls_args_bool(&args, &help, "h", "help", huge_desc, 0);
+
+ help_str = ls_args_help(&args);
+ ASSERT(help_str != NULL);
+ ASSERT_STR_EQ(args.last_error, "Success");
+ /* The huge description should appear in the help output */
+ ASSERT(strstr(help_str, huge_desc));
+
+ LS_FREE(huge_desc);
+ ls_args_free(&args);
+ return 0;
+}
+
+TEST_CASE(help_output_basic) {
+ int help = 0;
+ const char* infile = NULL;
+ const char* outfile = "out.txt";
+ ls_args args;
+ char* help_str;
+
+ ls_args_init(&args);
+ ls_args_bool(&args, &help, "h", "help", "Provides help", 0);
+ ls_args_string(&args, &outfile, "o", "out",
+ "Specify the outfile, default 'out.txt'", 0);
+ ls_args_pos_string(&args, &infile, "Input file", 0);
+
+ help_str = ls_args_help(&args);
+ ASSERT(help_str != NULL);
+ ASSERT_STR_EQ(args.last_error, "Success");
+
+ ASSERT(strstr(help_str, "-h"));
+ ASSERT(strstr(help_str, "--help"));
+ ASSERT(strstr(help_str, "-o"));
+ ASSERT(strstr(help_str, "--out"));
+
+ ASSERT(strstr(help_str, "Provides help"));
+ ASSERT(strstr(help_str, "Specify the outfile"));
+
+ ASSERT(strstr(help_str, "[OPTION]"));
+ ASSERT(strstr(help_str, "[Input file]"));
+
+ ASSERT(strstr(help_str, "default 'out.txt'"));
+
+ ASSERT(strstr(help_str, "Input file"));
+
+ ASSERT(strstr(help_str, "-h"));
+ ASSERT(strstr(help_str, "--help"));
+ ASSERT(strstr(help_str, "-o"));
+ ASSERT(strstr(help_str, "--out"));
+
+ ls_args_free(&args);
+ return 0;
+}
+
+TEST_CASE(help_output_basic_required_pos) {
+ int help = 0;
+ const char* infile = NULL;
+ const char* outfile = "out.txt";
+ ls_args args;
+ char* help_str;
+
+ ls_args_init(&args);
+ ls_args_bool(&args, &help, "h", "help", "Provides help", 0);
+ ls_args_string(&args, &outfile, "o", "out",
+ "Specify the outfile, default 'out.txt'", 0);
+ ls_args_pos_string(&args, &infile, "Input file", LS_ARGS_REQUIRED);
+
+ help_str = ls_args_help(&args);
+ ASSERT(help_str != NULL);
+ ASSERT_STR_EQ(args.last_error, "Success");
+
+ ASSERT(strstr(help_str, "-h"));
+ ASSERT(strstr(help_str, "--help"));
+ ASSERT(strstr(help_str, "-o"));
+ ASSERT(strstr(help_str, "--out"));
+
+ ASSERT(strstr(help_str, "Provides help"));
+ ASSERT(strstr(help_str, "Specify the outfile"));
+
+ ASSERT(strstr(help_str, "[OPTION]"));
+ ASSERT(strstr(help_str, "<Input file>"));
+
+ ASSERT(strstr(help_str, "default 'out.txt'"));
+
+ ASSERT(strstr(help_str, "Input file"));
+
+ ASSERT(strstr(help_str, "-h"));
+ ASSERT(strstr(help_str, "--help"));
+ ASSERT(strstr(help_str, "-o"));
+ ASSERT(strstr(help_str, "--out"));
+
+ ls_args_free(&args);
+ return 0;
+}
+
+TEST_CASE(help_alloc_limit_sweep) {
+ int help = 0;
+ int limit;
+ const char* infile = NULL;
+ const char* outfile = "out.txt";
+ ls_args args;
+ char* help_str = NULL;
+ int succeeded = 0;
+
+ ls_args_init(&args);
+ args.help_description = "My description!";
+ ls_args_bool(&args, &help, "h", "help", "Provides help", 0);
+ ls_args_string(&args, &outfile, "o", "out",
+ "Specify the outfile, default 'out.txt'", 0);
+ ls_args_pos_string(&args, &infile, "Input file", 0);
+
+ /* Sweep alloc_limit from very small sizes upward to ensure all
+ * allocation attempts inside ls_args_help are exercised.
+ * For each limit, call ls_args_help multiple times to verify repeated failures. */
+ for (limit = 0; limit <= 8192 && !succeeded; ++limit) {
+
+ /* First attempt */
+ alloc_limit = limit;
+ help_str = ls_args_help(&args);
+ alloc_limit = -1;
+ if (help_str == NULL || strcmp(args.last_error, "Success") != 0) {
+ /* Expect allocation-related failure while we are below the needed size */
+ ASSERT_STR_EQ(args.last_error, "Allocation failure");
+ ASSERT(help_str != NULL);
+ ASSERT_STR_EQ(help_str, "Not enough memory available to generate help text.");
+
+ /* Second attempt (repeated failure path) */
+ alloc_limit = limit;
+ help_str = ls_args_help(&args);
+ alloc_limit = -1;
+ ASSERT_STR_EQ(args.last_error, "Allocation failure");
+ ASSERT(help_str != NULL);
+ ASSERT_STR_EQ(help_str, "Not enough memory available to generate help text.");
+ } else {
+ /* Success achieved at this alloc_limit; verify content */
+ succeeded = 1;
+ ASSERT(help_str != NULL);
+ ASSERT_STR_EQ(args.last_error, "Success");
+ ASSERT(strstr(help_str, "Provides help"));
+ ASSERT(strstr(help_str, "Specify the outfile"));
+ ASSERT(strstr(help_str, "Input file"));
+ }
+ }
+
+ /* Ensure we eventually succeeded in generating help text */
+ ASSERT(succeeded);
+
+ ls_args_free(&args);
+ return 0;
+}
+
+TEST_CASE(help_output_empty_description) {
+ int help = 0;
+ ls_args args;
+ char* help_str;
+
+ ls_args_init(&args);
+ ls_args_bool(&args, &help, "h", "help", "", 0);
+
+ help_str = ls_args_help(&args);
+ ASSERT(help_str != NULL);
+ ASSERT_STR_EQ(args.last_error, "Success");
+
+ /* Should show the option, but not crash or print garbage for description */
+ ASSERT(strstr(help_str, "-h"));
+ ASSERT(strstr(help_str, "--help"));
+ /* Should not print any description after the option */
+ /* Accept either a blank line or just the option itself */
+ /* There should not be any non-space character after the option on its line */
+ {
+ const char* opt_line = strstr(help_str, "-h \t--help");
+ ASSERT(opt_line != NULL);
+ /* Find the end of the line */
+ const char* end = strchr(opt_line, '\n');
+ if (end) {
+ /* Check that between the end of the option and the newline, only spaces/tabs appear */
+ const char* after = opt_line + strlen("-h \t--help");
+ while (after < end && (*after == ' ' || *after == '\t')) ++after;
+ ASSERT(after == end);
+ }
+ }
+
+ ls_args_free(&args);
+ return 0;
+}
+
+TEST_CASE(free_null) {
+ /* don't crash */
+ ls_args_free(NULL);
+ return 0;
+}
+
TEST_CASE(help_alloc_fail) {
int help = 0;
ls_args args;
char* help_str;
ls_args_init(&args);
ls_args_bool(&args, &help, "h", "help", "Provides help", 0);
- fail_alloc = 1;
+ fail_alloc_once = 1;
help_str = ls_args_help(&args);
- fail_alloc = 0;
ASSERT_STR_EQ(args.last_error, "Allocation failure");
ASSERT_STR_EQ(help_str, "Not enough memory available to generate help text.");
ls_args_free(&args);
@@ -447,10 +683,10 @@ TEST_CASE(alloc_fail) {
ls_args_init(&args);
ASSERT_EQ(args.args_len, 0, "%uz");
/* deliberately fail the allocation here */
- fail_alloc = 1;
+ fail_alloc_once = 1;
/* if the allocation fails, this fails */
ret = ls_args_bool(&args, &help, "h", "help", "Provides help", 0);
- fail_alloc = 0;
+
ASSERT(!ret);
ASSERT_STR_EQ(args.last_error, "Allocation failure");
/* there is no documented error state for this; we simply fail to add the
@@ -470,10 +706,10 @@ TEST_CASE(alloc_fail_pos_string) {
ls_args_init(&args);
ASSERT_EQ(args.args_len, 0, "%uz");
/* deliberately fail the allocation here */
- fail_alloc = 1;
+ fail_alloc_once = 1;
/* if the allocation fails, this fails */
ret = ls_args_pos_string(&args, &input, "Input file", 0);
- fail_alloc = 0;
+
ASSERT(!ret);
ASSERT_STR_EQ(args.last_error, "Allocation failure");
ASSERT_EQ(args.args_len, 0, "%uz");