cmStringCommand.cxx 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759
  1. /*============================================================================
  2. CMake - Cross Platform Makefile Generator
  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 "cmStringCommand.h"
  11. #include <cmsys/RegularExpression.hxx>
  12. #include <cmsys/SystemTools.hxx>
  13. #include <stdlib.h> // required for atoi
  14. #include <ctype.h>
  15. #include <time.h>
  16. //----------------------------------------------------------------------------
  17. bool cmStringCommand
  18. ::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
  19. {
  20. if(args.size() < 1)
  21. {
  22. this->SetError("must be called with at least one argument.");
  23. return false;
  24. }
  25. const std::string &subCommand = args[0];
  26. if(subCommand == "REGEX")
  27. {
  28. return this->HandleRegexCommand(args);
  29. }
  30. else if(subCommand == "REPLACE")
  31. {
  32. return this->HandleReplaceCommand(args);
  33. }
  34. else if(subCommand == "TOLOWER")
  35. {
  36. return this->HandleToUpperLowerCommand(args, false);
  37. }
  38. else if(subCommand == "TOUPPER")
  39. {
  40. return this->HandleToUpperLowerCommand(args, true);
  41. }
  42. else if(subCommand == "COMPARE")
  43. {
  44. return this->HandleCompareCommand(args);
  45. }
  46. else if(subCommand == "ASCII")
  47. {
  48. return this->HandleAsciiCommand(args);
  49. }
  50. else if(subCommand == "CONFIGURE")
  51. {
  52. return this->HandleConfigureCommand(args);
  53. }
  54. else if(subCommand == "LENGTH")
  55. {
  56. return this->HandleLengthCommand(args);
  57. }
  58. else if(subCommand == "SUBSTRING")
  59. {
  60. return this->HandleSubstringCommand(args);
  61. }
  62. else if(subCommand == "STRIP")
  63. {
  64. return this->HandleStripCommand(args);
  65. }
  66. else if(subCommand == "RANDOM")
  67. {
  68. return this->HandleRandomCommand(args);
  69. }
  70. std::string e = "does not recognize sub-command "+subCommand;
  71. this->SetError(e.c_str());
  72. return false;
  73. }
  74. //----------------------------------------------------------------------------
  75. bool cmStringCommand::HandleToUpperLowerCommand(
  76. std::vector<std::string> const& args, bool toUpper)
  77. {
  78. if ( args.size() < 3 )
  79. {
  80. this->SetError("no output variable specified");
  81. return false;
  82. }
  83. std::string outvar = args[2];
  84. std::string output;
  85. if (toUpper)
  86. {
  87. output = cmSystemTools::UpperCase(args[1]);
  88. }
  89. else
  90. {
  91. output = cmSystemTools::LowerCase(args[1]);
  92. }
  93. // Store the output in the provided variable.
  94. this->Makefile->AddDefinition(outvar.c_str(), output.c_str());
  95. return true;
  96. }
  97. //----------------------------------------------------------------------------
  98. bool cmStringCommand::HandleAsciiCommand(std::vector<std::string> const& args)
  99. {
  100. if ( args.size() < 3 )
  101. {
  102. this->SetError("No output variable specified");
  103. return false;
  104. }
  105. std::string::size_type cc;
  106. std::string outvar = args[args.size()-1];
  107. std::string output = "";
  108. for ( cc = 1; cc < args.size()-1; cc ++ )
  109. {
  110. int ch = atoi(args[cc].c_str());
  111. if ( ch > 0 && ch < 256 )
  112. {
  113. output += static_cast<char>(ch);
  114. }
  115. else
  116. {
  117. std::string error = "Character with code ";
  118. error += args[cc];
  119. error += " does not exist.";
  120. this->SetError(error.c_str());
  121. return false;
  122. }
  123. }
  124. // Store the output in the provided variable.
  125. this->Makefile->AddDefinition(outvar.c_str(), output.c_str());
  126. return true;
  127. }
  128. //----------------------------------------------------------------------------
  129. bool cmStringCommand::HandleConfigureCommand(
  130. std::vector<std::string> const& args)
  131. {
  132. if ( args.size() < 2 )
  133. {
  134. this->SetError("No input string specified.");
  135. return false;
  136. }
  137. else if ( args.size() < 3 )
  138. {
  139. this->SetError("No output variable specified.");
  140. return false;
  141. }
  142. // Parse options.
  143. bool escapeQuotes = false;
  144. bool atOnly = false;
  145. for(unsigned int i = 3; i < args.size(); ++i)
  146. {
  147. if(args[i] == "@ONLY")
  148. {
  149. atOnly = true;
  150. }
  151. else if(args[i] == "ESCAPE_QUOTES")
  152. {
  153. escapeQuotes = true;
  154. }
  155. else
  156. {
  157. cmOStringStream err;
  158. err << "Unrecognized argument \"" << args[i] << "\"";
  159. this->SetError(err.str().c_str());
  160. return false;
  161. }
  162. }
  163. // Configure the string.
  164. std::string output;
  165. this->Makefile->ConfigureString(args[1], output, atOnly, escapeQuotes);
  166. // Store the output in the provided variable.
  167. this->Makefile->AddDefinition(args[2].c_str(), output.c_str());
  168. return true;
  169. }
  170. //----------------------------------------------------------------------------
  171. bool cmStringCommand::HandleRegexCommand(std::vector<std::string> const& args)
  172. {
  173. if(args.size() < 2)
  174. {
  175. this->SetError("sub-command REGEX requires a mode to be specified.");
  176. return false;
  177. }
  178. std::string mode = args[1];
  179. if(mode == "MATCH")
  180. {
  181. if(args.size() < 5)
  182. {
  183. this->SetError("sub-command REGEX, mode MATCH needs "
  184. "at least 5 arguments total to command.");
  185. return false;
  186. }
  187. return this->RegexMatch(args);
  188. }
  189. else if(mode == "MATCHALL")
  190. {
  191. if(args.size() < 5)
  192. {
  193. this->SetError("sub-command REGEX, mode MATCHALL needs "
  194. "at least 5 arguments total to command.");
  195. return false;
  196. }
  197. return this->RegexMatchAll(args);
  198. }
  199. else if(mode == "REPLACE")
  200. {
  201. if(args.size() < 6)
  202. {
  203. this->SetError("sub-command REGEX, mode REPLACE needs "
  204. "at least 6 arguments total to command.");
  205. return false;
  206. }
  207. return this->RegexReplace(args);
  208. }
  209. std::string e = "sub-command REGEX does not recognize mode "+mode;
  210. this->SetError(e.c_str());
  211. return false;
  212. }
  213. //----------------------------------------------------------------------------
  214. bool cmStringCommand::RegexMatch(std::vector<std::string> const& args)
  215. {
  216. //"STRING(REGEX MATCH <regular_expression> <output variable>
  217. // <input> [<input>...])\n";
  218. std::string regex = args[2];
  219. std::string outvar = args[3];
  220. // Concatenate all the last arguments together.
  221. std::string input = args[4];
  222. for(unsigned int i=5; i < args.size(); ++i)
  223. {
  224. input += args[i];
  225. }
  226. this->ClearMatches(this->Makefile);
  227. // Compile the regular expression.
  228. cmsys::RegularExpression re;
  229. if(!re.compile(regex.c_str()))
  230. {
  231. std::string e =
  232. "sub-command REGEX, mode MATCH failed to compile regex \""+regex+"\".";
  233. this->SetError(e.c_str());
  234. return false;
  235. }
  236. // Scan through the input for all matches.
  237. std::string output;
  238. if(re.find(input.c_str()))
  239. {
  240. this->StoreMatches(this->Makefile, re);
  241. std::string::size_type l = re.start();
  242. std::string::size_type r = re.end();
  243. if(r-l == 0)
  244. {
  245. std::string e =
  246. "sub-command REGEX, mode MATCH regex \""+regex+
  247. "\" matched an empty string.";
  248. this->SetError(e.c_str());
  249. return false;
  250. }
  251. output = input.substr(l, r-l);
  252. }
  253. // Store the output in the provided variable.
  254. this->Makefile->AddDefinition(outvar.c_str(), output.c_str());
  255. return true;
  256. }
  257. //----------------------------------------------------------------------------
  258. bool cmStringCommand::RegexMatchAll(std::vector<std::string> const& args)
  259. {
  260. //"STRING(REGEX MATCHALL <regular_expression> <output variable> <input>
  261. // [<input>...])\n";
  262. std::string regex = args[2];
  263. std::string outvar = args[3];
  264. // Concatenate all the last arguments together.
  265. std::string input = args[4];
  266. for(unsigned int i=5; i < args.size(); ++i)
  267. {
  268. input += args[i];
  269. }
  270. this->ClearMatches(this->Makefile);
  271. // Compile the regular expression.
  272. cmsys::RegularExpression re;
  273. if(!re.compile(regex.c_str()))
  274. {
  275. std::string e =
  276. "sub-command REGEX, mode MATCHALL failed to compile regex \""+
  277. regex+"\".";
  278. this->SetError(e.c_str());
  279. return false;
  280. }
  281. // Scan through the input for all matches.
  282. std::string output;
  283. const char* p = input.c_str();
  284. while(re.find(p))
  285. {
  286. this->StoreMatches(this->Makefile, re);
  287. std::string::size_type l = re.start();
  288. std::string::size_type r = re.end();
  289. if(r-l == 0)
  290. {
  291. std::string e = "sub-command REGEX, mode MATCHALL regex \""+
  292. regex+"\" matched an empty string.";
  293. this->SetError(e.c_str());
  294. return false;
  295. }
  296. if(output.length() > 0)
  297. {
  298. output += ";";
  299. }
  300. output += std::string(p+l, r-l);
  301. p += r;
  302. }
  303. // Store the output in the provided variable.
  304. this->Makefile->AddDefinition(outvar.c_str(), output.c_str());
  305. return true;
  306. }
  307. //----------------------------------------------------------------------------
  308. bool cmStringCommand::RegexReplace(std::vector<std::string> const& args)
  309. {
  310. //"STRING(REGEX REPLACE <regular_expression> <replace_expression>
  311. // <output variable> <input> [<input>...])\n"
  312. std::string regex = args[2];
  313. std::string replace = args[3];
  314. std::string outvar = args[4];
  315. // Pull apart the replace expression to find the escaped [0-9] values.
  316. std::vector<RegexReplacement> replacement;
  317. std::string::size_type l = 0;
  318. while(l < replace.length())
  319. {
  320. std::string::size_type r = replace.find("\\", l);
  321. if(r == std::string::npos)
  322. {
  323. r = replace.length();
  324. replacement.push_back(replace.substr(l, r-l));
  325. }
  326. else
  327. {
  328. if(r-l > 0)
  329. {
  330. replacement.push_back(replace.substr(l, r-l));
  331. }
  332. if(r == (replace.length()-1))
  333. {
  334. this->SetError("sub-command REGEX, mode REPLACE: "
  335. "replace-expression ends in a backslash.");
  336. return false;
  337. }
  338. if((replace[r+1] >= '0') && (replace[r+1] <= '9'))
  339. {
  340. replacement.push_back(replace[r+1]-'0');
  341. }
  342. else if(replace[r+1] == 'n')
  343. {
  344. replacement.push_back("\n");
  345. }
  346. else if(replace[r+1] == '\\')
  347. {
  348. replacement.push_back("\\");
  349. }
  350. else
  351. {
  352. std::string e = "sub-command REGEX, mode REPLACE: Unknown escape \"";
  353. e += replace.substr(r, 2);
  354. e += "\"in replace-expression.";
  355. this->SetError(e.c_str());
  356. return false;
  357. }
  358. r += 2;
  359. }
  360. l = r;
  361. }
  362. // Concatenate all the last arguments together.
  363. std::string input = args[5];
  364. for(unsigned int i=6; i < args.size(); ++i)
  365. {
  366. input += args[i];
  367. }
  368. this->ClearMatches(this->Makefile);
  369. // Compile the regular expression.
  370. cmsys::RegularExpression re;
  371. if(!re.compile(regex.c_str()))
  372. {
  373. std::string e =
  374. "sub-command REGEX, mode REPLACE failed to compile regex \""+
  375. regex+"\".";
  376. this->SetError(e.c_str());
  377. return false;
  378. }
  379. // Scan through the input for all matches.
  380. std::string output;
  381. std::string::size_type base = 0;
  382. while(re.find(input.c_str()+base))
  383. {
  384. this->StoreMatches(this->Makefile, re);
  385. std::string::size_type l2 = re.start();
  386. std::string::size_type r = re.end();
  387. // Concatenate the part of the input that was not matched.
  388. output += input.substr(base, l2);
  389. // Make sure the match had some text.
  390. if(r-l2 == 0)
  391. {
  392. std::string e = "sub-command REGEX, mode REPLACE regex \""+
  393. regex+"\" matched an empty string.";
  394. this->SetError(e.c_str());
  395. return false;
  396. }
  397. // Concatenate the replacement for the match.
  398. for(unsigned int i=0; i < replacement.size(); ++i)
  399. {
  400. if(replacement[i].number < 0)
  401. {
  402. // This is just a plain-text part of the replacement.
  403. output += replacement[i].value;
  404. }
  405. else
  406. {
  407. // Replace with part of the match.
  408. int n = replacement[i].number;
  409. std::string::size_type start = re.start(n);
  410. std::string::size_type end = re.end(n);
  411. std::string::size_type len = input.length()-base;
  412. if((start != std::string::npos) && (end != std::string::npos) &&
  413. (start <= len) && (end <= len))
  414. {
  415. output += input.substr(base+start, end-start);
  416. }
  417. else
  418. {
  419. std::string e =
  420. "sub-command REGEX, mode REPLACE: replace expression \""+
  421. replace+"\" contains an out-of-range escape for regex \""+
  422. regex+"\".";
  423. this->SetError(e.c_str());
  424. return false;
  425. }
  426. }
  427. }
  428. // Move past the match.
  429. base += r;
  430. }
  431. // Concatenate the text after the last match.
  432. output += input.substr(base, input.length()-base);
  433. // Store the output in the provided variable.
  434. this->Makefile->AddDefinition(outvar.c_str(), output.c_str());
  435. return true;
  436. }
  437. //----------------------------------------------------------------------------
  438. void cmStringCommand::ClearMatches(cmMakefile* mf)
  439. {
  440. for (unsigned int i=0; i<10; i++)
  441. {
  442. char name[128];
  443. sprintf(name, "CMAKE_MATCH_%d", i);
  444. mf->AddDefinition(name, "");
  445. }
  446. }
  447. //----------------------------------------------------------------------------
  448. void cmStringCommand::StoreMatches(cmMakefile* mf,cmsys::RegularExpression& re)
  449. {
  450. for (unsigned int i=0; i<10; i++)
  451. {
  452. char name[128];
  453. sprintf(name, "CMAKE_MATCH_%d", i);
  454. mf->AddDefinition(name, re.match(i).c_str());
  455. }
  456. }
  457. //----------------------------------------------------------------------------
  458. bool cmStringCommand::HandleCompareCommand(std::vector<std::string> const&
  459. args)
  460. {
  461. if(args.size() < 2)
  462. {
  463. this->SetError("sub-command COMPARE requires a mode to be specified.");
  464. return false;
  465. }
  466. std::string mode = args[1];
  467. if((mode == "EQUAL") || (mode == "NOTEQUAL") ||
  468. (mode == "LESS") || (mode == "GREATER"))
  469. {
  470. if(args.size() < 5)
  471. {
  472. std::string e = "sub-command COMPARE, mode ";
  473. e += mode;
  474. e += " needs at least 5 arguments total to command.";
  475. this->SetError(e.c_str());
  476. return false;
  477. }
  478. const std::string& left = args[2];
  479. const std::string& right = args[3];
  480. const std::string& outvar = args[4];
  481. bool result;
  482. if(mode == "LESS")
  483. {
  484. result = (left < right);
  485. }
  486. else if(mode == "GREATER")
  487. {
  488. result = (left > right);
  489. }
  490. else if(mode == "EQUAL")
  491. {
  492. result = (left == right);
  493. }
  494. else // if(mode == "NOTEQUAL")
  495. {
  496. result = !(left == right);
  497. }
  498. if(result)
  499. {
  500. this->Makefile->AddDefinition(outvar.c_str(), "1");
  501. }
  502. else
  503. {
  504. this->Makefile->AddDefinition(outvar.c_str(), "0");
  505. }
  506. return true;
  507. }
  508. std::string e = "sub-command COMPARE does not recognize mode "+mode;
  509. this->SetError(e.c_str());
  510. return false;
  511. }
  512. //----------------------------------------------------------------------------
  513. bool cmStringCommand::HandleReplaceCommand(std::vector<std::string> const&
  514. args)
  515. {
  516. if(args.size() < 5)
  517. {
  518. this->SetError("sub-command REPLACE requires four arguments.");
  519. return false;
  520. }
  521. const std::string& matchExpression = args[1];
  522. const std::string& replaceExpression = args[2];
  523. const std::string& variableName = args[3];
  524. std::string input = args[4];
  525. for(unsigned int i=5; i < args.size(); ++i)
  526. {
  527. input += args[i];
  528. }
  529. cmsys::SystemTools::ReplaceString(input, matchExpression.c_str(),
  530. replaceExpression.c_str());
  531. this->Makefile->AddDefinition(variableName.c_str(), input.c_str());
  532. return true;
  533. }
  534. //----------------------------------------------------------------------------
  535. bool cmStringCommand::HandleSubstringCommand(std::vector<std::string> const&
  536. args)
  537. {
  538. if(args.size() != 5)
  539. {
  540. this->SetError("sub-command REPLACE requires four arguments.");
  541. return false;
  542. }
  543. const std::string& stringValue = args[1];
  544. int begin = atoi(args[2].c_str());
  545. int end = atoi(args[3].c_str());
  546. const std::string& variableName = args[4];
  547. size_t stringLength = stringValue.size();
  548. int intStringLength = static_cast<int>(stringLength);
  549. if ( begin < 0 || begin > intStringLength )
  550. {
  551. cmOStringStream ostr;
  552. ostr << "begin index: " << begin << " is out of range 0 - "
  553. << stringLength;
  554. this->SetError(ostr.str().c_str());
  555. return false;
  556. }
  557. int leftOverLength = intStringLength - begin;
  558. if ( end < 0 || end > leftOverLength )
  559. {
  560. cmOStringStream ostr;
  561. ostr << "end index: " << end << " is out of range " << 0 << " - "
  562. << leftOverLength;
  563. this->SetError(ostr.str().c_str());
  564. return false;
  565. }
  566. this->Makefile->AddDefinition(variableName.c_str(),
  567. stringValue.substr(begin, end).c_str());
  568. return true;
  569. }
  570. //----------------------------------------------------------------------------
  571. bool cmStringCommand
  572. ::HandleLengthCommand(std::vector<std::string> const& args)
  573. {
  574. if(args.size() != 3)
  575. {
  576. this->SetError("sub-command LENGTH requires two arguments.");
  577. return false;
  578. }
  579. const std::string& stringValue = args[1];
  580. const std::string& variableName = args[2];
  581. size_t length = stringValue.size();
  582. char buffer[1024];
  583. sprintf(buffer, "%d", static_cast<int>(length));
  584. this->Makefile->AddDefinition(variableName.c_str(), buffer);
  585. return true;
  586. }
  587. //----------------------------------------------------------------------------
  588. bool cmStringCommand::HandleStripCommand(
  589. std::vector<std::string> const& args)
  590. {
  591. if(args.size() != 3)
  592. {
  593. this->SetError("sub-command LENGTH requires two arguments.");
  594. return false;
  595. }
  596. const std::string& stringValue = args[1];
  597. const std::string& variableName = args[2];
  598. size_t inStringLength = stringValue.size();
  599. size_t startPos = inStringLength + 1;
  600. size_t endPos = 0;
  601. const char* ptr = stringValue.c_str();
  602. size_t cc;
  603. for ( cc = 0; cc < inStringLength; ++ cc )
  604. {
  605. if ( !isspace(*ptr) )
  606. {
  607. if ( startPos > inStringLength )
  608. {
  609. startPos = cc;
  610. }
  611. endPos = cc;
  612. }
  613. ++ ptr;
  614. }
  615. size_t outLength = 0;
  616. // if the input string didn't contain any non-space characters, return
  617. // an empty string
  618. if (startPos > inStringLength)
  619. {
  620. outLength = 0;
  621. startPos = 0;
  622. }
  623. else
  624. {
  625. outLength=endPos - startPos + 1;
  626. }
  627. this->Makefile->AddDefinition(variableName.c_str(),
  628. stringValue.substr(startPos, outLength).c_str());
  629. return true;
  630. }
  631. //----------------------------------------------------------------------------
  632. bool cmStringCommand
  633. ::HandleRandomCommand(std::vector<std::string> const& args)
  634. {
  635. if(args.size() < 2 || args.size() == 3 || args.size() == 5)
  636. {
  637. this->SetError("sub-command RANDOM requires at least one argument.");
  638. return false;
  639. }
  640. int length = 5;
  641. const char cmStringCommandDefaultAlphabet[] = "qwertyuiopasdfghjklzxcvbnm"
  642. "QWERTYUIOPASDFGHJKLZXCVBNM"
  643. "0123456789";
  644. std::string alphabet;
  645. if ( args.size() > 3 )
  646. {
  647. size_t i = 1;
  648. size_t stopAt = args.size() - 2;
  649. for ( ; i < stopAt; ++i )
  650. {
  651. if ( args[i] == "LENGTH" )
  652. {
  653. ++i;
  654. length = atoi(args[i].c_str());
  655. }
  656. else if ( args[i] == "ALPHABET" )
  657. {
  658. ++i;
  659. alphabet = args[i];
  660. }
  661. }
  662. }
  663. if ( !alphabet.size() )
  664. {
  665. alphabet = cmStringCommandDefaultAlphabet;
  666. }
  667. double sizeofAlphabet = alphabet.size();
  668. if ( sizeofAlphabet < 1 )
  669. {
  670. this->SetError("sub-command RANDOM invoked with bad alphabet.");
  671. return false;
  672. }
  673. if ( length < 1 )
  674. {
  675. this->SetError("sub-command RANDOM invoked with bad length.");
  676. return false;
  677. }
  678. const std::string& variableName = args[args.size()-1];
  679. std::vector<char> result;
  680. srand((int)time(NULL));
  681. const char* alphaPtr = alphabet.c_str();
  682. int cc;
  683. for ( cc = 0; cc < length; cc ++ )
  684. {
  685. int idx=(int) (sizeofAlphabet* rand()/(RAND_MAX+1.0));
  686. result.push_back(*(alphaPtr + idx));
  687. }
  688. result.push_back(0);
  689. this->Makefile->AddDefinition(variableName.c_str(), &*result.begin());
  690. return true;
  691. }