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 }