From d1ef8c1c0236cefec9a8cad12a816998bd670819 Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Tue, 27 Aug 2013 22:44:01 +0200 Subject: issue 7, c version MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- src/argparser.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++--------- src/argparser.h | 19 ++++++++++++++- src/test.c | 2 +- 3 files changed, 82 insertions(+), 13 deletions(-) diff --git a/src/argparser.c b/src/argparser.c index 644f6fd..7c80759 100644 --- a/src/argparser.c +++ b/src/argparser.c @@ -31,6 +31,7 @@ #define VARIADIC 3 /* Prototype for static functions */ +static char* args__abbreviations(char* argument); static void _sort(char** list, long count, char** temp); static void sort(char** list, long count); static void _sort_ptr(void** list, long count, void** temp); @@ -123,8 +124,9 @@ static long args_map_values_size; * @param program The name of the program, `null` for automatic * @param usestderr Whether to use stderr instead of stdout * @param alternative Whether to use single dash/plus long options + * @param abbreviations Abbreviated option expander, `null` for disabled */ -void args_init(char* description, char* usage, char* longdescription, char* program, long usestderr, long alternative) +void args_init(char* description, char* usage, char* longdescription, char* program, long usestderr, long alternative, char* (*abbreviations)(char*, char**, long)) { char* term = getenv("TERM"); args_linuxvt = 0; @@ -159,6 +161,7 @@ void args_init(char* description, char* usage, char* longdescription, char* prog args_options = (args_Option*)malloc(args_options_size * sizeof(args_Option)); map_init(&args_optmap); map_init(&args_opts); + args_abbreviations = abbreviations; } @@ -224,6 +227,49 @@ void args_dispose() } +/** + * The standard abbrevation expander + * + * @param argument The option that not recognised + * @param options All recognised options + * @param count The number of elements in `options` + * @return The only possible expansion, otherwise `null` + */ +char* args_standard_abbreviations(char* argument, char** options, long count) +{ + char* rc = null; + long i; + for (i = 0; i < count; i++) + { + long match = 0; + char* opt = *options; + while (*(argument + match) && (*(opt + match) == *(argument + match))) + match++; + if (*(argument + match) == 0) + { + if (rc) + return null; + rc = opt; + } + } + return rc; +} + + +/** + * Abbreviated option expansion function + * + * @param argument The option that is not recognised + * @return The only alternative, or `null` + */ +char* args__abbreviations(char* argument) +{ + if (args_abbreviations == null) + return null; + return args_abbreviations(argument, args_get_optmap(), args_get_optmap_count()); +} + + /** * Creates, but does not add, a option that takes no arguments * @@ -1309,6 +1355,7 @@ long args_parse(int argc, char** argv) char** argend = argv + argc; long dashed = false, tmpdashed = false, get = 0, dontget = 0, rc = true; long argptr = 0, optptr = 0, queuesize = argc - 1; + char* injection = null; char** argqueue; char** optqueue; @@ -1337,9 +1384,10 @@ long args_parse(int argc, char** argv) optqueue = (char**)malloc(queuesize * sizeof(char*)); args_freequeue = (void**)malloc(queuesize * sizeof(void*)); - while (argv != argend) + while ((argv != argend) || injection) { - char* arg = *argv++; + char* arg = injection ? injection : *argv++; + injection = null; if ((get > 0) && (dontget == 0)) { char* arg_opt = *(optqueue + optptr - get--); @@ -1413,9 +1461,12 @@ long args_parse(int argc, char** argv) } else { - if (++args_unrecognised_count <= 5) - fprintf(args_out, "%s: warning: unrecognised option %s\n", args_program, arg); - rc = false; + if ((injection = args__abbreviations(arg)) == null) + { + if (++args_unrecognised_count <= 5) + fprintf(args_out, "%s: warning: unrecognised option %s\n", args_program, arg_opt); + rc = false; + } free(arg_opt); } } @@ -1432,11 +1483,12 @@ long args_parse(int argc, char** argv) args_optmap_trigger(arg, null); } else - { - if (++args_unrecognised_count <= 5) - fprintf(args_out, "%s: warning: unrecognised option %s\n", args_program, arg); - rc = false; - } + if ((injection = args__abbreviations(arg)) == null) + { + if (++args_unrecognised_count <= 5) + fprintf(args_out, "%s: warning: unrecognised option %s\n", args_program, arg); + rc = false; + } } else { diff --git a/src/argparser.h b/src/argparser.h index 3c06584..eb073cd 100644 --- a/src/argparser.h +++ b/src/argparser.h @@ -192,6 +192,11 @@ char** args_files; */ long args_files_count; +/** + * Abbreviated option expander, `null` for disabled + */ +char* (*args_abbreviations)(char*, char**, long); + /** @@ -204,8 +209,9 @@ long args_files_count; * @param program The name of the program, `null` for automatic * @param usestderr Whether to use stderr instead of stdout * @param alternative Whether to use single dash/plus long options + * @param abbreviations Abbreviated option expander, `null` for disabled */ -extern void args_init(char* description, char* usage, char* longdescription, char* program, long usestderr, long alternative); +extern void args_init(char* description, char* usage, char* longdescription, char* program, long usestderr, long alternative, char* (*abbreviations)(char*, char**, long)); /** @@ -214,6 +220,17 @@ extern void args_init(char* description, char* usage, char* longdescription, cha extern void args_dispose(void); +/** + * The standard abbrevation expander + * + * @param argument The option that not recognised + * @param options All recognised options + * @param count The number of elements in `options` + * @return The only possible expansion, otherwise `null` + */ +extern char* args_standard_abbreviations(char* argument, char** options, long count); + + /** * Creates, but does not add, a option that takes no arguments * diff --git a/src/test.c b/src/test.c index 4e52f1e..9d65b2e 100644 --- a/src/test.c +++ b/src/test.c @@ -41,7 +41,7 @@ int main(int argc, char** argv) "GNU Affero General Public License for more details.\n" "\n" "You should have received a copy of the GNU Affero General Public License\n" - "along with this library. If not, see .", 0, 1, 0); + "along with this library. If not, see .", 0, 1, 0, args_standard_abbreviations); args_add_option(args_new_argumentless(NULL, 1, "-h", "-?", "--help", NULL), "Prints this help message\n(and exits)"); args_add_option(args_new_argumentless(NULL, 0, "--hello", NULL), "Prints the text: hello world"); -- cgit v1.2.3-70-g09d2