CommandLineArguments.cxx 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856
  1. /*============================================================================
  2. KWSys - Kitware System Library
  3. Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
  4. Distributed under the OSI-approved BSD License (the "License");
  5. see accompanying file Copyright.txt for details.
  6. This software is distributed WITHOUT ANY WARRANTY; without even the
  7. implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  8. See the License for more information.
  9. ============================================================================*/
  10. #include "kwsysPrivate.h"
  11. #include KWSYS_HEADER(CommandLineArguments.hxx)
  12. #include KWSYS_HEADER(Configure.hxx)
  13. #include KWSYS_HEADER(String.hxx)
  14. // Work-around CMake dependency scanning limitation. This must
  15. // duplicate the above list of headers.
  16. #if 0
  17. # include "CommandLineArguments.hxx.in"
  18. # include "Configure.hxx.in"
  19. #endif
  20. #include <vector>
  21. #include <map>
  22. #include <set>
  23. #include <sstream>
  24. #include <iostream>
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <string.h>
  28. #ifdef _MSC_VER
  29. # pragma warning (disable: 4786)
  30. #endif
  31. #if defined(__sgi) && !defined(__GNUC__)
  32. # pragma set woff 1375 /* base class destructor not virtual */
  33. #endif
  34. #if 0
  35. # define CommandLineArguments_DEBUG(x) \
  36. std::cout << __LINE__ << " CLA: " << x << std::endl
  37. #else
  38. # define CommandLineArguments_DEBUG(x)
  39. #endif
  40. namespace KWSYS_NAMESPACE
  41. {
  42. //----------------------------------------------------------------------------
  43. //============================================================================
  44. struct CommandLineArgumentsCallbackStructure
  45. {
  46. const char* Argument;
  47. int ArgumentType;
  48. CommandLineArguments::CallbackType Callback;
  49. void* CallData;
  50. void* Variable;
  51. int VariableType;
  52. const char* Help;
  53. };
  54. class CommandLineArgumentsVectorOfStrings :
  55. public std::vector<kwsys::String> {};
  56. class CommandLineArgumentsSetOfStrings :
  57. public std::set<kwsys::String> {};
  58. class CommandLineArgumentsMapOfStrucs :
  59. public std::map<kwsys::String,
  60. CommandLineArgumentsCallbackStructure> {};
  61. class CommandLineArgumentsInternal
  62. {
  63. public:
  64. CommandLineArgumentsInternal()
  65. {
  66. this->UnknownArgumentCallback = 0;
  67. this->ClientData = 0;
  68. this->LastArgument = 0;
  69. }
  70. typedef CommandLineArgumentsVectorOfStrings VectorOfStrings;
  71. typedef CommandLineArgumentsMapOfStrucs CallbacksMap;
  72. typedef kwsys::String String;
  73. typedef CommandLineArgumentsSetOfStrings SetOfStrings;
  74. VectorOfStrings Argv;
  75. String Argv0;
  76. CallbacksMap Callbacks;
  77. CommandLineArguments::ErrorCallbackType UnknownArgumentCallback;
  78. void* ClientData;
  79. VectorOfStrings::size_type LastArgument;
  80. VectorOfStrings UnusedArguments;
  81. };
  82. //============================================================================
  83. //----------------------------------------------------------------------------
  84. //----------------------------------------------------------------------------
  85. CommandLineArguments::CommandLineArguments()
  86. {
  87. this->Internals = new CommandLineArguments::Internal;
  88. this->Help = "";
  89. this->LineLength = 80;
  90. this->StoreUnusedArgumentsFlag = false;
  91. }
  92. //----------------------------------------------------------------------------
  93. CommandLineArguments::~CommandLineArguments()
  94. {
  95. delete this->Internals;
  96. }
  97. //----------------------------------------------------------------------------
  98. void CommandLineArguments::Initialize(int argc, const char* const argv[])
  99. {
  100. int cc;
  101. this->Initialize();
  102. this->Internals->Argv0 = argv[0];
  103. for ( cc = 1; cc < argc; cc ++ )
  104. {
  105. this->ProcessArgument(argv[cc]);
  106. }
  107. }
  108. //----------------------------------------------------------------------------
  109. void CommandLineArguments::Initialize(int argc, char* argv[])
  110. {
  111. this->Initialize(argc, static_cast<const char* const*>(argv));
  112. }
  113. //----------------------------------------------------------------------------
  114. void CommandLineArguments::Initialize()
  115. {
  116. this->Internals->Argv.clear();
  117. this->Internals->LastArgument = 0;
  118. }
  119. //----------------------------------------------------------------------------
  120. void CommandLineArguments::ProcessArgument(const char* arg)
  121. {
  122. this->Internals->Argv.push_back(arg);
  123. }
  124. //----------------------------------------------------------------------------
  125. bool CommandLineArguments::GetMatchedArguments(
  126. std::vector<std::string>* matches,
  127. const std::string& arg)
  128. {
  129. matches->clear();
  130. CommandLineArguments::Internal::CallbacksMap::iterator it;
  131. // Does the argument match to any we know about?
  132. for ( it = this->Internals->Callbacks.begin();
  133. it != this->Internals->Callbacks.end();
  134. it ++ )
  135. {
  136. const CommandLineArguments::Internal::String& parg = it->first;
  137. CommandLineArgumentsCallbackStructure *cs = &it->second;
  138. if (cs->ArgumentType == CommandLineArguments::NO_ARGUMENT ||
  139. cs->ArgumentType == CommandLineArguments::SPACE_ARGUMENT)
  140. {
  141. if ( arg == parg )
  142. {
  143. matches->push_back(parg);
  144. }
  145. }
  146. else if ( arg.find( parg ) == 0 )
  147. {
  148. matches->push_back(parg);
  149. }
  150. }
  151. return !matches->empty();
  152. }
  153. //----------------------------------------------------------------------------
  154. int CommandLineArguments::Parse()
  155. {
  156. std::vector<std::string>::size_type cc;
  157. std::vector<std::string> matches;
  158. if ( this->StoreUnusedArgumentsFlag )
  159. {
  160. this->Internals->UnusedArguments.clear();
  161. }
  162. for ( cc = 0; cc < this->Internals->Argv.size(); cc ++ )
  163. {
  164. const std::string& arg = this->Internals->Argv[cc];
  165. CommandLineArguments_DEBUG("Process argument: " << arg);
  166. this->Internals->LastArgument = cc;
  167. if ( this->GetMatchedArguments(&matches, arg) )
  168. {
  169. // Ok, we found one or more arguments that match what user specified.
  170. // Let's find the longest one.
  171. CommandLineArguments::Internal::VectorOfStrings::size_type kk;
  172. CommandLineArguments::Internal::VectorOfStrings::size_type maxidx = 0;
  173. CommandLineArguments::Internal::String::size_type maxlen = 0;
  174. for ( kk = 0; kk < matches.size(); kk ++ )
  175. {
  176. if ( matches[kk].size() > maxlen )
  177. {
  178. maxlen = matches[kk].size();
  179. maxidx = kk;
  180. }
  181. }
  182. // So, the longest one is probably the right one. Now see if it has any
  183. // additional value
  184. CommandLineArgumentsCallbackStructure *cs
  185. = &this->Internals->Callbacks[matches[maxidx]];
  186. const std::string& sarg = matches[maxidx];
  187. if ( cs->Argument != sarg )
  188. {
  189. abort();
  190. }
  191. switch ( cs->ArgumentType )
  192. {
  193. case NO_ARGUMENT:
  194. // No value
  195. if ( !this->PopulateVariable(cs, 0) )
  196. {
  197. return 0;
  198. }
  199. break;
  200. case SPACE_ARGUMENT:
  201. if ( cc == this->Internals->Argv.size()-1 )
  202. {
  203. this->Internals->LastArgument --;
  204. return 0;
  205. }
  206. CommandLineArguments_DEBUG("This is a space argument: " << arg
  207. << " value: " << this->Internals->Argv[cc+1]);
  208. // Value is the next argument
  209. if ( !this->PopulateVariable(cs, this->Internals->Argv[cc+1].c_str()) )
  210. {
  211. return 0;
  212. }
  213. cc ++;
  214. break;
  215. case EQUAL_ARGUMENT:
  216. if ( arg.size() == sarg.size() || arg.at(sarg.size()) != '=' )
  217. {
  218. this->Internals->LastArgument --;
  219. return 0;
  220. }
  221. // Value is everythng followed the '=' sign
  222. if ( !this->PopulateVariable(cs, arg.c_str() + sarg.size() + 1) )
  223. {
  224. return 0;
  225. }
  226. break;
  227. case CONCAT_ARGUMENT:
  228. // Value is whatever follows the argument
  229. if ( !this->PopulateVariable(cs, arg.c_str() + sarg.size()) )
  230. {
  231. return 0;
  232. }
  233. break;
  234. case MULTI_ARGUMENT:
  235. // Suck in all the rest of the arguments
  236. CommandLineArguments_DEBUG("This is a multi argument: " << arg);
  237. for (cc++; cc < this->Internals->Argv.size(); ++ cc )
  238. {
  239. const std::string& marg = this->Internals->Argv[cc];
  240. CommandLineArguments_DEBUG(" check multi argument value: " << marg);
  241. if ( this->GetMatchedArguments(&matches, marg) )
  242. {
  243. CommandLineArguments_DEBUG("End of multi argument " << arg << " with value: " << marg);
  244. break;
  245. }
  246. CommandLineArguments_DEBUG(" populate multi argument value: " << marg);
  247. if ( !this->PopulateVariable(cs, marg.c_str()) )
  248. {
  249. return 0;
  250. }
  251. }
  252. if ( cc != this->Internals->Argv.size() )
  253. {
  254. CommandLineArguments_DEBUG("Again End of multi argument " << arg);
  255. cc--;
  256. continue;
  257. }
  258. break;
  259. default:
  260. std::cerr << "Got unknown argument type: \"" << cs->ArgumentType << "\"" << std::endl;
  261. this->Internals->LastArgument --;
  262. return 0;
  263. }
  264. }
  265. else
  266. {
  267. // Handle unknown arguments
  268. if ( this->Internals->UnknownArgumentCallback )
  269. {
  270. if ( !this->Internals->UnknownArgumentCallback(arg.c_str(),
  271. this->Internals->ClientData) )
  272. {
  273. this->Internals->LastArgument --;
  274. return 0;
  275. }
  276. return 1;
  277. }
  278. else if ( this->StoreUnusedArgumentsFlag )
  279. {
  280. CommandLineArguments_DEBUG("Store unused argument " << arg);
  281. this->Internals->UnusedArguments.push_back(arg);
  282. }
  283. else
  284. {
  285. std::cerr << "Got unknown argument: \"" << arg << "\"" << std::endl;
  286. this->Internals->LastArgument --;
  287. return 0;
  288. }
  289. }
  290. }
  291. return 1;
  292. }
  293. //----------------------------------------------------------------------------
  294. void CommandLineArguments::GetRemainingArguments(int* argc, char*** argv)
  295. {
  296. CommandLineArguments::Internal::VectorOfStrings::size_type size
  297. = this->Internals->Argv.size() - this->Internals->LastArgument + 1;
  298. CommandLineArguments::Internal::VectorOfStrings::size_type cc;
  299. // Copy Argv0 as the first argument
  300. char** args = new char*[ size ];
  301. args[0] = new char[ this->Internals->Argv0.size() + 1 ];
  302. strcpy(args[0], this->Internals->Argv0.c_str());
  303. int cnt = 1;
  304. // Copy everything after the LastArgument, since that was not parsed.
  305. for ( cc = this->Internals->LastArgument+1;
  306. cc < this->Internals->Argv.size(); cc ++ )
  307. {
  308. args[cnt] = new char[ this->Internals->Argv[cc].size() + 1];
  309. strcpy(args[cnt], this->Internals->Argv[cc].c_str());
  310. cnt ++;
  311. }
  312. *argc = cnt;
  313. *argv = args;
  314. }
  315. //----------------------------------------------------------------------------
  316. void CommandLineArguments::GetUnusedArguments(int* argc, char*** argv)
  317. {
  318. CommandLineArguments::Internal::VectorOfStrings::size_type size
  319. = this->Internals->UnusedArguments.size() + 1;
  320. CommandLineArguments::Internal::VectorOfStrings::size_type cc;
  321. // Copy Argv0 as the first argument
  322. char** args = new char*[ size ];
  323. args[0] = new char[ this->Internals->Argv0.size() + 1 ];
  324. strcpy(args[0], this->Internals->Argv0.c_str());
  325. int cnt = 1;
  326. // Copy everything after the LastArgument, since that was not parsed.
  327. for ( cc = 0;
  328. cc < this->Internals->UnusedArguments.size(); cc ++ )
  329. {
  330. kwsys::String &str = this->Internals->UnusedArguments[cc];
  331. args[cnt] = new char[ str.size() + 1];
  332. strcpy(args[cnt], str.c_str());
  333. cnt ++;
  334. }
  335. *argc = cnt;
  336. *argv = args;
  337. }
  338. //----------------------------------------------------------------------------
  339. void CommandLineArguments::DeleteRemainingArguments(int argc, char*** argv)
  340. {
  341. int cc;
  342. for ( cc = 0; cc < argc; ++ cc )
  343. {
  344. delete [] (*argv)[cc];
  345. }
  346. delete [] *argv;
  347. }
  348. //----------------------------------------------------------------------------
  349. void CommandLineArguments::AddCallback(const char* argument, ArgumentTypeEnum type,
  350. CallbackType callback, void* call_data, const char* help)
  351. {
  352. CommandLineArgumentsCallbackStructure s;
  353. s.Argument = argument;
  354. s.ArgumentType = type;
  355. s.Callback = callback;
  356. s.CallData = call_data;
  357. s.VariableType = CommandLineArguments::NO_VARIABLE_TYPE;
  358. s.Variable = 0;
  359. s.Help = help;
  360. this->Internals->Callbacks[argument] = s;
  361. this->GenerateHelp();
  362. }
  363. //----------------------------------------------------------------------------
  364. void CommandLineArguments::AddArgument(const char* argument, ArgumentTypeEnum type,
  365. VariableTypeEnum vtype, void* variable, const char* help)
  366. {
  367. CommandLineArgumentsCallbackStructure s;
  368. s.Argument = argument;
  369. s.ArgumentType = type;
  370. s.Callback = 0;
  371. s.CallData = 0;
  372. s.VariableType = vtype;
  373. s.Variable = variable;
  374. s.Help = help;
  375. this->Internals->Callbacks[argument] = s;
  376. this->GenerateHelp();
  377. }
  378. //----------------------------------------------------------------------------
  379. #define CommandLineArgumentsAddArgumentMacro(type, ctype) \
  380. void CommandLineArguments::AddArgument(const char* argument, ArgumentTypeEnum type, \
  381. ctype* variable, const char* help) \
  382. { \
  383. this->AddArgument(argument, type, CommandLineArguments::type##_TYPE, variable, help); \
  384. }
  385. CommandLineArgumentsAddArgumentMacro(BOOL, bool)
  386. CommandLineArgumentsAddArgumentMacro(INT, int)
  387. CommandLineArgumentsAddArgumentMacro(DOUBLE, double)
  388. CommandLineArgumentsAddArgumentMacro(STRING, char*)
  389. CommandLineArgumentsAddArgumentMacro(STL_STRING, std::string)
  390. CommandLineArgumentsAddArgumentMacro(VECTOR_BOOL, std::vector<bool>)
  391. CommandLineArgumentsAddArgumentMacro(VECTOR_INT, std::vector<int>)
  392. CommandLineArgumentsAddArgumentMacro(VECTOR_DOUBLE, std::vector<double>)
  393. CommandLineArgumentsAddArgumentMacro(VECTOR_STRING, std::vector<char*>)
  394. CommandLineArgumentsAddArgumentMacro(VECTOR_STL_STRING, std::vector<std::string>)
  395. //----------------------------------------------------------------------------
  396. #define CommandLineArgumentsAddBooleanArgumentMacro(type, ctype) \
  397. void CommandLineArguments::AddBooleanArgument(const char* argument, \
  398. ctype* variable, const char* help) \
  399. { \
  400. this->AddArgument(argument, CommandLineArguments::NO_ARGUMENT, \
  401. CommandLineArguments::type##_TYPE, variable, help); \
  402. }
  403. CommandLineArgumentsAddBooleanArgumentMacro(BOOL, bool)
  404. CommandLineArgumentsAddBooleanArgumentMacro(INT, int)
  405. CommandLineArgumentsAddBooleanArgumentMacro(DOUBLE, double)
  406. CommandLineArgumentsAddBooleanArgumentMacro(STRING, char*)
  407. CommandLineArgumentsAddBooleanArgumentMacro(STL_STRING, std::string)
  408. //----------------------------------------------------------------------------
  409. void CommandLineArguments::SetClientData(void* client_data)
  410. {
  411. this->Internals->ClientData = client_data;
  412. }
  413. //----------------------------------------------------------------------------
  414. void CommandLineArguments::SetUnknownArgumentCallback(
  415. CommandLineArguments::ErrorCallbackType callback)
  416. {
  417. this->Internals->UnknownArgumentCallback = callback;
  418. }
  419. //----------------------------------------------------------------------------
  420. const char* CommandLineArguments::GetHelp(const char* arg)
  421. {
  422. CommandLineArguments::Internal::CallbacksMap::iterator it
  423. = this->Internals->Callbacks.find(arg);
  424. if ( it == this->Internals->Callbacks.end() )
  425. {
  426. return 0;
  427. }
  428. // Since several arguments may point to the same argument, find the one this
  429. // one point to if this one is pointing to another argument.
  430. CommandLineArgumentsCallbackStructure *cs = &(it->second);
  431. for(;;)
  432. {
  433. CommandLineArguments::Internal::CallbacksMap::iterator hit
  434. = this->Internals->Callbacks.find(cs->Help);
  435. if ( hit == this->Internals->Callbacks.end() )
  436. {
  437. break;
  438. }
  439. cs = &(hit->second);
  440. }
  441. return cs->Help;
  442. }
  443. //----------------------------------------------------------------------------
  444. void CommandLineArguments::SetLineLength(unsigned int ll)
  445. {
  446. if ( ll < 9 || ll > 1000 )
  447. {
  448. return;
  449. }
  450. this->LineLength = ll;
  451. this->GenerateHelp();
  452. }
  453. //----------------------------------------------------------------------------
  454. const char* CommandLineArguments::GetArgv0()
  455. {
  456. return this->Internals->Argv0.c_str();
  457. }
  458. //----------------------------------------------------------------------------
  459. unsigned int CommandLineArguments::GetLastArgument()
  460. {
  461. return static_cast<unsigned int>(this->Internals->LastArgument + 1);
  462. }
  463. //----------------------------------------------------------------------------
  464. void CommandLineArguments::GenerateHelp()
  465. {
  466. std::ostringstream str;
  467. // Collapse all arguments into the map of vectors of all arguments that do
  468. // the same thing.
  469. CommandLineArguments::Internal::CallbacksMap::iterator it;
  470. typedef std::map<CommandLineArguments::Internal::String,
  471. CommandLineArguments::Internal::SetOfStrings > MapArgs;
  472. MapArgs mp;
  473. MapArgs::iterator mpit, smpit;
  474. for ( it = this->Internals->Callbacks.begin();
  475. it != this->Internals->Callbacks.end();
  476. it ++ )
  477. {
  478. CommandLineArgumentsCallbackStructure *cs = &(it->second);
  479. mpit = mp.find(cs->Help);
  480. if ( mpit != mp.end() )
  481. {
  482. mpit->second.insert(it->first);
  483. mp[it->first].insert(it->first);
  484. }
  485. else
  486. {
  487. mp[it->first].insert(it->first);
  488. }
  489. }
  490. for ( it = this->Internals->Callbacks.begin();
  491. it != this->Internals->Callbacks.end();
  492. it ++ )
  493. {
  494. CommandLineArgumentsCallbackStructure *cs = &(it->second);
  495. mpit = mp.find(cs->Help);
  496. if ( mpit != mp.end() )
  497. {
  498. mpit->second.insert(it->first);
  499. smpit = mp.find(it->first);
  500. CommandLineArguments::Internal::SetOfStrings::iterator sit;
  501. for ( sit = smpit->second.begin(); sit != smpit->second.end(); sit++ )
  502. {
  503. mpit->second.insert(*sit);
  504. }
  505. mp.erase(smpit);
  506. }
  507. else
  508. {
  509. mp[it->first].insert(it->first);
  510. }
  511. }
  512. // Find the length of the longest string
  513. CommandLineArguments::Internal::String::size_type maxlen = 0;
  514. for ( mpit = mp.begin();
  515. mpit != mp.end();
  516. mpit ++ )
  517. {
  518. CommandLineArguments::Internal::SetOfStrings::iterator sit;
  519. for ( sit = mpit->second.begin(); sit != mpit->second.end(); sit++ )
  520. {
  521. CommandLineArguments::Internal::String::size_type clen = sit->size();
  522. switch ( this->Internals->Callbacks[*sit].ArgumentType )
  523. {
  524. case CommandLineArguments::NO_ARGUMENT: clen += 0; break;
  525. case CommandLineArguments::CONCAT_ARGUMENT: clen += 3; break;
  526. case CommandLineArguments::SPACE_ARGUMENT: clen += 4; break;
  527. case CommandLineArguments::EQUAL_ARGUMENT: clen += 4; break;
  528. }
  529. if ( clen > maxlen )
  530. {
  531. maxlen = clen;
  532. }
  533. }
  534. }
  535. // Create format for that string
  536. char format[80];
  537. sprintf(format, " %%-%us ", static_cast<unsigned int>(maxlen));
  538. maxlen += 4; // For the space before and after the option
  539. // Print help for each option
  540. for ( mpit = mp.begin();
  541. mpit != mp.end();
  542. mpit ++ )
  543. {
  544. CommandLineArguments::Internal::SetOfStrings::iterator sit;
  545. for ( sit = mpit->second.begin(); sit != mpit->second.end(); sit++ )
  546. {
  547. str << std::endl;
  548. char argument[100];
  549. sprintf(argument, "%s", sit->c_str());
  550. switch ( this->Internals->Callbacks[*sit].ArgumentType )
  551. {
  552. case CommandLineArguments::NO_ARGUMENT: break;
  553. case CommandLineArguments::CONCAT_ARGUMENT: strcat(argument, "opt"); break;
  554. case CommandLineArguments::SPACE_ARGUMENT: strcat(argument, " opt"); break;
  555. case CommandLineArguments::EQUAL_ARGUMENT: strcat(argument, "=opt"); break;
  556. case CommandLineArguments::MULTI_ARGUMENT: strcat(argument, " opt opt ..."); break;
  557. }
  558. char buffer[80];
  559. sprintf(buffer, format, argument);
  560. str << buffer;
  561. }
  562. const char* ptr = this->Internals->Callbacks[mpit->first].Help;
  563. size_t len = strlen(ptr);
  564. int cnt = 0;
  565. while ( len > 0)
  566. {
  567. // If argument with help is longer than line length, split it on previous
  568. // space (or tab) and continue on the next line
  569. CommandLineArguments::Internal::String::size_type cc;
  570. for ( cc = 0; ptr[cc]; cc ++ )
  571. {
  572. if ( *ptr == ' ' || *ptr == '\t' )
  573. {
  574. ptr ++;
  575. len --;
  576. }
  577. }
  578. if ( cnt > 0 )
  579. {
  580. for ( cc = 0; cc < maxlen; cc ++ )
  581. {
  582. str << " ";
  583. }
  584. }
  585. CommandLineArguments::Internal::String::size_type skip = len;
  586. if ( skip > this->LineLength - maxlen )
  587. {
  588. skip = this->LineLength - maxlen;
  589. for ( cc = skip-1; cc > 0; cc -- )
  590. {
  591. if ( ptr[cc] == ' ' || ptr[cc] == '\t' )
  592. {
  593. break;
  594. }
  595. }
  596. if ( cc != 0 )
  597. {
  598. skip = cc;
  599. }
  600. }
  601. str.write(ptr, static_cast<std::streamsize>(skip));
  602. str << std::endl;
  603. ptr += skip;
  604. len -= skip;
  605. cnt ++;
  606. }
  607. }
  608. /*
  609. // This can help debugging help string
  610. str << endl;
  611. unsigned int cc;
  612. for ( cc = 0; cc < this->LineLength; cc ++ )
  613. {
  614. str << cc % 10;
  615. }
  616. str << endl;
  617. */
  618. this->Help = str.str();
  619. }
  620. //----------------------------------------------------------------------------
  621. void CommandLineArguments::PopulateVariable(
  622. bool* variable, const std::string& value)
  623. {
  624. if ( value == "1" || value == "ON" || value == "on" || value == "On" ||
  625. value == "TRUE" || value == "true" || value == "True" ||
  626. value == "yes" || value == "Yes" || value == "YES" )
  627. {
  628. *variable = true;
  629. }
  630. else
  631. {
  632. *variable = false;
  633. }
  634. }
  635. //----------------------------------------------------------------------------
  636. void CommandLineArguments::PopulateVariable(
  637. int* variable, const std::string& value)
  638. {
  639. char* res = 0;
  640. *variable = static_cast<int>(strtol(value.c_str(), &res, 10));
  641. //if ( res && *res )
  642. // {
  643. // Can handle non-int
  644. // }
  645. }
  646. //----------------------------------------------------------------------------
  647. void CommandLineArguments::PopulateVariable(
  648. double* variable, const std::string& value)
  649. {
  650. char* res = 0;
  651. *variable = strtod(value.c_str(), &res);
  652. //if ( res && *res )
  653. // {
  654. // Can handle non-double
  655. // }
  656. }
  657. //----------------------------------------------------------------------------
  658. void CommandLineArguments::PopulateVariable(
  659. char** variable, const std::string& value)
  660. {
  661. if ( *variable )
  662. {
  663. delete [] *variable;
  664. *variable = 0;
  665. }
  666. *variable = new char[ value.size() + 1 ];
  667. strcpy(*variable, value.c_str());
  668. }
  669. //----------------------------------------------------------------------------
  670. void CommandLineArguments::PopulateVariable(
  671. std::string* variable, const std::string& value)
  672. {
  673. *variable = value;
  674. }
  675. //----------------------------------------------------------------------------
  676. void CommandLineArguments::PopulateVariable(
  677. std::vector<bool>* variable, const std::string& value)
  678. {
  679. bool val = false;
  680. if ( value == "1" || value == "ON" || value == "on" || value == "On" ||
  681. value == "TRUE" || value == "true" || value == "True" ||
  682. value == "yes" || value == "Yes" || value == "YES" )
  683. {
  684. val = true;
  685. }
  686. variable->push_back(val);
  687. }
  688. //----------------------------------------------------------------------------
  689. void CommandLineArguments::PopulateVariable(
  690. std::vector<int>* variable, const std::string& value)
  691. {
  692. char* res = 0;
  693. variable->push_back(static_cast<int>(strtol(value.c_str(), &res, 10)));
  694. //if ( res && *res )
  695. // {
  696. // Can handle non-int
  697. // }
  698. }
  699. //----------------------------------------------------------------------------
  700. void CommandLineArguments::PopulateVariable(
  701. std::vector<double>* variable, const std::string& value)
  702. {
  703. char* res = 0;
  704. variable->push_back(strtod(value.c_str(), &res));
  705. //if ( res && *res )
  706. // {
  707. // Can handle non-int
  708. // }
  709. }
  710. //----------------------------------------------------------------------------
  711. void CommandLineArguments::PopulateVariable(
  712. std::vector<char*>* variable, const std::string& value)
  713. {
  714. char* var = new char[ value.size() + 1 ];
  715. strcpy(var, value.c_str());
  716. variable->push_back(var);
  717. }
  718. //----------------------------------------------------------------------------
  719. void CommandLineArguments::PopulateVariable(
  720. std::vector<std::string>* variable,
  721. const std::string& value)
  722. {
  723. variable->push_back(value);
  724. }
  725. //----------------------------------------------------------------------------
  726. bool CommandLineArguments::PopulateVariable(CommandLineArgumentsCallbackStructure* cs,
  727. const char* value)
  728. {
  729. // Call the callback
  730. if ( cs->Callback )
  731. {
  732. if ( !cs->Callback(cs->Argument, value, cs->CallData) )
  733. {
  734. this->Internals->LastArgument --;
  735. return 0;
  736. }
  737. }
  738. CommandLineArguments_DEBUG("Set argument: " << cs->Argument << " to " << value);
  739. if ( cs->Variable )
  740. {
  741. std::string var = "1";
  742. if ( value )
  743. {
  744. var = value;
  745. }
  746. switch ( cs->VariableType )
  747. {
  748. case CommandLineArguments::INT_TYPE:
  749. this->PopulateVariable(static_cast<int*>(cs->Variable), var);
  750. break;
  751. case CommandLineArguments::DOUBLE_TYPE:
  752. this->PopulateVariable(static_cast<double*>(cs->Variable), var);
  753. break;
  754. case CommandLineArguments::STRING_TYPE:
  755. this->PopulateVariable(static_cast<char**>(cs->Variable), var);
  756. break;
  757. case CommandLineArguments::STL_STRING_TYPE:
  758. this->PopulateVariable(static_cast<std::string*>(cs->Variable), var);
  759. break;
  760. case CommandLineArguments::BOOL_TYPE:
  761. this->PopulateVariable(static_cast<bool*>(cs->Variable), var);
  762. break;
  763. case CommandLineArguments::VECTOR_BOOL_TYPE:
  764. this->PopulateVariable(static_cast<std::vector<bool>*>(cs->Variable), var);
  765. break;
  766. case CommandLineArguments::VECTOR_INT_TYPE:
  767. this->PopulateVariable(static_cast<std::vector<int>*>(cs->Variable), var);
  768. break;
  769. case CommandLineArguments::VECTOR_DOUBLE_TYPE:
  770. this->PopulateVariable(static_cast<std::vector<double>*>(cs->Variable), var);
  771. break;
  772. case CommandLineArguments::VECTOR_STRING_TYPE:
  773. this->PopulateVariable(static_cast<std::vector<char*>*>(cs->Variable), var);
  774. break;
  775. case CommandLineArguments::VECTOR_STL_STRING_TYPE:
  776. this->PopulateVariable(static_cast<std::vector<std::string>*>(cs->Variable), var);
  777. break;
  778. default:
  779. std::cerr << "Got unknown variable type: \"" << cs->VariableType << "\"" << std::endl;
  780. this->Internals->LastArgument --;
  781. return 0;
  782. }
  783. }
  784. return 1;
  785. }
  786. } // namespace KWSYS_NAMESPACE