Annotation of /trunk/indra/newview/llcommandlineparser.cpp
Parent Directory
|
Revision Log
Revision 137 - (view) (download)
| 1 : | mjm | 135 | /** |
| 2 : | * @file llcommandlineparser.cpp | ||
| 3 : | * @brief The LLCommandLineParser class definitions | ||
| 4 : | * | ||
| 5 : | * $LicenseInfo:firstyear=2007&license=viewergpl$ | ||
| 6 : | * | ||
| 7 : | mjm | 137 | * Copyright (c) 2007-2010, Linden Research, Inc. |
| 8 : | mjm | 135 | * |
| 9 : | * Second Life Viewer Source Code | ||
| 10 : | * The source code in this file ("Source Code") is provided by Linden Lab | ||
| 11 : | * to you under the terms of the GNU General Public License, version 2.0 | ||
| 12 : | * ("GPL"), unless you have obtained a separate licensing agreement | ||
| 13 : | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
| 14 : | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
| 15 : | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 | ||
| 16 : | * | ||
| 17 : | * There are special exceptions to the terms and conditions of the GPL as | ||
| 18 : | * it is applied to this Source Code. View the full text of the exception | ||
| 19 : | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
| 20 : | * online at | ||
| 21 : | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
| 22 : | * | ||
| 23 : | * By copying, modifying or distributing this software, you acknowledge | ||
| 24 : | * that you have read and understood your obligations described above, | ||
| 25 : | * and agree to abide by those obligations. | ||
| 26 : | * | ||
| 27 : | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
| 28 : | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
| 29 : | * COMPLETENESS OR PERFORMANCE. | ||
| 30 : | * $/LicenseInfo$ | ||
| 31 : | */ | ||
| 32 : | |||
| 33 : | #include "llviewerprecompiledheaders.h" | ||
| 34 : | #include "llcommandlineparser.h" | ||
| 35 : | |||
| 36 : | // *NOTE: The boost::lexical_cast generates | ||
| 37 : | // the warning C4701(local used with out assignment) in VC7.1. | ||
| 38 : | // Disable the warning for the boost includes. | ||
| 39 : | #if _MSC_VER | ||
| 40 : | # pragma warning(push) | ||
| 41 : | # pragma warning( disable : 4701 ) | ||
| 42 : | #else | ||
| 43 : | // NOTE: For the other platforms? | ||
| 44 : | #endif | ||
| 45 : | |||
| 46 : | #include <boost/program_options.hpp> | ||
| 47 : | #include <boost/bind.hpp> | ||
| 48 : | #include<boost/tokenizer.hpp> | ||
| 49 : | |||
| 50 : | #if _MSC_VER | ||
| 51 : | # pragma warning(pop) | ||
| 52 : | #endif | ||
| 53 : | |||
| 54 : | #include "llsdserialize.h" | ||
| 55 : | #include <iostream> | ||
| 56 : | #include <sstream> | ||
| 57 : | |||
| 58 : | #include "llcontrol.h" | ||
| 59 : | |||
| 60 : | namespace po = boost::program_options; | ||
| 61 : | |||
| 62 : | // *NTOE:MEP - Currently the boost object reside in file scope. | ||
| 63 : | // This has a couple of negatives, they are always around and | ||
| 64 : | // there can be only one instance of each. | ||
| 65 : | // The plus is that the boost-ly-ness of this implementation is | ||
| 66 : | // hidden from the rest of the world. | ||
| 67 : | // Its importatnt to realize that multiple LLCommandLineParser objects | ||
| 68 : | // will all have this single repository of option escs and parsed options. | ||
| 69 : | // This could be good or bad, and probably won't matter for most use cases. | ||
| 70 : | namespace | ||
| 71 : | { | ||
| 72 : | po::options_description gOptionsDesc; | ||
| 73 : | po::positional_options_description gPositionalOptions; | ||
| 74 : | po::variables_map gVariableMap; | ||
| 75 : | |||
| 76 : | const LLCommandLineParser::token_vector_t gEmptyValue; | ||
| 77 : | |||
| 78 : | void read_file_into_string(std::string& str, const std::basic_istream < char >& file) | ||
| 79 : | { | ||
| 80 : | std::ostringstream oss; | ||
| 81 : | oss << file.rdbuf(); | ||
| 82 : | str = oss.str(); | ||
| 83 : | } | ||
| 84 : | |||
| 85 : | bool gPastLastOption = false; | ||
| 86 : | } | ||
| 87 : | |||
| 88 : | class LLCLPError : public std::logic_error { | ||
| 89 : | public: | ||
| 90 : | LLCLPError(const std::string& what) : std::logic_error(what) {} | ||
| 91 : | }; | ||
| 92 : | |||
| 93 : | class LLCLPLastOption : public std::logic_error { | ||
| 94 : | public: | ||
| 95 : | LLCLPLastOption(const std::string& what) : std::logic_error(what) {} | ||
| 96 : | }; | ||
| 97 : | |||
| 98 : | class LLCLPValue : public po::value_semantic_codecvt_helper<char> | ||
| 99 : | { | ||
| 100 : | unsigned mMinTokens; | ||
| 101 : | unsigned mMaxTokens; | ||
| 102 : | bool mIsComposing; | ||
| 103 : | typedef boost::function1<void, const LLCommandLineParser::token_vector_t&> notify_callback_t; | ||
| 104 : | notify_callback_t mNotifyCallback; | ||
| 105 : | bool mLastOption; | ||
| 106 : | |||
| 107 : | public: | ||
| 108 : | LLCLPValue() : | ||
| 109 : | mMinTokens(0), | ||
| 110 : | mMaxTokens(0), | ||
| 111 : | mIsComposing(false), | ||
| 112 : | mLastOption(false) | ||
| 113 : | {} | ||
| 114 : | |||
| 115 : | virtual ~LLCLPValue() {}; | ||
| 116 : | |||
| 117 : | void setMinTokens(unsigned c) | ||
| 118 : | { | ||
| 119 : | mMinTokens = c; | ||
| 120 : | } | ||
| 121 : | |||
| 122 : | void setMaxTokens(unsigned c) | ||
| 123 : | { | ||
| 124 : | mMaxTokens = c; | ||
| 125 : | } | ||
| 126 : | |||
| 127 : | void setComposing(bool c) | ||
| 128 : | { | ||
| 129 : | mIsComposing = c; | ||
| 130 : | } | ||
| 131 : | |||
| 132 : | void setLastOption(bool c) | ||
| 133 : | { | ||
| 134 : | mLastOption = c; | ||
| 135 : | } | ||
| 136 : | |||
| 137 : | void setNotifyCallback(notify_callback_t f) | ||
| 138 : | { | ||
| 139 : | mNotifyCallback = f; | ||
| 140 : | } | ||
| 141 : | |||
| 142 : | // Overrides to support the value_semantic interface. | ||
| 143 : | virtual std::string name() const | ||
| 144 : | { | ||
| 145 : | const std::string arg("arg"); | ||
| 146 : | const std::string args("args"); | ||
| 147 : | return (max_tokens() > 1) ? args : arg; | ||
| 148 : | } | ||
| 149 : | |||
| 150 : | virtual unsigned min_tokens() const | ||
| 151 : | { | ||
| 152 : | return mMinTokens; | ||
| 153 : | } | ||
| 154 : | |||
| 155 : | virtual unsigned max_tokens() const | ||
| 156 : | { | ||
| 157 : | return mMaxTokens; | ||
| 158 : | } | ||
| 159 : | |||
| 160 : | virtual bool is_composing() const | ||
| 161 : | { | ||
| 162 : | return mIsComposing; | ||
| 163 : | } | ||
| 164 : | |||
| 165 : | virtual bool apply_default(boost::any& value_store) const | ||
| 166 : | { | ||
| 167 : | return false; // No defaults. | ||
| 168 : | } | ||
| 169 : | |||
| 170 : | virtual void notify(const boost::any& value_store) const | ||
| 171 : | { | ||
| 172 : | const LLCommandLineParser::token_vector_t* value = | ||
| 173 : | boost::any_cast<const LLCommandLineParser::token_vector_t>(&value_store); | ||
| 174 : | if(mNotifyCallback) | ||
| 175 : | { | ||
| 176 : | mNotifyCallback(*value); | ||
| 177 : | } | ||
| 178 : | |||
| 179 : | } | ||
| 180 : | |||
| 181 : | protected: | ||
| 182 : | void xparse(boost::any& value_store, | ||
| 183 : | const std::vector<std::string>& new_tokens) const | ||
| 184 : | { | ||
| 185 : | if(gPastLastOption) | ||
| 186 : | { | ||
| 187 : | throw(LLCLPLastOption("Don't parse no more!")); | ||
| 188 : | } | ||
| 189 : | |||
| 190 : | // Error checks. Needed? | ||
| 191 : | if (!value_store.empty() && !is_composing()) | ||
| 192 : | { | ||
| 193 : | throw(LLCLPError("Non composing value with multiple occurences.")); | ||
| 194 : | } | ||
| 195 : | if (new_tokens.size() < min_tokens() || new_tokens.size() > max_tokens()) | ||
| 196 : | { | ||
| 197 : | throw(LLCLPError("Illegal number of tokens specified.")); | ||
| 198 : | } | ||
| 199 : | |||
| 200 : | if(value_store.empty()) | ||
| 201 : | { | ||
| 202 : | value_store = boost::any(LLCommandLineParser::token_vector_t()); | ||
| 203 : | } | ||
| 204 : | LLCommandLineParser::token_vector_t* tv = | ||
| 205 : | boost::any_cast<LLCommandLineParser::token_vector_t>(&value_store); | ||
| 206 : | |||
| 207 : | for(unsigned i = 0; i < new_tokens.size() && i < mMaxTokens; ++i) | ||
| 208 : | { | ||
| 209 : | tv->push_back(new_tokens[i]); | ||
| 210 : | } | ||
| 211 : | |||
| 212 : | if(mLastOption) | ||
| 213 : | { | ||
| 214 : | gPastLastOption = true; | ||
| 215 : | } | ||
| 216 : | } | ||
| 217 : | }; | ||
| 218 : | |||
| 219 : | //---------------------------------------------------------------------------- | ||
| 220 : | // LLCommandLineParser defintions | ||
| 221 : | //---------------------------------------------------------------------------- | ||
| 222 : | void LLCommandLineParser::addOptionDesc(const std::string& option_name, | ||
| 223 : | boost::function1<void, const token_vector_t&> notify_callback, | ||
| 224 : | unsigned int token_count, | ||
| 225 : | const std::string& description, | ||
| 226 : | const std::string& short_name, | ||
| 227 : | bool composing, | ||
| 228 : | bool positional, | ||
| 229 : | bool last_option) | ||
| 230 : | { | ||
| 231 : | // Compose the name for boost::po. | ||
| 232 : | // It takes the format "long_name, short name" | ||
| 233 : | const std::string comma(","); | ||
| 234 : | std::string boost_option_name = option_name; | ||
| 235 : | if(short_name != LLStringUtil::null) | ||
| 236 : | { | ||
| 237 : | boost_option_name += comma; | ||
| 238 : | boost_option_name += short_name; | ||
| 239 : | } | ||
| 240 : | |||
| 241 : | LLCLPValue* value_desc = new LLCLPValue(); | ||
| 242 : | value_desc->setMinTokens(token_count); | ||
| 243 : | value_desc->setMaxTokens(token_count); | ||
| 244 : | value_desc->setComposing(composing); | ||
| 245 : | value_desc->setLastOption(last_option); | ||
| 246 : | |||
| 247 : | boost::shared_ptr<po::option_description> d( | ||
| 248 : | new po::option_description(boost_option_name.c_str(), | ||
| 249 : | value_desc, | ||
| 250 : | description.c_str())); | ||
| 251 : | |||
| 252 : | if(!notify_callback.empty()) | ||
| 253 : | { | ||
| 254 : | value_desc->setNotifyCallback(notify_callback); | ||
| 255 : | } | ||
| 256 : | |||
| 257 : | gOptionsDesc.add(d); | ||
| 258 : | |||
| 259 : | if(positional) | ||
| 260 : | { | ||
| 261 : | gPositionalOptions.add(boost_option_name.c_str(), token_count); | ||
| 262 : | } | ||
| 263 : | } | ||
| 264 : | |||
| 265 : | bool LLCommandLineParser::parseAndStoreResults(po::command_line_parser& clp) | ||
| 266 : | { | ||
| 267 : | try | ||
| 268 : | { | ||
| 269 : | clp.options(gOptionsDesc); | ||
| 270 : | clp.positional(gPositionalOptions); | ||
| 271 : | clp.style(po::command_line_style::default_style | ||
| 272 : | | po::command_line_style::allow_long_disguise); | ||
| 273 : | if(mExtraParser) | ||
| 274 : | { | ||
| 275 : | clp.extra_parser(mExtraParser); | ||
| 276 : | } | ||
| 277 : | |||
| 278 : | po::basic_parsed_options<char> opts = clp.run(); | ||
| 279 : | po::store(opts, gVariableMap); | ||
| 280 : | } | ||
| 281 : | catch(po::error& e) | ||
| 282 : | { | ||
| 283 : | llwarns << "Caught Error:" << e.what() << llendl; | ||
| 284 : | mErrorMsg = e.what(); | ||
| 285 : | return false; | ||
| 286 : | } | ||
| 287 : | catch(LLCLPError& e) | ||
| 288 : | { | ||
| 289 : | llwarns << "Caught Error:" << e.what() << llendl; | ||
| 290 : | mErrorMsg = e.what(); | ||
| 291 : | return false; | ||
| 292 : | } | ||
| 293 : | catch(LLCLPLastOption&) | ||
| 294 : | { | ||
| 295 : | // This exception means a token was read after an option | ||
| 296 : | // that must be the last option was reached (see url and slurl options) | ||
| 297 : | |||
| 298 : | // boost::po will have stored a malformed option. | ||
| 299 : | // All such options will be removed below. | ||
| 300 : | // The last option read, the last_option option, and its value | ||
| 301 : | // are put into the error message. | ||
| 302 : | std::string last_option; | ||
| 303 : | std::string last_value; | ||
| 304 : | for(po::variables_map::iterator i = gVariableMap.begin(); i != gVariableMap.end();) | ||
| 305 : | { | ||
| 306 : | po::variables_map::iterator tempI = i++; | ||
| 307 : | if(tempI->second.empty()) | ||
| 308 : | { | ||
| 309 : | gVariableMap.erase(tempI); | ||
| 310 : | } | ||
| 311 : | else | ||
| 312 : | { | ||
| 313 : | last_option = tempI->first; | ||
| 314 : | LLCommandLineParser::token_vector_t* tv = | ||
| 315 : | boost::any_cast<LLCommandLineParser::token_vector_t>(&(tempI->second.value())); | ||
| 316 : | if(!tv->empty()) | ||
| 317 : | { | ||
| 318 : | last_value = (*tv)[tv->size()-1]; | ||
| 319 : | } | ||
| 320 : | } | ||
| 321 : | } | ||
| 322 : | |||
| 323 : | // Continue without parsing. | ||
| 324 : | std::ostringstream msg; | ||
| 325 : | msg << "Caught Error: Found options after last option: " | ||
| 326 : | << last_option << " " | ||
| 327 : | << last_value; | ||
| 328 : | |||
| 329 : | llwarns << msg.str() << llendl; | ||
| 330 : | mErrorMsg = msg.str(); | ||
| 331 : | return false; | ||
| 332 : | } | ||
| 333 : | return true; | ||
| 334 : | } | ||
| 335 : | |||
| 336 : | bool LLCommandLineParser::parseCommandLine(int argc, char **argv) | ||
| 337 : | { | ||
| 338 : | po::command_line_parser clp(argc, argv); | ||
| 339 : | return parseAndStoreResults(clp); | ||
| 340 : | } | ||
| 341 : | |||
| 342 : | bool LLCommandLineParser::parseCommandLineString(const std::string& str) | ||
| 343 : | { | ||
| 344 : | // Split the string content into tokens | ||
| 345 : | boost::escaped_list_separator<char> sep("\\", "\r\n ", "\"'"); | ||
| 346 : | boost::tokenizer< boost::escaped_list_separator<char> > tok(str, sep); | ||
| 347 : | std::vector<std::string> tokens; | ||
| 348 : | // std::copy(tok.begin(), tok.end(), std::back_inserter(tokens)); | ||
| 349 : | for(boost::tokenizer< boost::escaped_list_separator<char> >::iterator i = tok.begin(); | ||
| 350 : | i != tok.end(); | ||
| 351 : | ++i) | ||
| 352 : | { | ||
| 353 : | if(0 != i->size()) | ||
| 354 : | { | ||
| 355 : | tokens.push_back(*i); | ||
| 356 : | } | ||
| 357 : | } | ||
| 358 : | |||
| 359 : | po::command_line_parser clp(tokens); | ||
| 360 : | return parseAndStoreResults(clp); | ||
| 361 : | |||
| 362 : | } | ||
| 363 : | |||
| 364 : | bool LLCommandLineParser::parseCommandLineFile(const std::basic_istream < char >& file) | ||
| 365 : | { | ||
| 366 : | std::string args; | ||
| 367 : | read_file_into_string(args, file); | ||
| 368 : | |||
| 369 : | return parseCommandLineString(args); | ||
| 370 : | } | ||
| 371 : | |||
| 372 : | void LLCommandLineParser::notify() | ||
| 373 : | { | ||
| 374 : | po::notify(gVariableMap); | ||
| 375 : | } | ||
| 376 : | |||
| 377 : | void LLCommandLineParser::printOptions() const | ||
| 378 : | { | ||
| 379 : | for(po::variables_map::iterator i = gVariableMap.begin(); i != gVariableMap.end(); ++i) | ||
| 380 : | { | ||
| 381 : | std::string name = i->first; | ||
| 382 : | token_vector_t values = i->second.as<token_vector_t>(); | ||
| 383 : | std::ostringstream oss; | ||
| 384 : | oss << name << ": "; | ||
| 385 : | for(token_vector_t::iterator t_itr = values.begin(); t_itr != values.end(); ++t_itr) | ||
| 386 : | { | ||
| 387 : | oss << t_itr->c_str() << " "; | ||
| 388 : | } | ||
| 389 : | llinfos << oss.str() << llendl; | ||
| 390 : | } | ||
| 391 : | } | ||
| 392 : | |||
| 393 : | std::ostream& LLCommandLineParser::printOptionsDesc(std::ostream& os) const | ||
| 394 : | { | ||
| 395 : | return os << gOptionsDesc; | ||
| 396 : | } | ||
| 397 : | |||
| 398 : | bool LLCommandLineParser::hasOption(const std::string& name) const | ||
| 399 : | { | ||
| 400 : | return gVariableMap.count(name) > 0; | ||
| 401 : | } | ||
| 402 : | |||
| 403 : | const LLCommandLineParser::token_vector_t& LLCommandLineParser::getOption(const std::string& name) const | ||
| 404 : | { | ||
| 405 : | if(hasOption(name)) | ||
| 406 : | { | ||
| 407 : | return gVariableMap[name].as<token_vector_t>(); | ||
| 408 : | } | ||
| 409 : | |||
| 410 : | return gEmptyValue; | ||
| 411 : | } | ||
| 412 : | |||
| 413 : | //---------------------------------------------------------------------------- | ||
| 414 : | // LLControlGroupCLP defintions | ||
| 415 : | //---------------------------------------------------------------------------- | ||
| 416 : | void setControlValueCB(const LLCommandLineParser::token_vector_t& value, | ||
| 417 : | const std::string& opt_name, | ||
| 418 : | LLControlGroup* ctrlGroup) | ||
| 419 : | { | ||
| 420 : | // *FIX: Do sematic conversion here. | ||
| 421 : | // LLSD (ImplString) Is no good for doing string to type conversion for... | ||
| 422 : | // booleans | ||
| 423 : | // compound types | ||
| 424 : | // ?... | ||
| 425 : | |||
| 426 : | LLControlVariable* ctrl = ctrlGroup->getControl(opt_name); | ||
| 427 : | if(NULL != ctrl) | ||
| 428 : | { | ||
| 429 : | switch(ctrl->type()) | ||
| 430 : | { | ||
| 431 : | case TYPE_BOOLEAN: | ||
| 432 : | if(value.size() > 1) | ||
| 433 : | { | ||
| 434 : | llwarns << "Ignoring extra tokens." << llendl; | ||
| 435 : | } | ||
| 436 : | |||
| 437 : | if(value.size() > 0) | ||
| 438 : | { | ||
| 439 : | // There's a token. check the string for true/false/1/0 etc. | ||
| 440 : | BOOL result = false; | ||
| 441 : | BOOL gotSet = LLStringUtil::convertToBOOL(value[0], result); | ||
| 442 : | if(gotSet) | ||
| 443 : | { | ||
| 444 : | ctrl->setValue(LLSD(result), false); | ||
| 445 : | } | ||
| 446 : | } | ||
| 447 : | else | ||
| 448 : | { | ||
| 449 : | ctrl->setValue(LLSD(true), false); | ||
| 450 : | } | ||
| 451 : | break; | ||
| 452 : | |||
| 453 : | default: | ||
| 454 : | { | ||
| 455 : | // For the default types, let llsd do the conversion. | ||
| 456 : | if(value.size() > 1 && ctrl->isType(TYPE_LLSD)) | ||
| 457 : | { | ||
| 458 : | // Assume its an array... | ||
| 459 : | LLSD llsdArray; | ||
| 460 : | for(unsigned int i = 0; i < value.size(); ++i) | ||
| 461 : | { | ||
| 462 : | LLSD llsdValue; | ||
| 463 : | llsdValue.assign(LLSD::String(value[i])); | ||
| 464 : | llsdArray.set(i, llsdValue); | ||
| 465 : | } | ||
| 466 : | |||
| 467 : | ctrl->setValue(llsdArray, false); | ||
| 468 : | } | ||
| 469 : | else if(value.size() > 0) | ||
| 470 : | { | ||
| 471 : | if(value.size() > 1) | ||
| 472 : | { | ||
| 473 : | llwarns << "Ignoring extra tokens mapped to the setting: " << opt_name << "." << llendl; | ||
| 474 : | } | ||
| 475 : | |||
| 476 : | LLSD llsdValue; | ||
| 477 : | llsdValue.assign(LLSD::String(value[0])); | ||
| 478 : | ctrl->setValue(llsdValue, false); | ||
| 479 : | } | ||
| 480 : | } | ||
| 481 : | break; | ||
| 482 : | } | ||
| 483 : | } | ||
| 484 : | else | ||
| 485 : | { | ||
| 486 : | llwarns << "Command Line option mapping '" | ||
| 487 : | << opt_name | ||
| 488 : | << "' not found! Ignoring." | ||
| 489 : | << llendl; | ||
| 490 : | } | ||
| 491 : | } | ||
| 492 : | |||
| 493 : | void LLControlGroupCLP::configure(const std::string& config_filename, LLControlGroup* controlGroup) | ||
| 494 : | { | ||
| 495 : | // This method reads the llsd based config file, and uses it to set | ||
| 496 : | // members of a control group. | ||
| 497 : | LLSD clpConfigLLSD; | ||
| 498 : | |||
| 499 : | llifstream input_stream; | ||
| 500 : | input_stream.open(config_filename, std::ios::in | std::ios::binary); | ||
| 501 : | |||
| 502 : | if(input_stream.is_open()) | ||
| 503 : | { | ||
| 504 : | LLSDSerialize::fromXML(clpConfigLLSD, input_stream); | ||
| 505 : | for(LLSD::map_iterator option_itr = clpConfigLLSD.beginMap(); | ||
| 506 : | option_itr != clpConfigLLSD.endMap(); | ||
| 507 : | ++option_itr) | ||
| 508 : | { | ||
| 509 : | LLSD::String long_name = option_itr->first; | ||
| 510 : | LLSD option_params = option_itr->second; | ||
| 511 : | |||
| 512 : | std::string desc("n/a"); | ||
| 513 : | if(option_params.has("desc")) | ||
| 514 : | { | ||
| 515 : | desc = option_params["desc"].asString(); | ||
| 516 : | } | ||
| 517 : | |||
| 518 : | std::string short_name = LLStringUtil::null; | ||
| 519 : | if(option_params.has("short")) | ||
| 520 : | { | ||
| 521 : | short_name = option_params["short"].asString(); | ||
| 522 : | } | ||
| 523 : | |||
| 524 : | unsigned int token_count = 0; | ||
| 525 : | if(option_params.has("count")) | ||
| 526 : | { | ||
| 527 : | token_count = option_params["count"].asInteger(); | ||
| 528 : | } | ||
| 529 : | |||
| 530 : | bool composing = false; | ||
| 531 : | if(option_params.has("compose")) | ||
| 532 : | { | ||
| 533 : | composing = option_params["compose"].asBoolean(); | ||
| 534 : | } | ||
| 535 : | |||
| 536 : | bool positional = false; | ||
| 537 : | if(option_params.has("positional")) | ||
| 538 : | { | ||
| 539 : | positional = option_params["positional"].asBoolean(); | ||
| 540 : | } | ||
| 541 : | |||
| 542 : | bool last_option = false; | ||
| 543 : | if(option_params.has("last_option")) | ||
| 544 : | { | ||
| 545 : | last_option = option_params["last_option"].asBoolean(); | ||
| 546 : | } | ||
| 547 : | |||
| 548 : | boost::function1<void, const token_vector_t&> callback; | ||
| 549 : | if(option_params.has("map-to") && (NULL != controlGroup)) | ||
| 550 : | { | ||
| 551 : | std::string controlName = option_params["map-to"].asString(); | ||
| 552 : | callback = boost::bind(setControlValueCB, _1, | ||
| 553 : | controlName, controlGroup); | ||
| 554 : | } | ||
| 555 : | |||
| 556 : | this->addOptionDesc( | ||
| 557 : | long_name, | ||
| 558 : | callback, | ||
| 559 : | token_count, | ||
| 560 : | desc, | ||
| 561 : | short_name, | ||
| 562 : | composing, | ||
| 563 : | positional, | ||
| 564 : | last_option); | ||
| 565 : | } | ||
| 566 : | } | ||
| 567 : | } |
| ViewVC Help | |
| Powered by ViewVC 1.0.0 |

