common_option.cpp
Go to the documentation of this file.00001
00012 #include <cstdlib>
00013
00014 #include <iostream>
00015 #include <sstream>
00016 #include <iterator>
00017 #include <cstdlib>
00018
00019 #include "op_config.h"
00020 #include "locate_images.h"
00021 #include "op_exception.h"
00022 #include "popt_options.h"
00023 #include "cverb.h"
00024 #include "common_option.h"
00025 #include "file_manip.h"
00026
00027 #include <sys/types.h>
00028 #include <sys/stat.h>
00029 #include <unistd.h>
00030 #include <limits.h>
00031
00032 using namespace std;
00033
00034 namespace options {
00035 double threshold = 0.0;
00036 string threshold_opt;
00037 string session_dir;
00038 string command_options;
00039 vector<string> image_path;
00040 string root_path;
00041 }
00042
00043 namespace {
00044
00045
00046 vector<string> verbose_strings;
00047
00048 popt::option common_options_array[] = {
00049 popt::option(verbose_strings, "verbose", 'V',
00050
00051 "verbose output", "all,debug,bfd,level1,sfile,stats,xml"),
00052 popt::option(options::session_dir, "session-dir", '\0',
00053 "specify session path to hold samples database and session data (" OP_SESSION_DIR_DEFAULT ")", "path"),
00054 popt::option(options::image_path, "image-path", 'p',
00055 "comma-separated path to search missing binaries", "path"),
00056 popt::option(options::root_path, "root", 'R',
00057 "path to filesystem to search for missing binaries", "path"),
00058 };
00059
00060 int session_dir_supplied;
00061
00062 double handle_threshold(string threshold)
00063 {
00064 double value = 0.0;
00065
00066 if (threshold.length()) {
00067 istringstream ss(threshold);
00068 if (!(ss >> value)) {
00069 cerr << "illegal threshold value: " << threshold
00070 << " allowed range: [0-100]" << endl;
00071 exit(EXIT_FAILURE);
00072 }
00073
00074 if (value < 0.0 || value > 100.0) {
00075 cerr << "illegal threshold value: " << threshold
00076 << " allowed range: [0-100]" << endl;
00077 exit(EXIT_FAILURE);
00078 }
00079 }
00080
00081 cverb << vdebug << "threshold: " << value << endl;;
00082
00083 return value;
00084 }
00085
00086
00087 vector<string> pre_parse_spec(vector<string> const & non_options)
00088 {
00089 vector<string> result;
00090
00091 for (size_t i = 0; i < non_options.size(); ++i) {
00092 if (non_options[i] == "{}") {
00093 result.push_back("{");
00094 result.push_back("}");
00095 } else {
00096 result.push_back(non_options[i]);
00097 }
00098 }
00099
00100 return result;
00101 }
00102
00103
00104 options::spec const parse_spec(vector<string> non_options)
00105 {
00106 bool in_first = false;
00107 bool in_second = false;
00108 bool first = false;
00109 bool second = false;
00110 options::spec pspec;
00111
00112 non_options = pre_parse_spec(non_options);
00113
00114 vector<string>::const_iterator it = non_options.begin();
00115 vector<string>::const_iterator end = non_options.end();
00116
00117 for (; it != end; ++it) {
00118 if (*it == "{") {
00119 if (in_first || in_second || second)
00120 goto fail;
00121 if (first) {
00122 in_second = true;
00123 second = true;
00124 } else {
00125 in_first = true;
00126 first = true;
00127 }
00128 continue;
00129 }
00130
00131 if (*it == "}") {
00132 if (in_first) {
00133 in_first = false;
00134 } else if (in_second) {
00135 in_second = false;
00136 } else {
00137 goto fail;
00138 }
00139 continue;
00140 }
00141
00142 if (in_first) {
00143 pspec.first.push_back(*it);
00144 } else if (in_second) {
00145 pspec.second.push_back(*it);
00146 } else {
00147 pspec.common.push_back(*it);
00148 }
00149 }
00150
00151 if (in_first || in_second || (first && !second))
00152 goto fail;
00153
00154 if (pspec.first.empty() && pspec.second.size())
00155 goto fail;
00156
00157 if (first && second) {
00158 pspec.first.insert(pspec.first.begin(), pspec.common.begin(),
00159 pspec.common.end());
00160 pspec.second.insert(pspec.second.begin(), pspec.common.begin(),
00161 pspec.common.end());
00162 }
00163
00164 return pspec;
00165 fail:
00166 cerr << "invalid profile specification ";
00167 copy(non_options.begin(), non_options.end(),
00168 ostream_iterator<string>(cerr, " "));
00169 cerr << endl;
00170 exit(EXIT_FAILURE);
00171 }
00172
00173 options::spec get_options(int argc, char const * argv[])
00174 {
00175 vector<string> non_options;
00176 popt::parse_options(argc, argv, non_options);
00177
00178
00179 if (options::session_dir.empty()) {
00180 char * cwd;
00181 struct stat sb;
00182
00183 cwd = new char[PATH_MAX];
00184 options::session_dir = (getcwd(cwd, PATH_MAX) == NULL) ? "" : cwd;
00185 delete [] cwd;
00186 options::session_dir +="/oprofile_data";
00187 if ((stat(options::session_dir.c_str(), &sb) < 0) ||
00188 ((sb.st_mode & S_IFMT) != S_IFDIR)) {
00189
00190 options::session_dir = "/var/lib/oprofile";
00191 }
00192 session_dir_supplied = 0;
00193 } else {
00194 session_dir_supplied = 1;
00195 }
00196 init_op_config_dirs(options::session_dir.c_str());
00197
00198 if (!options::threshold_opt.empty())
00199 options::threshold = handle_threshold(options::threshold_opt);
00200
00201 if (!verbose::setup(verbose_strings)) {
00202 cerr << "unknown --verbose= options\n";
00203 exit(EXIT_FAILURE);
00204 }
00205
00206
00207 ostringstream str;
00208 for (int i = 1; i < argc; ++i)
00209 str << argv[i] << " ";
00210 options::command_options = str.str();
00211
00212 return parse_spec(non_options);
00213 }
00214
00215 }
00216
00217
00218 int run_pp_tool(int argc, char const * argv[], pp_fct_run_t fct)
00219 {
00220 try {
00221 return fct(get_options(argc, argv));
00222 }
00223 catch (op_runtime_error const & e) {
00224 cerr << argv[0] << " error: " << e.what() << endl;
00225 }
00226 catch (op_fatal_error const & e) {
00227 cerr << argv[0] << " error: " << e.what() << endl;
00228 }
00229 catch (op_exception const & e) {
00230 cerr << argv[0] << " error: " << e.what() << endl;
00231 }
00232 catch (invalid_argument const & e) {
00233 cerr << argv[0] << " error: " << e.what() << endl;
00234 }
00235 catch (exception const & e) {
00236 cerr << argv[0] << " error: " << e.what() << endl;
00237 }
00238 catch (...) {
00239 cerr << argv[0] << " unknown exception" << endl;
00240 }
00241
00242 return EXIT_FAILURE;
00243 }
00244
00245
00246 demangle_type handle_demangle_option(string const & option)
00247 {
00248 if (option == "none")
00249 return dmt_none;
00250 if (option == "smart")
00251 return dmt_smart;
00252 if (option == "normal")
00253 return dmt_normal;
00254
00255 throw op_runtime_error("invalid option --demangle=" + option);
00256 }
00257
00258
00259 merge_option handle_merge_option(vector<string> const & mergespec,
00260 bool allow_lib, bool exclude_dependent)
00261 {
00262 using namespace options;
00263 merge_option merge_by;
00264
00265 merge_by.cpu = false;
00266 merge_by.lib = false;
00267 merge_by.tid = false;
00268 merge_by.tgid = false;
00269 merge_by.unitmask = false;
00270
00271 if (!allow_lib)
00272 merge_by.lib = true;
00273
00274 bool is_all = false;
00275
00276 vector<string>::const_iterator cit = mergespec.begin();
00277 vector<string>::const_iterator end = mergespec.end();
00278
00279 for (; cit != end; ++cit) {
00280 if (*cit == "cpu") {
00281 merge_by.cpu = true;
00282 } else if (*cit == "tid") {
00283 merge_by.tid = true;
00284 } else if (*cit == "tgid") {
00285
00286 merge_by.tgid = true;
00287 merge_by.tid = true;
00288 } else if ((*cit == "lib" || *cit == "library") && allow_lib) {
00289 merge_by.lib = true;
00290 } else if (*cit == "unitmask") {
00291 merge_by.unitmask = true;
00292 } else if (*cit == "all") {
00293 merge_by.cpu = true;
00294 merge_by.lib = true;
00295 merge_by.tid = true;
00296 merge_by.tgid = true;
00297 merge_by.unitmask = true;
00298 is_all = true;
00299 } else {
00300 cerr << "unknown merge option: " << *cit << endl;
00301 exit(EXIT_FAILURE);
00302 }
00303 }
00304
00305
00306
00307
00308 if (exclude_dependent && merge_by.lib && allow_lib && !is_all) {
00309 cerr << "--merge=lib is meaningless "
00310 << "with --exclude-dependent" << endl;
00311 exit(EXIT_FAILURE);
00312 }
00313
00314 return merge_by;
00315 }
00316
00317 bool was_session_dir_supplied(void)
00318 {
00319 return session_dir_supplied;
00320 }