* 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 */
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;
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;
ARGPAR_ITER_NEXT_STATUS_END,
ARGPAR_ITER_NEXT_STATUS_ERROR_UNKNOWN_OPT,
ARGPAR_ITER_NEXT_STATUS_ERROR_MISSING_OPT_ARG,
- ARGPAR_ITER_NEXT_STATUS_ERROR_INVALID_ARG,
ARGPAR_ITER_NEXT_STATUS_ERROR_UNEXPECTED_OPT_ARG,
ARGPAR_ITER_NEXT_STATUS_ERROR_MEMORY,
};
* `ARGPAR_ITER_NEXT_STATUS_ERROR_MISSING_OPT_ARG`:
* Missing option argument.
*
- * `ARGPAR_ITER_NEXT_STATUS_ERROR_INVALID_ARG`:
- * Invalid argument.
- *
* `ARGPAR_ITER_NEXT_STATUS_ERROR_UNEXPECTED_OPT_ARG`:
* Unexpected option argument.
*
#include <assert.h>
#include <stdlib.h>
+#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <glib.h>
"-f --<1,0> -f",
descrs, 3);
}
+
+ /* Very long name of long option */
+ {
+ const char opt_name[] =
+ "kale-chips-waistcoat-yr-bicycle-rights-gochujang-"
+ "woke-tumeric-flexitarian-biodiesel-chillwave-cliche-"
+ "ethical-cardigan-listicle-pok-pok-sustainable-live-"
+ "edge-jianbing-gochujang-butcher-disrupt-tattooed-"
+ "tumeric-prism-photo-booth-vape-kogi-jean-shorts-"
+ "blog-williamsburg-fingerstache-palo-santo-artisan-"
+ "affogato-occupy-skateboard-adaptogen-neutra-celiac-"
+ "put-a-bird-on-it-kombucha-everyday-carry-hot-chicken-"
+ "craft-beer-subway-tile-tote-bag-disrupt-selvage-"
+ "raclette-art-party-readymade-paleo-heirloom-trust-"
+ "fund-small-batch-kinfolk-woke-cardigan-prism-"
+ "chambray-la-croix-hashtag-unicorn-edison-bulb-tbh-"
+ "cornhole-cliche-tattooed-green-juice-adaptogen-"
+ "kitsch-lo-fi-vexillologist-migas-gentrify-"
+ "viral-raw-denim";
+ const struct argpar_opt_descr descrs[] = {
+ { 0, '\0', opt_name, true },
+ ARGPAR_OPT_DESCR_SENTINEL
+ };
+ char cmdline[1024];
+
+ sprintf(cmdline, "--%s=23", opt_name);
+ test_succeed(cmdline, cmdline, descrs, 1);
+ }
}
/*
int main(void)
{
- plan_tests(423);
+ plan_tests(434);
succeed_tests();
fail_tests();
return exit_status();