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