cmStringCommand.cxx 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776
  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. mf->MarkVariableAsUsed(name);
  446. }
  447. }
  448. //----------------------------------------------------------------------------
  449. void cmStringCommand::StoreMatches(cmMakefile* mf,cmsys::RegularExpression& re)
  450. {
  451. for (unsigned int i=0; i<10; i++)
  452. {
  453. char name[128];
  454. sprintf(name, "CMAKE_MATCH_%d", i);
  455. mf->AddDefinition(name, re.match(i).c_str());
  456. mf->MarkVariableAsUsed(name);
  457. }
  458. }
  459. //----------------------------------------------------------------------------
  460. bool cmStringCommand::HandleCompareCommand(std::vector<std::string> const&
  461. args)
  462. {
  463. if(args.size() < 2)
  464. {
  465. this->SetError("sub-command COMPARE requires a mode to be specified.");
  466. return false;
  467. }
  468. std::string mode = args[1];
  469. if((mode == "EQUAL") || (mode == "NOTEQUAL") ||
  470. (mode == "LESS") || (mode == "GREATER"))
  471. {
  472. if(args.size() < 5)
  473. {
  474. std::string e = "sub-command COMPARE, mode ";
  475. e += mode;
  476. e += " needs at least 5 arguments total to command.";
  477. this->SetError(e.c_str());
  478. return false;
  479. }
  480. const std::string& left = args[2];
  481. const std::string& right = args[3];
  482. const std::string& outvar = args[4];
  483. bool result;
  484. if(mode == "LESS")
  485. {
  486. result = (left < right);
  487. }
  488. else if(mode == "GREATER")
  489. {
  490. result = (left > right);
  491. }
  492. else if(mode == "EQUAL")
  493. {
  494. result = (left == right);
  495. }
  496. else // if(mode == "NOTEQUAL")
  497. {
  498. result = !(left == right);
  499. }
  500. if(result)
  501. {
  502. this->Makefile->AddDefinition(outvar.c_str(), "1");
  503. }
  504. else
  505. {
  506. this->Makefile->AddDefinition(outvar.c_str(), "0");
  507. }
  508. return true;
  509. }
  510. std::string e = "sub-command COMPARE does not recognize mode "+mode;
  511. this->SetError(e.c_str());
  512. return false;
  513. }
  514. //----------------------------------------------------------------------------
  515. bool cmStringCommand::HandleReplaceCommand(std::vector<std::string> const&
  516. args)
  517. {
  518. if(args.size() < 5)
  519. {
  520. this->SetError("sub-command REPLACE requires at least four arguments.");
  521. return false;
  522. }
  523. const std::string& matchExpression = args[1];
  524. const std::string& replaceExpression = args[2];
  525. const std::string& variableName = args[3];
  526. std::string input = args[4];
  527. for(unsigned int i=5; i < args.size(); ++i)
  528. {
  529. input += args[i];
  530. }
  531. cmsys::SystemTools::ReplaceString(input, matchExpression.c_str(),
  532. replaceExpression.c_str());
  533. this->Makefile->AddDefinition(variableName.c_str(), input.c_str());
  534. return true;
  535. }
  536. //----------------------------------------------------------------------------
  537. bool cmStringCommand::HandleSubstringCommand(std::vector<std::string> const&
  538. args)
  539. {
  540. if(args.size() != 5)
  541. {
  542. this->SetError("sub-command SUBSTRING requires four arguments.");
  543. return false;
  544. }
  545. const std::string& stringValue = args[1];
  546. int begin = atoi(args[2].c_str());
  547. int end = atoi(args[3].c_str());
  548. const std::string& variableName = args[4];
  549. size_t stringLength = stringValue.size();
  550. int intStringLength = static_cast<int>(stringLength);
  551. if ( begin < 0 || begin > intStringLength )
  552. {
  553. cmOStringStream ostr;
  554. ostr << "begin index: " << begin << " is out of range 0 - "
  555. << stringLength;
  556. this->SetError(ostr.str().c_str());
  557. return false;
  558. }
  559. int leftOverLength = intStringLength - begin;
  560. if ( end < -1 || end > leftOverLength )
  561. {
  562. cmOStringStream ostr;
  563. ostr << "end index: " << end << " is out of range " << 0 << " - "
  564. << leftOverLength;
  565. this->SetError(ostr.str().c_str());
  566. return false;
  567. }
  568. this->Makefile->AddDefinition(variableName.c_str(),
  569. stringValue.substr(begin, end).c_str());
  570. return true;
  571. }
  572. //----------------------------------------------------------------------------
  573. bool cmStringCommand
  574. ::HandleLengthCommand(std::vector<std::string> const& args)
  575. {
  576. if(args.size() != 3)
  577. {
  578. this->SetError("sub-command LENGTH requires two arguments.");
  579. return false;
  580. }
  581. const std::string& stringValue = args[1];
  582. const std::string& variableName = args[2];
  583. size_t length = stringValue.size();
  584. char buffer[1024];
  585. sprintf(buffer, "%d", static_cast<int>(length));
  586. this->Makefile->AddDefinition(variableName.c_str(), buffer);
  587. return true;
  588. }
  589. //----------------------------------------------------------------------------
  590. bool cmStringCommand::HandleStripCommand(
  591. std::vector<std::string> const& args)
  592. {
  593. if(args.size() != 3)
  594. {
  595. this->SetError("sub-command STRIP requires two arguments.");
  596. return false;
  597. }
  598. const std::string& stringValue = args[1];
  599. const std::string& variableName = args[2];
  600. size_t inStringLength = stringValue.size();
  601. size_t startPos = inStringLength + 1;
  602. size_t endPos = 0;
  603. const char* ptr = stringValue.c_str();
  604. size_t cc;
  605. for ( cc = 0; cc < inStringLength; ++ cc )
  606. {
  607. if ( !isspace(*ptr) )
  608. {
  609. if ( startPos > inStringLength )
  610. {
  611. startPos = cc;
  612. }
  613. endPos = cc;
  614. }
  615. ++ ptr;
  616. }
  617. size_t outLength = 0;
  618. // if the input string didn't contain any non-space characters, return
  619. // an empty string
  620. if (startPos > inStringLength)
  621. {
  622. outLength = 0;
  623. startPos = 0;
  624. }
  625. else
  626. {
  627. outLength=endPos - startPos + 1;
  628. }
  629. this->Makefile->AddDefinition(variableName.c_str(),
  630. stringValue.substr(startPos, outLength).c_str());
  631. return true;
  632. }
  633. //----------------------------------------------------------------------------
  634. bool cmStringCommand
  635. ::HandleRandomCommand(std::vector<std::string> const& args)
  636. {
  637. if(args.size() < 2 || args.size() == 3 || args.size() == 5)
  638. {
  639. this->SetError("sub-command RANDOM requires at least one argument.");
  640. return false;
  641. }
  642. static bool seeded = false;
  643. bool force_seed = false;
  644. int seed = (int) time(NULL);
  645. int length = 5;
  646. const char cmStringCommandDefaultAlphabet[] = "qwertyuiopasdfghjklzxcvbnm"
  647. "QWERTYUIOPASDFGHJKLZXCVBNM"
  648. "0123456789";
  649. std::string alphabet;
  650. if ( args.size() > 3 )
  651. {
  652. size_t i = 1;
  653. size_t stopAt = args.size() - 2;
  654. for ( ; i < stopAt; ++i )
  655. {
  656. if ( args[i] == "LENGTH" )
  657. {
  658. ++i;
  659. length = atoi(args[i].c_str());
  660. }
  661. else if ( args[i] == "ALPHABET" )
  662. {
  663. ++i;
  664. alphabet = args[i];
  665. }
  666. else if ( args[i] == "RANDOM_SEED" )
  667. {
  668. ++i;
  669. seed = atoi(args[i].c_str());
  670. force_seed = true;
  671. }
  672. }
  673. }
  674. if ( !alphabet.size() )
  675. {
  676. alphabet = cmStringCommandDefaultAlphabet;
  677. }
  678. double sizeofAlphabet = static_cast<double>(alphabet.size());
  679. if ( sizeofAlphabet < 1 )
  680. {
  681. this->SetError("sub-command RANDOM invoked with bad alphabet.");
  682. return false;
  683. }
  684. if ( length < 1 )
  685. {
  686. this->SetError("sub-command RANDOM invoked with bad length.");
  687. return false;
  688. }
  689. const std::string& variableName = args[args.size()-1];
  690. std::vector<char> result;
  691. if (!seeded || force_seed)
  692. {
  693. seeded = true;
  694. srand(seed);
  695. }
  696. const char* alphaPtr = alphabet.c_str();
  697. int cc;
  698. for ( cc = 0; cc < length; cc ++ )
  699. {
  700. int idx=(int) (sizeofAlphabet* rand()/(RAND_MAX+1.0));
  701. result.push_back(*(alphaPtr + idx));
  702. }
  703. result.push_back(0);
  704. this->Makefile->AddDefinition(variableName.c_str(), &*result.begin());
  705. return true;
  706. }