From 2f543a4d8c07c325f2d9aed2ef39318eb17092b9 Mon Sep 17 00:00:00 2001 From: Dominik Meyer Date: Sat, 31 Mar 2018 19:11:23 +0200 Subject: [PATCH] ADD: support for flag arguments and -h --- src/argparse.c | 107 +++++++++++++++++++++++++++++++++++++++++++++++++ src/argparse.h | 14 ++++++- 2 files changed, 120 insertions(+), 1 deletion(-) diff --git a/src/argparse.c b/src/argparse.c index 8cc7218..6d97558 100644 --- a/src/argparse.c +++ b/src/argparse.c @@ -29,6 +29,24 @@ along with this program. If not, see . #include #include "argparse.h" + +void argparse_usage(struct arg_parse_ctx *ctx, char *program); ///< forward declaration of function +int argparse_add_flag(struct arg_parse_ctx *ctx, struct arg_flag *flag); ///< forward declaration of function + +/** +* @brief wrapper function for calling argparse_usage from the -h arg_flag command line argument +* +* @param ctx - the current yaap context +* @param user - some user specific data in this case the command line arguments +* +* @return 0 - everything is fine +*/ +int argparse_help(void *ctx, void *user) +{ + argparse_usage(ctx, ((char **) user)[0]); + return 0; +} + /** * @brief initialize the argparse context * @@ -54,6 +72,15 @@ struct arg_parse_ctx * argparse_init() return NULL; } + // flag argument for -h and --help + struct arg_flag *flag = (struct arg_flag *) calloc(sizeof(struct arg_flag),1); + flag->base.type = ARG_FLAG; + flag->short_flag='h'; + flag->long_flag="help"; + flag->description="print help message"; + flag->cb=&argparse_help; + argparse_add_flag(ctx, flag); + return ctx; } @@ -66,6 +93,19 @@ struct arg_parse_ctx * argparse_init() */ void argparse_free(struct arg_parse_ctx *ctx) { + int i; + + //search for -h flag argument and free it + for(i=0; i< ctx->nr_arguments;i++) + { + if (to_argbase(ctx->arguments[i])->type == ARG_FLAG) + { + if (to_flag(ctx->arguments[i])->short_flag=='h') + { + free(ctx->arguments[i]); + } + } + } // free the arg_parse_cmd array free(ctx->arguments); @@ -134,6 +174,36 @@ int argparse_add_string(struct arg_parse_ctx *ctx, struct arg_str *str) return 0; } +/** +* @brief add an arg_flag to the context for later parsing +* +* @param ctx - the context the command should be added to +* @param flag - the arg_flag to add +* +* @return 0 = everything is fine, -1 error occured +*/ +int argparse_add_flag(struct arg_parse_ctx *ctx, struct arg_flag *flag) +{ + if (ctx == NULL || flag == NULL) + { + return -1; + } + + flag->base.type=ARG_FLAG; + + + // check if the array size has to be increased + if (ctx->nr_arguments % ARGPARSE_INITIAL_COMMAND_NR == 0) + { + ctx->arguments= (void **) realloc(ctx->arguments, sizeof(void *)*(ctx->nr_arguments+ARGPARSE_INITIAL_COMMAND_NR)); + } + + // append the command to the array + ctx->arguments[ctx->nr_arguments]=flag; + ctx->nr_arguments++; + + return 0; +} /** * @brief internal function to print usage information, not exported to user @@ -172,6 +242,13 @@ void argparse_usage(struct arg_parse_ctx *ctx, char *program) printf("\t-%c |--%s=\t\t%s\n", to_str(ctx->arguments[i])->short_flag, to_str(ctx->arguments[i])->long_flag, to_str(ctx->arguments[i])->description); + + break; + case ARG_FLAG: + printf("\t-%c | --%s\t\t%s\n", to_flag(ctx->arguments[i])->short_flag, + to_flag(ctx->arguments[i])->long_flag, + to_flag(ctx->arguments[i])->description); + break; default: break; }; @@ -271,6 +348,36 @@ int argparse_parse(struct arg_parse_ctx *ctx, int argc, char **argv) } } } + // check if the argument is a flag argument + else if (argv[i][0]=='-' && to_argbase(ctx->arguments[r])->type == ARG_FLAG) + { + // check for long argument format or short + if(argv[i][1]=='-') + { + if (strcmp(&argv[i][2],to_flag(ctx->arguments[r])->long_flag)==0) + { + to_flag(ctx->arguments[r])->base.set=1; + found=1; + if (to_flag(ctx->arguments[r])->cb != NULL) + { + return to_flag(ctx->arguments[r])->cb(ctx, argv); + } + } + } + else + { + if(argv[i][1] == to_flag(ctx->arguments[r])->short_flag) + { + found=1; + to_flag(ctx->arguments[r])->base.set=1; + if (to_flag(ctx->arguments[r])->cb != NULL) + { + return to_flag(ctx->arguments[r])->cb(ctx, argv); + } + + } + } + } } if (found == 0) diff --git a/src/argparse.h b/src/argparse.h index 5352aaa..1110368 100644 --- a/src/argparse.h +++ b/src/argparse.h @@ -68,6 +68,7 @@ along with this program. If not, see . #define to_argbase(ptr) ((struct arg_base *) ptr) ///< convert a pointer to an arg_base structure pointer #define to_cmd(ptr) ((struct arg_parse_cmd *)ptr) ///< convert a pointer to an arg_parse_cmd structure pointer #define to_str(ptr) ((struct arg_str *)ptr) ///< convert a pointer to an arg_str structure pointer +#define to_flag(ptr) ((struct arg_flag *) ptr) ///< convert a pointer to an arg_flag structure pointer /** * @brief supported argument types @@ -106,13 +107,24 @@ struct arg_parse_cmd */ struct arg_str { struct arg_base base; ///< base of the command line argument - const char short_flag; ///< one char flag identifying the argument, ignored if NULL + char short_flag; ///< one char flag identifying the argument, ignored if NULL const char *long_flag; ///< multi char flag identifying the argument, ignore if NULL char *value; ///< memory already allocated for the string parameter int maxchars; ///< the maximum number of chars for the string parameters const char *description; ///< short description of the argument }; +/** +* qbrief structure repsenting a simple flag command line argument +*/ +struct arg_flag { + struct arg_base base; ///< base of the command line argument + char short_flag; ///< one char flag identifying the argument, ignored if NULL + const char *long_flag; ///< multi char flag identifying the argument, ignore if NULL + const char *description; ///< short description of the argument + int (*cb)(void *ctx, void *userdata); ///< callback called if argument is found +}; + /** * @brief structure for the argparse context, holding argparse specific data structures