1b528cefcSMark Murray /* 2b528cefcSMark Murray * Copyright (c) 1997, 1998, 1999 Kungliga Tekniska H�gskolan 3b528cefcSMark Murray * (Royal Institute of Technology, Stockholm, Sweden). 4b528cefcSMark Murray * All rights reserved. 5b528cefcSMark Murray * 6b528cefcSMark Murray * Redistribution and use in source and binary forms, with or without 7b528cefcSMark Murray * modification, are permitted provided that the following conditions 8b528cefcSMark Murray * are met: 9b528cefcSMark Murray * 10b528cefcSMark Murray * 1. Redistributions of source code must retain the above copyright 11b528cefcSMark Murray * notice, this list of conditions and the following disclaimer. 12b528cefcSMark Murray * 13b528cefcSMark Murray * 2. Redistributions in binary form must reproduce the above copyright 14b528cefcSMark Murray * notice, this list of conditions and the following disclaimer in the 15b528cefcSMark Murray * documentation and/or other materials provided with the distribution. 16b528cefcSMark Murray * 17b528cefcSMark Murray * 3. Neither the name of the Institute nor the names of its contributors 18b528cefcSMark Murray * may be used to endorse or promote products derived from this software 19b528cefcSMark Murray * without specific prior written permission. 20b528cefcSMark Murray * 21b528cefcSMark Murray * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22b528cefcSMark Murray * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23b528cefcSMark Murray * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24b528cefcSMark Murray * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25b528cefcSMark Murray * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26b528cefcSMark Murray * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27b528cefcSMark Murray * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28b528cefcSMark Murray * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29b528cefcSMark Murray * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30b528cefcSMark Murray * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31b528cefcSMark Murray * SUCH DAMAGE. 32b528cefcSMark Murray */ 33b528cefcSMark Murray 34b528cefcSMark Murray #ifdef HAVE_CONFIG_H 35b528cefcSMark Murray #include <config.h> 36b528cefcSMark Murray RCSID("$Id: getarg.c,v 1.32 1999/12/02 16:58:46 joda Exp $"); 37b528cefcSMark Murray #endif 38b528cefcSMark Murray 39b528cefcSMark Murray #include <stdio.h> 40b528cefcSMark Murray #include <roken.h> 41b528cefcSMark Murray #include "getarg.h" 42b528cefcSMark Murray 43b528cefcSMark Murray #define ISFLAG(X) ((X).type == arg_flag || (X).type == arg_negative_flag) 44b528cefcSMark Murray 45b528cefcSMark Murray static size_t 46b528cefcSMark Murray print_arg (char *string, size_t len, int mdoc, int longp, struct getargs *arg) 47b528cefcSMark Murray { 48b528cefcSMark Murray const char *s; 49b528cefcSMark Murray 50b528cefcSMark Murray *string = '\0'; 51b528cefcSMark Murray 52b528cefcSMark Murray if (ISFLAG(*arg) || (!longp && arg->type == arg_counter)) 53b528cefcSMark Murray return 0; 54b528cefcSMark Murray 55b528cefcSMark Murray if(mdoc){ 56b528cefcSMark Murray if(longp) 57b528cefcSMark Murray strlcat(string, "= Ns", len); 58b528cefcSMark Murray strlcat(string, " Ar ", len); 59b528cefcSMark Murray }else 60b528cefcSMark Murray if (longp) 61b528cefcSMark Murray strlcat (string, "=", len); 62b528cefcSMark Murray else 63b528cefcSMark Murray strlcat (string, " ", len); 64b528cefcSMark Murray 65b528cefcSMark Murray if (arg->arg_help) 66b528cefcSMark Murray s = arg->arg_help; 67b528cefcSMark Murray else if (arg->type == arg_integer || arg->type == arg_counter) 68b528cefcSMark Murray s = "integer"; 69b528cefcSMark Murray else if (arg->type == arg_string) 70b528cefcSMark Murray s = "string"; 71b528cefcSMark Murray else if (arg->type == arg_double) 72b528cefcSMark Murray s = "float"; 73b528cefcSMark Murray else 74b528cefcSMark Murray s = "<undefined>"; 75b528cefcSMark Murray 76b528cefcSMark Murray strlcat(string, s, len); 77b528cefcSMark Murray return 1 + strlen(s); 78b528cefcSMark Murray } 79b528cefcSMark Murray 80b528cefcSMark Murray static void 81b528cefcSMark Murray mandoc_template(struct getargs *args, 82b528cefcSMark Murray size_t num_args, 83b528cefcSMark Murray const char *progname, 84b528cefcSMark Murray const char *extra_string) 85b528cefcSMark Murray { 86b528cefcSMark Murray int i; 87b528cefcSMark Murray char timestr[64], cmd[64]; 88b528cefcSMark Murray char buf[128]; 89b528cefcSMark Murray const char *p; 90b528cefcSMark Murray time_t t; 91b528cefcSMark Murray 92b528cefcSMark Murray printf(".\\\" Things to fix:\n"); 93b528cefcSMark Murray printf(".\\\" * correct section, and operating system\n"); 94b528cefcSMark Murray printf(".\\\" * remove Op from mandatory flags\n"); 95b528cefcSMark Murray printf(".\\\" * use better macros for arguments (like .Pa for files)\n"); 96b528cefcSMark Murray printf(".\\\"\n"); 97b528cefcSMark Murray t = time(NULL); 98b528cefcSMark Murray strftime(timestr, sizeof(timestr), "%B %e, %Y", localtime(&t)); 99b528cefcSMark Murray printf(".Dd %s\n", timestr); 100b528cefcSMark Murray p = strrchr(progname, '/'); 101b528cefcSMark Murray if(p) p++; else p = progname; 102b528cefcSMark Murray strlcpy(cmd, p, sizeof(cmd)); 103b528cefcSMark Murray strupr(cmd); 104b528cefcSMark Murray 105b528cefcSMark Murray printf(".Dt %s SECTION\n", cmd); 106b528cefcSMark Murray printf(".Os OPERATING_SYSTEM\n"); 107b528cefcSMark Murray printf(".Sh NAME\n"); 108b528cefcSMark Murray printf(".Nm %s\n", p); 109b528cefcSMark Murray printf(".Nd\n"); 110b528cefcSMark Murray printf("in search of a description\n"); 111b528cefcSMark Murray printf(".Sh SYNOPSIS\n"); 112b528cefcSMark Murray printf(".Nm\n"); 113b528cefcSMark Murray for(i = 0; i < num_args; i++){ 114b528cefcSMark Murray /* we seem to hit a limit on number of arguments if doing 115b528cefcSMark Murray short and long flags with arguments -- split on two lines */ 116b528cefcSMark Murray if(ISFLAG(args[i]) || 117b528cefcSMark Murray args[i].short_name == 0 || args[i].long_name == NULL) { 118b528cefcSMark Murray printf(".Op "); 119b528cefcSMark Murray 120b528cefcSMark Murray if(args[i].short_name) { 121b528cefcSMark Murray print_arg(buf, sizeof(buf), 1, 0, args + i); 122b528cefcSMark Murray printf("Fl %c%s", args[i].short_name, buf); 123b528cefcSMark Murray if(args[i].long_name) 124b528cefcSMark Murray printf(" | "); 125b528cefcSMark Murray } 126b528cefcSMark Murray if(args[i].long_name) { 127b528cefcSMark Murray print_arg(buf, sizeof(buf), 1, 1, args + i); 128b528cefcSMark Murray printf("Fl -%s%s", args[i].long_name, buf); 129b528cefcSMark Murray } 130b528cefcSMark Murray printf("\n"); 131b528cefcSMark Murray } else { 132b528cefcSMark Murray print_arg(buf, sizeof(buf), 1, 0, args + i); 133b528cefcSMark Murray printf(".Oo Fl %c%s \\*(Ba Xo\n", args[i].short_name, buf); 134b528cefcSMark Murray print_arg(buf, sizeof(buf), 1, 1, args + i); 135b528cefcSMark Murray printf(".Fl -%s%s Oc\n.Xc\n", args[i].long_name, buf); 136b528cefcSMark Murray } 137b528cefcSMark Murray /* 138b528cefcSMark Murray if(args[i].type == arg_strings) 139b528cefcSMark Murray fprintf (stderr, "..."); 140b528cefcSMark Murray */ 141b528cefcSMark Murray } 142b528cefcSMark Murray if (extra_string && *extra_string) 143b528cefcSMark Murray printf (".Ar %s\n", extra_string); 144b528cefcSMark Murray printf(".Sh DESCRIPTION\n"); 145b528cefcSMark Murray printf("Supported options:\n"); 146b528cefcSMark Murray printf(".Bl -tag -width Ds\n"); 147b528cefcSMark Murray for(i = 0; i < num_args; i++){ 148b528cefcSMark Murray printf(".It Xo\n"); 149b528cefcSMark Murray if(args[i].short_name){ 150b528cefcSMark Murray printf(".Fl %c", args[i].short_name); 151b528cefcSMark Murray print_arg(buf, sizeof(buf), 1, 0, args + i); 152b528cefcSMark Murray printf("%s", buf); 153b528cefcSMark Murray if(args[i].long_name) 154b528cefcSMark Murray printf(" Ns ,"); 155b528cefcSMark Murray printf("\n"); 156b528cefcSMark Murray } 157b528cefcSMark Murray if(args[i].long_name){ 158b528cefcSMark Murray printf(".Fl -%s", args[i].long_name); 159b528cefcSMark Murray print_arg(buf, sizeof(buf), 1, 1, args + i); 160b528cefcSMark Murray printf("%s\n", buf); 161b528cefcSMark Murray } 162b528cefcSMark Murray printf(".Xc\n"); 163b528cefcSMark Murray if(args[i].help) 164b528cefcSMark Murray printf("%s\n", args[i].help); 165b528cefcSMark Murray /* 166b528cefcSMark Murray if(args[i].type == arg_strings) 167b528cefcSMark Murray fprintf (stderr, "..."); 168b528cefcSMark Murray */ 169b528cefcSMark Murray } 170b528cefcSMark Murray printf(".El\n"); 171b528cefcSMark Murray printf(".\\\".Sh ENVIRONMENT\n"); 172b528cefcSMark Murray printf(".\\\".Sh FILES\n"); 173b528cefcSMark Murray printf(".\\\".Sh EXAMPLES\n"); 174b528cefcSMark Murray printf(".\\\".Sh DIAGNOSTICS\n"); 175b528cefcSMark Murray printf(".\\\".Sh SEE ALSO\n"); 176b528cefcSMark Murray printf(".\\\".Sh STANDARDS\n"); 177b528cefcSMark Murray printf(".\\\".Sh HISTORY\n"); 178b528cefcSMark Murray printf(".\\\".Sh AUTHORS\n"); 179b528cefcSMark Murray printf(".\\\".Sh BUGS\n"); 180b528cefcSMark Murray } 181b528cefcSMark Murray 182b528cefcSMark Murray static int 183b528cefcSMark Murray check_column(FILE *f, int col, int len, int columns) 184b528cefcSMark Murray { 185b528cefcSMark Murray if(col + len > columns) { 186b528cefcSMark Murray fprintf(f, "\n"); 187b528cefcSMark Murray col = fprintf(f, " "); 188b528cefcSMark Murray } 189b528cefcSMark Murray return col; 190b528cefcSMark Murray } 191b528cefcSMark Murray 192b528cefcSMark Murray void 193b528cefcSMark Murray arg_printusage (struct getargs *args, 194b528cefcSMark Murray size_t num_args, 195b528cefcSMark Murray const char *progname, 196b528cefcSMark Murray const char *extra_string) 197b528cefcSMark Murray { 198b528cefcSMark Murray int i; 199b528cefcSMark Murray size_t max_len = 0; 200b528cefcSMark Murray char buf[128]; 201b528cefcSMark Murray int col = 0, columns; 202b528cefcSMark Murray struct winsize ws; 203b528cefcSMark Murray 204b528cefcSMark Murray if (progname == NULL) 205b528cefcSMark Murray progname = __progname; 206b528cefcSMark Murray 207b528cefcSMark Murray if(getenv("GETARGMANDOC")){ 208b528cefcSMark Murray mandoc_template(args, num_args, progname, extra_string); 209b528cefcSMark Murray return; 210b528cefcSMark Murray } 211b528cefcSMark Murray if(get_window_size(2, &ws) == 0) 212b528cefcSMark Murray columns = ws.ws_col; 213b528cefcSMark Murray else 214b528cefcSMark Murray columns = 80; 215b528cefcSMark Murray col = 0; 216b528cefcSMark Murray col += fprintf (stderr, "Usage: %s", progname); 217b528cefcSMark Murray for (i = 0; i < num_args; ++i) { 218b528cefcSMark Murray size_t len = 0; 219b528cefcSMark Murray 220b528cefcSMark Murray if (args[i].long_name) { 221b528cefcSMark Murray buf[0] = '\0'; 222b528cefcSMark Murray strlcat(buf, "[--", sizeof(buf)); 223b528cefcSMark Murray len += 2; 224b528cefcSMark Murray if(args[i].type == arg_negative_flag) { 225b528cefcSMark Murray strlcat(buf, "no-", sizeof(buf)); 226b528cefcSMark Murray len += 3; 227b528cefcSMark Murray } 228b528cefcSMark Murray strlcat(buf, args[i].long_name, sizeof(buf)); 229b528cefcSMark Murray len += strlen(args[i].long_name); 230b528cefcSMark Murray len += print_arg(buf + strlen(buf), sizeof(buf) - strlen(buf), 231b528cefcSMark Murray 0, 1, &args[i]); 232b528cefcSMark Murray strlcat(buf, "]", sizeof(buf)); 233b528cefcSMark Murray if(args[i].type == arg_strings) 234b528cefcSMark Murray strlcat(buf, "...", sizeof(buf)); 235b528cefcSMark Murray col = check_column(stderr, col, strlen(buf) + 1, columns); 236b528cefcSMark Murray col += fprintf(stderr, " %s", buf); 237b528cefcSMark Murray } 238b528cefcSMark Murray if (args[i].short_name) { 239b528cefcSMark Murray snprintf(buf, sizeof(buf), "[-%c", args[i].short_name); 240b528cefcSMark Murray len += 2; 241b528cefcSMark Murray len += print_arg(buf + strlen(buf), sizeof(buf) - strlen(buf), 242b528cefcSMark Murray 0, 0, &args[i]); 243b528cefcSMark Murray strlcat(buf, "]", sizeof(buf)); 244b528cefcSMark Murray if(args[i].type == arg_strings) 245b528cefcSMark Murray strlcat(buf, "...", sizeof(buf)); 246b528cefcSMark Murray col = check_column(stderr, col, strlen(buf) + 1, columns); 247b528cefcSMark Murray col += fprintf(stderr, " %s", buf); 248b528cefcSMark Murray } 249b528cefcSMark Murray if (args[i].long_name && args[i].short_name) 250b528cefcSMark Murray len += 2; /* ", " */ 251b528cefcSMark Murray max_len = max(max_len, len); 252b528cefcSMark Murray } 253b528cefcSMark Murray if (extra_string) { 254b528cefcSMark Murray col = check_column(stderr, col, strlen(extra_string) + 1, columns); 255b528cefcSMark Murray fprintf (stderr, " %s\n", extra_string); 256b528cefcSMark Murray } else 257b528cefcSMark Murray fprintf (stderr, "\n"); 258b528cefcSMark Murray for (i = 0; i < num_args; ++i) { 259b528cefcSMark Murray if (args[i].help) { 260b528cefcSMark Murray size_t count = 0; 261b528cefcSMark Murray 262b528cefcSMark Murray if (args[i].short_name) { 263b528cefcSMark Murray count += fprintf (stderr, "-%c", args[i].short_name); 264b528cefcSMark Murray print_arg (buf, sizeof(buf), 0, 0, &args[i]); 265b528cefcSMark Murray count += fprintf(stderr, "%s", buf); 266b528cefcSMark Murray } 267b528cefcSMark Murray if (args[i].short_name && args[i].long_name) 268b528cefcSMark Murray count += fprintf (stderr, ", "); 269b528cefcSMark Murray if (args[i].long_name) { 270b528cefcSMark Murray count += fprintf (stderr, "--"); 271b528cefcSMark Murray if (args[i].type == arg_negative_flag) 272b528cefcSMark Murray count += fprintf (stderr, "no-"); 273b528cefcSMark Murray count += fprintf (stderr, "%s", args[i].long_name); 274b528cefcSMark Murray print_arg (buf, sizeof(buf), 0, 1, &args[i]); 275b528cefcSMark Murray count += fprintf(stderr, "%s", buf); 276b528cefcSMark Murray } 277b528cefcSMark Murray while(count++ <= max_len) 278b528cefcSMark Murray putc (' ', stderr); 279b528cefcSMark Murray fprintf (stderr, "%s\n", args[i].help); 280b528cefcSMark Murray } 281b528cefcSMark Murray } 282b528cefcSMark Murray } 283b528cefcSMark Murray 284b528cefcSMark Murray static void 285b528cefcSMark Murray add_string(getarg_strings *s, char *value) 286b528cefcSMark Murray { 287b528cefcSMark Murray s->strings = realloc(s->strings, (s->num_strings + 1) * sizeof(*s->strings)); 288b528cefcSMark Murray s->strings[s->num_strings] = value; 289b528cefcSMark Murray s->num_strings++; 290b528cefcSMark Murray } 291b528cefcSMark Murray 292b528cefcSMark Murray static int 293b528cefcSMark Murray arg_match_long(struct getargs *args, size_t num_args, 294b528cefcSMark Murray char *argv, int argc, char **rargv, int *optind) 295b528cefcSMark Murray { 296b528cefcSMark Murray int i; 297b528cefcSMark Murray char *optarg = NULL; 298b528cefcSMark Murray int negate = 0; 299b528cefcSMark Murray int partial_match = 0; 300b528cefcSMark Murray struct getargs *partial = NULL; 301b528cefcSMark Murray struct getargs *current = NULL; 302b528cefcSMark Murray int argv_len; 303b528cefcSMark Murray char *p; 304b528cefcSMark Murray 305b528cefcSMark Murray argv_len = strlen(argv); 306b528cefcSMark Murray p = strchr (argv, '='); 307b528cefcSMark Murray if (p != NULL) 308b528cefcSMark Murray argv_len = p - argv; 309b528cefcSMark Murray 310b528cefcSMark Murray for (i = 0; i < num_args; ++i) { 311b528cefcSMark Murray if(args[i].long_name) { 312b528cefcSMark Murray int len = strlen(args[i].long_name); 313b528cefcSMark Murray char *p = argv; 314b528cefcSMark Murray int p_len = argv_len; 315b528cefcSMark Murray negate = 0; 316b528cefcSMark Murray 317b528cefcSMark Murray for (;;) { 318b528cefcSMark Murray if (strncmp (args[i].long_name, p, p_len) == 0) { 319b528cefcSMark Murray if(p_len == len) 320b528cefcSMark Murray current = &args[i]; 321b528cefcSMark Murray else { 322b528cefcSMark Murray ++partial_match; 323b528cefcSMark Murray partial = &args[i]; 324b528cefcSMark Murray } 325b528cefcSMark Murray optarg = p + p_len; 326b528cefcSMark Murray } else if (ISFLAG(args[i]) && strncmp (p, "no-", 3) == 0) { 327b528cefcSMark Murray negate = !negate; 328b528cefcSMark Murray p += 3; 329b528cefcSMark Murray p_len -= 3; 330b528cefcSMark Murray continue; 331b528cefcSMark Murray } 332b528cefcSMark Murray break; 333b528cefcSMark Murray } 334b528cefcSMark Murray if (current) 335b528cefcSMark Murray break; 336b528cefcSMark Murray } 337b528cefcSMark Murray } 338b528cefcSMark Murray if (current == NULL) { 339b528cefcSMark Murray if (partial_match == 1) 340b528cefcSMark Murray current = partial; 341b528cefcSMark Murray else 342b528cefcSMark Murray return ARG_ERR_NO_MATCH; 343b528cefcSMark Murray } 344b528cefcSMark Murray 345b528cefcSMark Murray if(*optarg == '\0' 346b528cefcSMark Murray && !ISFLAG(*current) 347b528cefcSMark Murray && current->type != arg_collect 348b528cefcSMark Murray && current->type != arg_counter) 349b528cefcSMark Murray return ARG_ERR_NO_MATCH; 350b528cefcSMark Murray switch(current->type){ 351b528cefcSMark Murray case arg_integer: 352b528cefcSMark Murray { 353b528cefcSMark Murray int tmp; 354b528cefcSMark Murray if(sscanf(optarg + 1, "%d", &tmp) != 1) 355b528cefcSMark Murray return ARG_ERR_BAD_ARG; 356b528cefcSMark Murray *(int*)current->value = tmp; 357b528cefcSMark Murray return 0; 358b528cefcSMark Murray } 359b528cefcSMark Murray case arg_string: 360b528cefcSMark Murray { 361b528cefcSMark Murray *(char**)current->value = optarg + 1; 362b528cefcSMark Murray return 0; 363b528cefcSMark Murray } 364b528cefcSMark Murray case arg_strings: 365b528cefcSMark Murray { 366b528cefcSMark Murray add_string((getarg_strings*)current->value, optarg + 1); 367b528cefcSMark Murray return 0; 368b528cefcSMark Murray } 369b528cefcSMark Murray case arg_flag: 370b528cefcSMark Murray case arg_negative_flag: 371b528cefcSMark Murray { 372b528cefcSMark Murray int *flag = current->value; 373b528cefcSMark Murray if(*optarg == '\0' || 374b528cefcSMark Murray strcmp(optarg + 1, "yes") == 0 || 375b528cefcSMark Murray strcmp(optarg + 1, "true") == 0){ 376b528cefcSMark Murray *flag = !negate; 377b528cefcSMark Murray return 0; 378b528cefcSMark Murray } else if (*optarg && strcmp(optarg + 1, "maybe") == 0) { 379b528cefcSMark Murray *flag = rand() & 1; 380b528cefcSMark Murray } else { 381b528cefcSMark Murray *flag = negate; 382b528cefcSMark Murray return 0; 383b528cefcSMark Murray } 384b528cefcSMark Murray return ARG_ERR_BAD_ARG; 385b528cefcSMark Murray } 386b528cefcSMark Murray case arg_counter : 387b528cefcSMark Murray { 388b528cefcSMark Murray int val; 389b528cefcSMark Murray 390b528cefcSMark Murray if (*optarg == '\0') 391b528cefcSMark Murray val = 1; 392b528cefcSMark Murray else { 393b528cefcSMark Murray char *endstr; 394b528cefcSMark Murray 395b528cefcSMark Murray val = strtol (optarg, &endstr, 0); 396b528cefcSMark Murray if (endstr == optarg) 397b528cefcSMark Murray return ARG_ERR_BAD_ARG; 398b528cefcSMark Murray } 399b528cefcSMark Murray *(int *)current->value += val; 400b528cefcSMark Murray return 0; 401b528cefcSMark Murray } 402b528cefcSMark Murray case arg_double: 403b528cefcSMark Murray { 404b528cefcSMark Murray double tmp; 405b528cefcSMark Murray if(sscanf(optarg + 1, "%lf", &tmp) != 1) 406b528cefcSMark Murray return ARG_ERR_BAD_ARG; 407b528cefcSMark Murray *(double*)current->value = tmp; 408b528cefcSMark Murray return 0; 409b528cefcSMark Murray } 410b528cefcSMark Murray case arg_collect:{ 411b528cefcSMark Murray struct getarg_collect_info *c = current->value; 412b528cefcSMark Murray int o = argv - rargv[*optind]; 413b528cefcSMark Murray return (*c->func)(FALSE, argc, rargv, optind, &o, c->data); 414b528cefcSMark Murray } 415b528cefcSMark Murray 416b528cefcSMark Murray default: 417b528cefcSMark Murray abort (); 418b528cefcSMark Murray } 419b528cefcSMark Murray } 420b528cefcSMark Murray 421b528cefcSMark Murray static int 422b528cefcSMark Murray arg_match_short (struct getargs *args, size_t num_args, 423b528cefcSMark Murray char *argv, int argc, char **rargv, int *optind) 424b528cefcSMark Murray { 425b528cefcSMark Murray int j, k; 426b528cefcSMark Murray 427b528cefcSMark Murray for(j = 1; j > 0 && j < strlen(rargv[*optind]); j++) { 428b528cefcSMark Murray for(k = 0; k < num_args; k++) { 429b528cefcSMark Murray char *optarg; 430b528cefcSMark Murray 431b528cefcSMark Murray if(args[k].short_name == 0) 432b528cefcSMark Murray continue; 433b528cefcSMark Murray if(argv[j] == args[k].short_name) { 434b528cefcSMark Murray if(args[k].type == arg_flag) { 435b528cefcSMark Murray *(int*)args[k].value = 1; 436b528cefcSMark Murray break; 437b528cefcSMark Murray } 438b528cefcSMark Murray if(args[k].type == arg_negative_flag) { 439b528cefcSMark Murray *(int*)args[k].value = 0; 440b528cefcSMark Murray break; 441b528cefcSMark Murray } 442b528cefcSMark Murray if(args[k].type == arg_counter) { 443b528cefcSMark Murray ++*(int *)args[k].value; 444b528cefcSMark Murray break; 445b528cefcSMark Murray } 446b528cefcSMark Murray if(args[k].type == arg_collect) { 447b528cefcSMark Murray struct getarg_collect_info *c = args[k].value; 448b528cefcSMark Murray 449b528cefcSMark Murray if((*c->func)(TRUE, argc, rargv, optind, &j, c->data)) 450b528cefcSMark Murray return ARG_ERR_BAD_ARG; 451b528cefcSMark Murray break; 452b528cefcSMark Murray } 453b528cefcSMark Murray 454b528cefcSMark Murray if(argv[j + 1]) 455b528cefcSMark Murray optarg = &argv[j + 1]; 456b528cefcSMark Murray else { 457b528cefcSMark Murray ++*optind; 458b528cefcSMark Murray optarg = rargv[*optind]; 459b528cefcSMark Murray } 460b528cefcSMark Murray if(optarg == NULL) 461b528cefcSMark Murray return ARG_ERR_NO_ARG; 462b528cefcSMark Murray if(args[k].type == arg_integer) { 463b528cefcSMark Murray int tmp; 464b528cefcSMark Murray if(sscanf(optarg, "%d", &tmp) != 1) 465b528cefcSMark Murray return ARG_ERR_BAD_ARG; 466b528cefcSMark Murray *(int*)args[k].value = tmp; 467b528cefcSMark Murray return 0; 468b528cefcSMark Murray } else if(args[k].type == arg_string) { 469b528cefcSMark Murray *(char**)args[k].value = optarg; 470b528cefcSMark Murray return 0; 471b528cefcSMark Murray } else if(args[k].type == arg_strings) { 472b528cefcSMark Murray add_string((getarg_strings*)args[k].value, optarg); 473b528cefcSMark Murray return 0; 474b528cefcSMark Murray } else if(args[k].type == arg_double) { 475b528cefcSMark Murray double tmp; 476b528cefcSMark Murray if(sscanf(optarg, "%lf", &tmp) != 1) 477b528cefcSMark Murray return ARG_ERR_BAD_ARG; 478b528cefcSMark Murray *(double*)args[k].value = tmp; 479b528cefcSMark Murray return 0; 480b528cefcSMark Murray } 481b528cefcSMark Murray return ARG_ERR_BAD_ARG; 482b528cefcSMark Murray } 483b528cefcSMark Murray } 484b528cefcSMark Murray if (k == num_args) 485b528cefcSMark Murray return ARG_ERR_NO_MATCH; 486b528cefcSMark Murray } 487b528cefcSMark Murray return 0; 488b528cefcSMark Murray } 489b528cefcSMark Murray 490b528cefcSMark Murray int 491b528cefcSMark Murray getarg(struct getargs *args, size_t num_args, 492b528cefcSMark Murray int argc, char **argv, int *optind) 493b528cefcSMark Murray { 494b528cefcSMark Murray int i; 495b528cefcSMark Murray int ret = 0; 496b528cefcSMark Murray 497b528cefcSMark Murray srand (time(NULL)); 498b528cefcSMark Murray (*optind)++; 499b528cefcSMark Murray for(i = *optind; i < argc; i++) { 500b528cefcSMark Murray if(argv[i][0] != '-') 501b528cefcSMark Murray break; 502b528cefcSMark Murray if(argv[i][1] == '-'){ 503b528cefcSMark Murray if(argv[i][2] == 0){ 504b528cefcSMark Murray i++; 505b528cefcSMark Murray break; 506b528cefcSMark Murray } 507b528cefcSMark Murray ret = arg_match_long (args, num_args, argv[i] + 2, 508b528cefcSMark Murray argc, argv, &i); 509b528cefcSMark Murray } else { 510b528cefcSMark Murray ret = arg_match_short (args, num_args, argv[i], 511b528cefcSMark Murray argc, argv, &i); 512b528cefcSMark Murray } 513b528cefcSMark Murray if(ret) 514b528cefcSMark Murray break; 515b528cefcSMark Murray } 516b528cefcSMark Murray *optind = i; 517b528cefcSMark Murray return ret; 518b528cefcSMark Murray } 519b528cefcSMark Murray 520b528cefcSMark Murray #if TEST 521b528cefcSMark Murray int foo_flag = 2; 522b528cefcSMark Murray int flag1 = 0; 523b528cefcSMark Murray int flag2 = 0; 524b528cefcSMark Murray int bar_int; 525b528cefcSMark Murray char *baz_string; 526b528cefcSMark Murray 527b528cefcSMark Murray struct getargs args[] = { 528b528cefcSMark Murray { NULL, '1', arg_flag, &flag1, "one", NULL }, 529b528cefcSMark Murray { NULL, '2', arg_flag, &flag2, "two", NULL }, 530b528cefcSMark Murray { "foo", 'f', arg_negative_flag, &foo_flag, "foo", NULL }, 531b528cefcSMark Murray { "bar", 'b', arg_integer, &bar_int, "bar", "seconds"}, 532b528cefcSMark Murray { "baz", 'x', arg_string, &baz_string, "baz", "name" }, 533b528cefcSMark Murray }; 534b528cefcSMark Murray 535b528cefcSMark Murray int main(int argc, char **argv) 536b528cefcSMark Murray { 537b528cefcSMark Murray int optind = 0; 538b528cefcSMark Murray while(getarg(args, 5, argc, argv, &optind)) 539b528cefcSMark Murray printf("Bad arg: %s\n", argv[optind]); 540b528cefcSMark Murray printf("flag1 = %d\n", flag1); 541b528cefcSMark Murray printf("flag2 = %d\n", flag2); 542b528cefcSMark Murray printf("foo_flag = %d\n", foo_flag); 543b528cefcSMark Murray printf("bar_int = %d\n", bar_int); 544b528cefcSMark Murray printf("baz_flag = %s\n", baz_string); 545b528cefcSMark Murray arg_printusage (args, 5, argv[0], "nothing here"); 546b528cefcSMark Murray } 547b528cefcSMark Murray #endif 548