From e0462efe8a46079556da9b85504412a74740d4cd Mon Sep 17 00:00:00 2001 From: Johan Danielsson Date: Fri, 18 Jul 1997 21:58:58 +0000 Subject: [PATCH] New option parsing code. git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@2435 ec53bebd-3082-4978-b11e-865c3cabbd6b --- lib/roken/getarg.c | 191 +++++++++++++++++++++++++++++++++++++++++++++ lib/roken/getarg.h | 63 +++++++++++++++ 2 files changed, 254 insertions(+) create mode 100644 lib/roken/getarg.c create mode 100644 lib/roken/getarg.h diff --git a/lib/roken/getarg.c b/lib/roken/getarg.c new file mode 100644 index 000000000..6bf0fcc3e --- /dev/null +++ b/lib/roken/getarg.c @@ -0,0 +1,191 @@ +/* + * Copyright (c) 1997 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +RCSID("$Id$"); +#endif + +#include "getarg.h" + +static int +arg_match(struct getargs *arg, char *argv) +{ + char *optarg; + int negate = 0; + if(arg->long_name){ + int len = strlen(arg->long_name); + if(strncmp(arg->long_name, argv, len)) + if(arg->type == arg_flag && strlen(argv) > 3 && + strncmp(arg->long_name, argv + 3, len) == 0){ + optarg = argv + 3 + len; + negate = 1; + } else + return ARG_ERR_NO_MATCH; + else + optarg = argv + len; + + if(*optarg != '=' && (arg->type != arg_flag && *optarg == 0)) + return ARG_ERR_NO_MATCH; + switch(arg->type){ + case arg_integer: + { + int tmp; + if(sscanf(optarg + 1, "%d", &tmp) != 1) + return ARG_ERR_BAD_ARG; + *(int*)arg->value = tmp; + return 0; + } + case arg_string: + { + *(char**)arg->value = optarg + 1; + return 0; + } + case arg_flag: + { + int *flag = arg->value; + if(*optarg == 0 || + strcmp(optarg + 1, "yes") == 0 || + strcmp(optarg + 1, "true") == 0){ + *flag = !negate; + return 0; + } else { + *flag = negate; + return 0; + } + return ARG_ERR_BAD_ARG; + } + } + } + return ARG_ERR_NO_MATCH; +} + +int +getarg(struct getargs *args, size_t num_args, + int argc, char **argv, int *optind) +{ + int i, j, k; + int ret = 0; + (*optind)++; + for(i = *optind; i < argc; i++){ + if(argv[i][0] != '-') + break; + if(argv[i][1] == '-'){ + if(argv[i][2] == 0){ + i++; + break; + } + for(j = 0; j < num_args; j++){ + ret = arg_match(&args[j], argv[i] + 2); + if(ret == ARG_ERR_NO_MATCH) + continue; + break; + } + if(ret) + break; + }else{ + for(j = 1; argv[i][j]; j++){ + for(k = 0; k < num_args; k++){ + char *optarg; + if(args[k].short_name == 0) + continue; + if(argv[i][j] == args[k].short_name){ + if(args[k].type == arg_flag){ + *(int*)args[k].value = 1; + break; + } + if(args[k].type == arg_negative_flag){ + *(int*)args[k].value = 0; + break; + } + if(argv[i][j + 1]) + optarg = &argv[i][j + 1]; + else{ + i++; + optarg = argv[i]; + } + if(optarg == NULL) + return ARG_ERR_NO_ARG; + if(args[k].type == arg_integer){ + int tmp; + if(sscanf(optarg, "%d", &tmp) != 1) + return ARG_ERR_BAD_ARG; + *(int*)args[k].value = tmp; + break; + }else if(args[k].type == arg_string){ + *(char**)args[k].value = optarg; + break; + } + return ARG_ERR_BAD_ARG; + } + + } + } + } + } + *optind = i; + return 0; +} + +#if TEST +int foo_flag = 2; +int flag1 = 0; +int flag2 = 0; +int bar_int; +char *baz_string; + +struct getargs args[] = { + { NULL, '1', arg_flag, &flag1, NULL }, + { NULL, '2', arg_flag, &flag2, NULL }, + { "foo", 'f', arg_flag, &foo_flag, NULL }, + { "bar", 'b', arg_integer, &bar_int, NULL }, + { "baz", 'x', arg_string, &baz_string, NULL }, +}; + +int main(int argc, char **argv) +{ + int optind = 0; + while(getarg(args, 5, argc, argv, &optind)) + printf("Bad arg: %s\n", argv[optind]); + printf("flag1 = %d\n", flag1); + printf("flag2 = %d\n", flag2); + printf("foo_flag = %d\n", foo_flag); + printf("bar_int = %d\n", bar_int); + printf("baz_flag = %s\n", baz_string); +} +#endif diff --git a/lib/roken/getarg.h b/lib/roken/getarg.h new file mode 100644 index 000000000..86670a7a4 --- /dev/null +++ b/lib/roken/getarg.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 1997 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* $Id$ */ + +#ifndef __GETARG_H__ +#define __GETARG_H__ + +#include + +struct getargs{ + const char *long_name; + char short_name; + enum { arg_integer, arg_string, arg_flag, arg_negative_flag } type; + void *value; + const char *help; +}; + +enum { + ARG_ERR_NO_MATCH = 1, + ARG_ERR_BAD_ARG, + ARG_ERR_NO_ARG +}; + +int getarg(struct getargs *args, size_t num_args, + int argc, char **argv, int *optind); + +#endif /* __GETARG_H__ */