std::vector<std::string> CommandLineOptions::parse(int argc, char const* const* argv) { int start_at = program_name_ ? 0 : 1; if (argc <= start_at) return std::vector<std::string>(); if (!program_name_) { program_name_ = std::string(argv[0]); } std::map<std::string, std::vector<Option>::iterator> options_index; for (auto it = options_.begin(); it != options_.end(); ++it) { if (it->long_form) { options_index[*it->long_form] = it; } if (it->short_form) { options_index[*it->short_form] = it; } } bool after_double_dash = false; std::vector<std::string> words; for (int i = start_at; i < argc; ++i) { std::string o = argv[i]; if (after_double_dash || o[0] != '-') { words.push_back(std::move(o)); continue; } if (o == "--") { after_double_dash = true; continue; } auto eq_pos = o.find('='); Maybe<std::string> value; std::vector<Option>::iterator it = options_.end(); if (eq_pos != std::string::npos) { value = o.substr(eq_pos + 1); o = o.substr(0, eq_pos); auto idx_it = options_index.find(o); if (idx_it != options_index.end()) { it = idx_it->second; } } else { auto idx_it = options_index.find(o); if (idx_it != options_index.end()) { it = idx_it->second; if (it->needs_value) { if (i+1 < argc) { value = std::string(argv[i+1]); ++i; } else { std::cerr << wayward::format("Option '{0}' expects a value.\n"); display_usage_and_exit(); } } } } if (it == options_.end()) { if (unrecognized_action_) { unrecognized_action_(std::move(o)); } } else { it->action(std::move(value)); } } return words; }
int main(int argc, char **argv) { prog_name = argv[0]; int show_the_system_info = 0; int show_the_numastat_info = 0; static struct option long_options[] = { {"help", 0, 0, '?'}, {0, 0, 0, 0} }; int long_option_index = 0; int opt; while ((opt = getopt_long(argc, argv, "cmnp:s::vVz?", long_options, &long_option_index)) != -1) { switch (opt) { case 0: printf("Unexpected long option %s", long_options[long_option_index].name); if (optarg) { printf(" with arg %s", optarg); } printf("\n"); display_usage_and_exit(); break; case 'c': compress_display = 1; break; case 'm': show_the_system_info = 1; break; case 'n': show_the_numastat_info = 1; break; case 'p': if ((optarg) && (all_digits(optarg))) { add_pid_to_list(atoi(optarg)); } else { add_pids_from_pattern_search(optarg); } break; case 's': sort_table = 1; if ((optarg) && (all_digits(optarg))) { sort_table_node = atoi(optarg); } break; case 'v': verbose = 1; break; case 'V': display_version_and_exit(); break; case 'z': show_zero_data = 0; break; default: case '?': display_usage_and_exit(); break; } } // Figure out the display width, which is used to format the tables // and limit the output columns per row screen_width = get_screen_width(); // Any remaining arguments are assumed to be additional process specifiers while (optind < argc) { if (all_digits(argv[optind])) { add_pid_to_list(atoi(argv[optind])); } else { add_pids_from_pattern_search(argv[optind]); } optind += 1; } // If there are no program options or arguments, be extremely compatible // with the old numastat perl script (which is included at the end of this // file for reference) compatibility_mode = (argc == 1); init_node_ix_map_and_header(compatibility_mode); // enumarate the NUMA nodes if (compatibility_mode) { show_numastat_info(); free_node_ix_map_and_header(); exit(EXIT_SUCCESS); } // Figure out page sizes page_size_in_bytes = (double)sysconf(_SC_PAGESIZE); huge_page_size_in_bytes = get_huge_page_size_in_bytes(); // Display the info for the process specifiers if (num_pids > 0) { sort_pids_and_remove_duplicates(); show_process_info(); } if (pid_array != NULL) { free(pid_array); } // Display the system-wide memory usage info if (show_the_system_info) { show_system_info(); } // Display the numastat statistics info if ((show_the_numastat_info) || ((num_pids == 0) && (!show_the_system_info))) { show_numastat_info(); } free_node_ix_map_and_header(); exit(EXIT_SUCCESS); }