int non_opt_index;
/*
- * Current character of the current short option group: if it's
- * not `NULL`, the parser is in within a short option group,
- * therefore it must resume there in the next
- * argpar_iter_next() call.
+ * Current character within the current short option group: if
+ * it's not `NULL`, the parser is within a short option group,
+ * therefore it must resume there in the next argpar_iter_next()
+ * call.
*/
- const char *short_opt_ch;
+ const char *short_opt_group_ch;
/* Temporary character buffer which only grows */
struct {
return;
}
-static
-bool push_item(struct argpar_item_array * const array,
- const struct argpar_item * const item)
-{
- bool success;
-
- ARGPAR_ASSERT(array);
- ARGPAR_ASSERT(item);
-
- if (array->n_items == array->n_alloc) {
- const unsigned int new_n_alloc = array->n_alloc * 2;
- const struct argpar_item ** const new_items =
- ARGPAR_REALLOC(array->items, const struct argpar_item *,
- new_n_alloc);
- if (!new_items) {
- success = false;
- goto end;
- }
-
- array->n_alloc = new_n_alloc;
- array->items = new_items;
- }
-
- array->items[array->n_items] = item;
- array->n_items++;
- success = true;
-
-end:
- return success;
-}
-
-static
-void destroy_item_array(struct argpar_item_array * const array)
-{
- if (array) {
- unsigned int i;
-
- for (i = 0; i < array->n_items; i++) {
- argpar_item_destroy(array->items[i]);
- }
-
- free(array->items);
- free(array);
- }
-}
-
-static
-struct argpar_item_array *create_item_array(void)
-{
- struct argpar_item_array *ret;
- const int initial_size = 10;
-
- ret = ARGPAR_ZALLOC(struct argpar_item_array);
- if (!ret) {
- goto end;
- }
-
- ret->items = ARGPAR_CALLOC(const struct argpar_item *, initial_size);
- if (!ret->items) {
- goto error;
- }
-
- ret->n_alloc = initial_size;
- goto end;
-
-error:
- destroy_item_array(ret);
- ret = NULL;
-
-end:
- return ret;
-}
-
static
struct argpar_item_opt *create_opt_item(
const struct argpar_opt_descr * const descr,
};
static
-enum parse_orig_arg_opt_ret parse_short_opts(const char * const short_opts,
+enum parse_orig_arg_opt_ret parse_short_opt_group(
+ const char * const short_opt_group,
const char * const next_orig_arg,
const struct argpar_opt_descr * const descrs,
struct argpar_iter * const iter,
const struct argpar_opt_descr *descr;
struct argpar_item_opt *opt_item;
- ARGPAR_ASSERT(strlen(short_opts) != 0);
+ ARGPAR_ASSERT(strlen(short_opt_group) != 0);
- if (!iter->short_opt_ch) {
- iter->short_opt_ch = short_opts;
+ if (!iter->short_opt_group_ch) {
+ iter->short_opt_group_ch = short_opt_group;
}
/* Find corresponding option descriptor */
- descr = find_descr(descrs, *iter->short_opt_ch, NULL);
+ descr = find_descr(descrs, *iter->short_opt_group_ch, NULL);
if (!descr) {
try_append_string_printf(error, "Unknown option `-%c`",
- *iter->short_opt_ch);
+ *iter->short_opt_group_ch);
ret = PARSE_ORIG_ARG_OPT_RET_ERROR_UNKNOWN_OPT;
goto error;
}
if (descr->with_arg) {
- if (iter->short_opt_ch[1]) {
+ if (iter->short_opt_group_ch[1]) {
/* `-oarg` form */
- opt_arg = &iter->short_opt_ch[1];
+ opt_arg = &iter->short_opt_group_ch[1];
} else {
/* `-o arg` form */
opt_arg = next_orig_arg;
* We accept `-o ''` (empty option argument), but not
* `-o` alone if an option argument is expected.
*/
- if (!opt_arg || (iter->short_opt_ch[1] &&
+ if (!opt_arg || (iter->short_opt_group_ch[1] &&
strlen(opt_arg) == 0)) {
try_append_string_printf(error,
"Missing required argument for option `-%c`",
- *iter->short_opt_ch);
+ *iter->short_opt_group_ch);
used_next_orig_arg = false;
ret = PARSE_ORIG_ARG_OPT_RET_ERROR_MISSING_OPT_ARG;
goto error;
}
*item = &opt_item->base;
- iter->short_opt_ch++;
+ iter->short_opt_group_ch++;
- if (descr->with_arg || !*iter->short_opt_ch) {
+ if (descr->with_arg || !*iter->short_opt_group_ch) {
/* Option has an argument: no more options */
- iter->short_opt_ch = NULL;
+ iter->short_opt_group_ch = NULL;
if (used_next_orig_arg) {
iter->i += 2;
next_orig_arg, descrs, iter, error, item);
} else {
/* Short option */
- ret = parse_short_opts(&orig_arg[1],
+ ret = parse_short_opt_group(&orig_arg[1],
next_orig_arg, descrs, iter, error, item);
}
{
return iter->i;
}
-
-ARGPAR_HIDDEN
-struct argpar_parse_ret argpar_parse(const unsigned int argc,
- const char * const * const argv,
- const struct argpar_opt_descr * const descrs,
- const bool fail_on_unknown_opt)
-{
- struct argpar_parse_ret parse_ret = { 0 };
- const struct argpar_item *item = NULL;
- struct argpar_iter *iter = NULL;
-
- parse_ret.items = create_item_array();
- if (!parse_ret.items) {
- parse_ret.error = strdup("Failed to create items array.");
- ARGPAR_ASSERT(parse_ret.error);
- goto error;
- }
-
- iter = argpar_iter_create(argc, argv, descrs);
- if (!iter) {
- parse_ret.error = strdup("Failed to create argpar iter.");
- ARGPAR_ASSERT(parse_ret.error);
- goto error;
- }
-
- while (true) {
- const enum argpar_iter_next_status status =
- argpar_iter_next(iter, &item, &parse_ret.error);
-
- switch (status) {
- case ARGPAR_ITER_NEXT_STATUS_ERROR_MISSING_OPT_ARG:
- case ARGPAR_ITER_NEXT_STATUS_ERROR_UNEXPECTED_OPT_ARG:
- case ARGPAR_ITER_NEXT_STATUS_ERROR_MEMORY:
- goto error;
- case ARGPAR_ITER_NEXT_STATUS_ERROR_UNKNOWN_OPT:
- if (fail_on_unknown_opt) {
- parse_ret.ingested_orig_args =
- argpar_iter_ingested_orig_args(iter);
- goto error;
- }
-
- free(parse_ret.error);
- parse_ret.error = NULL;
- goto success;
- case ARGPAR_ITER_NEXT_STATUS_END:
- goto success;
- default:
- ARGPAR_ASSERT(status == ARGPAR_ITER_NEXT_STATUS_OK);
- break;
- }
-
- if (!push_item(parse_ret.items, item)) {
- goto error;
- }
-
- item = NULL;
- }
-
-success:
- ARGPAR_ASSERT(!parse_ret.error);
- parse_ret.ingested_orig_args = argpar_iter_ingested_orig_args(iter);
- goto end;
-
-error:
- ARGPAR_ASSERT(parse_ret.error);
-
- /* That's how we indicate that an error occurred */
- destroy_item_array(parse_ret.items);
- parse_ret.items = NULL;
-
-end:
- argpar_iter_destroy(iter);
- argpar_item_destroy(item);
- return parse_ret;
-}
-
-ARGPAR_HIDDEN
-void argpar_parse_ret_fini(struct argpar_parse_ret * const ret)
-{
- ARGPAR_ASSERT(ret);
- destroy_item_array(ret->items);
- ret->items = NULL;
- free(ret->error);
- ret->error = NULL;
-}