This source file includes following definitions.
- find_option
- opal_cmd_line_add
- opal_cmd_line_make_opt_mca
- opal_cmd_line_make_opt3
- opal_cmd_line_parse
- opal_cmd_line_get_usage_msg
- opal_cmd_line_is_taken
- opal_cmd_line_get_ninsts
- opal_cmd_line_get_param
- opal_cmd_line_get_argc
- opal_cmd_line_get_argv
- opal_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 "opal_config.h"
  28 
  29 #include <stdio.h>
  30 #include <string.h>
  31 #include <ctype.h>
  32 
  33 #include "opal/class/opal_object.h"
  34 #include "opal/class/opal_list.h"
  35 #include "opal/threads/mutex.h"
  36 #include "opal/util/argv.h"
  37 #include "opal/util/cmd_line.h"
  38 #include "opal/util/output.h"
  39 #include "opal/util/opal_environ.h"
  40 
  41 #include "opal/mca/base/mca_base_var.h"
  42 #include "opal/constants.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 ompi_cmd_line_option_t {
  61     opal_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     opal_cmd_line_type_t clo_type;
  71     char *clo_mca_param_env_var;
  72     void *clo_variable_dest;
  73     bool clo_variable_set;
  74     opal_cmd_line_otype_t clo_otype;
  75 };
  76 typedef struct ompi_cmd_line_option_t ompi_cmd_line_option_t;
  77 static void option_constructor(ompi_cmd_line_option_t *cmd);
  78 static void option_destructor(ompi_cmd_line_option_t *cmd);
  79 
  80 OBJ_CLASS_INSTANCE(ompi_cmd_line_option_t,
  81                    opal_list_item_t,
  82                    option_constructor, option_destructor);
  83 
  84 
  85 
  86 
  87 struct ompi_cmd_line_param_t {
  88     opal_list_item_t super;
  89 
  90     
  91 
  92 
  93 
  94     char *clp_arg;
  95 
  96     
  97 
  98 
  99     ompi_cmd_line_option_t *clp_option;
 100 
 101     
 102 
 103 
 104 
 105     int clp_argc;
 106     char **clp_argv;
 107 };
 108 typedef struct ompi_cmd_line_param_t ompi_cmd_line_param_t;
 109 static void param_constructor(ompi_cmd_line_param_t *cmd);
 110 static void param_destructor(ompi_cmd_line_param_t *cmd);
 111 OBJ_CLASS_INSTANCE(ompi_cmd_line_param_t,
 112                    opal_list_item_t,
 113                    param_constructor, param_destructor);
 114 
 115 
 116 
 117 
 118 static void cmd_line_constructor(opal_cmd_line_t *cmd);
 119 static void cmd_line_destructor(opal_cmd_line_t *cmd);
 120 OBJ_CLASS_INSTANCE(opal_cmd_line_t,
 121                    opal_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(opal_cmd_line_t *cmd, opal_cmd_line_init_t *e);
 136 static void free_parse_results(opal_cmd_line_t *cmd);
 137 static int split_shorts(opal_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 ompi_cmd_line_option_t *find_option(opal_cmd_line_t *cmd,
 142                                       const char *option_name) __opal_attribute_nonnull__(1) __opal_attribute_nonnull__(2);
 143 static int set_dest(ompi_cmd_line_option_t *option, char *sval);
 144 static void fill(const ompi_cmd_line_option_t *a, char result[3][BUFSIZ]);
 145 static int qsort_callback(const void *a, const void *b);
 146 static opal_cmd_line_otype_t get_help_otype(opal_cmd_line_t *cmd);
 147 static char *build_parsable(ompi_cmd_line_option_t *option);
 148 
 149 
 150 
 151 
 152 
 153 int opal_cmd_line_create(opal_cmd_line_t *cmd,
 154                          opal_cmd_line_init_t *table)
 155 {
 156     int ret = OPAL_SUCCESS;
 157 
 158     
 159 
 160     if (NULL == cmd) {
 161         return OPAL_ERR_BAD_PARAM;
 162     }
 163     OBJ_CONSTRUCT(cmd, opal_cmd_line_t);
 164 
 165     if (NULL != table) {
 166         ret = opal_cmd_line_add(cmd, table);
 167     }
 168     return ret;
 169 }
 170 
 171 
 172 int opal_cmd_line_add(opal_cmd_line_t *cmd,
 173                       opal_cmd_line_init_t *table)
 174 {
 175     int i, ret;
 176 
 177     
 178     if (NULL == table) {
 179         return OPAL_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 (OPAL_SUCCESS != ret) {
 195             return ret;
 196         }
 197     }
 198 
 199     return OPAL_SUCCESS;
 200 }
 201 
 202 
 203 
 204 int opal_cmd_line_make_opt_mca(opal_cmd_line_t *cmd,
 205                                opal_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 OPAL_SUCCESS;
 212     }
 213 
 214     return make_opt(cmd, &entry);
 215 }
 216 
 217 
 218 
 219 
 220 
 221 int opal_cmd_line_make_opt3(opal_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     opal_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 = OPAL_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 opal_cmd_line_parse(opal_cmd_line_t *cmd, bool ignore_unknown, bool ignore_unknown_option,
 249                         int argc, char **argv)
 250 {
 251     int i, j, orig, ret;
 252     ompi_cmd_line_option_t *option;
 253     ompi_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 OPAL_SUCCESS;
 268     }
 269 
 270     
 271 
 272     opal_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 = opal_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                 opal_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 (OPAL_SUCCESS == ret) {
 351                     option = find_option(cmd, shortsv[0] + 1);
 352 
 353                     if (NULL != option) {
 354                         opal_argv_delete(&cmd->lcl_argc,
 355                                          &cmd->lcl_argv, i,
 356                                          1 + num_args_used);
 357                         opal_argv_insert(&cmd->lcl_argv, i, shortsv);
 358                         cmd->lcl_argc = opal_argv_count(cmd->lcl_argv);
 359                     } else {
 360                         is_unknown_option = true;
 361                     }
 362                     opal_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 = OBJ_NEW(ompi_cmd_line_param_t);
 390                 if (NULL == param) {
 391                     opal_mutex_unlock(&cmd->lcl_mutex);
 392                     return OPAL_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                         OBJ_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                                 opal_argv_free(param->clp_argv);
 439                             }
 440                             OBJ_RELEASE(param);
 441                             printed_error = true;
 442                             goto error;
 443                         }
 444 
 445                         
 446 
 447                         else {
 448                             
 449 
 450                             opal_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 (OPAL_SUCCESS != (ret = set_dest(option, cmd->lcl_argv[i]))) {
 461                                     opal_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 (OPAL_SUCCESS != (ret = set_dest(option, "1"))) {
 475                         opal_mutex_unlock(&cmd->lcl_mutex);
 476                         return ret;
 477                     }
 478                 }
 479 
 480                 
 481 
 482 
 483                 if (NULL != param) {
 484                     opal_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                 opal_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     opal_mutex_unlock(&cmd->lcl_mutex);
 517 
 518     
 519     if (printed_error) {
 520         return OPAL_ERR_SILENT;
 521     }
 522 
 523     return OPAL_SUCCESS;
 524 }
 525 
 526 
 527 
 528 
 529 
 530 char *opal_cmd_line_get_usage_msg(opal_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     opal_list_item_t *item;
 539     ompi_cmd_line_option_t *option, **sorted;
 540     opal_cmd_line_otype_t otype;
 541 
 542     
 543 
 544     opal_mutex_lock(&cmd->lcl_mutex);
 545 
 546     
 547 
 548     argc = 0;
 549     argv = NULL;
 550     ret = NULL;
 551 
 552     
 553 
 554     sorted = (ompi_cmd_line_option_t**)malloc(sizeof(ompi_cmd_line_option_t *) *
 555                                          opal_list_get_size(&cmd->lcl_options));
 556     if (NULL == sorted) {
 557         opal_mutex_unlock(&cmd->lcl_mutex);
 558         return NULL;
 559     }
 560     i = 0;
 561     OPAL_LIST_FOREACH(item, &cmd->lcl_options, opal_list_item_t) {
 562         sorted[i++] = (ompi_cmd_line_option_t *) item;
 563     }
 564     qsort(sorted, i, sizeof(ompi_cmd_line_option_t*), qsort_callback);
 565 
 566     
 567 
 568     otype = get_help_otype(cmd);
 569 
 570     
 571 
 572     for (j = 0; j < opal_list_get_size(&cmd->lcl_options); ++j) {
 573         option = sorted[j];
 574         if(otype == OPAL_CMD_LINE_OTYPE_PARSABLE) {
 575             ret = build_parsable(option);
 576             opal_argv_append(&argc, &argv, ret);
 577             free(ret);
 578             ret = NULL;
 579         } else if(otype == OPAL_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                     opal_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                     opal_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                         opal_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                             opal_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                                 opal_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                             opal_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(otype == OPAL_CMD_LINE_OTYPE_NULL || otype == OPAL_CMD_LINE_OTYPE_GENERAL) {
 730         char *argument_line = "\nFor additional mpirun arguments, run 'mpirun --help <category>'\n\nThe following categories exist: general (Defaults to this option), debug,\n    output, input, mapping, ranking, binding, devel (arguments useful to OMPI\n    Developers), compatibility (arguments supported for backwards compatibility),\n    launch (arguments to modify launch options), and dvm (Distributed Virtual\n    Machine arguments).";
 731 
 732         opal_argv_append(&argc, &argv, argument_line);
 733     }
 734     if (NULL != argv) {
 735         ret = opal_argv_join(argv, '\n');
 736         opal_argv_free(argv);
 737     } else {
 738         ret = strdup("");
 739     }
 740     free(sorted);
 741 
 742     
 743     opal_mutex_unlock(&cmd->lcl_mutex);
 744 
 745     
 746     return ret;
 747 }
 748 
 749 
 750 
 751 
 752 
 753 bool opal_cmd_line_is_taken(opal_cmd_line_t *cmd, const char *opt)
 754 {
 755     return (opal_cmd_line_get_ninsts(cmd, opt) > 0);
 756 }
 757 
 758 
 759 
 760 
 761 
 762 int opal_cmd_line_get_ninsts(opal_cmd_line_t *cmd, const char *opt)
 763 {
 764     int ret;
 765     ompi_cmd_line_param_t *param;
 766     ompi_cmd_line_option_t *option;
 767 
 768     
 769 
 770     opal_mutex_lock(&cmd->lcl_mutex);
 771 
 772     
 773 
 774 
 775     ret = 0;
 776     option = find_option(cmd, opt);
 777     if (NULL != option) {
 778         OPAL_LIST_FOREACH(param, &cmd->lcl_params, ompi_cmd_line_param_t) {
 779             if (param->clp_option == option) {
 780                 ++ret;
 781             }
 782         }
 783     }
 784 
 785     
 786 
 787     opal_mutex_unlock(&cmd->lcl_mutex);
 788 
 789     
 790 
 791     return ret;
 792 }
 793 
 794 
 795 
 796 
 797 
 798 
 799 char *opal_cmd_line_get_param(opal_cmd_line_t *cmd, const char *opt, int inst,
 800                               int idx)
 801 {
 802     int num_found;
 803     ompi_cmd_line_param_t *param;
 804     ompi_cmd_line_option_t *option;
 805 
 806     
 807 
 808     opal_mutex_lock(&cmd->lcl_mutex);
 809 
 810     
 811 
 812 
 813     num_found = 0;
 814     option = find_option(cmd, opt);
 815     if (NULL != option) {
 816 
 817         
 818 
 819 
 820         if (idx < option->clo_num_params) {
 821             OPAL_LIST_FOREACH(param, &cmd->lcl_params, ompi_cmd_line_param_t) {
 822                 if (param->clp_argc > 0 && param->clp_option == option) {
 823                     if (num_found == inst) {
 824                         opal_mutex_unlock(&cmd->lcl_mutex);
 825                         return param->clp_argv[idx];
 826                     }
 827                     ++num_found;
 828                 }
 829             }
 830         }
 831     }
 832 
 833     
 834 
 835     opal_mutex_unlock(&cmd->lcl_mutex);
 836 
 837     
 838 
 839     return NULL;
 840 }
 841 
 842 
 843 
 844 
 845 
 846 int opal_cmd_line_get_argc(opal_cmd_line_t *cmd)
 847 {
 848     return (NULL != cmd) ? cmd->lcl_argc : OPAL_ERROR;
 849 }
 850 
 851 
 852 
 853 
 854 
 855 char *opal_cmd_line_get_argv(opal_cmd_line_t *cmd, int index)
 856 {
 857     return (NULL == cmd) ? NULL :
 858         (index >= cmd->lcl_argc || index < 0) ? NULL : cmd->lcl_argv[index];
 859 }
 860 
 861 
 862 
 863 
 864 
 865 
 866 int opal_cmd_line_get_tail(opal_cmd_line_t *cmd, int *tailc, char ***tailv)
 867 {
 868     if (NULL != cmd) {
 869         opal_mutex_lock(&cmd->lcl_mutex);
 870         *tailc = cmd->lcl_tail_argc;
 871         *tailv = opal_argv_copy(cmd->lcl_tail_argv);
 872         opal_mutex_unlock(&cmd->lcl_mutex);
 873         return OPAL_SUCCESS;
 874     } else {
 875         return OPAL_ERROR;
 876     }
 877 }
 878 
 879 
 880 
 881 
 882 
 883 
 884 static void option_constructor(ompi_cmd_line_option_t *o)
 885 {
 886     o->clo_short_name = '\0';
 887     o->clo_single_dash_name = NULL;
 888     o->clo_long_name = NULL;
 889     o->clo_num_params = 0;
 890     o->clo_description = NULL;
 891 
 892     o->clo_type = OPAL_CMD_LINE_TYPE_NULL;
 893     o->clo_mca_param_env_var = NULL;
 894     o->clo_variable_dest = NULL;
 895     o->clo_variable_set = false;
 896     o->clo_otype = OPAL_CMD_LINE_OTYPE_NULL;
 897 }
 898 
 899 
 900 static void option_destructor(ompi_cmd_line_option_t *o)
 901 {
 902     if (NULL != o->clo_single_dash_name) {
 903         free(o->clo_single_dash_name);
 904     }
 905     if (NULL != o->clo_long_name) {
 906         free(o->clo_long_name);
 907     }
 908     if (NULL != o->clo_description) {
 909         free(o->clo_description);
 910     }
 911     if (NULL != o->clo_mca_param_env_var) {
 912         free(o->clo_mca_param_env_var);
 913     }
 914 }
 915 
 916 
 917 static void param_constructor(ompi_cmd_line_param_t *p)
 918 {
 919     p->clp_arg = NULL;
 920     p->clp_option = NULL;
 921     p->clp_argc = 0;
 922     p->clp_argv = NULL;
 923 }
 924 
 925 
 926 static void param_destructor(ompi_cmd_line_param_t *p)
 927 {
 928     if (NULL != p->clp_argv) {
 929         opal_argv_free(p->clp_argv);
 930     }
 931 }
 932 
 933 
 934 static void cmd_line_constructor(opal_cmd_line_t *cmd)
 935 {
 936     
 937 
 938 
 939 
 940     OBJ_CONSTRUCT(&cmd->lcl_mutex, opal_recursive_mutex_t);
 941 
 942     
 943 
 944     OBJ_CONSTRUCT(&cmd->lcl_options, opal_list_t);
 945     OBJ_CONSTRUCT(&cmd->lcl_params, opal_list_t);
 946 
 947     
 948 
 949     cmd->lcl_argc = 0;
 950     cmd->lcl_argv = NULL;
 951     cmd->lcl_tail_argc = 0;
 952     cmd->lcl_tail_argv = NULL;
 953 }
 954 
 955 
 956 static void cmd_line_destructor(opal_cmd_line_t *cmd)
 957 {
 958     opal_list_item_t *item;
 959 
 960     
 961 
 962 
 963     for (item = opal_list_remove_first(&cmd->lcl_options);
 964          NULL != item;
 965          item = opal_list_remove_first(&cmd->lcl_options)) {
 966         OBJ_RELEASE(item);
 967     }
 968 
 969     
 970 
 971     free_parse_results(cmd);
 972 
 973     
 974 
 975     OBJ_DESTRUCT(&cmd->lcl_options);
 976     OBJ_DESTRUCT(&cmd->lcl_params);
 977 
 978     
 979 
 980     OBJ_DESTRUCT(&cmd->lcl_mutex);
 981 }
 982 
 983 
 984 static int make_opt(opal_cmd_line_t *cmd, opal_cmd_line_init_t *e)
 985 {
 986     ompi_cmd_line_option_t *option;
 987 
 988     
 989 
 990     if (NULL == cmd) {
 991         return OPAL_ERR_BAD_PARAM;
 992     } else if ('\0' == e->ocl_cmd_short_name &&
 993                NULL == e->ocl_cmd_single_dash_name &&
 994                NULL == e->ocl_cmd_long_name) {
 995         return OPAL_ERR_BAD_PARAM;
 996     } else if (e->ocl_num_params < 0) {
 997         return OPAL_ERR_BAD_PARAM;
 998     }
 999 
1000     
1001     if (NULL != e->ocl_cmd_single_dash_name &&
1002         NULL != find_option(cmd, e->ocl_cmd_single_dash_name)) {
1003         opal_output(0, "Duplicate cmd line entry %s", e->ocl_cmd_single_dash_name);
1004         return OPAL_ERR_BAD_PARAM;
1005     }
1006     if (NULL != e->ocl_cmd_long_name &&
1007         NULL != find_option(cmd, e->ocl_cmd_long_name)) {
1008         opal_output(0, "Duplicate cmd line entry %s", e->ocl_cmd_long_name);
1009         return OPAL_ERR_BAD_PARAM;
1010     }
1011 
1012     
1013     option = OBJ_NEW(ompi_cmd_line_option_t);
1014     if (NULL == option) {
1015         return OPAL_ERR_OUT_OF_RESOURCE;
1016     }
1017 
1018     option->clo_short_name = e->ocl_cmd_short_name;
1019     if (NULL != e->ocl_cmd_single_dash_name) {
1020         option->clo_single_dash_name = strdup(e->ocl_cmd_single_dash_name);
1021     }
1022     if (NULL != e->ocl_cmd_long_name) {
1023         option->clo_long_name = strdup(e->ocl_cmd_long_name);
1024     }
1025     option->clo_num_params = e->ocl_num_params;
1026     if (NULL != e->ocl_description) {
1027         option->clo_description = strdup(e->ocl_description);
1028     }
1029 
1030     option->clo_type = e->ocl_variable_type;
1031     option->clo_variable_dest = e->ocl_variable_dest;
1032     if (NULL != e->ocl_mca_param_name) {
1033         (void) mca_base_var_env_name (e->ocl_mca_param_name,
1034                                      &option->clo_mca_param_env_var);
1035     }
1036 
1037     option->clo_otype = e->ocl_otype;
1038 
1039     
1040 
1041     opal_mutex_lock(&cmd->lcl_mutex);
1042     opal_list_append(&cmd->lcl_options, &option->super);
1043     opal_mutex_unlock(&cmd->lcl_mutex);
1044 
1045     
1046 
1047     return OPAL_SUCCESS;
1048 }
1049 
1050 
1051 static void free_parse_results(opal_cmd_line_t *cmd)
1052 {
1053     opal_list_item_t *item;
1054 
1055     
1056 
1057 
1058     for (item = opal_list_remove_first(&cmd->lcl_params);
1059          NULL != item;
1060          item = opal_list_remove_first(&cmd->lcl_params)) {
1061         OBJ_RELEASE(item);
1062     }
1063 
1064     
1065 
1066     if (NULL != cmd->lcl_argv) {
1067         opal_argv_free(cmd->lcl_argv);
1068     }
1069     cmd->lcl_argv = NULL;
1070     cmd->lcl_argc = 0;
1071 
1072     if (NULL != cmd->lcl_tail_argv) {
1073         opal_argv_free(cmd->lcl_tail_argv);
1074     }
1075     cmd->lcl_tail_argv = NULL;
1076     cmd->lcl_tail_argc = 0;
1077 }
1078 
1079 
1080 
1081 
1082 
1083 
1084 
1085 
1086 static int split_shorts(opal_cmd_line_t *cmd, char *token, char **args,
1087                         int *output_argc, char ***output_argv,
1088                         int *num_args_used, bool ignore_unknown)
1089 {
1090     int i, j, len;
1091     ompi_cmd_line_option_t *option;
1092     char fake_token[3];
1093     int num_args;
1094 
1095     
1096 
1097     num_args = opal_argv_count(args);
1098     *num_args_used = 0;
1099 
1100     
1101 
1102 
1103 
1104 
1105     len = (int)strlen(token);
1106     if (0 == len) {
1107         return OPAL_ERR_BAD_PARAM;
1108     }
1109     fake_token[0] = '-';
1110     fake_token[2] = '\0';
1111     for (i = 0; i < len; ++i) {
1112         fake_token[1] = token[i];
1113         option = find_option(cmd, fake_token + 1);
1114 
1115         
1116 
1117 
1118         if (NULL == option) {
1119             if (!ignore_unknown) {
1120                 return OPAL_ERR_BAD_PARAM;
1121             } else {
1122                 opal_argv_append(output_argc, output_argv, fake_token);
1123             }
1124         }
1125 
1126         
1127 
1128 
1129 
1130 
1131         else {
1132             opal_argv_append(output_argc, output_argv, fake_token);
1133             for (j = 0; j < option->clo_num_params; ++j) {
1134                 if (*num_args_used < num_args) {
1135                     opal_argv_append(output_argc, output_argv,
1136                                      args[*num_args_used]);
1137                     ++(*num_args_used);
1138                 } else {
1139                     opal_argv_append(output_argc, output_argv,
1140                                      special_empty_token);
1141                 }
1142             }
1143         }
1144     }
1145 
1146     
1147 
1148     return OPAL_SUCCESS;
1149 }
1150 
1151 
1152 static ompi_cmd_line_option_t *find_option(opal_cmd_line_t *cmd,
1153                                       const char *option_name)
1154 {
1155     ompi_cmd_line_option_t *option;
1156 
1157     
1158 
1159 
1160 
1161     OPAL_LIST_FOREACH(option, &cmd->lcl_options, ompi_cmd_line_option_t) {
1162         if ((NULL != option->clo_long_name &&
1163              0 == strcmp(option_name, option->clo_long_name)) ||
1164             (NULL != option->clo_single_dash_name &&
1165              0 == strcmp(option_name, option->clo_single_dash_name)) ||
1166             (strlen(option_name) == 1 &&
1167              option_name[0] == option->clo_short_name)) {
1168             return option;
1169         }
1170     }
1171 
1172     
1173 
1174     return NULL;
1175 }
1176 
1177 
1178 static int set_dest(ompi_cmd_line_option_t *option, char *sval)
1179 {
1180     int ival = atol(sval);
1181     long lval = strtoul(sval, NULL, 10);
1182     size_t i;
1183 
1184     
1185 
1186 
1187 
1188 
1189 
1190 
1191 
1192 
1193 
1194     if (NULL != option->clo_mca_param_env_var) {
1195         switch(option->clo_type) {
1196         case OPAL_CMD_LINE_TYPE_STRING:
1197         case OPAL_CMD_LINE_TYPE_INT:
1198         case OPAL_CMD_LINE_TYPE_SIZE_T:
1199             opal_setenv(option->clo_mca_param_env_var, sval, true, &environ);
1200             break;
1201         case OPAL_CMD_LINE_TYPE_BOOL:
1202             opal_setenv(option->clo_mca_param_env_var, "1", true, &environ);
1203             break;
1204         default:
1205             break;
1206         }
1207     }
1208 
1209     
1210 
1211     if (NULL != option->clo_variable_dest) {
1212         switch(option->clo_type) {
1213         case OPAL_CMD_LINE_TYPE_STRING:
1214             *((char**) option->clo_variable_dest) = strdup(sval);
1215             break;
1216         case OPAL_CMD_LINE_TYPE_INT:
1217             
1218             for (i=0; i < strlen(sval); i++) {
1219                 if (!isdigit(sval[i]) && '-' != sval[i]) {
1220                     
1221 
1222 
1223                     fprintf(stderr, "----------------------------------------------------------------------------\n");
1224                     fprintf(stderr, "Open MPI has detected that a parameter given to a command line\n");
1225                     fprintf(stderr, "option does not match the expected format:\n\n");
1226                     if (NULL != option->clo_long_name) {
1227                         fprintf(stderr, "  Option: %s\n", option->clo_long_name);
1228                     } else if ('\0' != option->clo_short_name) {
1229                         fprintf(stderr, "  Option: %c\n", option->clo_short_name);
1230                     } else {
1231                         fprintf(stderr, "  Option: <unknown>\n");
1232                     }
1233                     fprintf(stderr, "  Param:  %s\n\n", sval);
1234                     fprintf(stderr, "This is frequently caused by omitting to provide the parameter\n");
1235                     fprintf(stderr, "to an option that requires one. Please check the command line and try again.\n");
1236                     fprintf(stderr, "----------------------------------------------------------------------------\n");
1237                     return OPAL_ERR_SILENT;
1238                 }
1239             }
1240             *((int*) option->clo_variable_dest) = ival;
1241             break;
1242         case OPAL_CMD_LINE_TYPE_SIZE_T:
1243             
1244             for (i=0; i < strlen(sval); i++) {
1245                 if (!isdigit(sval[i]) && '-' != sval[i]) {
1246                     
1247 
1248 
1249                     fprintf(stderr, "----------------------------------------------------------------------------\n");
1250                     fprintf(stderr, "Open MPI has detected that a parameter given to a command line\n");
1251                     fprintf(stderr, "option does not match the expected format:\n\n");
1252                     if (NULL != option->clo_long_name) {
1253                         fprintf(stderr, "  Option: %s\n", option->clo_long_name);
1254                     } else if ('\0' != option->clo_short_name) {
1255                         fprintf(stderr, "  Option: %c\n", option->clo_short_name);
1256                     } else {
1257                         fprintf(stderr, "  Option: <unknown>\n");
1258                     }
1259                     fprintf(stderr, "  Param:  %s\n\n", sval);
1260                     fprintf(stderr, "This is frequently caused by omitting to provide the parameter\n");
1261                     fprintf(stderr, "to an option that requires one. Please check the command line and try again.\n");
1262                     fprintf(stderr, "----------------------------------------------------------------------------\n");
1263                     return OPAL_ERR_SILENT;
1264                 }
1265             }
1266             *((size_t*) option->clo_variable_dest) = lval;
1267             break;
1268         case OPAL_CMD_LINE_TYPE_BOOL:
1269             *((bool*) option->clo_variable_dest) = 1;
1270             break;
1271         default:
1272             break;
1273         }
1274     }
1275     return OPAL_SUCCESS;
1276 }
1277 
1278 
1279 
1280 
1281 
1282 static void fill(const ompi_cmd_line_option_t *a, char result[3][BUFSIZ])
1283 {
1284     int i = 0;
1285 
1286     result[0][0] = '\0';
1287     result[1][0] = '\0';
1288     result[2][0] = '\0';
1289 
1290     if ('\0' != a->clo_short_name) {
1291         snprintf(&result[i][0], BUFSIZ, "%c", a->clo_short_name);
1292         ++i;
1293     }
1294     if (NULL != a->clo_single_dash_name) {
1295         snprintf(&result[i][0], BUFSIZ, "%s", a->clo_single_dash_name);
1296         ++i;
1297     }
1298     if (NULL != a->clo_long_name) {
1299         snprintf(&result[i][0], BUFSIZ, "%s", a->clo_long_name);
1300         ++i;
1301     }
1302 }
1303 
1304 
1305 static int qsort_callback(const void *aa, const void *bb)
1306 {
1307     int ret, i;
1308     char str1[3][BUFSIZ], str2[3][BUFSIZ];
1309     const ompi_cmd_line_option_t *a = *((const ompi_cmd_line_option_t**) aa);
1310     const ompi_cmd_line_option_t *b = *((const ompi_cmd_line_option_t**) bb);
1311 
1312     
1313 
1314 
1315 
1316 
1317     fill(a, str1);
1318     fill(b, str2);
1319 
1320     for (i = 0; i < 3; ++i) {
1321         if (0 != (ret = strcasecmp(str1[i], str2[i]))) {
1322             return ret;
1323         }
1324     }
1325 
1326     
1327 
1328     return 0;
1329 }
1330 
1331 
1332 
1333 
1334 
1335 
1336 static opal_cmd_line_otype_t get_help_otype(opal_cmd_line_t *cmd)
1337 {
1338     
1339 
1340     opal_cmd_line_otype_t otype = OPAL_CMD_LINE_OTYPE_NULL;
1341     char *arg;
1342 
1343     arg = opal_cmd_line_get_param(cmd, "help", 0, 0);
1344 
1345     
1346     if(NULL == arg) {
1347         arg = opal_cmd_line_get_param(cmd, "h", 0, 0);
1348     }
1349 
1350     
1351     if(NULL == arg) {
1352         arg = "general";
1353     }
1354 
1355     if (0 == strcmp(arg, "debug")) {
1356         otype = OPAL_CMD_LINE_OTYPE_DEBUG;
1357     } else if (0 == strcmp(arg, "output")) {
1358         otype = OPAL_CMD_LINE_OTYPE_OUTPUT;
1359     } else if (0 == strcmp(arg, "input")) {
1360         otype = OPAL_CMD_LINE_OTYPE_INPUT;
1361     } else if (0 == strcmp(arg, "mapping")) {
1362         otype = OPAL_CMD_LINE_OTYPE_MAPPING;
1363     } else if (0 == strcmp(arg, "ranking")) {
1364         otype = OPAL_CMD_LINE_OTYPE_RANKING;
1365     } else if (0 == strcmp(arg, "binding")) {
1366         otype = OPAL_CMD_LINE_OTYPE_BINDING;
1367     } else if (0 == strcmp(arg, "devel")) {
1368         otype = OPAL_CMD_LINE_OTYPE_DEVEL;
1369     } else if (0 == strcmp(arg, "compatibility")) {
1370         otype = OPAL_CMD_LINE_OTYPE_COMPAT;
1371     } else if (0 == strcmp(arg, "launch")) {
1372         otype = OPAL_CMD_LINE_OTYPE_LAUNCH;
1373     } else if (0 == strcmp(arg, "dvm")) {
1374         otype = OPAL_CMD_LINE_OTYPE_DVM;
1375     } else if (0 == strcmp(arg, "general")) {
1376         otype = OPAL_CMD_LINE_OTYPE_GENERAL;
1377     } else if (0 == strcmp(arg, "parsable")) {
1378         otype = OPAL_CMD_LINE_OTYPE_PARSABLE;
1379     }
1380 
1381     return otype;
1382 }
1383 
1384 
1385 
1386 
1387 
1388 static char *build_parsable(ompi_cmd_line_option_t *option) {
1389     char *line;
1390     int length;
1391 
1392     length = snprintf(NULL, 0, "%c:%s:%s:%d:%s\n", option->clo_short_name, option->clo_single_dash_name,
1393                       option->clo_long_name, option->clo_num_params, option->clo_description);
1394 
1395     line = (char *)malloc(length * sizeof(char));
1396 
1397     if('\0' == option->clo_short_name) {
1398         snprintf(line, length, "0:%s:%s:%d:%s\n", option->clo_single_dash_name, option->clo_long_name,
1399                  option->clo_num_params, option->clo_description);
1400     } else {
1401         snprintf(line, length, "%c:%s:%s:%d:%s\n", option->clo_short_name, option->clo_single_dash_name,
1402                  option->clo_long_name, option->clo_num_params, option->clo_description);
1403     }
1404 
1405     return line;
1406 }