From bd533f99665cab3c9d64c14c242a8f80bdce71c5 Mon Sep 17 00:00:00 2001 From: Andre Noll Date: Sun, 29 Jul 2012 18:39:58 +0200 Subject: [PATCH] Introduce create_shifted_argv(). In order to create argument vectors for the gengetopt parsers, filter_common.c and recv_common.c call create_argv() on the given --filter or --receiver option, then shift the returned array by one to the right because gengetopt expects the program name in argv[0]. This commit creates a new helper function for this purpose and changes the two callers to use the new function. --- filter_common.c | 13 ++------- recv_common.c | 15 +++-------- string.c | 71 ++++++++++++++++++++++++++++++++++--------------- string.h | 1 + 4 files changed, 55 insertions(+), 45 deletions(-) diff --git a/filter_common.c b/filter_common.c index ffb2199b..0d3377b1 100644 --- a/filter_common.c +++ b/filter_common.c @@ -41,25 +41,16 @@ void filter_init(void) static int parse_filter_args(int filter_num, char *options, void **conf) { struct filter *f = &filters[filter_num]; - int ret, i, argc = 2; + int ret, argc; char **argv; -// PARA_DEBUG_LOG("%s, options: %s, parser: %p\n", f->name, -// options? options : "(none)", f->parse_config); if (!f->parse_config) return strlen(options)? -E_BAD_FILTER_OPTIONS : filter_num; -// PARA_DEBUG_LOG("options: %s\n", options); - argc = create_argv(options, " \t", &argv); + argc = create_shifted_argv(options, " \t", &argv); if (argc < 0) return -E_BAD_FILTER_OPTIONS; - PARA_DEBUG_LOG("argc = %d, argv[0]: %s\n", argc, argv[0]); - for (i = argc - 1; i >= 0; i--) - argv[i + 1] = argv[i]; argv[0] = para_strdup(f->name); - argc++; ret = f->parse_config(argc, argv, conf); - free(argv[argc - 1]); - argv[argc - 1] = NULL; free_argv(argv); return ret < 0? ret : filter_num; } diff --git a/recv_common.c b/recv_common.c index 4f157ab5..7d7d2b05 100644 --- a/recv_common.c +++ b/recv_common.c @@ -33,20 +33,13 @@ static void *parse_receiver_args(int receiver_num, char *options) { struct receiver *r = &receivers[receiver_num]; char **argv; - int argc, i; + int argc; void *conf; - - PARA_DEBUG_LOG("%s, options: %s\n", r->name, - options? options : "(none)"); if (options) { - PARA_DEBUG_LOG("options: %s\n", options); - argc = create_argv(options, " \t", &argv); + argc = create_shifted_argv(options, " \t", &argv); if (argc < 0) return NULL; - for (i = argc - 1; i >= 0; i--) - argv[i + 1] = argv[i]; - argc++; } else { argc = 1; argv = para_malloc(2 * sizeof(char*)); @@ -54,9 +47,7 @@ static void *parse_receiver_args(int receiver_num, char *options) } argv[0] = make_message("%s_recv", r->name); conf = r->parse_config(argc, argv); - for (i = 0; i < argc; i++) - free(argv[i]); - free(argv); + free_argv(argv); return conf; } diff --git a/string.c b/string.c index a727f2a9..283c46e2 100644 --- a/string.c +++ b/string.c @@ -800,7 +800,7 @@ int compute_word_num(const char *buf, const char *delim, int point) } /** - * Free an array of words created by create_argv(). + * Free an array of words created by create_argv() or create_shifted_argv(). * * \param argv A pointer previously obtained by \ref create_argv(). */ @@ -815,6 +815,35 @@ void free_argv(char **argv) free(argv); } +static int create_argv_offset(int offset, const char *buf, const char *delim, + char ***result) +{ + char *word, **argv = para_malloc((offset + 1) * sizeof(char *)); + const char *p; + int i, ret; + + for (i = 0; i < offset; i++) + argv[i] = NULL; + for (p = buf; p && *p; p += ret, i++) { + ret = get_next_word(p, delim, &word); + if (ret < 0) + goto err; + if (!ret) + break; + argv = para_realloc(argv, (i + 2) * sizeof(char*)); + argv[i] = word; + } + argv[i] = NULL; + *result = argv; + return i; +err: + while (i > 0) + free(argv[--i]); + free(argv); + *result = NULL; + return ret; +} + /** * Split a buffer into words. * @@ -831,28 +860,26 @@ void free_argv(char **argv) */ int create_argv(const char *buf, const char *delim, char ***result) { - char *word, **argv = para_malloc(sizeof(char *)); - const char *p; - int ret, num_words; + return create_argv_offset(0, buf, delim, result); +} - for (p = buf, num_words = 0; ; p += ret, num_words++) { - ret = get_next_word(p, delim, &word); - if (ret < 0) - goto err; - if (!ret) - break; - argv = para_realloc(argv, (num_words + 2) * sizeof(char*)); - argv[num_words] = word; - } - argv[num_words] = NULL; - *result = argv; - return num_words; -err: - while (num_words > 0) - free(argv[--num_words]); - free(argv); - *result = NULL; - return ret; +/** + * Split a buffer into words, offset one. + * + * This is similar to \ref create_argv() but the returned array is one element + * larger, words start at index one and element zero is initialized to \p NULL. + * Callers must set element zero to a non-NULL value before calling free_argv() + * on the returned array to avoid a memory leak. + * + * \param buf See \ref create_argv(). + * \param delim See \ref create_argv(). + * \param result See \ref create_argv(). + * + * \return Number of words plus one on success, negative on errors. + */ +int create_shifted_argv(const char *buf, const char *delim, char ***result) +{ + return create_argv_offset(1, buf, delim, result); } /** diff --git a/string.h b/string.h index aebb6516..cf02d978 100644 --- a/string.h +++ b/string.h @@ -83,6 +83,7 @@ int para_atoi32(const char *str, int32_t *value); int get_loglevel_by_name(const char *txt); int read_size_header(const char *buf); int create_argv(const char *buf, const char *delim, char ***result); +int create_shifted_argv(const char *buf, const char *delim, char ***result); int find_arg(const char *arg, char **argv); void free_argv(char **argv); int para_regcomp(regex_t *preg, const char *regex, int cflags); -- 2.39.5