CommandLineArguments.cxx 24 KB

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