mirror of
https://github.com/reactos/CMake.git
synced 2025-01-10 13:41:20 +00:00
96afb12087
This converts the CMake license to a pure 3-clause OSI-approved BSD License. We drop the previous license clause requiring modified versions to be plainly marked. We also update the CMake copyright to cover the full development time range.
760 lines
20 KiB
C++
760 lines
20 KiB
C++
/*============================================================================
|
|
CMake - Cross Platform Makefile Generator
|
|
Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
|
|
|
|
Distributed under the OSI-approved BSD License (the "License");
|
|
see accompanying file Copyright.txt for details.
|
|
|
|
This software is distributed WITHOUT ANY WARRANTY; without even the
|
|
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
See the License for more information.
|
|
============================================================================*/
|
|
#include "cmStringCommand.h"
|
|
#include <cmsys/RegularExpression.hxx>
|
|
#include <cmsys/SystemTools.hxx>
|
|
|
|
#include <stdlib.h> // required for atoi
|
|
#include <ctype.h>
|
|
#include <time.h>
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool cmStringCommand
|
|
::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
|
|
{
|
|
if(args.size() < 1)
|
|
{
|
|
this->SetError("must be called with at least one argument.");
|
|
return false;
|
|
}
|
|
|
|
const std::string &subCommand = args[0];
|
|
if(subCommand == "REGEX")
|
|
{
|
|
return this->HandleRegexCommand(args);
|
|
}
|
|
else if(subCommand == "REPLACE")
|
|
{
|
|
return this->HandleReplaceCommand(args);
|
|
}
|
|
else if(subCommand == "TOLOWER")
|
|
{
|
|
return this->HandleToUpperLowerCommand(args, false);
|
|
}
|
|
else if(subCommand == "TOUPPER")
|
|
{
|
|
return this->HandleToUpperLowerCommand(args, true);
|
|
}
|
|
else if(subCommand == "COMPARE")
|
|
{
|
|
return this->HandleCompareCommand(args);
|
|
}
|
|
else if(subCommand == "ASCII")
|
|
{
|
|
return this->HandleAsciiCommand(args);
|
|
}
|
|
else if(subCommand == "CONFIGURE")
|
|
{
|
|
return this->HandleConfigureCommand(args);
|
|
}
|
|
else if(subCommand == "LENGTH")
|
|
{
|
|
return this->HandleLengthCommand(args);
|
|
}
|
|
else if(subCommand == "SUBSTRING")
|
|
{
|
|
return this->HandleSubstringCommand(args);
|
|
}
|
|
else if(subCommand == "STRIP")
|
|
{
|
|
return this->HandleStripCommand(args);
|
|
}
|
|
else if(subCommand == "RANDOM")
|
|
{
|
|
return this->HandleRandomCommand(args);
|
|
}
|
|
|
|
std::string e = "does not recognize sub-command "+subCommand;
|
|
this->SetError(e.c_str());
|
|
return false;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool cmStringCommand::HandleToUpperLowerCommand(
|
|
std::vector<std::string> const& args, bool toUpper)
|
|
{
|
|
if ( args.size() < 3 )
|
|
{
|
|
this->SetError("no output variable specified");
|
|
return false;
|
|
}
|
|
|
|
std::string outvar = args[2];
|
|
std::string output;
|
|
|
|
if (toUpper)
|
|
{
|
|
output = cmSystemTools::UpperCase(args[1]);
|
|
}
|
|
else
|
|
{
|
|
output = cmSystemTools::LowerCase(args[1]);
|
|
}
|
|
|
|
// Store the output in the provided variable.
|
|
this->Makefile->AddDefinition(outvar.c_str(), output.c_str());
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool cmStringCommand::HandleAsciiCommand(std::vector<std::string> const& args)
|
|
{
|
|
if ( args.size() < 3 )
|
|
{
|
|
this->SetError("No output variable specified");
|
|
return false;
|
|
}
|
|
std::string::size_type cc;
|
|
std::string outvar = args[args.size()-1];
|
|
std::string output = "";
|
|
for ( cc = 1; cc < args.size()-1; cc ++ )
|
|
{
|
|
int ch = atoi(args[cc].c_str());
|
|
if ( ch > 0 && ch < 256 )
|
|
{
|
|
output += static_cast<char>(ch);
|
|
}
|
|
else
|
|
{
|
|
std::string error = "Character with code ";
|
|
error += ch;
|
|
error += " does not exist.";
|
|
this->SetError(error.c_str());
|
|
return false;
|
|
}
|
|
}
|
|
// Store the output in the provided variable.
|
|
this->Makefile->AddDefinition(outvar.c_str(), output.c_str());
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool cmStringCommand::HandleConfigureCommand(
|
|
std::vector<std::string> const& args)
|
|
{
|
|
if ( args.size() < 2 )
|
|
{
|
|
this->SetError("No input string specified.");
|
|
return false;
|
|
}
|
|
else if ( args.size() < 3 )
|
|
{
|
|
this->SetError("No output variable specified.");
|
|
return false;
|
|
}
|
|
|
|
// Parse options.
|
|
bool escapeQuotes = false;
|
|
bool atOnly = false;
|
|
for(unsigned int i = 3; i < args.size(); ++i)
|
|
{
|
|
if(args[i] == "@ONLY")
|
|
{
|
|
atOnly = true;
|
|
}
|
|
else if(args[i] == "ESCAPE_QUOTES")
|
|
{
|
|
escapeQuotes = true;
|
|
}
|
|
else
|
|
{
|
|
cmOStringStream err;
|
|
err << "Unrecognized argument \"" << args[i] << "\"";
|
|
this->SetError(err.str().c_str());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Configure the string.
|
|
std::string output;
|
|
this->Makefile->ConfigureString(args[1], output, atOnly, escapeQuotes);
|
|
|
|
// Store the output in the provided variable.
|
|
this->Makefile->AddDefinition(args[2].c_str(), output.c_str());
|
|
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool cmStringCommand::HandleRegexCommand(std::vector<std::string> const& args)
|
|
{
|
|
if(args.size() < 2)
|
|
{
|
|
this->SetError("sub-command REGEX requires a mode to be specified.");
|
|
return false;
|
|
}
|
|
std::string mode = args[1];
|
|
if(mode == "MATCH")
|
|
{
|
|
if(args.size() < 5)
|
|
{
|
|
this->SetError("sub-command REGEX, mode MATCH needs "
|
|
"at least 5 arguments total to command.");
|
|
return false;
|
|
}
|
|
return this->RegexMatch(args);
|
|
}
|
|
else if(mode == "MATCHALL")
|
|
{
|
|
if(args.size() < 5)
|
|
{
|
|
this->SetError("sub-command REGEX, mode MATCHALL needs "
|
|
"at least 5 arguments total to command.");
|
|
return false;
|
|
}
|
|
return this->RegexMatchAll(args);
|
|
}
|
|
else if(mode == "REPLACE")
|
|
{
|
|
if(args.size() < 6)
|
|
{
|
|
this->SetError("sub-command REGEX, mode REPLACE needs "
|
|
"at least 6 arguments total to command.");
|
|
return false;
|
|
}
|
|
return this->RegexReplace(args);
|
|
}
|
|
|
|
std::string e = "sub-command REGEX does not recognize mode "+mode;
|
|
this->SetError(e.c_str());
|
|
return false;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool cmStringCommand::RegexMatch(std::vector<std::string> const& args)
|
|
{
|
|
//"STRING(REGEX MATCH <regular_expression> <output variable>
|
|
// <input> [<input>...])\n";
|
|
std::string regex = args[2];
|
|
std::string outvar = args[3];
|
|
|
|
// Concatenate all the last arguments together.
|
|
std::string input = args[4];
|
|
for(unsigned int i=5; i < args.size(); ++i)
|
|
{
|
|
input += args[i];
|
|
}
|
|
|
|
this->ClearMatches(this->Makefile);
|
|
// Compile the regular expression.
|
|
cmsys::RegularExpression re;
|
|
if(!re.compile(regex.c_str()))
|
|
{
|
|
std::string e =
|
|
"sub-command REGEX, mode MATCH failed to compile regex \""+regex+"\".";
|
|
this->SetError(e.c_str());
|
|
return false;
|
|
}
|
|
|
|
// Scan through the input for all matches.
|
|
std::string output;
|
|
if(re.find(input.c_str()))
|
|
{
|
|
this->StoreMatches(this->Makefile, re);
|
|
std::string::size_type l = re.start();
|
|
std::string::size_type r = re.end();
|
|
if(r-l == 0)
|
|
{
|
|
std::string e =
|
|
"sub-command REGEX, mode MATCH regex \""+regex+
|
|
"\" matched an empty string.";
|
|
this->SetError(e.c_str());
|
|
return false;
|
|
}
|
|
output = input.substr(l, r-l);
|
|
}
|
|
|
|
// Store the output in the provided variable.
|
|
this->Makefile->AddDefinition(outvar.c_str(), output.c_str());
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool cmStringCommand::RegexMatchAll(std::vector<std::string> const& args)
|
|
{
|
|
//"STRING(REGEX MATCHALL <regular_expression> <output variable> <input>
|
|
// [<input>...])\n";
|
|
std::string regex = args[2];
|
|
std::string outvar = args[3];
|
|
|
|
// Concatenate all the last arguments together.
|
|
std::string input = args[4];
|
|
for(unsigned int i=5; i < args.size(); ++i)
|
|
{
|
|
input += args[i];
|
|
}
|
|
|
|
this->ClearMatches(this->Makefile);
|
|
// Compile the regular expression.
|
|
cmsys::RegularExpression re;
|
|
if(!re.compile(regex.c_str()))
|
|
{
|
|
std::string e =
|
|
"sub-command REGEX, mode MATCHALL failed to compile regex \""+
|
|
regex+"\".";
|
|
this->SetError(e.c_str());
|
|
return false;
|
|
}
|
|
|
|
// Scan through the input for all matches.
|
|
std::string output;
|
|
const char* p = input.c_str();
|
|
while(re.find(p))
|
|
{
|
|
this->StoreMatches(this->Makefile, re);
|
|
std::string::size_type l = re.start();
|
|
std::string::size_type r = re.end();
|
|
if(r-l == 0)
|
|
{
|
|
std::string e = "sub-command REGEX, mode MATCHALL regex \""+
|
|
regex+"\" matched an empty string.";
|
|
this->SetError(e.c_str());
|
|
return false;
|
|
}
|
|
if(output.length() > 0)
|
|
{
|
|
output += ";";
|
|
}
|
|
output += std::string(p+l, r-l);
|
|
p += r;
|
|
}
|
|
|
|
// Store the output in the provided variable.
|
|
this->Makefile->AddDefinition(outvar.c_str(), output.c_str());
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool cmStringCommand::RegexReplace(std::vector<std::string> const& args)
|
|
{
|
|
//"STRING(REGEX REPLACE <regular_expression> <replace_expression>
|
|
// <output variable> <input> [<input>...])\n"
|
|
std::string regex = args[2];
|
|
std::string replace = args[3];
|
|
std::string outvar = args[4];
|
|
|
|
// Pull apart the replace expression to find the escaped [0-9] values.
|
|
std::vector<RegexReplacement> replacement;
|
|
std::string::size_type l = 0;
|
|
while(l < replace.length())
|
|
{
|
|
std::string::size_type r = replace.find("\\", l);
|
|
if(r == std::string::npos)
|
|
{
|
|
r = replace.length();
|
|
replacement.push_back(replace.substr(l, r-l));
|
|
}
|
|
else
|
|
{
|
|
if(r-l > 0)
|
|
{
|
|
replacement.push_back(replace.substr(l, r-l));
|
|
}
|
|
if(r == (replace.length()-1))
|
|
{
|
|
this->SetError("sub-command REGEX, mode REPLACE: "
|
|
"replace-expression ends in a backslash.");
|
|
return false;
|
|
}
|
|
if((replace[r+1] >= '0') && (replace[r+1] <= '9'))
|
|
{
|
|
replacement.push_back(replace[r+1]-'0');
|
|
}
|
|
else if(replace[r+1] == 'n')
|
|
{
|
|
replacement.push_back("\n");
|
|
}
|
|
else if(replace[r+1] == '\\')
|
|
{
|
|
replacement.push_back("\\");
|
|
}
|
|
else
|
|
{
|
|
std::string e = "sub-command REGEX, mode REPLACE: Unknown escape \"";
|
|
e += replace.substr(r, 2);
|
|
e += "\"in replace-expression.";
|
|
this->SetError(e.c_str());
|
|
return false;
|
|
}
|
|
r += 2;
|
|
}
|
|
l = r;
|
|
}
|
|
|
|
// Concatenate all the last arguments together.
|
|
std::string input = args[5];
|
|
for(unsigned int i=6; i < args.size(); ++i)
|
|
{
|
|
input += args[i];
|
|
}
|
|
|
|
this->ClearMatches(this->Makefile);
|
|
// Compile the regular expression.
|
|
cmsys::RegularExpression re;
|
|
if(!re.compile(regex.c_str()))
|
|
{
|
|
std::string e =
|
|
"sub-command REGEX, mode REPLACE failed to compile regex \""+
|
|
regex+"\".";
|
|
this->SetError(e.c_str());
|
|
return false;
|
|
}
|
|
|
|
// Scan through the input for all matches.
|
|
std::string output;
|
|
std::string::size_type base = 0;
|
|
while(re.find(input.c_str()+base))
|
|
{
|
|
this->StoreMatches(this->Makefile, re);
|
|
std::string::size_type l2 = re.start();
|
|
std::string::size_type r = re.end();
|
|
|
|
// Concatenate the part of the input that was not matched.
|
|
output += input.substr(base, l2);
|
|
|
|
// Make sure the match had some text.
|
|
if(r-l2 == 0)
|
|
{
|
|
std::string e = "sub-command REGEX, mode REPLACE regex \""+
|
|
regex+"\" matched an empty string.";
|
|
this->SetError(e.c_str());
|
|
return false;
|
|
}
|
|
|
|
// Concatenate the replacement for the match.
|
|
for(unsigned int i=0; i < replacement.size(); ++i)
|
|
{
|
|
if(replacement[i].number < 0)
|
|
{
|
|
// This is just a plain-text part of the replacement.
|
|
output += replacement[i].value;
|
|
}
|
|
else
|
|
{
|
|
// Replace with part of the match.
|
|
int n = replacement[i].number;
|
|
std::string::size_type start = re.start(n);
|
|
std::string::size_type end = re.end(n);
|
|
std::string::size_type len = input.length()-base;
|
|
if((start != std::string::npos) && (end != std::string::npos) &&
|
|
(start <= len) && (end <= len))
|
|
{
|
|
output += input.substr(base+start, end-start);
|
|
}
|
|
else
|
|
{
|
|
std::string e =
|
|
"sub-command REGEX, mode REPLACE: replace expression \""+
|
|
replace+"\" contains an out-of-range escape for regex \""+
|
|
regex+"\".";
|
|
this->SetError(e.c_str());
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Move past the match.
|
|
base += r;
|
|
}
|
|
|
|
// Concatenate the text after the last match.
|
|
output += input.substr(base, input.length()-base);
|
|
|
|
// Store the output in the provided variable.
|
|
this->Makefile->AddDefinition(outvar.c_str(), output.c_str());
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void cmStringCommand::ClearMatches(cmMakefile* mf)
|
|
{
|
|
for (unsigned int i=0; i<10; i++)
|
|
{
|
|
char name[128];
|
|
sprintf(name, "CMAKE_MATCH_%d", i);
|
|
mf->AddDefinition(name, "");
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void cmStringCommand::StoreMatches(cmMakefile* mf,cmsys::RegularExpression& re)
|
|
{
|
|
for (unsigned int i=0; i<10; i++)
|
|
{
|
|
char name[128];
|
|
sprintf(name, "CMAKE_MATCH_%d", i);
|
|
mf->AddDefinition(name, re.match(i).c_str());
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool cmStringCommand::HandleCompareCommand(std::vector<std::string> const&
|
|
args)
|
|
{
|
|
if(args.size() < 2)
|
|
{
|
|
this->SetError("sub-command COMPARE requires a mode to be specified.");
|
|
return false;
|
|
}
|
|
std::string mode = args[1];
|
|
if((mode == "EQUAL") || (mode == "NOTEQUAL") ||
|
|
(mode == "LESS") || (mode == "GREATER"))
|
|
{
|
|
if(args.size() < 5)
|
|
{
|
|
std::string e = "sub-command COMPARE, mode ";
|
|
e += mode;
|
|
e += " needs at least 5 arguments total to command.";
|
|
this->SetError(e.c_str());
|
|
return false;
|
|
}
|
|
|
|
const std::string& left = args[2];
|
|
const std::string& right = args[3];
|
|
const std::string& outvar = args[4];
|
|
bool result;
|
|
if(mode == "LESS")
|
|
{
|
|
result = (left < right);
|
|
}
|
|
else if(mode == "GREATER")
|
|
{
|
|
result = (left > right);
|
|
}
|
|
else if(mode == "EQUAL")
|
|
{
|
|
result = (left == right);
|
|
}
|
|
else // if(mode == "NOTEQUAL")
|
|
{
|
|
result = !(left == right);
|
|
}
|
|
if(result)
|
|
{
|
|
this->Makefile->AddDefinition(outvar.c_str(), "1");
|
|
}
|
|
else
|
|
{
|
|
this->Makefile->AddDefinition(outvar.c_str(), "0");
|
|
}
|
|
return true;
|
|
}
|
|
std::string e = "sub-command COMPARE does not recognize mode "+mode;
|
|
this->SetError(e.c_str());
|
|
return false;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool cmStringCommand::HandleReplaceCommand(std::vector<std::string> const&
|
|
args)
|
|
{
|
|
if(args.size() < 5)
|
|
{
|
|
this->SetError("sub-command REPLACE requires four arguments.");
|
|
return false;
|
|
}
|
|
|
|
const std::string& matchExpression = args[1];
|
|
const std::string& replaceExpression = args[2];
|
|
const std::string& variableName = args[3];
|
|
|
|
std::string input = args[4];
|
|
for(unsigned int i=5; i < args.size(); ++i)
|
|
{
|
|
input += args[i];
|
|
}
|
|
|
|
cmsys::SystemTools::ReplaceString(input, matchExpression.c_str(),
|
|
replaceExpression.c_str());
|
|
|
|
this->Makefile->AddDefinition(variableName.c_str(), input.c_str());
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool cmStringCommand::HandleSubstringCommand(std::vector<std::string> const&
|
|
args)
|
|
{
|
|
if(args.size() != 5)
|
|
{
|
|
this->SetError("sub-command REPLACE requires four arguments.");
|
|
return false;
|
|
}
|
|
|
|
const std::string& stringValue = args[1];
|
|
int begin = atoi(args[2].c_str());
|
|
int end = atoi(args[3].c_str());
|
|
const std::string& variableName = args[4];
|
|
|
|
size_t stringLength = stringValue.size();
|
|
int intStringLength = static_cast<int>(stringLength);
|
|
if ( begin < 0 || begin > intStringLength )
|
|
{
|
|
cmOStringStream ostr;
|
|
ostr << "begin index: " << begin << " is out of range 0 - "
|
|
<< stringLength;
|
|
this->SetError(ostr.str().c_str());
|
|
return false;
|
|
}
|
|
int leftOverLength = intStringLength - begin;
|
|
if ( end < 0 || end > leftOverLength )
|
|
{
|
|
cmOStringStream ostr;
|
|
ostr << "end index: " << end << " is out of range " << 0 << " - "
|
|
<< leftOverLength;
|
|
this->SetError(ostr.str().c_str());
|
|
return false;
|
|
}
|
|
|
|
this->Makefile->AddDefinition(variableName.c_str(),
|
|
stringValue.substr(begin, end).c_str());
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool cmStringCommand
|
|
::HandleLengthCommand(std::vector<std::string> const& args)
|
|
{
|
|
if(args.size() != 3)
|
|
{
|
|
this->SetError("sub-command LENGTH requires two arguments.");
|
|
return false;
|
|
}
|
|
|
|
const std::string& stringValue = args[1];
|
|
const std::string& variableName = args[2];
|
|
|
|
size_t length = stringValue.size();
|
|
char buffer[1024];
|
|
sprintf(buffer, "%d", static_cast<int>(length));
|
|
|
|
this->Makefile->AddDefinition(variableName.c_str(), buffer);
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool cmStringCommand::HandleStripCommand(
|
|
std::vector<std::string> const& args)
|
|
{
|
|
if(args.size() != 3)
|
|
{
|
|
this->SetError("sub-command LENGTH requires two arguments.");
|
|
return false;
|
|
}
|
|
|
|
const std::string& stringValue = args[1];
|
|
const std::string& variableName = args[2];
|
|
size_t inStringLength = stringValue.size();
|
|
size_t startPos = inStringLength + 1;
|
|
size_t endPos = 0;
|
|
const char* ptr = stringValue.c_str();
|
|
size_t cc;
|
|
for ( cc = 0; cc < inStringLength; ++ cc )
|
|
{
|
|
if ( !isspace(*ptr) )
|
|
{
|
|
if ( startPos > inStringLength )
|
|
{
|
|
startPos = cc;
|
|
}
|
|
endPos = cc;
|
|
}
|
|
++ ptr;
|
|
}
|
|
|
|
size_t outLength = 0;
|
|
|
|
// if the input string didn't contain any non-space characters, return
|
|
// an empty string
|
|
if (startPos > inStringLength)
|
|
{
|
|
outLength = 0;
|
|
startPos = 0;
|
|
}
|
|
else
|
|
{
|
|
outLength=endPos - startPos + 1;
|
|
}
|
|
|
|
this->Makefile->AddDefinition(variableName.c_str(),
|
|
stringValue.substr(startPos, outLength).c_str());
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool cmStringCommand
|
|
::HandleRandomCommand(std::vector<std::string> const& args)
|
|
{
|
|
if(args.size() < 2 || args.size() == 3 || args.size() == 5)
|
|
{
|
|
this->SetError("sub-command RANDOM requires at least one argument.");
|
|
return false;
|
|
}
|
|
|
|
int length = 5;
|
|
const char cmStringCommandDefaultAlphabet[] = "qwertyuiopasdfghjklzxcvbnm"
|
|
"QWERTYUIOPASDFGHJKLZXCVBNM"
|
|
"0123456789";
|
|
std::string alphabet;
|
|
|
|
if ( args.size() > 3 )
|
|
{
|
|
size_t i = 1;
|
|
size_t stopAt = args.size() - 2;
|
|
|
|
for ( ; i < stopAt; ++i )
|
|
{
|
|
if ( args[i] == "LENGTH" )
|
|
{
|
|
++i;
|
|
length = atoi(args[i].c_str());
|
|
}
|
|
else if ( args[i] == "ALPHABET" )
|
|
{
|
|
++i;
|
|
alphabet = args[i];
|
|
}
|
|
}
|
|
}
|
|
if ( !alphabet.size() )
|
|
{
|
|
alphabet = cmStringCommandDefaultAlphabet;
|
|
}
|
|
|
|
double sizeofAlphabet = alphabet.size();
|
|
if ( sizeofAlphabet < 1 )
|
|
{
|
|
this->SetError("sub-command RANDOM invoked with bad alphabet.");
|
|
return false;
|
|
}
|
|
if ( length < 1 )
|
|
{
|
|
this->SetError("sub-command RANDOM invoked with bad length.");
|
|
return false;
|
|
}
|
|
const std::string& variableName = args[args.size()-1];
|
|
|
|
std::vector<char> result;
|
|
srand((int)time(NULL));
|
|
const char* alphaPtr = alphabet.c_str();
|
|
int cc;
|
|
for ( cc = 0; cc < length; cc ++ )
|
|
{
|
|
int idx=(int) (sizeofAlphabet* rand()/(RAND_MAX+1.0));
|
|
result.push_back(*(alphaPtr + idx));
|
|
}
|
|
result.push_back(0);
|
|
|
|
this->Makefile->AddDefinition(variableName.c_str(), &*result.begin());
|
|
return true;
|
|
}
|