getarg.c
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:15k
源码类别:

MySQL数据库

开发平台:

Visual C++

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