This source file includes following definitions.
- find_option
- pmix_cmd_line_add
- pmix_cmd_line_make_opt_mca
- pmix_cmd_line_make_opt3
- pmix_cmd_line_parse
- pmix_cmd_line_get_usage_msg
- pmix_cmd_line_is_taken
- pmix_cmd_line_get_ninsts
- pmix_cmd_line_get_param
- pmix_cmd_line_get_argc
- pmix_cmd_line_get_argv
- pmix_cmd_line_get_tail
- option_constructor
- option_destructor
- param_constructor
- param_destructor
- cmd_line_constructor
- cmd_line_destructor
- make_opt
- free_parse_results
- split_shorts
- find_option
- set_dest
- fill
- qsort_callback
- get_help_otype
- build_parsable
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 
  14 
  15 
  16 
  17 
  18 
  19 
  20 
  21 
  22 
  23 
  24 
  25 
  26 
  27 #include "pmix_config.h"
  28 
  29 #include <stdio.h>
  30 #include <string.h>
  31 #include <ctype.h>
  32 
  33 #include "src/class/pmix_object.h"
  34 #include "src/class/pmix_list.h"
  35 #include "src/threads/mutex.h"
  36 #include "src/util/argv.h"
  37 #include "src/util/cmd_line.h"
  38 #include "src/util/output.h"
  39 #include "src/util/pmix_environ.h"
  40 
  41 #include "src/mca/base/pmix_mca_base_var.h"
  42 #include "pmix_common.h"
  43 
  44 
  45 
  46 
  47 
  48 
  49 
  50 
  51 #define PARAM_WIDTH 25
  52 
  53 
  54 
  55 #define MAX_WIDTH 76
  56 
  57 
  58 
  59 
  60 struct pmix_cmd_line_option_t {
  61     pmix_list_item_t super;
  62 
  63     char clo_short_name;
  64     char *clo_single_dash_name;
  65     char *clo_long_name;
  66 
  67     int clo_num_params;
  68     char *clo_description;
  69 
  70     pmix_cmd_line_type_t clo_type;
  71     char *clo_mca_param_env_var;
  72     void *clo_variable_dest;
  73     bool clo_variable_set;
  74     pmix_cmd_line_otype_t clo_otype;
  75 };
  76 typedef struct pmix_cmd_line_option_t pmix_cmd_line_option_t;
  77 static void option_constructor(pmix_cmd_line_option_t *cmd);
  78 static void option_destructor(pmix_cmd_line_option_t *cmd);
  79 
  80 PMIX_CLASS_INSTANCE(pmix_cmd_line_option_t,
  81                     pmix_list_item_t,
  82                     option_constructor, option_destructor);
  83 
  84 
  85 
  86 
  87 struct pmix_cmd_line_param_t {
  88     pmix_list_item_t super;
  89 
  90     
  91 
  92 
  93 
  94     char *clp_arg;
  95 
  96     
  97 
  98 
  99     pmix_cmd_line_option_t *clp_option;
 100 
 101     
 102 
 103 
 104 
 105     int clp_argc;
 106     char **clp_argv;
 107 };
 108 typedef struct pmix_cmd_line_param_t pmix_cmd_line_param_t;
 109 static void param_constructor(pmix_cmd_line_param_t *cmd);
 110 static void param_destructor(pmix_cmd_line_param_t *cmd);
 111 PMIX_CLASS_INSTANCE(pmix_cmd_line_param_t,
 112                     pmix_list_item_t,
 113                     param_constructor, param_destructor);
 114 
 115 
 116 
 117 
 118 static void cmd_line_constructor(pmix_cmd_line_t *cmd);
 119 static void cmd_line_destructor(pmix_cmd_line_t *cmd);
 120 PMIX_CLASS_INSTANCE(pmix_cmd_line_t,
 121                     pmix_object_t,
 122                     cmd_line_constructor,
 123                     cmd_line_destructor);
 124 
 125 
 126 
 127 
 128 static char special_empty_token[] = {
 129     1, 2, 3, 4, 5, 6, 7, 8, 9, 10, '\0'
 130 };
 131 
 132 
 133 
 134 
 135 static int make_opt(pmix_cmd_line_t *cmd, pmix_cmd_line_init_t *e);
 136 static void free_parse_results(pmix_cmd_line_t *cmd);
 137 static int split_shorts(pmix_cmd_line_t *cmd,
 138                         char *token, char **args,
 139                         int *output_argc, char ***output_argv,
 140                         int *num_args_used, bool ignore_unknown);
 141 static pmix_cmd_line_option_t *find_option(pmix_cmd_line_t *cmd,
 142                                            const char *option_name) __pmix_attribute_nonnull__(1) __pmix_attribute_nonnull__(2);
 143 static int set_dest(pmix_cmd_line_option_t *option, char *sval);
 144 static void fill(const pmix_cmd_line_option_t *a, char result[3][BUFSIZ]);
 145 static int qsort_callback(const void *a, const void *b);
 146 static pmix_cmd_line_otype_t get_help_otype(pmix_cmd_line_t *cmd);
 147 static char *build_parsable(pmix_cmd_line_option_t *option);
 148 
 149 
 150 
 151 
 152 
 153 int pmix_cmd_line_create(pmix_cmd_line_t *cmd,
 154                          pmix_cmd_line_init_t *table)
 155 {
 156     int ret = PMIX_SUCCESS;
 157 
 158     
 159 
 160     if (NULL == cmd) {
 161         return PMIX_ERR_BAD_PARAM;
 162     }
 163     PMIX_CONSTRUCT(cmd, pmix_cmd_line_t);
 164 
 165     if (NULL != table) {
 166         ret = pmix_cmd_line_add(cmd, table);
 167     }
 168     return ret;
 169 }
 170 
 171 
 172 int pmix_cmd_line_add(pmix_cmd_line_t *cmd,
 173                       pmix_cmd_line_init_t *table)
 174 {
 175     int i, ret;
 176 
 177     
 178     if (NULL == table) {
 179         return PMIX_SUCCESS;
 180     }
 181 
 182     
 183 
 184     for (i = 0; ; ++i) {
 185         
 186         if ('\0' == table[i].ocl_cmd_short_name &&
 187             NULL == table[i].ocl_cmd_single_dash_name &&
 188             NULL == table[i].ocl_cmd_long_name) {
 189             break;
 190         }
 191 
 192         
 193         ret = make_opt(cmd, &table[i]);
 194         if (PMIX_SUCCESS != ret) {
 195             return ret;
 196         }
 197     }
 198 
 199     return PMIX_SUCCESS;
 200 }
 201 
 202 
 203 
 204 int pmix_cmd_line_make_opt_mca(pmix_cmd_line_t *cmd,
 205                                pmix_cmd_line_init_t entry)
 206 {
 207     
 208     if ('\0' == entry.ocl_cmd_short_name &&
 209         NULL == entry.ocl_cmd_single_dash_name &&
 210         NULL == entry.ocl_cmd_long_name) {
 211         return PMIX_SUCCESS;
 212     }
 213 
 214     return make_opt(cmd, &entry);
 215 }
 216 
 217 
 218 
 219 
 220 
 221 int pmix_cmd_line_make_opt3(pmix_cmd_line_t *cmd, char short_name,
 222                             const char *sd_name, const char *long_name,
 223                             int num_params, const char *desc)
 224 {
 225     pmix_cmd_line_init_t e;
 226 
 227     e.ocl_mca_param_name = NULL;
 228 
 229     e.ocl_cmd_short_name = short_name;
 230     e.ocl_cmd_single_dash_name = sd_name;
 231     e.ocl_cmd_long_name = long_name;
 232 
 233     e.ocl_num_params = num_params;
 234 
 235     e.ocl_variable_dest = NULL;
 236     e.ocl_variable_type = PMIX_CMD_LINE_TYPE_NULL;
 237 
 238     e.ocl_description = desc;
 239 
 240     return make_opt(cmd, &e);
 241 }
 242 
 243 
 244 
 245 
 246 
 247 
 248 int pmix_cmd_line_parse(pmix_cmd_line_t *cmd, bool ignore_unknown, bool ignore_unknown_option,
 249                         int argc, char **argv)
 250 {
 251     int i, j, orig, ret;
 252     pmix_cmd_line_option_t *option;
 253     pmix_cmd_line_param_t *param;
 254     bool is_unknown_option;
 255     bool is_unknown_token;
 256     bool is_option;
 257     char **shortsv;
 258     int shortsc;
 259     int num_args_used;
 260     bool have_help_option = false;
 261     bool printed_error = false;
 262     bool help_without_arg = false;
 263 
 264     
 265 
 266     if (0 == argc || NULL == argv) {
 267         return PMIX_SUCCESS;
 268     }
 269 
 270     
 271 
 272     pmix_mutex_lock(&cmd->lcl_mutex);
 273 
 274     
 275 
 276     free_parse_results(cmd);
 277 
 278     
 279 
 280     cmd->lcl_argc = argc;
 281     cmd->lcl_argv = pmix_argv_copy(argv);
 282 
 283     
 284 
 285     option = find_option(cmd, "help");
 286     if (NULL != option) {
 287         have_help_option = true;
 288     }
 289 
 290     
 291 
 292 
 293 
 294     param = NULL;
 295     option = NULL;
 296     for (i = 1; i < cmd->lcl_argc; ) {
 297         is_unknown_option = false;
 298         is_unknown_token = false;
 299         is_option = false;
 300 
 301         
 302 
 303 
 304 
 305         if (0 == strcmp(cmd->lcl_argv[i], "--")) {
 306             ++i;
 307             while (i < cmd->lcl_argc) {
 308                 pmix_argv_append(&cmd->lcl_tail_argc, &cmd->lcl_tail_argv,
 309                                  cmd->lcl_argv[i]);
 310                 ++i;
 311             }
 312 
 313             break;
 314         }
 315 
 316         
 317 
 318 
 319 
 320         else if ('-' != cmd->lcl_argv[i][0]) {
 321             is_unknown_token = true;
 322         }
 323 
 324         
 325 
 326         else if (0 == strncmp(cmd->lcl_argv[i], "--", 2)) {
 327             is_option = true;
 328             option = find_option(cmd, cmd->lcl_argv[i] + 2);
 329         }
 330 
 331         
 332 
 333         else {
 334             option = find_option(cmd, cmd->lcl_argv[i] + 1);
 335 
 336             
 337 
 338 
 339 
 340 
 341 
 342 
 343             if (NULL == option) {
 344                 shortsv = NULL;
 345                 shortsc = 0;
 346                 ret = split_shorts(cmd, cmd->lcl_argv[i] + 1,
 347                                    &(cmd->lcl_argv[i + 1]),
 348                                    &shortsc, &shortsv,
 349                                    &num_args_used, ignore_unknown);
 350                 if (PMIX_SUCCESS == ret) {
 351                     option = find_option(cmd, shortsv[0] + 1);
 352 
 353                     if (NULL != option) {
 354                         pmix_argv_delete(&cmd->lcl_argc,
 355                                          &cmd->lcl_argv, i,
 356                                          1 + num_args_used);
 357                         pmix_argv_insert(&cmd->lcl_argv, i, shortsv);
 358                         cmd->lcl_argc = pmix_argv_count(cmd->lcl_argv);
 359                     } else {
 360                         is_unknown_option = true;
 361                     }
 362                     pmix_argv_free(shortsv);
 363                 } else {
 364                     is_unknown_option = true;
 365                 }
 366             }
 367 
 368             if (NULL != option) {
 369                 is_option = true;
 370             }
 371         }
 372 
 373         
 374 
 375         if (is_option) {
 376             if (NULL == option) {
 377                 is_unknown_option = true;
 378             } else {
 379                 is_unknown_option = false;
 380                 orig = i;
 381                 ++i;
 382 
 383                 
 384 
 385 
 386 
 387 
 388 
 389                 param = PMIX_NEW(pmix_cmd_line_param_t);
 390                 if (NULL == param) {
 391                     pmix_mutex_unlock(&cmd->lcl_mutex);
 392                     return PMIX_ERR_OUT_OF_RESOURCE;
 393                 }
 394                 param->clp_arg = cmd->lcl_argv[i];
 395                 param->clp_option = option;
 396 
 397                 
 398 
 399 
 400 
 401                 for (j = 0; j < option->clo_num_params; ++j, ++i) {
 402                     
 403 
 404                     if (i >= cmd->lcl_argc) {
 405                     
 406                         if((NULL != option->clo_single_dash_name &&
 407                            0 == strcmp(option->clo_single_dash_name, "h")) ||
 408                            (NULL != option->clo_long_name &&
 409                            0 == strcmp(option->clo_long_name, "help"))) {
 410                             help_without_arg = true;
 411                             continue;
 412                         }
 413                         fprintf(stderr, "%s: Error: option \"%s\" did not "
 414                                 "have enough parameters (%d)\n",
 415                                 cmd->lcl_argv[0],
 416                                 cmd->lcl_argv[orig],
 417                                 option->clo_num_params);
 418                         if (have_help_option) {
 419                             fprintf(stderr, "Type '%s --help' for usage.\n",
 420                                     cmd->lcl_argv[0]);
 421                         }
 422                         PMIX_RELEASE(param);
 423                         printed_error = true;
 424                         goto error;
 425                     } else {
 426                         if (0 == strcmp(cmd->lcl_argv[i],
 427                                         special_empty_token)) {
 428                             fprintf(stderr, "%s: Error: option \"%s\" did not "
 429                                     "have enough parameters (%d)\n",
 430                                     cmd->lcl_argv[0],
 431                                     cmd->lcl_argv[orig],
 432                                     option->clo_num_params);
 433                             if (have_help_option) {
 434                                 fprintf(stderr, "Type '%s --help' for usage.\n",
 435                                         cmd->lcl_argv[0]);
 436                             }
 437                             if (NULL != param->clp_argv) {
 438                                 pmix_argv_free(param->clp_argv);
 439                             }
 440                             PMIX_RELEASE(param);
 441                             printed_error = true;
 442                             goto error;
 443                         }
 444 
 445                         
 446 
 447                         else {
 448                             
 449 
 450                             pmix_argv_append(¶m->clp_argc,
 451                                              ¶m->clp_argv,
 452                                              cmd->lcl_argv[i]);
 453 
 454                             
 455 
 456 
 457                             if (0 == j &&
 458                                 (NULL != option->clo_mca_param_env_var ||
 459                                  NULL != option->clo_variable_dest)) {
 460                                 if (PMIX_SUCCESS != (ret = set_dest(option, cmd->lcl_argv[i]))) {
 461                                     pmix_mutex_unlock(&cmd->lcl_mutex);
 462                                     return ret;
 463                                 }
 464                             }
 465                         }
 466                     }
 467                 }
 468 
 469                 
 470 
 471 
 472 
 473                 if (0 == option->clo_num_params || help_without_arg) {
 474                     if (PMIX_SUCCESS != (ret = set_dest(option, "1"))) {
 475                         pmix_mutex_unlock(&cmd->lcl_mutex);
 476                         return ret;
 477                     }
 478                 }
 479 
 480                 
 481 
 482 
 483                 if (NULL != param) {
 484                     pmix_list_append(&cmd->lcl_params, ¶m->super);
 485                 }
 486             }
 487         }
 488 
 489         
 490 
 491 
 492 
 493         if (is_unknown_option || is_unknown_token) {
 494             if (!ignore_unknown || (is_unknown_option && !ignore_unknown_option)) {
 495                 fprintf(stderr, "%s: Error: unknown option \"%s\"\n",
 496                         cmd->lcl_argv[0], cmd->lcl_argv[i]);
 497                 printed_error = true;
 498                 if (have_help_option) {
 499                     fprintf(stderr, "Type '%s --help' for usage.\n",
 500                             cmd->lcl_argv[0]);
 501                 }
 502             }
 503         error:
 504             while (i < cmd->lcl_argc) {
 505                 pmix_argv_append(&cmd->lcl_tail_argc, &cmd->lcl_tail_argv,
 506                                  cmd->lcl_argv[i]);
 507                 ++i;
 508             }
 509 
 510             
 511         }
 512     }
 513 
 514     
 515 
 516     pmix_mutex_unlock(&cmd->lcl_mutex);
 517 
 518     
 519     if (printed_error) {
 520         return PMIX_ERR_SILENT;
 521     }
 522 
 523     return PMIX_SUCCESS;
 524 }
 525 
 526 
 527 
 528 
 529 
 530 char *pmix_cmd_line_get_usage_msg(pmix_cmd_line_t *cmd)
 531 {
 532     size_t i, len;
 533     int argc;
 534     size_t j;
 535     char **argv;
 536     char *ret, temp[MAX_WIDTH * 2], line[MAX_WIDTH * 2];
 537     char *start, *desc, *ptr;
 538     pmix_list_item_t *item;
 539     pmix_cmd_line_option_t *option, **sorted;
 540     pmix_cmd_line_otype_t otype;
 541 
 542     
 543 
 544     pmix_mutex_lock(&cmd->lcl_mutex);
 545 
 546     
 547 
 548     argc = 0;
 549     argv = NULL;
 550     ret = NULL;
 551 
 552     
 553 
 554     sorted = (pmix_cmd_line_option_t**)malloc(sizeof(pmix_cmd_line_option_t *) *
 555                                          pmix_list_get_size(&cmd->lcl_options));
 556     if (NULL == sorted) {
 557         pmix_mutex_unlock(&cmd->lcl_mutex);
 558         return NULL;
 559     }
 560     i = 0;
 561     PMIX_LIST_FOREACH(item, &cmd->lcl_options, pmix_list_item_t) {
 562         sorted[i++] = (pmix_cmd_line_option_t *) item;
 563     }
 564     qsort(sorted, i, sizeof(pmix_cmd_line_option_t*), qsort_callback);
 565 
 566     
 567 
 568     otype = get_help_otype(cmd);
 569 
 570     
 571 
 572     for (j = 0; j < pmix_list_get_size(&cmd->lcl_options); ++j) {
 573         option = sorted[j];
 574         if(otype == PMIX_CMD_LINE_OTYPE_PARSABLE) {
 575             ret = build_parsable(option);
 576             pmix_argv_append(&argc, &argv, ret);
 577             free(ret);
 578             ret = NULL;
 579         } else if(otype == PMIX_CMD_LINE_OTYPE_NULL || option->clo_otype == otype) {
 580             if (NULL != option->clo_description) {
 581                 bool filled = false;
 582 
 583                 
 584 
 585                 memset(line, 0, sizeof(line));
 586                 if ('\0' != option->clo_short_name) {
 587                     line[0] = '-';
 588                     line[1] = option->clo_short_name;
 589                     filled = true;
 590                 } else {
 591                     line[0] = ' ';
 592                     line[1] = ' ';
 593                 }
 594                 if (NULL != option->clo_single_dash_name) {
 595                     line[2] = (filled) ? '|' : ' ';
 596                     strncat(line, "-", sizeof(line) - 1);
 597                     strncat(line, option->clo_single_dash_name, sizeof(line) - 1);
 598                     filled = true;
 599                 }
 600                 if (NULL != option->clo_long_name) {
 601                     if (filled) {
 602                         strncat(line, "|", sizeof(line) - 1);
 603                     } else {
 604                         strncat(line, " ", sizeof(line) - 1);
 605                     }
 606                     strncat(line, "--", sizeof(line) - 1);
 607                     strncat(line, option->clo_long_name, sizeof(line) - 1);
 608                 }
 609                 strncat(line, " ", sizeof(line) - 1);
 610                 for (i = 0; (int)i < option->clo_num_params; ++i) {
 611                     len = sizeof(temp);
 612                     snprintf(temp, len, "<arg%d> ", (int)i);
 613                     strncat(line, temp, sizeof(line) - 1);
 614                 }
 615                 if (option->clo_num_params > 0) {
 616                     strncat(line, " ", sizeof(line) - 1);
 617                 }
 618 
 619                 
 620 
 621 
 622 
 623                 if (strlen(line) > PARAM_WIDTH) {
 624                     pmix_argv_append(&argc, &argv, line);
 625 
 626                     
 627 
 628 
 629 
 630                     memset(line, ' ', PARAM_WIDTH);
 631                     line[PARAM_WIDTH] = '\0';
 632                 } else {
 633 
 634                     
 635 
 636 
 637                     for (i = strlen(line); i < PARAM_WIDTH; ++i) {
 638                         line[i] = ' ';
 639                     }
 640                     line[i] = '\0';
 641                 }
 642 
 643                 
 644 
 645 
 646 
 647 
 648 
 649 
 650                 desc = strdup(option->clo_description);
 651                 if (NULL == desc) {
 652                     free(sorted);
 653                     pmix_mutex_unlock(&cmd->lcl_mutex);
 654                     return strdup("");
 655                 }
 656                 start = desc;
 657                 len = strlen(desc);
 658                 do {
 659 
 660                     
 661 
 662                     while (isspace(*start) && start < desc + len) {
 663                         ++start;
 664                     }
 665                     if (start >= desc + len) {
 666                         break;
 667                     }
 668 
 669                     
 670 
 671                     if (strlen(start) < (MAX_WIDTH - PARAM_WIDTH)) {
 672                         strncat(line, start, sizeof(line) - 1);
 673                         pmix_argv_append(&argc, &argv, line);
 674                         break;
 675                     }
 676 
 677                     
 678 
 679 
 680 
 681                     for (ptr = start + (MAX_WIDTH - PARAM_WIDTH);
 682                          ptr > start; --ptr) {
 683                         if (isspace(*ptr)) {
 684                             *ptr = '\0';
 685                             strncat(line, start, sizeof(line) - 1);
 686                             pmix_argv_append(&argc, &argv, line);
 687 
 688                             start = ptr + 1;
 689                             memset(line, ' ', PARAM_WIDTH);
 690                             line[PARAM_WIDTH] = '\0';
 691                             break;
 692                         }
 693                     }
 694 
 695                     
 696 
 697 
 698 
 699                     if (ptr == start) {
 700                         for (ptr = start + (MAX_WIDTH - PARAM_WIDTH);
 701                              ptr < start + len; ++ptr) {
 702                             if (isspace(*ptr)) {
 703                                 *ptr = '\0';
 704 
 705                                 strncat(line, start, sizeof(line) - 1);
 706                                 pmix_argv_append(&argc, &argv, line);
 707 
 708                                 start = ptr + 1;
 709                                 memset(line, ' ', PARAM_WIDTH);
 710                                 line[PARAM_WIDTH] = '\0';
 711                                 break;
 712                             }
 713                         }
 714 
 715                         
 716 
 717 
 718                         if (ptr >= start + len) {
 719                             strncat(line, start, sizeof(line) - 1);
 720                             pmix_argv_append(&argc, &argv, line);
 721                             start = desc + len + 1;
 722                         }
 723                     }
 724                 } while (start < desc + len);
 725                 free(desc);
 726             }
 727         }
 728     }
 729     if (NULL != argv) {
 730         ret = pmix_argv_join(argv, '\n');
 731         pmix_argv_free(argv);
 732     } else {
 733         ret = strdup("");
 734     }
 735     free(sorted);
 736 
 737     
 738     pmix_mutex_unlock(&cmd->lcl_mutex);
 739 
 740     
 741     return ret;
 742 }
 743 
 744 
 745 
 746 
 747 
 748 bool pmix_cmd_line_is_taken(pmix_cmd_line_t *cmd, const char *opt)
 749 {
 750     return (pmix_cmd_line_get_ninsts(cmd, opt) > 0);
 751 }
 752 
 753 
 754 
 755 
 756 
 757 int pmix_cmd_line_get_ninsts(pmix_cmd_line_t *cmd, const char *opt)
 758 {
 759     int ret;
 760     pmix_cmd_line_param_t *param;
 761     pmix_cmd_line_option_t *option;
 762 
 763     
 764 
 765     pmix_mutex_lock(&cmd->lcl_mutex);
 766 
 767     
 768 
 769 
 770     ret = 0;
 771     option = find_option(cmd, opt);
 772     if (NULL != option) {
 773         PMIX_LIST_FOREACH(param, &cmd->lcl_params, pmix_cmd_line_param_t) {
 774             if (param->clp_option == option) {
 775                 ++ret;
 776             }
 777         }
 778     }
 779 
 780     
 781 
 782     pmix_mutex_unlock(&cmd->lcl_mutex);
 783 
 784     
 785 
 786     return ret;
 787 }
 788 
 789 
 790 
 791 
 792 
 793 
 794 char *pmix_cmd_line_get_param(pmix_cmd_line_t *cmd, const char *opt, int inst,
 795                               int idx)
 796 {
 797     int num_found;
 798     pmix_cmd_line_param_t *param;
 799     pmix_cmd_line_option_t *option;
 800 
 801     
 802 
 803     pmix_mutex_lock(&cmd->lcl_mutex);
 804 
 805     
 806 
 807 
 808     num_found = 0;
 809     option = find_option(cmd, opt);
 810     if (NULL != option) {
 811 
 812         
 813 
 814 
 815         if (idx < option->clo_num_params) {
 816             PMIX_LIST_FOREACH(param, &cmd->lcl_params, pmix_cmd_line_param_t) {
 817                 if (param->clp_argc > 0 && param->clp_option == option) {
 818                     if (num_found == inst) {
 819                         pmix_mutex_unlock(&cmd->lcl_mutex);
 820                         return param->clp_argv[idx];
 821                     }
 822                     ++num_found;
 823                 }
 824             }
 825         }
 826     }
 827 
 828     
 829 
 830     pmix_mutex_unlock(&cmd->lcl_mutex);
 831 
 832     
 833 
 834     return NULL;
 835 }
 836 
 837 
 838 
 839 
 840 
 841 int pmix_cmd_line_get_argc(pmix_cmd_line_t *cmd)
 842 {
 843     return (NULL != cmd) ? cmd->lcl_argc : PMIX_ERROR;
 844 }
 845 
 846 
 847 
 848 
 849 
 850 char *pmix_cmd_line_get_argv(pmix_cmd_line_t *cmd, int index)
 851 {
 852     return (NULL == cmd) ? NULL :
 853         (index >= cmd->lcl_argc || index < 0) ? NULL : cmd->lcl_argv[index];
 854 }
 855 
 856 
 857 
 858 
 859 
 860 
 861 int pmix_cmd_line_get_tail(pmix_cmd_line_t *cmd, int *tailc, char ***tailv)
 862 {
 863     if (NULL != cmd) {
 864         pmix_mutex_lock(&cmd->lcl_mutex);
 865         *tailc = cmd->lcl_tail_argc;
 866         *tailv = pmix_argv_copy(cmd->lcl_tail_argv);
 867         pmix_mutex_unlock(&cmd->lcl_mutex);
 868         return PMIX_SUCCESS;
 869     } else {
 870         return PMIX_ERROR;
 871     }
 872 }
 873 
 874 
 875 
 876 
 877 
 878 
 879 static void option_constructor(pmix_cmd_line_option_t *o)
 880 {
 881     o->clo_short_name = '\0';
 882     o->clo_single_dash_name = NULL;
 883     o->clo_long_name = NULL;
 884     o->clo_num_params = 0;
 885     o->clo_description = NULL;
 886 
 887     o->clo_type = PMIX_CMD_LINE_TYPE_NULL;
 888     o->clo_mca_param_env_var = NULL;
 889     o->clo_variable_dest = NULL;
 890     o->clo_variable_set = false;
 891     o->clo_otype = PMIX_CMD_LINE_OTYPE_NULL;
 892 }
 893 
 894 
 895 static void option_destructor(pmix_cmd_line_option_t *o)
 896 {
 897     if (NULL != o->clo_single_dash_name) {
 898         free(o->clo_single_dash_name);
 899     }
 900     if (NULL != o->clo_long_name) {
 901         free(o->clo_long_name);
 902     }
 903     if (NULL != o->clo_description) {
 904         free(o->clo_description);
 905     }
 906     if (NULL != o->clo_mca_param_env_var) {
 907         free(o->clo_mca_param_env_var);
 908     }
 909 }
 910 
 911 
 912 static void param_constructor(pmix_cmd_line_param_t *p)
 913 {
 914     p->clp_arg = NULL;
 915     p->clp_option = NULL;
 916     p->clp_argc = 0;
 917     p->clp_argv = NULL;
 918 }
 919 
 920 
 921 static void param_destructor(pmix_cmd_line_param_t *p)
 922 {
 923     if (NULL != p->clp_argv) {
 924         pmix_argv_free(p->clp_argv);
 925     }
 926 }
 927 
 928 
 929 static void cmd_line_constructor(pmix_cmd_line_t *cmd)
 930 {
 931     
 932 
 933 
 934 
 935     PMIX_CONSTRUCT(&cmd->lcl_mutex, pmix_recursive_mutex_t);
 936 
 937     
 938 
 939     PMIX_CONSTRUCT(&cmd->lcl_options, pmix_list_t);
 940     PMIX_CONSTRUCT(&cmd->lcl_params, pmix_list_t);
 941 
 942     
 943 
 944     cmd->lcl_argc = 0;
 945     cmd->lcl_argv = NULL;
 946     cmd->lcl_tail_argc = 0;
 947     cmd->lcl_tail_argv = NULL;
 948 }
 949 
 950 
 951 static void cmd_line_destructor(pmix_cmd_line_t *cmd)
 952 {
 953     pmix_list_item_t *item;
 954 
 955     
 956 
 957 
 958     for (item = pmix_list_remove_first(&cmd->lcl_options);
 959          NULL != item;
 960          item = pmix_list_remove_first(&cmd->lcl_options)) {
 961         PMIX_RELEASE(item);
 962     }
 963 
 964     
 965 
 966     free_parse_results(cmd);
 967 
 968     
 969 
 970     PMIX_DESTRUCT(&cmd->lcl_options);
 971     PMIX_DESTRUCT(&cmd->lcl_params);
 972 
 973     
 974 
 975     PMIX_DESTRUCT(&cmd->lcl_mutex);
 976 }
 977 
 978 
 979 static int make_opt(pmix_cmd_line_t *cmd, pmix_cmd_line_init_t *e)
 980 {
 981     pmix_cmd_line_option_t *option;
 982 
 983     
 984 
 985     if (NULL == cmd) {
 986         return PMIX_ERR_BAD_PARAM;
 987     } else if ('\0' == e->ocl_cmd_short_name &&
 988                NULL == e->ocl_cmd_single_dash_name &&
 989                NULL == e->ocl_cmd_long_name) {
 990         return PMIX_ERR_BAD_PARAM;
 991     } else if (e->ocl_num_params < 0) {
 992         return PMIX_ERR_BAD_PARAM;
 993     }
 994 
 995     
 996     if (NULL != e->ocl_cmd_single_dash_name &&
 997         NULL != find_option(cmd, e->ocl_cmd_single_dash_name)) {
 998         pmix_output(0, "Duplicate cmd line entry %s", e->ocl_cmd_single_dash_name);
 999         return PMIX_ERR_BAD_PARAM;
1000     }
1001     if (NULL != e->ocl_cmd_long_name &&
1002         NULL != find_option(cmd, e->ocl_cmd_long_name)) {
1003         pmix_output(0, "Duplicate cmd line entry %s", e->ocl_cmd_long_name);
1004         return PMIX_ERR_BAD_PARAM;
1005     }
1006 
1007     
1008     option = PMIX_NEW(pmix_cmd_line_option_t);
1009     if (NULL == option) {
1010         return PMIX_ERR_OUT_OF_RESOURCE;
1011     }
1012 
1013     option->clo_short_name = e->ocl_cmd_short_name;
1014     if (NULL != e->ocl_cmd_single_dash_name) {
1015         option->clo_single_dash_name = strdup(e->ocl_cmd_single_dash_name);
1016     }
1017     if (NULL != e->ocl_cmd_long_name) {
1018         option->clo_long_name = strdup(e->ocl_cmd_long_name);
1019     }
1020     option->clo_num_params = e->ocl_num_params;
1021     if (NULL != e->ocl_description) {
1022         option->clo_description = strdup(e->ocl_description);
1023     }
1024 
1025     option->clo_type = e->ocl_variable_type;
1026     option->clo_variable_dest = e->ocl_variable_dest;
1027     if (NULL != e->ocl_mca_param_name) {
1028         (void) pmix_mca_base_var_env_name (e->ocl_mca_param_name,
1029                                            &option->clo_mca_param_env_var);
1030     }
1031 
1032     option->clo_otype = e->ocl_otype;
1033 
1034     
1035 
1036     pmix_mutex_lock(&cmd->lcl_mutex);
1037     pmix_list_append(&cmd->lcl_options, &option->super);
1038     pmix_mutex_unlock(&cmd->lcl_mutex);
1039 
1040     
1041 
1042     return PMIX_SUCCESS;
1043 }
1044 
1045 
1046 static void free_parse_results(pmix_cmd_line_t *cmd)
1047 {
1048     pmix_list_item_t *item;
1049 
1050     
1051 
1052 
1053     for (item = pmix_list_remove_first(&cmd->lcl_params);
1054          NULL != item;
1055          item = pmix_list_remove_first(&cmd->lcl_params)) {
1056         PMIX_RELEASE(item);
1057     }
1058 
1059     
1060 
1061     if (NULL != cmd->lcl_argv) {
1062         pmix_argv_free(cmd->lcl_argv);
1063     }
1064     cmd->lcl_argv = NULL;
1065     cmd->lcl_argc = 0;
1066 
1067     if (NULL != cmd->lcl_tail_argv) {
1068         pmix_argv_free(cmd->lcl_tail_argv);
1069     }
1070     cmd->lcl_tail_argv = NULL;
1071     cmd->lcl_tail_argc = 0;
1072 }
1073 
1074 
1075 
1076 
1077 
1078 
1079 
1080 
1081 static int split_shorts(pmix_cmd_line_t *cmd, char *token, char **args,
1082                         int *output_argc, char ***output_argv,
1083                         int *num_args_used, bool ignore_unknown)
1084 {
1085     int i, j, len;
1086     pmix_cmd_line_option_t *option;
1087     char fake_token[3];
1088     int num_args;
1089 
1090     
1091 
1092     num_args = pmix_argv_count(args);
1093     *num_args_used = 0;
1094 
1095     
1096 
1097 
1098 
1099 
1100     len = (int)strlen(token);
1101     if (0 == len) {
1102         return PMIX_ERR_BAD_PARAM;
1103     }
1104     fake_token[0] = '-';
1105     fake_token[2] = '\0';
1106     for (i = 0; i < len; ++i) {
1107         fake_token[1] = token[i];
1108         option = find_option(cmd, fake_token + 1);
1109 
1110         
1111 
1112 
1113         if (NULL == option) {
1114             if (!ignore_unknown) {
1115                 return PMIX_ERR_BAD_PARAM;
1116             } else {
1117                 pmix_argv_append(output_argc, output_argv, fake_token);
1118             }
1119         }
1120 
1121         
1122 
1123 
1124 
1125 
1126         else {
1127             pmix_argv_append(output_argc, output_argv, fake_token);
1128             for (j = 0; j < option->clo_num_params; ++j) {
1129                 if (*num_args_used < num_args) {
1130                     pmix_argv_append(output_argc, output_argv,
1131                                      args[*num_args_used]);
1132                     ++(*num_args_used);
1133                 } else {
1134                     pmix_argv_append(output_argc, output_argv,
1135                                      special_empty_token);
1136                 }
1137             }
1138         }
1139     }
1140 
1141     
1142 
1143     return PMIX_SUCCESS;
1144 }
1145 
1146 
1147 static pmix_cmd_line_option_t *find_option(pmix_cmd_line_t *cmd,
1148                                            const char *option_name)
1149 {
1150     pmix_cmd_line_option_t *option;
1151 
1152     
1153 
1154 
1155 
1156     PMIX_LIST_FOREACH(option, &cmd->lcl_options, pmix_cmd_line_option_t) {
1157         if ((NULL != option->clo_long_name &&
1158              0 == strcmp(option_name, option->clo_long_name)) ||
1159             (NULL != option->clo_single_dash_name &&
1160              0 == strcmp(option_name, option->clo_single_dash_name)) ||
1161             (strlen(option_name) == 1 &&
1162              option_name[0] == option->clo_short_name)) {
1163             return option;
1164         }
1165     }
1166 
1167     
1168 
1169     return NULL;
1170 }
1171 
1172 
1173 static int set_dest(pmix_cmd_line_option_t *option, char *sval)
1174 {
1175     int ival = atol(sval);
1176     long lval = strtoul(sval, NULL, 10);
1177     size_t i;
1178 
1179     
1180 
1181 
1182 
1183 
1184 
1185 
1186 
1187 
1188 
1189     if (NULL != option->clo_mca_param_env_var) {
1190         switch(option->clo_type) {
1191         case PMIX_CMD_LINE_TYPE_STRING:
1192         case PMIX_CMD_LINE_TYPE_INT:
1193         case PMIX_CMD_LINE_TYPE_SIZE_T:
1194             pmix_setenv(option->clo_mca_param_env_var, sval, true, &environ);
1195             break;
1196         case PMIX_CMD_LINE_TYPE_BOOL:
1197             pmix_setenv(option->clo_mca_param_env_var, "1", true, &environ);
1198             break;
1199         default:
1200             break;
1201         }
1202     }
1203 
1204     
1205 
1206     if (NULL != option->clo_variable_dest) {
1207         switch(option->clo_type) {
1208         case PMIX_CMD_LINE_TYPE_STRING:
1209             *((char**) option->clo_variable_dest) = strdup(sval);
1210             break;
1211         case PMIX_CMD_LINE_TYPE_INT:
1212             
1213             for (i=0; i < strlen(sval); i++) {
1214                 if (!isdigit(sval[i]) && '-' != sval[i]) {
1215                     
1216 
1217 
1218                     fprintf(stderr, "----------------------------------------------------------------------------\n");
1219                     fprintf(stderr, "Open MPI has detected that a parameter given to a command line\n");
1220                     fprintf(stderr, "option does not match the expected format:\n\n");
1221                     if (NULL != option->clo_long_name) {
1222                         fprintf(stderr, "  Option: %s\n", option->clo_long_name);
1223                     } else if ('\0' != option->clo_short_name) {
1224                         fprintf(stderr, "  Option: %c\n", option->clo_short_name);
1225                     } else {
1226                         fprintf(stderr, "  Option: <unknown>\n");
1227                     }
1228                     fprintf(stderr, "  Param:  %s\n\n", sval);
1229                     fprintf(stderr, "This is frequently caused by omitting to provide the parameter\n");
1230                     fprintf(stderr, "to an option that requires one. Please check the command line and try again.\n");
1231                     fprintf(stderr, "----------------------------------------------------------------------------\n");
1232                     return PMIX_ERR_SILENT;
1233                 }
1234             }
1235             *((int*) option->clo_variable_dest) = ival;
1236             break;
1237         case PMIX_CMD_LINE_TYPE_SIZE_T:
1238             
1239             for (i=0; i < strlen(sval); i++) {
1240                 if (!isdigit(sval[i]) && '-' != sval[i]) {
1241                     
1242 
1243 
1244                     fprintf(stderr, "----------------------------------------------------------------------------\n");
1245                     fprintf(stderr, "Open MPI has detected that a parameter given to a command line\n");
1246                     fprintf(stderr, "option does not match the expected format:\n\n");
1247                     if (NULL != option->clo_long_name) {
1248                         fprintf(stderr, "  Option: %s\n", option->clo_long_name);
1249                     } else if ('\0' != option->clo_short_name) {
1250                         fprintf(stderr, "  Option: %c\n", option->clo_short_name);
1251                     } else {
1252                         fprintf(stderr, "  Option: <unknown>\n");
1253                     }
1254                     fprintf(stderr, "  Param:  %s\n\n", sval);
1255                     fprintf(stderr, "This is frequently caused by omitting to provide the parameter\n");
1256                     fprintf(stderr, "to an option that requires one. Please check the command line and try again.\n");
1257                     fprintf(stderr, "----------------------------------------------------------------------------\n");
1258                     return PMIX_ERR_SILENT;
1259                 }
1260             }
1261             *((size_t*) option->clo_variable_dest) = lval;
1262             break;
1263         case PMIX_CMD_LINE_TYPE_BOOL:
1264             *((bool*) option->clo_variable_dest) = 1;
1265             break;
1266         default:
1267             break;
1268         }
1269     }
1270     return PMIX_SUCCESS;
1271 }
1272 
1273 
1274 
1275 
1276 
1277 static void fill(const pmix_cmd_line_option_t *a, char result[3][BUFSIZ])
1278 {
1279     int i = 0;
1280 
1281     result[0][0] = '\0';
1282     result[1][0] = '\0';
1283     result[2][0] = '\0';
1284 
1285     if ('\0' != a->clo_short_name) {
1286         snprintf(&result[i][0], BUFSIZ, "%c", a->clo_short_name);
1287         ++i;
1288     }
1289     if (NULL != a->clo_single_dash_name) {
1290         snprintf(&result[i][0], BUFSIZ, "%s", a->clo_single_dash_name);
1291         ++i;
1292     }
1293     if (NULL != a->clo_long_name) {
1294         snprintf(&result[i][0], BUFSIZ, "%s", a->clo_long_name);
1295         ++i;
1296     }
1297 }
1298 
1299 
1300 static int qsort_callback(const void *aa, const void *bb)
1301 {
1302     int ret, i;
1303     char str1[3][BUFSIZ], str2[3][BUFSIZ];
1304     const pmix_cmd_line_option_t *a = *((const pmix_cmd_line_option_t**) aa);
1305     const pmix_cmd_line_option_t *b = *((const pmix_cmd_line_option_t**) bb);
1306 
1307     
1308 
1309 
1310 
1311 
1312     fill(a, str1);
1313     fill(b, str2);
1314 
1315     for (i = 0; i < 3; ++i) {
1316         if (0 != (ret = strcasecmp(str1[i], str2[i]))) {
1317             return ret;
1318         }
1319     }
1320 
1321     
1322 
1323     return 0;
1324 }
1325 
1326 
1327 
1328 
1329 
1330 
1331 static pmix_cmd_line_otype_t get_help_otype(pmix_cmd_line_t *cmd)
1332 {
1333     
1334 
1335     pmix_cmd_line_otype_t otype = PMIX_CMD_LINE_OTYPE_NULL;
1336     char *arg;
1337 
1338     arg = pmix_cmd_line_get_param(cmd, "help", 0, 0);
1339 
1340     
1341     if(NULL == arg) {
1342         arg = pmix_cmd_line_get_param(cmd, "h", 0, 0);
1343     }
1344 
1345     
1346     if(NULL == arg) {
1347         arg = "general";
1348     }
1349 
1350     if (0 == strcmp(arg, "debug")) {
1351         otype = PMIX_CMD_LINE_OTYPE_DEBUG;
1352     } else if (0 == strcmp(arg, "output")) {
1353         otype = PMIX_CMD_LINE_OTYPE_OUTPUT;
1354     } else if (0 == strcmp(arg, "input")) {
1355         otype = PMIX_CMD_LINE_OTYPE_INPUT;
1356     } else if (0 == strcmp(arg, "mapping")) {
1357         otype = PMIX_CMD_LINE_OTYPE_MAPPING;
1358     } else if (0 == strcmp(arg, "ranking")) {
1359         otype = PMIX_CMD_LINE_OTYPE_RANKING;
1360     } else if (0 == strcmp(arg, "binding")) {
1361         otype = PMIX_CMD_LINE_OTYPE_BINDING;
1362     } else if (0 == strcmp(arg, "devel")) {
1363         otype = PMIX_CMD_LINE_OTYPE_DEVEL;
1364     } else if (0 == strcmp(arg, "compatibility")) {
1365         otype = PMIX_CMD_LINE_OTYPE_COMPAT;
1366     } else if (0 == strcmp(arg, "launch")) {
1367         otype = PMIX_CMD_LINE_OTYPE_LAUNCH;
1368     } else if (0 == strcmp(arg, "dvm")) {
1369         otype = PMIX_CMD_LINE_OTYPE_DVM;
1370     } else if (0 == strcmp(arg, "general")) {
1371         otype = PMIX_CMD_LINE_OTYPE_GENERAL;
1372     } else if (0 == strcmp(arg, "parsable")) {
1373         otype = PMIX_CMD_LINE_OTYPE_PARSABLE;
1374     }
1375 
1376     return otype;
1377 }
1378 
1379 
1380 
1381 
1382 
1383 static char *build_parsable(pmix_cmd_line_option_t *option) {
1384     char *line;
1385     int length;
1386 
1387     length = snprintf(NULL, 0, "%c:%s:%s:%d:%s\n", option->clo_short_name, option->clo_single_dash_name,
1388                       option->clo_long_name, option->clo_num_params, option->clo_description);
1389 
1390     line = (char *)malloc(length * sizeof(char));
1391 
1392     if('\0' == option->clo_short_name) {
1393         snprintf(line, length, "0:%s:%s:%d:%s\n", option->clo_single_dash_name, option->clo_long_name,
1394                  option->clo_num_params, option->clo_description);
1395     } else {
1396         snprintf(line, length, "%c:%s:%s:%d:%s\n", option->clo_short_name, option->clo_single_dash_name,
1397                  option->clo_long_name, option->clo_num_params, option->clo_description);
1398     }
1399 
1400     return line;
1401 }