* argpar_iter_next() call.
*/
const char *short_opt_ch;
+
+ /* Temporary character buffer which only grows */
+ struct {
+ size_t size;
+ char *data;
+ } tmp_buf;
};
/* Base parsing item */
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,
PARSE_ORIG_ARG_OPT_RET_OK,
PARSE_ORIG_ARG_OPT_RET_ERROR_UNKNOWN_OPT = -1,
PARSE_ORIG_ARG_OPT_RET_ERROR_MISSING_OPT_ARG = -2,
- PARSE_ORIG_ARG_OPT_RET_ERROR_INVALID_ARG = -3,
PARSE_ORIG_ARG_OPT_RET_ERROR_UNEXPECTED_OPT_ARG = -4,
PARSE_ORIG_ARG_OPT_RET_ERROR_MEMORY = -5,
};
struct argpar_iter * const iter,
char ** const error, struct argpar_item ** const item)
{
- const size_t max_len = 127;
enum parse_orig_arg_opt_ret ret = PARSE_ORIG_ARG_OPT_RET_OK;
const struct argpar_opt_descr *descr;
struct argpar_item_opt *opt_item;
/* Position of first `=`, if any */
const char *eq_pos;
- /* Buffer holding option name when `long_opt_arg` contains `=` */
- char buf[max_len + 1];
-
/* Option name */
const char *long_opt_name = long_opt_arg;
const size_t long_opt_name_size = eq_pos - long_opt_arg;
/* Isolate the option name */
- if (long_opt_name_size > max_len) {
- try_append_string_printf(error,
- "Invalid argument `--%s`", long_opt_arg);
- ret = PARSE_ORIG_ARG_OPT_RET_ERROR_INVALID_ARG;
- goto error;
+ while (long_opt_name_size > iter->tmp_buf.size - 1) {
+ iter->tmp_buf.size *= 2;
+ iter->tmp_buf.data = ARGPAR_REALLOC(iter->tmp_buf.data,
+ char, iter->tmp_buf.size);
+ if (!iter->tmp_buf.data) {
+ ret = PARSE_ORIG_ARG_OPT_RET_ERROR_MEMORY;
+ goto error;
+ }
}
- memcpy(buf, long_opt_arg, long_opt_name_size);
- buf[long_opt_name_size] = '\0';
- long_opt_name = buf;
+ memcpy(iter->tmp_buf.data, long_opt_arg, long_opt_name_size);
+ iter->tmp_buf.data[long_opt_name_size] = '\0';
+ long_opt_name = iter->tmp_buf.data;
}
/* Find corresponding option descriptor */
const char * const * const argv,
const struct argpar_opt_descr * const descrs)
{
- struct argpar_iter * const iter = ARGPAR_ZALLOC(struct argpar_iter);
+ struct argpar_iter *iter = ARGPAR_ZALLOC(struct argpar_iter);
if (!iter) {
goto end;
iter->argc = argc;
iter->argv = argv;
iter->descrs = descrs;
+ iter->tmp_buf.size = 128;
+ iter->tmp_buf.data = ARGPAR_CALLOC(char, iter->tmp_buf.size);
+ if (!iter->tmp_buf.data) {
+ argpar_iter_destroy(iter);
+ iter = NULL;
+ goto end;
+ }
end:
return iter;
ARGPAR_HIDDEN
void argpar_iter_destroy(struct argpar_iter * const iter)
{
- free(iter);
+ if (iter) {
+ free(iter->tmp_buf.data);
+ free(iter);
+ }
}
ARGPAR_HIDDEN
break;
case PARSE_ORIG_ARG_OPT_RET_ERROR_UNKNOWN_OPT:
case PARSE_ORIG_ARG_OPT_RET_ERROR_MISSING_OPT_ARG:
- case PARSE_ORIG_ARG_OPT_RET_ERROR_INVALID_ARG:
case PARSE_ORIG_ARG_OPT_RET_ERROR_UNEXPECTED_OPT_ARG:
try_prepend_while_parsing_arg_to_error(error, iter->i,
orig_arg);
case PARSE_ORIG_ARG_OPT_RET_ERROR_MISSING_OPT_ARG:
status = ARGPAR_ITER_NEXT_STATUS_ERROR_MISSING_OPT_ARG;
break;
- case PARSE_ORIG_ARG_OPT_RET_ERROR_INVALID_ARG:
- status = ARGPAR_ITER_NEXT_STATUS_ERROR_INVALID_ARG;
- break;
case PARSE_ORIG_ARG_OPT_RET_ERROR_UNEXPECTED_OPT_ARG:
status = ARGPAR_ITER_NEXT_STATUS_ERROR_UNEXPECTED_OPT_ARG;
break;
{
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_INVALID_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;
-}