diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 3ef6aef..bd00939 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -21,7 +21,7 @@ jobs: uses: actions/checkout@v2 - name: Run Regression - uses: exoticlibraries/exotic-action@v1.3 + uses: exoticlibraries/exotic-action@v1.4 with: download-exotic-libraries: true run-regression: true @@ -51,7 +51,7 @@ jobs: uses: actions/checkout@v2 - name: Setup Exotic Libraries - uses: exoticlibraries/exotic-action@v1.3 + uses: exoticlibraries/exotic-action@v1.4 with: download-exotic-libraries: true run-regression: false diff --git a/include/exotic/cline/cliarg.h b/include/exotic/cline/cliarg.h index 9b9d1fc..c2c1f45 100644 --- a/include/exotic/cline/cliarg.h +++ b/include/exotic/cline/cliarg.h @@ -1,7 +1,7 @@ /*! \copyright MIT License Copyright (c) 2021, Adewale Azeez - \author Adewale Azeez + \author Adewale Azeez \date 11 February 2021 \file cliarg.h @@ -15,10 +15,7 @@ extern "C" { #endif -#include -#include -#include -#include +#include "cline_common.h" /*#include */ /*TODO remove and move to xtd*/ @@ -46,9 +43,11 @@ struct cline_arg_option_s { bool case_sensitive; bool is_present; bool ignored; + size_t choices_size; size_t min_value_count; size_t max_value_count; size_t found_value_count; /*!< The number of the value gotten from the augument, also equivalent to the size of cline_arg_option_s::values */ + size_t splited_option_keys_size; char **splited_option_keys; char **choices; char *description; @@ -174,10 +173,10 @@ static void destroy_cline_arg(ClineArgs *cline_arg) { sub_iterator = XITERATOR_INIT2(xhashtable, cstr, ClineArgsOption, entry->value->cliopts); XFOREACH(const xhashtable_entry(cstr, ClineArgsOption) *sub_entry, sub_iterator, { if (sub_entry->value->splited_option_keys != XTD_NULL) { - xfreep2p(sub_entry->value->splited_option_keys, cline_arg->allocator); + xfreep2p_wl(cline_arg->allocator, sub_entry->value->splited_option_keys, sub_entry->value->splited_option_keys_size); } if (sub_entry->value->choices != XTD_NULL) { - xfreep2p(sub_entry->value->choices, cline_arg->allocator); + xfreep2p_wl(cline_arg->allocator, sub_entry->value->choices, sub_entry->value->choices_size); } if (sub_entry->value->values != XTD_NULL) { cline_arg->allocator.memory_free(sub_entry->value->values); @@ -202,7 +201,7 @@ static void destroy_cline_arg(ClineArgs *cline_arg) { */ static enum x_stat cline_arg_set_name(ClineArgs *cline_arg, char *name) { if (!cline_arg || !name) { - return XTD_INVALID_PARAMETER; + return XTD_INVALID_PARAMETER_ERR; } cline_arg->name = name; return XTD_OK; @@ -213,7 +212,7 @@ static enum x_stat cline_arg_set_name(ClineArgs *cline_arg, char *name) { */ static enum x_stat cline_arg_set_description(ClineArgs *cline_arg, char *description) { if (!cline_arg || !description) { - return XTD_INVALID_PARAMETER; + return XTD_INVALID_PARAMETER_ERR; } cline_arg->description = description; return XTD_OK; @@ -224,7 +223,7 @@ static enum x_stat cline_arg_set_description(ClineArgs *cline_arg, char *descrip */ static enum x_stat cline_arg_set_epilog(ClineArgs *cline_arg, char *epilog) { if (!cline_arg || !epilog) { - return XTD_INVALID_PARAMETER; + return XTD_INVALID_PARAMETER_ERR; } cline_arg->epilog = epilog; return XTD_OK; @@ -235,7 +234,7 @@ static enum x_stat cline_arg_set_epilog(ClineArgs *cline_arg, char *epilog) { */ static enum x_stat cline_arg_set_usage(ClineArgs *cline_arg, char *usage) { if (!cline_arg || !usage) { - return XTD_INVALID_PARAMETER; + return XTD_INVALID_PARAMETER_ERR; } cline_arg->usage = usage; return XTD_OK; @@ -246,7 +245,7 @@ static enum x_stat cline_arg_set_usage(ClineArgs *cline_arg, char *usage) { */ static enum x_stat cline_arg_set_option_delimiter(ClineArgs *cline_arg, char *option_delimiter) { if (!cline_arg || !option_delimiter) { - return XTD_INVALID_PARAMETER; + return XTD_INVALID_PARAMETER_ERR; } cline_arg->option_delimiter = option_delimiter; return XTD_OK; @@ -314,7 +313,8 @@ static bool cline_arg_find_arg_option(ClineArgs *cline_arg, const char *section, } goto cline_arg_find_arg_option_return; } - for (index = 0; entry->value->splited_option_keys[index] != XTD_NULL; index++) { + for (index = 0; index < entry->value->splited_option_keys_size; index++) { + /*printf("Value::%s::%s::\n", entry->key, entry->value->splited_option_keys[index]);*/ if (xstring_cstr_equals(entry->value->splited_option_keys[index], flag) || ((entry->value->is_prefix || check_starts_with) && xstring_cstr_starts_with(flag, entry->value->splited_option_keys[index])) || ((entry->value->is_suffix || check_ends_with) && xstring_cstr_ends_with(flag, entry->value->splited_option_keys[index]))) { @@ -461,8 +461,8 @@ static enum x_stat cline_arg_add_cli_args_option(ClineArgs *cline_arg, if (!cline_arg_option) { return XTD_ALLOC_ERR; } - cline_arg_option->splited_option_keys = xstring_cstr_split(option_str, cline_arg->option_delimiter, cline_arg->allocator); - cline_arg_option->choices = xstring_cstr_split(choices_str, "|", cline_arg->allocator); + cline_arg_option->splited_option_keys_size = xstring_cstr_split(cline_arg->allocator, (char *) option_str, cline_arg->option_delimiter, &cline_arg_option->splited_option_keys); + cline_arg_option->choices_size = xstring_cstr_split(cline_arg->allocator, (char *) choices_str, "|", &cline_arg_option->choices); cline_arg_option->description = description; cline_arg_option->epilog = XTD_NULL; cline_arg_option->values = default_value; @@ -477,11 +477,11 @@ static enum x_stat cline_arg_add_cli_args_option(ClineArgs *cline_arg, cline_arg_option->found_value_count = 0; cline_arg_option->is_present = FALSE; cline_arg_option->ignored = ignored; - status = xhashtable_get(cstr, ClineArgsGroup)(cline_arg->cli_groups, (section == XTD_NULL || xstring_cstr_is_empty(section) ? "" : section), &cli_group); + status = xhashtable_get(cstr, ClineArgsGroup)(cline_arg->cli_groups, (section == XTD_NULL || xstring_cstr_is_empty((char *) section) ? "" : section), &cli_group); if (status != XTD_OK) { goto cline_arg_add_option_free_after_failure; } - status = xhashtable_put(cstr, ClineArgsOption)(cli_group->cliopts, option_str, cline_arg_option); + status = xhashtable_put(cstr, ClineArgsOption)(cli_group->cliopts, (char *) option_str, cline_arg_option); if (status != XTD_OK) { goto cline_arg_add_option_free_after_failure; } @@ -491,7 +491,8 @@ static enum x_stat cline_arg_add_cli_args_option(ClineArgs *cline_arg, return XTD_OK; cline_arg_add_option_free_after_failure: - xfreep2p(cline_arg_option->splited_option_keys, cline_arg->allocator); + xfreep2p_wl(cline_arg->allocator, cline_arg_option->splited_option_keys, cline_arg_option->splited_option_keys_size); + xfreep2p_wl(cline_arg->allocator, cline_arg_option->choices, cline_arg_option->choices_size); cline_arg->allocator.memory_free(cline_arg_option); return XTD_ERR; } @@ -502,7 +503,7 @@ static enum x_stat cline_arg_add_cli_args_option(ClineArgs *cline_arg, static enum x_stat cline_arg_collect_orphans(ClineArgs *cline_arg, const char *help_var, bool collect_orphans) { enum x_stat status; if (!cline_arg || collect_orphans < 0 || collect_orphans > 1) { - return XTD_INVALID_PARAMETER; + return XTD_INVALID_PARAMETER_ERR; } status = cline_arg_add_cli_args_option(cline_arg, XTD_NULL, EXOTIC_CLINE_ORPHAN_PARAM_KEY, XTD_NULL, XTD_NULL, XTD_NULL, help_var, XTD_NULL, FALSE, FALSE, FALSE, FALSE, FALSE, 0, (sizeof(size_t)-1/2)); @@ -582,15 +583,17 @@ static enum x_stat cline_arg_parse_in_range(ClineArgs *cline_arg, size_t from, s XIterator *sub_iterator; if (!cline_arg || !argv) { - return XTD_INVALID_PARAMETER; + return XTD_INVALID_PARAMETER_ERR; } for (index = from; index < argc; index++) { is_orphan = FALSE; argument_length = xstring_cstr_length(argv[index]); + if (!argument_length) continue; is_true = cline_arg_find_arg_option(cline_arg, XTD_NULL, argv[index], &cline_arg_option, &matching_value, TRUE, TRUE); if (!is_true || ((!cline_arg_option->is_prefix && !xstring_cstr_equals(argv[index], matching_value)) && (!cline_arg_option->is_suffix && !xstring_cstr_equals(argv[index], matching_value)))) { if (!cline_arg->collect_orphans) { + printf("WTF '%s'-'%s'\n", matching_value, argv[index]); return XTD_INVALID_PARAMETER_FOUND_ERR; } is_true = cline_arg_find_arg_option(cline_arg, XTD_NULL, EXOTIC_CLINE_ORPHAN_PARAM_KEY, &cline_arg_option, &matching_value, TRUE, TRUE); @@ -613,7 +616,7 @@ static enum x_stat cline_arg_parse_in_range(ClineArgs *cline_arg, size_t from, s } if (cline_arg_option->choices != XTD_NULL) { is_true = FALSE; - for (sub_index = 0; cline_arg_option->choices[sub_index] != XTD_NULL; sub_index++) { + for (sub_index = 0; sub_index < cline_arg_option->choices_size; sub_index++) { if (xstring_cstr_equals(cline_arg_option->choices[sub_index], val)) { is_true = TRUE; break; @@ -644,11 +647,11 @@ static enum x_stat cline_arg_parse_in_range(ClineArgs *cline_arg, size_t from, s } if (cline_arg_option->is_prefix || cline_arg_option->is_suffix) { /* checkback ent5ering when not suppose to */ prefix_delimiter_length = xstring_cstr_length(cline_arg_option->prefix_delimeter); - char *suffix_value = (char *) cline_arg->allocator.memory_calloc(argument_length-matching_value_length, sizeof(char)); + char *suffix_value; if (cline_arg_option->is_prefix) { - status = xstring_cstr_sub_string(argv[index], matching_value_length+prefix_delimiter_length, suffix_value); + status = xstring_cstr_sub_string(cline_arg->allocator, argv[index], matching_value_length+prefix_delimiter_length, &suffix_value); } else { - status = xstring_cstr_sub_string_in_range(argv[index], 0, argument_length-matching_value_length-prefix_delimiter_length, suffix_value); + status = xstring_cstr_sub_string_in_range(cline_arg->allocator, argv[index], 0, argument_length-matching_value_length-prefix_delimiter_length, &suffix_value); } if (status != XTD_OK) { cline_arg->allocator.memory_free(cline_arg_option->values); @@ -686,7 +689,7 @@ static enum x_stat cline_arg_parse_in_range(ClineArgs *cline_arg, size_t from, s /*! */ -char *cline_arg_get_section_description(ClineArgs *cline_arg, const char *section) { +static char *cline_arg_get_section_description(ClineArgs *cline_arg, const char *section) { ClineArgsOption cli_opt; if (section == XTD_NULL) { return cline_arg->description; } if (!cline_arg_find_arg_option(cline_arg, section, EXOTIC_CLINE_SECTION_DESCRIPTION, &cli_opt, XTD_NULL, FALSE, FALSE)) { @@ -714,7 +717,7 @@ static enum x_stat cline_arg_set_section_description(ClineArgs *cline_arg, const /*! */ -char *cline_arg_get_section_epilog(ClineArgs *cline_arg, const char *section) { +static char *cline_arg_get_section_epilog(ClineArgs *cline_arg, const char *section) { ClineArgsOption cli_opt; if (section == XTD_NULL) { return cline_arg->epilog; } if (!cline_arg_find_arg_option(cline_arg, section, EXOTIC_CLINE_SECTION_DESCRIPTION, &cli_opt, XTD_NULL, FALSE, FALSE)) { @@ -776,93 +779,97 @@ static enum x_stat cline_arg_section_help(ClineArgs *cline_arg, const char *sect XIterator *iterator; XIterator *sub_iterator; - options_text = xstring_cstr_concat_cstr(options_text, "\n", cline_arg->allocator); + options_text = xstring_cstr_concat_cstr(cline_arg->allocator, options_text, "\n"); if (section == XTD_NULL) { if (cline_arg->usage != XTD_NULL) { - //xstring_cstr_replace(usage, "${name}", cline_arg->name, cline_arg->allocator) - usage_text = xstring_cstr_concat_cstr(usage_text, cline_arg_get_usage(cline_arg), cline_arg->allocator); + //xstring_cstr_replace(cline_arg->allocator, usage, "${name}", cline_arg->name) + usage_text = xstring_cstr_concat_cstr(cline_arg->allocator, usage_text, cline_arg_get_usage(cline_arg)); } else { - usage_text = xstring_cstr_concat_cstr(usage_text, CLINE_ARG_TRANSLATE__INTERNAL__("usage"), cline_arg->allocator); - usage_text = xstring_cstr_concat_cstr(usage_text, ": ", cline_arg->allocator); - usage_text = xstring_cstr_concat_cstr(usage_text, cline_arg_get_name(cline_arg), cline_arg->allocator); + usage_text = xstring_cstr_concat_cstr(cline_arg->allocator, usage_text, CLINE_ARG_TRANSLATE__INTERNAL__("usage")); + usage_text = xstring_cstr_concat_cstr(cline_arg->allocator, usage_text, ": "); + usage_text = xstring_cstr_concat_cstr(cline_arg->allocator, usage_text, cline_arg_get_name(cline_arg)); iterator = XITERATOR_INIT2(xhashtable, cstr, ClineArgsGroup, cline_arg->cli_groups); XFOREACH(const xhashtable_entry(cstr, ClineArgsGroup) *entry, iterator, { sub_iterator = XITERATOR_INIT2(xhashtable, cstr, ClineArgsOption, entry->value->cliopts); XFOREACH(const xhashtable_entry(cstr, ClineArgsOption) *sub_entry, sub_iterator, { if (sub_entry->value->help_var != XTD_NULL) { - if (!sub_entry->value->is_prefix && !sub_entry->value->is_suffix) { - help_var_text = xstring_cstr_concat_cstr(help_var_text, (sub_entry->value->prefix_delimeter != XTD_NULL ? sub_entry->value->prefix_delimeter : " "), cline_arg->allocator); - } - help_var_text = xstring_cstr_concat_cstr(help_var_text, "<", cline_arg->allocator); - help_var_text = xstring_cstr_concat_cstr(help_var_text, sub_entry->value->help_var, cline_arg->allocator); - help_var_text = xstring_cstr_concat_cstr(help_var_text, ">", cline_arg->allocator); + if (sub_entry->value->min_value_count > 0 && sub_entry->value->prefix_delimeter != XTD_NULL) { + help_var_text = xstring_cstr_concat_cstr(cline_arg->allocator, help_var_text, sub_entry->value->prefix_delimeter); + } else if (!sub_entry->value->is_prefix && !sub_entry->value->is_suffix) { + help_var_text = xstring_cstr_concat_cstr(cline_arg->allocator, help_var_text, " "); + } + help_var_text = xstring_cstr_concat_cstr(cline_arg->allocator, help_var_text, "<"); + help_var_text = xstring_cstr_concat_cstr(cline_arg->allocator, help_var_text, sub_entry->value->help_var); + help_var_text = xstring_cstr_concat_cstr(cline_arg->allocator, help_var_text, ">"); } - usage_text = xstring_cstr_concat_cstr(usage_text, " ", cline_arg->allocator); + usage_text = xstring_cstr_concat_cstr(cline_arg->allocator, usage_text, " "); if (!sub_entry->value->mandatory) { - usage_text = xstring_cstr_concat_cstr(usage_text, "[", cline_arg->allocator); + usage_text = xstring_cstr_concat_cstr(cline_arg->allocator, usage_text, "["); } - option_text = xstring_cstr_concat_cstr(option_text, " ", cline_arg->allocator); - if (help_var_text != XTD_NULL && sub_entry->value->is_suffix) { - usage_text = xstring_cstr_concat_cstr(usage_text, help_var_text, cline_arg->allocator); - option_text = xstring_cstr_concat_cstr(option_text, help_var_text, cline_arg->allocator); + option_text = xstring_cstr_concat_cstr(cline_arg->allocator, option_text, " "); + if (help_var_text != XTD_NULL && sub_entry->value->is_suffix && !xstring_cstr_equals(sub_entry->key, EXOTIC_CLINE_ORPHAN_PARAM_KEY)) { + usage_text = xstring_cstr_concat_cstr(cline_arg->allocator, usage_text, help_var_text); + option_text = xstring_cstr_concat_cstr(cline_arg->allocator, option_text, help_var_text); cline_arg->allocator.memory_free(help_var_text); help_var_text = XTD_NULL; } - usage_text = xstring_cstr_concat_cstr(usage_text, CLINE_ARG_ORPHAN_OR_OPTION__INTERNAL__(sub_entry), cline_arg->allocator); - option_text = xstring_cstr_concat_cstr(option_text, CLINE_ARG_ORPHAN_OR_OPTION__INTERNAL__(sub_entry), cline_arg->allocator); + usage_text = xstring_cstr_concat_cstr(cline_arg->allocator, usage_text, CLINE_ARG_ORPHAN_OR_OPTION__INTERNAL__(sub_entry)); + option_text = xstring_cstr_concat_cstr(cline_arg->allocator, option_text, CLINE_ARG_ORPHAN_OR_OPTION__INTERNAL__(sub_entry)); if (xstring_cstr_equals(sub_entry->key, EXOTIC_CLINE_ORPHAN_PARAM_KEY)) { cached_text = sub_entry->value->description; sub_entry->value->description = XTD_NULL; sub_entry->value->help_var = XTD_NULL; } - if (help_var_text != XTD_NULL && !sub_entry->value->is_suffix) { - usage_text = xstring_cstr_concat_cstr(usage_text, help_var_text, cline_arg->allocator); - option_text = xstring_cstr_concat_cstr(option_text, help_var_text, cline_arg->allocator); + if (help_var_text != XTD_NULL && !sub_entry->value->is_suffix && !xstring_cstr_equals(sub_entry->key, EXOTIC_CLINE_ORPHAN_PARAM_KEY)) { + usage_text = xstring_cstr_concat_cstr(cline_arg->allocator, usage_text, help_var_text); + option_text = xstring_cstr_concat_cstr(cline_arg->allocator, option_text, help_var_text); cline_arg->allocator.memory_free(help_var_text); help_var_text = XTD_NULL; } - for (index = 1; sub_entry->value->splited_option_keys[index] != XTD_NULL; index++) { + for (index = 1; index < sub_entry->value->splited_option_keys_size; index++) { if (sub_entry->value->help_var != XTD_NULL) { - if (!sub_entry->value->is_prefix && !sub_entry->value->is_suffix) { - help_var_text = xstring_cstr_concat_cstr(help_var_text, " ", cline_arg->allocator); - } - help_var_text = xstring_cstr_concat_cstr(help_var_text, "<", cline_arg->allocator); - help_var_text = xstring_cstr_concat_cstr(help_var_text, sub_entry->value->help_var, cline_arg->allocator); - help_var_text = xstring_cstr_concat_cstr(help_var_text, ">", cline_arg->allocator); + if (sub_entry->value->min_value_count > 0 && sub_entry->value->prefix_delimeter != XTD_NULL) { + help_var_text = xstring_cstr_concat_cstr(cline_arg->allocator, help_var_text, sub_entry->value->prefix_delimeter); + } else if (!sub_entry->value->is_prefix && !sub_entry->value->is_suffix) { + help_var_text = xstring_cstr_concat_cstr(cline_arg->allocator, help_var_text, " "); + } + help_var_text = xstring_cstr_concat_cstr(cline_arg->allocator, help_var_text, "<"); + help_var_text = xstring_cstr_concat_cstr(cline_arg->allocator, help_var_text, sub_entry->value->help_var); + help_var_text = xstring_cstr_concat_cstr(cline_arg->allocator, help_var_text, ">"); } - usage_text = xstring_cstr_concat_char(usage_text, '|', cline_arg->allocator); - option_text = xstring_cstr_concat_cstr(option_text, ", ", cline_arg->allocator); + usage_text = xstring_cstr_concat_char(cline_arg->allocator, usage_text, '|'); + option_text = xstring_cstr_concat_cstr(cline_arg->allocator, option_text, ", "); if (help_var_text != XTD_NULL && sub_entry->value->is_suffix) { - usage_text = xstring_cstr_concat_cstr(usage_text, help_var_text, cline_arg->allocator); - option_text = xstring_cstr_concat_cstr(option_text, help_var_text, cline_arg->allocator); + usage_text = xstring_cstr_concat_cstr(cline_arg->allocator, usage_text, help_var_text); + option_text = xstring_cstr_concat_cstr(cline_arg->allocator, option_text, help_var_text); cline_arg->allocator.memory_free(help_var_text); help_var_text = XTD_NULL; } - usage_text = xstring_cstr_concat_cstr(usage_text, sub_entry->value->splited_option_keys[index], cline_arg->allocator); - option_text = xstring_cstr_concat_cstr(option_text, sub_entry->value->splited_option_keys[index], cline_arg->allocator); + usage_text = xstring_cstr_concat_cstr(cline_arg->allocator, usage_text, sub_entry->value->splited_option_keys[index]); + option_text = xstring_cstr_concat_cstr(cline_arg->allocator, option_text, sub_entry->value->splited_option_keys[index]); if (help_var_text != XTD_NULL && !sub_entry->value->is_suffix) { - usage_text = xstring_cstr_concat_cstr(usage_text, help_var_text, cline_arg->allocator); - option_text = xstring_cstr_concat_cstr(option_text, help_var_text, cline_arg->allocator); + usage_text = xstring_cstr_concat_cstr(cline_arg->allocator, usage_text, help_var_text); + option_text = xstring_cstr_concat_cstr(cline_arg->allocator, option_text, help_var_text); cline_arg->allocator.memory_free(help_var_text); help_var_text = XTD_NULL; } } if (sub_entry->value->is_prefix || sub_entry->value->is_suffix || sub_entry->value->max_value_count > 1) { - usage_text = xstring_cstr_concat_cstr(usage_text, " ...", cline_arg->allocator); - option_text = xstring_cstr_concat_cstr(option_text, " ...", cline_arg->allocator); + usage_text = xstring_cstr_concat_cstr(cline_arg->allocator, usage_text, " ..."); + option_text = xstring_cstr_concat_cstr(cline_arg->allocator, option_text, " ..."); } option_text_length = xstring_cstr_length(option_text); do { - option_text = xstring_cstr_concat_char(option_text, ' ', cline_arg->allocator); + option_text = xstring_cstr_concat_char(cline_arg->allocator, option_text, ' '); } while (option_text_length++ < CLINE_ARG_HELP_OPTION_PRE_SPACE_SIZE-1); if (!sub_entry->value->mandatory) { - usage_text = xstring_cstr_concat_char(usage_text, ']', cline_arg->allocator); + usage_text = xstring_cstr_concat_char(cline_arg->allocator, usage_text, ']'); } if (sub_entry->value->description != XTD_NULL) { - option_text = xstring_cstr_concat_cstr(option_text, sub_entry->value->description, cline_arg->allocator); - option_text = xstring_cstr_concat_char(option_text, '\n', cline_arg->allocator); - options_text = xstring_cstr_concat_cstr(options_text, option_text, cline_arg->allocator); + option_text = xstring_cstr_concat_cstr(cline_arg->allocator, option_text, sub_entry->value->description); + option_text = xstring_cstr_concat_char(cline_arg->allocator, option_text, '\n'); + options_text = xstring_cstr_concat_cstr(cline_arg->allocator, options_text, option_text); } cline_arg->allocator.memory_free(option_text); option_text = XTD_NULL; @@ -875,24 +882,24 @@ static enum x_stat cline_arg_section_help(ClineArgs *cline_arg, const char *sect }) XITERATOR_DESTROY(iterator); } - usage_text = xstring_cstr_concat_cstr(usage_text, "\n\n", cline_arg->allocator); + usage_text = xstring_cstr_concat_cstr(cline_arg->allocator, usage_text, "\n\n"); } - help_text = xstring_cstr_concat_cstr(help_text, usage_text, cline_arg->allocator); + help_text = xstring_cstr_concat_cstr(cline_arg->allocator, help_text, usage_text); cline_arg->allocator.memory_free(usage_text); text = CLINE_ARG_TRANSLATE__INTERNAL__(cline_arg_get_section_description(cline_arg, section)); if (text != XTD_NULL) { - help_text = xstring_cstr_concat_cstr(help_text, text, cline_arg->allocator); - help_text = xstring_cstr_concat_cstr(help_text, "\n", cline_arg->allocator); + help_text = xstring_cstr_concat_cstr(cline_arg->allocator, help_text, text); + help_text = xstring_cstr_concat_cstr(cline_arg->allocator, help_text, "\n"); } if (option_text_length > 0) { - help_text = xstring_cstr_concat_cstr(help_text, options_text, cline_arg->allocator); + help_text = xstring_cstr_concat_cstr(cline_arg->allocator, help_text, options_text); cline_arg->allocator.memory_free(options_text); } text = CLINE_ARG_TRANSLATE__INTERNAL__(cline_arg_get_section_epilog(cline_arg, section)); if (text != XTD_NULL) { - help_text = xstring_cstr_concat_cstr(help_text, "\n", cline_arg->allocator); - help_text = xstring_cstr_concat_cstr(help_text, text, cline_arg->allocator); - help_text = xstring_cstr_concat_cstr(help_text, "\n", cline_arg->allocator); + help_text = xstring_cstr_concat_cstr(cline_arg->allocator, help_text, "\n"); + help_text = xstring_cstr_concat_cstr(cline_arg->allocator, help_text, text); + help_text = xstring_cstr_concat_cstr(cline_arg->allocator, help_text, "\n"); } *out = help_text; @@ -912,7 +919,7 @@ static enum x_stat cline_arg_help(ClineArgs *cline_arg, char **selected_sections if (status != XTD_OK) { return status; } - help_text = xstring_cstr_concat_cstr(help_text, section_help, cline_arg->allocator); + help_text = xstring_cstr_concat_cstr(cline_arg->allocator, XTD_NULL, section_help); cline_arg->allocator.memory_free(section_help); if (selected_sections != XTD_NULL) { for (index = 0; selected_sections[index] != XTD_NULL; index++) { @@ -920,11 +927,11 @@ static enum x_stat cline_arg_help(ClineArgs *cline_arg, char **selected_sections if (status != XTD_OK) { return status; } - help_text = xstring_cstr_concat_cstr(help_text, section_help, cline_arg->allocator); + help_text = xstring_cstr_concat_cstr(cline_arg->allocator, help_text, section_help); cline_arg->allocator.memory_free(section_help); } } - help_text = xstring_cstr_concat_cstr(help_text, "\n", cline_arg->allocator); + help_text = xstring_cstr_concat_cstr(cline_arg->allocator, help_text, "\n"); *out = help_text; return XTD_OK; diff --git a/include/exotic/cline/cline_common.h b/include/exotic/cline/cline_common.h index 493965a..a5dd620 100644 --- a/include/exotic/cline/cline_common.h +++ b/include/exotic/cline/cline_common.h @@ -1,7 +1,7 @@ /*! \copyright MIT License Copyright (c) 2021, Adewale Azeez - \author Adewale Azeez + \author Adewale Azeez \date 19 February 2021 \file cline_common.h @@ -15,8 +15,13 @@ extern "C" { #endif +#include #include #include +#include +#include +#include +#include #ifdef _WIN32 #include @@ -63,7 +68,7 @@ extern "C" { /*! */ -void cline_platform_printnl_if() +static void cline_platform_printnl_if() { #ifndef _WIN32 printf("\n"); @@ -74,7 +79,7 @@ void cline_platform_printnl_if() printf("libcline FATAL_ERROR -> %s:%d ", file_name, line_number);\ printf(__VA_ARGS__); \ cline_platform_printnl_if(); \ - exit(EXIT_FAILURE);\ + exit(1);\ } #ifdef _WIN32 @@ -104,7 +109,7 @@ static unsigned already_change_mode = 0; /*! */ -char *cline_ansi_encoder(const char *file_name, const int line_number, const char ansi_code_terminator, const int argscount, ...) +static char *cline_ansi_encoder(const char *file_name, const int line_number, const char ansi_code_terminator, const int argscount, ...) { va_list ap; const char *p; diff --git a/include/exotic/cline/cursor_nav.h b/include/exotic/cline/cursor_nav.h index ad0c0e0..225e2d0 100644 --- a/include/exotic/cline/cursor_nav.h +++ b/include/exotic/cline/cursor_nav.h @@ -1,7 +1,7 @@ /*! \copyright MIT License Copyright (c) 2021, Adewale Azeez - \author Adewale Azeez + \author Adewale Azeez \date 19 February 2021 \file cursor_nav.h diff --git a/include/exotic/cline/font_effect.h b/include/exotic/cline/font_effect.h index 77e6950..1e2cffc 100644 --- a/include/exotic/cline/font_effect.h +++ b/include/exotic/cline/font_effect.h @@ -1,7 +1,7 @@ /*! \copyright MIT License Copyright (c) 2021, Adewale Azeez - \author Adewale Azeez + \author Adewale Azeez \date 12 February 2021 \file font_effect.h @@ -146,7 +146,7 @@ extern "C" { this can be used to quick disable the effects without having to delete the other font effect options. */ -const char *cline_fe_str_with_end_fe(const char *file_name, const int line_number, const char *text, const char *fe, const char *end_fe) +static const char *cline_fe_str_with_end_fe(const char *file_name, const int line_number, const char *text, const char *fe, const char *end_fe) { int fe_length = strlen(fe); int concatenated_length = strlen(text) + fe_length + (fe_length > 0 ? strlen(end_fe) : 0); diff --git a/include/exotic/cline/term_input.h b/include/exotic/cline/term_input.h index a65fb36..de46476 100644 --- a/include/exotic/cline/term_input.h +++ b/include/exotic/cline/term_input.h @@ -1,7 +1,7 @@ /*! \copyright MIT License Copyright (c) 2021, Adewale Azeez - \author Adewale Azeez + \author Adewale Azeez \date 19 February 2021 \file term_input.h diff --git a/include/exotic/cline/xtd_printers.h b/include/exotic/cline/xtd_printers.h new file mode 100644 index 0000000..ac60e0e --- /dev/null +++ b/include/exotic/cline/xtd_printers.h @@ -0,0 +1,212 @@ + +/*! + \copyright MIT License Copyright (c) 2021, Adewale Azeez + \author Adewale Azeez + \date 07 October 2021 + \file xtd_printers.h + + xtd_printers.h is ... +*/ + +#ifndef EXOTIC_CLINE_FONT_EFFECT_H +#define EXOTIC_CLINE_FONT_EFFECT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + +*/ +#include "cline_common.h" +#include + +/* LIBXTD FILLER */ +#ifndef xpair +#define xpair xhashtable_entry +#endif + +/*! + +*/ +#define CLINE_XTD_GENERIC_FORMAT_SPECIFIER(value) _Generic(value,\ + char: "%c",\ + unsigned char: "%c",\ + short: "%hi",\ + unsigned short: "%hu",\ + int: "%i",\ + unsigned int: "%u",\ + long: "%ld",\ + unsigned long: "%ld",\ + float: "%f",\ + double: "%lf",\ + long double: "%Lf",\ + char *: "%s",\ + default: "%p"\ + ) + +/*! + +*/ +#define CLINE_XTD_PRINTER_SELECT_QUOTE(value) _Generic(value,\ + char: "'",\ + char *: "\"",\ + default: ""\ + ) + +/*! + +*/ +#define CLINE_XTD_PRINTER_FPRINT_VALUE(stream, value) fprintf(stream, CLINE_XTD_PRINTER_SELECT_QUOTE(value));\ + fprintf(stream, CLINE_XTD_GENERIC_FORMAT_SPECIFIER(value), value);\ + fprintf(stream, CLINE_XTD_PRINTER_SELECT_QUOTE(value));\ + +/*! + +*/ +#define CLINE_XPRINT_XTD_CONTAINER(container_type, stream, type, container, var_suffix) XIterator *iterator##var_suffix = XITERATOR_INIT(container_type, type, container);\ + fprintf(stream, "["); size_t size##var_suffix = container_type##_size(container);\ + XFOREACH_INDEX(size_t index##var_suffix, type value##var_suffix, iterator##var_suffix, {\ + CLINE_XTD_PRINTER_FPRINT_VALUE(stream, value##var_suffix); if (index##var_suffix < size##var_suffix-1) fprintf(stream, ", ");\ + }); fprintf(stream, "]"); XITERATOR_DESTROY(iterator##var_suffix); + + +/*! + +*/ +#define CLINE_XPRINT_XTD_CONTAINER_PAIR(container_type, stream, type1, type2, container, var_suffix) \ + XIterator *iterator##var_suffix = XITERATOR_INIT2(container_type, type1, type2, container);\ + fprintf(stream, "{"); size_t size##var_suffix = container_type##_size(container);\ + XFOREACH_INDEX(size_t index##var_suffix, const xpair(type1, type2) *value##var_suffix, iterator##var_suffix, {\ + CLINE_XTD_PRINTER_FPRINT_VALUE(stream, (type1) value##var_suffix->key); fprintf(stream, ": ");\ + CLINE_XTD_PRINTER_FPRINT_VALUE(stream, (type2) value##var_suffix->value); if (index##var_suffix < size##var_suffix-1) fprintf(stream, ", ");\ + }); fprintf(stream, "}"); XITERATOR_DESTROY(iterator##var_suffix); + +/*! + +*/ +#define CLINE_XPRINT_XDEQUE(stream, type, container) CLINE_XPRINT_XTD_CONTAINER(xdeque, stream, type, container, __LINE__) + +/*! + +*/ +#define CLINE_XPRINT_XLIST(stream, type, container) CLINE_XPRINT_XTD_CONTAINER(xlist, stream, type, container, __LINE__) + +/*! + +*/ +#define CLINE_XPRINT_XSLIST(stream, type, container) CLINE_XPRINT_XTD_CONTAINER(xslist, stream, type, container, __LINE__) + +/*! + +*/ +#define CLINE_XPRINT_XQUEUE(stream, type, container) CLINE_XPRINT_XTD_CONTAINER(xqueue, stream, type, container, __LINE__) + +/*! + +*/ +#define CLINE_XPRINT_XSTACK(stream, type, container) CLINE_XPRINT_XTD_CONTAINER(xstack, stream, type, container, __LINE__) + +/*! + +*/ +#define CLINE_XPRINT_XPRIORITY_QUEUE(stream, type, container) CLINE_XPRINT_XTD_CONTAINER(xpriority_queue, stream, type, container, __LINE__) + +/*! + +*/ +#define CLINE_XPRINT_XVECTOR(stream, type, container) CLINE_XPRINT_XTD_CONTAINER(xvector, stream, type, container, __LINE__) + +/*! + +*/ +#define CLINE_XPRINT_XSET(stream, type, container) CLINE_XPRINT_XTD_CONTAINER(xset, stream, type, container, __LINE__) + +/*! + +*/ +#define CLINE_XPRINT_XUNORDERED_SET(stream, type, container) CLINE_XPRINT_XTD_CONTAINER(xunordered_set, stream, type, container, __LINE__) + +/*! + +*/ +#define CLINE_XPRINT_XHASHTABLE(stream, type1, type2, container) CLINE_XPRINT_XTD_CONTAINER_PAIR(xhashtable, stream, type1, type2, container, __LINE__) + +/*! + +*/ +#define CLINE_XPRINT_XTD_CONTAINER_CUSTOM(container_type, stream, type, container, value_formatter, var_suffix) XIterator *iterator##var_suffix = XITERATOR_INIT(container_type, type, container);\ + fprintf(stream, "["); size_t size##var_suffix = container_type##_size(container);\ + XFOREACH_INDEX(size_t index##var_suffix, type value##var_suffix, iterator##var_suffix, {\ + fprintf(stream, value_formatter(value##var_suffix));\ + if (index##var_suffix < size##var_suffix-1) fprintf(stream, ", ");\ + }); fprintf(stream, "]"); XITERATOR_DESTROY(iterator##var_suffix); + +/*! + +*/ +#define CLINE_XPRINT_XTD_CONTAINER_CUSTOM_PAIR(container_type, stream, type1, type2, container, key_formatter, value_formatter, var_suffix)\ + XIterator *iterator##var_suffix = XITERATOR_INIT2(container_type, type1, type2, container);\ + fprintf(stream, "{"); size_t size##var_suffix = container_type##_size(container);\ + XFOREACH_INDEX(size_t index##var_suffix, const xpair(type1, type2) *value##var_suffix, iterator##var_suffix, {\ + fprintf(stream, key_formatter(value##var_suffix->key)); fprintf(stream, ": ");\ + fprintf(stream, value_formatter(value##var_suffix->value)); if (index##var_suffix < size##var_suffix-1) fprintf(stream, ", ");\ + }); fprintf(stream, "}"); XITERATOR_DESTROY(iterator##var_suffix); + + +/*! + +*/ +#define CLINE_XPRINT_XDEQUE_CUSTOM(stream, type, container, value_formatter) CLINE_XPRINT_XTD_CONTAINER_CUSTOM(xdeque, stream, type, container, value_formatter, __LINE__) + +/*! + +*/ +#define CLINE_XPRINT_XLIST_CUSTOM(stream, type, container, value_formatter) CLINE_XPRINT_XTD_CONTAINER_CUSTOM(xlist, stream, type, container, value_formatter, __LINE__) + +/*! + +*/ +#define CLINE_XPRINT_XSLIST_CUSTOM(stream, type, container, value_formatter) CLINE_XPRINT_XTD_CONTAINER_CUSTOM(xslist, stream, type, container, value_formatter, __LINE__) + +/*! + +*/ +#define CLINE_XPRINT_XQUEUE_CUSTOM(stream, type, container, value_formatter) CLINE_XPRINT_XTD_CONTAINER_CUSTOM(xqueue, stream, type, container, value_formatter, __LINE__) + +/*! + +*/ +#define CLINE_XPRINT_XSTACK_CUSTOM(stream, type, container, value_formatter) CLINE_XPRINT_XTD_CONTAINER_CUSTOM(xstack, stream, type, container, value_formatter, __LINE__) + +/*! + +*/ +#define CLINE_XPRINT_XPRIORITY_QUEUE_CUSTOM(stream, type, container, value_formatter) CLINE_XPRINT_XTD_CONTAINER_CUSTOM(xpriority_queue, stream, type, container, value_formatter, __LINE__) + +/*! + +*/ +#define CLINE_XPRINT_XVECTOR_CUSTOM(stream, type, container, value_formatter) CLINE_XPRINT_XTD_CONTAINER_CUSTOM(xvector, stream, type, container, value_formatter, __LINE__) + +/*! + +*/ +#define CLINE_XPRINT_XSET_CUSTOM(stream, type, container, value_formatter) CLINE_XPRINT_XTD_CONTAINER_CUSTOM(xset, stream, type, container, value_formatter, __LINE__) + +/*! + +*/ +#define CLINE_XPRINT_XUNORDERED_SET_CUSTOM(stream, type, container, value_formatter) CLINE_XPRINT_XTD_CONTAINER_CUSTOM(xunordered_set, stream, type, container, value_formatter, __LINE__) + +/*! + +*/ +#define CLINE_XPRINT_XHASHTABLE_CUSTOM(stream, type1, type2, container, key_formatter, value_formatter) CLINE_XPRINT_XTD_CONTAINER_CUSTOM_PAIR(xhashtable, stream, type1, type2, container, key_formatter, value_formatter, __LINE__) + + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/test/cline/test_clinearg_basic.c b/test/cline/cliarg/test_clinearg_basic.c similarity index 99% rename from test/cline/test_clinearg_basic.c rename to test/cline/cliarg/test_clinearg_basic.c index 28478c4..196cc2a 100644 --- a/test/cline/test_clinearg_basic.c +++ b/test/cline/cliarg/test_clinearg_basic.c @@ -1,4 +1,4 @@ -/*!gcc {0} -I. -I../include/ -I../../include/ -o out; ./out */ +/*!gcc {0} -I. -I../include/ -I../../../include/ -o out; ./out */ #include #include @@ -101,7 +101,7 @@ CESTER_TEST(cline_arg_get_arg_option, inst, { cester_assert_int_eq(cline_arg_add_option(cline_arg, XTD_NULL, "-h<:>--help", "Print this help message", FALSE), XTD_OK); cester_assert_int_eq(cline_arg_add_option(cline_arg, XTD_NULL, "-v<:>--version", "Print the version information and exit", FALSE), XTD_OK); cester_assert_int_eq(cline_arg_add_option(cline_arg, XTD_NULL, "--verbose", "Be extra verbose", FALSE), XTD_OK); - + cester_assert_int_eq(cline_arg_get_arg_option(cline_arg, XTD_NULL, "--version", &cline_arg_option), TRUE); cester_assert_str_equal_(cline_arg_option->splited_option_keys[0], "-v"); cester_assert_str_equal_(cline_arg_option->splited_option_keys[1], "--version"); diff --git a/test/cline/test_clinearg_help.c b/test/cline/cliarg/test_clinearg_help.c similarity index 87% rename from test/cline/test_clinearg_help.c rename to test/cline/cliarg/test_clinearg_help.c index ef74cc3..aed614c 100644 --- a/test/cline/test_clinearg_help.c +++ b/test/cline/cliarg/test_clinearg_help.c @@ -1,10 +1,8 @@ -/*!gcc {0} -I. -I../include/ -I../../include/ -o out; ./out */ +/*!clang {0} -I. -I../include/ -I../../../include/ -o out; ./out */ #include #include -#define cester_assert_str_equal_(x,y) cester_assert_true(xstring_cstr_equals(x,y)) - CESTER_BODY( ) @@ -18,7 +16,7 @@ CESTER_TEST(cline_arg_help_section_name_and_description, inst, { cester_assert_int_eq(init_cline_arg(&allocator, &cline_arg, "CliCalc"), XTD_OK); cester_assert_int_eq(cline_arg_set_description(cline_arg, "A simple command line calculator"), XTD_OK); cester_assert_int_eq(cline_arg_section_help(cline_arg, XTD_NULL, XTD_NULL, &help_text), XTD_OK); - cester_assert_str_equal_(help_text, "usage: CliCalc\n\nA simple command line calculator\n"); + cester_assert_str_eq(help_text, "usage: CliCalc\n\nA simple command line calculator\n"); destroy_cline_arg(cline_arg); }) @@ -32,7 +30,7 @@ CESTER_TEST(cline_arg_help_section_usage, inst, { cester_assert_int_eq(init_cline_arg(&allocator, &cline_arg, "CliCalc"), XTD_OK); cester_assert_int_eq(cline_arg_set_usage(cline_arg, "usage: CliCalc [-h] (--number | --letters)"), XTD_OK); cester_assert_int_eq(cline_arg_section_help(cline_arg, XTD_NULL, XTD_NULL, &help_text), XTD_OK); - cester_assert_str_equal_(help_text, "usage: CliCalc [-h] (--number | --letters)\n\n"); + cester_assert_str_eq(help_text, "usage: CliCalc [-h] (--number | --letters)\n\n"); destroy_cline_arg(cline_arg); }) @@ -46,7 +44,7 @@ CESTER_TEST(cline_arg_help_section_epilog, inst, { cester_assert_int_eq(init_cline_arg(&allocator, &cline_arg, "CliCalc"), XTD_OK); cester_assert_int_eq(cline_arg_set_epilog(cline_arg, "Visit https://exoticlibraries.github.io/ for more"), XTD_OK); cester_assert_int_eq(cline_arg_section_help(cline_arg, XTD_NULL, XTD_NULL, &help_text), XTD_OK); - cester_assert_str_equal_(help_text, "usage: CliCalc\n\n\nVisit https://exoticlibraries.github.io/ for more\n"); + cester_assert_str_eq(help_text, "usage: CliCalc\n\n\nVisit https://exoticlibraries.github.io/ for more\n"); destroy_cline_arg(cline_arg); }) @@ -62,7 +60,7 @@ CESTER_TEST(cline_arg_help_section_description_usage_epilog, inst, { cester_assert_int_eq(cline_arg_set_description(cline_arg, "A simple command line calculator"), XTD_OK); cester_assert_int_eq(cline_arg_set_epilog(cline_arg, "Visit https://exoticlibraries.github.io/ for more"), XTD_OK); cester_assert_int_eq(cline_arg_section_help(cline_arg, XTD_NULL, XTD_NULL, &help_text), XTD_OK); - cester_assert_str_equal_(help_text, "usage: CliCalc [-h] (--number | --letters)\n\nA simple command line calculator\n\nVisit https://exoticlibraries.github.io/ for more\n"); + cester_assert_str_eq(help_text, "usage: CliCalc [-h] (--number | --letters)\n\nA simple command line calculator\n\nVisit https://exoticlibraries.github.io/ for more\n"); destroy_cline_arg(cline_arg); }) @@ -78,7 +76,7 @@ CESTER_TEST(cline_arg_help_name_and_description, inst, { cester_assert_int_eq(cline_arg_set_description(cline_arg, "A simple command line calculator"), XTD_OK); cester_assert_int_eq(cline_arg_set_epilog(cline_arg, "Visit https://exoticlibraries.github.io/ for more"), XTD_OK); cester_assert_int_eq(cline_arg_help(cline_arg, XTD_NULL, XTD_NULL, &help_text), XTD_OK); - cester_assert_str_equal_(help_text, "usage: CliCalc [-h] (--number | --letters)\n\nA simple command line calculator\n\nVisit https://exoticlibraries.github.io/ for more\n\n"); + cester_assert_str_eq(help_text, "usage: CliCalc [-h] (--number | --letters)\n\nA simple command line calculator\n\nVisit https://exoticlibraries.github.io/ for more\n\n"); destroy_cline_arg(cline_arg); }) @@ -95,7 +93,7 @@ CESTER_TEST(cline_arg_help_description_and_options, inst, { cester_assert_int_eq(cline_arg_add_option(cline_arg, XTD_NULL, "--version", "Print the version information and exit", FALSE), XTD_OK); cester_assert_int_eq(cline_arg_add_option(cline_arg, XTD_NULL, "--verbose", "Be extra verbose", FALSE), XTD_OK); cester_assert_int_eq(cline_arg_section_help(cline_arg, XTD_NULL, XTD_NULL, &help_text), XTD_OK); - cester_assert_str_equal_(help_text, "usage: CliCalc [-h|--help] [--verbose] [--version]\n" + cester_assert_str_eq(help_text, "usage: CliCalc [-h|--help] [--verbose] [--version]\n" "\n" "A simple command line calculator\n" "\n" @@ -117,7 +115,7 @@ CESTER_TEST(cline_arg_help_description_and_arguments, inst, { cester_assert_int_eq(cline_arg_add_argument(cline_arg, XTD_NULL, "--help", "Print this help message", "section", FALSE), XTD_OK); cester_assert_int_eq(cline_arg_add_argument(cline_arg, XTD_NULL, "--source", "The source file", "file", TRUE), XTD_OK); cester_assert_int_eq(cline_arg_section_help(cline_arg, XTD_NULL, XTD_NULL, &help_text), XTD_OK); - cester_assert_str_equal_(help_text, "usage: CliCalc [--source ] [--help
]\n" + cester_assert_str_eq(help_text, "usage: CliCalc --source [--help
]\n" "\n" "A simple command line calculator\n" "\n" @@ -138,7 +136,7 @@ CESTER_TEST(cline_arg_help_description_and_properties, inst, { cester_assert_int_eq(cline_arg_add_property(cline_arg, XTD_NULL, "-I<:>/I", "Specify the include path", "include_path", FALSE), XTD_OK); cester_assert_int_eq(cline_arg_add_property(cline_arg, XTD_NULL, "-X", "Send option to the assembler", "option", FALSE), XTD_OK); cester_assert_int_eq(cline_arg_section_help(cline_arg, XTD_NULL, XTD_NULL, &help_text), XTD_OK); - cester_assert_str_equal_(help_text, "usage: CliCalc [-X