Browse Source

cmCommand refactor: cmStringCommand

Gabor Bencze 6 years ago
parent
commit
6ab28b9413
3 changed files with 241 additions and 221 deletions
  1. 1 1
      Source/cmCommands.cxx
  2. 237 166
      Source/cmStringCommand.cxx
  3. 3 54
      Source/cmStringCommand.h

+ 1 - 1
Source/cmCommands.cxx

@@ -158,7 +158,7 @@ void GetScriptingCommands(cmState* state)
                            cmSetDirectoryPropertiesCommand);
   state->AddBuiltinCommand("set_property", cmSetPropertyCommand);
   state->AddBuiltinCommand("site_name", cmSiteNameCommand);
-  state->AddBuiltinCommand("string", cm::make_unique<cmStringCommand>());
+  state->AddBuiltinCommand("string", cmStringCommand);
   state->AddBuiltinCommand("unset", cmUnsetCommand);
   state->AddBuiltinCommand("while", cmWhileCommand);
 

+ 237 - 166
Source/cmStringCommand.cxx

@@ -8,12 +8,14 @@
 #include <algorithm>
 #include <ctype.h>
 #include <iterator>
+#include <memory>
 #include <sstream>
 #include <stdio.h>
 #include <stdlib.h>
 
 #include "cmAlgorithms.h"
 #include "cmCryptoHash.h"
+#include "cmExecutionStatus.h"
 #include "cmGeneratorExpression.h"
 #include "cmMakefile.h"
 #include "cmMessageType.h"
@@ -24,123 +26,177 @@
 #include "cmTimestamp.h"
 #include "cmUuid.h"
 
-class cmExecutionStatus;
+namespace {
+bool HandleConfigureCommand(std::vector<std::string> const& args,
+                            cmExecutionStatus& status);
+bool HandleAsciiCommand(std::vector<std::string> const& args,
+                        cmExecutionStatus& status);
+bool HandleRegexCommand(std::vector<std::string> const& args,
+                        cmExecutionStatus& status);
+bool RegexMatch(std::vector<std::string> const& args,
+                cmExecutionStatus& status);
+bool RegexMatchAll(std::vector<std::string> const& args,
+                   cmExecutionStatus& status);
+bool RegexReplace(std::vector<std::string> const& args,
+                  cmExecutionStatus& status);
+bool HandleHashCommand(std::vector<std::string> const& args,
+                       cmExecutionStatus& status);
+bool HandleToUpperLowerCommand(std::vector<std::string> const& args,
+                               bool toUpper, cmExecutionStatus& status);
+bool HandleCompareCommand(std::vector<std::string> const& args,
+                          cmExecutionStatus& status);
+bool HandleReplaceCommand(std::vector<std::string> const& args,
+                          cmExecutionStatus& status);
+bool HandleLengthCommand(std::vector<std::string> const& args,
+                         cmExecutionStatus& status);
+bool HandleSubstringCommand(std::vector<std::string> const& args,
+                            cmExecutionStatus& status);
+bool HandleAppendCommand(std::vector<std::string> const& args,
+                         cmExecutionStatus& status);
+bool HandlePrependCommand(std::vector<std::string> const& args,
+                          cmExecutionStatus& status);
+bool HandleConcatCommand(std::vector<std::string> const& args,
+                         cmExecutionStatus& status);
+bool HandleJoinCommand(std::vector<std::string> const& args,
+                       cmExecutionStatus& status);
+bool HandleStripCommand(std::vector<std::string> const& args,
+                        cmExecutionStatus& status);
+bool HandleRepeatCommand(std::vector<std::string> const& args,
+                         cmMakefile& makefile);
+bool HandleRandomCommand(std::vector<std::string> const& args,
+                         cmExecutionStatus& status);
+bool HandleFindCommand(std::vector<std::string> const& args,
+                       cmExecutionStatus& status);
+bool HandleTimestampCommand(std::vector<std::string> const& args,
+                            cmExecutionStatus& status);
+bool HandleMakeCIdentifierCommand(std::vector<std::string> const& args,
+                                  cmExecutionStatus& status);
+bool HandleGenexStripCommand(std::vector<std::string> const& args,
+                             cmExecutionStatus& status);
+bool HandleUuidCommand(std::vector<std::string> const& args,
+                       cmExecutionStatus& status);
+
+bool joinImpl(std::vector<std::string> const& args, std::string const& glue,
+              size_t varIdx, cmMakefile& makefile);
+}
 
-bool cmStringCommand::InitialPass(std::vector<std::string> const& args,
-                                  cmExecutionStatus&)
+bool cmStringCommand(std::vector<std::string> const& args,
+                     cmExecutionStatus& status)
 {
   if (args.empty()) {
-    this->SetError("must be called with at least one argument.");
+    status.SetError("must be called with at least one argument.");
     return false;
   }
 
   const std::string& subCommand = args[0];
   if (subCommand == "REGEX") {
-    return this->HandleRegexCommand(args);
+    return HandleRegexCommand(args, status);
   }
   if (subCommand == "REPLACE") {
-    return this->HandleReplaceCommand(args);
+    return HandleReplaceCommand(args, status);
   }
   if (subCommand == "MD5" || subCommand == "SHA1" || subCommand == "SHA224" ||
       subCommand == "SHA256" || subCommand == "SHA384" ||
       subCommand == "SHA512" || subCommand == "SHA3_224" ||
       subCommand == "SHA3_256" || subCommand == "SHA3_384" ||
       subCommand == "SHA3_512") {
-    return this->HandleHashCommand(args);
+    return HandleHashCommand(args, status);
   }
   if (subCommand == "TOLOWER") {
-    return this->HandleToUpperLowerCommand(args, false);
+    return HandleToUpperLowerCommand(args, false, status);
   }
   if (subCommand == "TOUPPER") {
-    return this->HandleToUpperLowerCommand(args, true);
+    return HandleToUpperLowerCommand(args, true, status);
   }
   if (subCommand == "COMPARE") {
-    return this->HandleCompareCommand(args);
+    return HandleCompareCommand(args, status);
   }
   if (subCommand == "ASCII") {
-    return this->HandleAsciiCommand(args);
+    return HandleAsciiCommand(args, status);
   }
   if (subCommand == "CONFIGURE") {
-    return this->HandleConfigureCommand(args);
+    return HandleConfigureCommand(args, status);
   }
   if (subCommand == "LENGTH") {
-    return this->HandleLengthCommand(args);
+    return HandleLengthCommand(args, status);
   }
   if (subCommand == "APPEND") {
-    return this->HandleAppendCommand(args);
+    return HandleAppendCommand(args, status);
   }
   if (subCommand == "PREPEND") {
-    return this->HandlePrependCommand(args);
+    return HandlePrependCommand(args, status);
   }
   if (subCommand == "CONCAT") {
-    return this->HandleConcatCommand(args);
+    return HandleConcatCommand(args, status);
   }
   if (subCommand == "JOIN") {
-    return this->HandleJoinCommand(args);
+    return HandleJoinCommand(args, status);
   }
   if (subCommand == "SUBSTRING") {
-    return this->HandleSubstringCommand(args);
+    return HandleSubstringCommand(args, status);
   }
   if (subCommand == "STRIP") {
-    return this->HandleStripCommand(args);
+    return HandleStripCommand(args, status);
   }
   if (subCommand == "REPEAT") {
-    return this->HandleRepeatCommand(args);
+    return HandleRepeatCommand(args, status.GetMakefile());
   }
   if (subCommand == "RANDOM") {
-    return this->HandleRandomCommand(args);
+    return HandleRandomCommand(args, status);
   }
   if (subCommand == "FIND") {
-    return this->HandleFindCommand(args);
+    return HandleFindCommand(args, status);
   }
   if (subCommand == "TIMESTAMP") {
-    return this->HandleTimestampCommand(args);
+    return HandleTimestampCommand(args, status);
   }
   if (subCommand == "MAKE_C_IDENTIFIER") {
-    return this->HandleMakeCIdentifierCommand(args);
+    return HandleMakeCIdentifierCommand(args, status);
   }
   if (subCommand == "GENEX_STRIP") {
-    return this->HandleGenexStripCommand(args);
+    return HandleGenexStripCommand(args, status);
   }
   if (subCommand == "UUID") {
-    return this->HandleUuidCommand(args);
+    return HandleUuidCommand(args, status);
   }
 
   std::string e = "does not recognize sub-command " + subCommand;
-  this->SetError(e);
+  status.SetError(e);
   return false;
 }
 
-bool cmStringCommand::HandleHashCommand(std::vector<std::string> const& args)
+namespace {
+bool HandleHashCommand(std::vector<std::string> const& args,
+                       cmExecutionStatus& status)
 {
 #if !defined(CMAKE_BOOTSTRAP)
   if (args.size() != 3) {
     std::ostringstream e;
     e << args[0] << " requires an output variable and an input string";
-    this->SetError(e.str());
+    status.SetError(e.str());
     return false;
   }
 
   std::unique_ptr<cmCryptoHash> hash(cmCryptoHash::New(args[0]));
   if (hash) {
     std::string out = hash->HashString(args[2]);
-    this->Makefile->AddDefinition(args[1], out);
+    status.GetMakefile().AddDefinition(args[1], out);
     return true;
   }
   return false;
 #else
   std::ostringstream e;
   e << args[0] << " not available during bootstrap";
-  this->SetError(e.str().c_str());
+  status.SetError(e.str().c_str());
   return false;
 #endif
 }
 
-bool cmStringCommand::HandleToUpperLowerCommand(
-  std::vector<std::string> const& args, bool toUpper)
+bool HandleToUpperLowerCommand(std::vector<std::string> const& args,
+                               bool toUpper, cmExecutionStatus& status)
 {
   if (args.size() < 3) {
-    this->SetError("no output variable specified");
+    status.SetError("no output variable specified");
     return false;
   }
 
@@ -154,14 +210,15 @@ bool cmStringCommand::HandleToUpperLowerCommand(
   }
 
   // Store the output in the provided variable.
-  this->Makefile->AddDefinition(outvar, output);
+  status.GetMakefile().AddDefinition(outvar, output);
   return true;
 }
 
-bool cmStringCommand::HandleAsciiCommand(std::vector<std::string> const& args)
+bool HandleAsciiCommand(std::vector<std::string> const& args,
+                        cmExecutionStatus& status)
 {
   if (args.size() < 3) {
-    this->SetError("No output variable specified");
+    status.SetError("No output variable specified");
     return false;
   }
   std::string::size_type cc;
@@ -175,24 +232,24 @@ bool cmStringCommand::HandleAsciiCommand(std::vector<std::string> const& args)
       std::string error = "Character with code ";
       error += args[cc];
       error += " does not exist.";
-      this->SetError(error);
+      status.SetError(error);
       return false;
     }
   }
   // Store the output in the provided variable.
-  this->Makefile->AddDefinition(outvar, output);
+  status.GetMakefile().AddDefinition(outvar, output);
   return true;
 }
 
-bool cmStringCommand::HandleConfigureCommand(
-  std::vector<std::string> const& args)
+bool HandleConfigureCommand(std::vector<std::string> const& args,
+                            cmExecutionStatus& status)
 {
   if (args.size() < 2) {
-    this->SetError("No input string specified.");
+    status.SetError("No input string specified.");
     return false;
   }
   if (args.size() < 3) {
-    this->SetError("No output variable specified.");
+    status.SetError("No output variable specified.");
     return false;
   }
 
@@ -207,73 +264,75 @@ bool cmStringCommand::HandleConfigureCommand(
     } else {
       std::ostringstream err;
       err << "Unrecognized argument \"" << args[i] << "\"";
-      this->SetError(err.str());
+      status.SetError(err.str());
       return false;
     }
   }
 
   // Configure the string.
   std::string output;
-  this->Makefile->ConfigureString(args[1], output, atOnly, escapeQuotes);
+  status.GetMakefile().ConfigureString(args[1], output, atOnly, escapeQuotes);
 
   // Store the output in the provided variable.
-  this->Makefile->AddDefinition(args[2], output);
+  status.GetMakefile().AddDefinition(args[2], output);
 
   return true;
 }
 
-bool cmStringCommand::HandleRegexCommand(std::vector<std::string> const& args)
+bool HandleRegexCommand(std::vector<std::string> const& args,
+                        cmExecutionStatus& status)
 {
   if (args.size() < 2) {
-    this->SetError("sub-command REGEX requires a mode to be specified.");
+    status.SetError("sub-command REGEX requires a mode to be specified.");
     return false;
   }
   std::string const& 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.");
+      status.SetError("sub-command REGEX, mode MATCH needs "
+                      "at least 5 arguments total to command.");
       return false;
     }
-    return this->RegexMatch(args);
+    return RegexMatch(args, status);
   }
   if (mode == "MATCHALL") {
     if (args.size() < 5) {
-      this->SetError("sub-command REGEX, mode MATCHALL needs "
-                     "at least 5 arguments total to command.");
+      status.SetError("sub-command REGEX, mode MATCHALL needs "
+                      "at least 5 arguments total to command.");
       return false;
     }
-    return this->RegexMatchAll(args);
+    return RegexMatchAll(args, status);
   }
   if (mode == "REPLACE") {
     if (args.size() < 6) {
-      this->SetError("sub-command REGEX, mode REPLACE needs "
-                     "at least 6 arguments total to command.");
+      status.SetError("sub-command REGEX, mode REPLACE needs "
+                      "at least 6 arguments total to command.");
       return false;
     }
-    return this->RegexReplace(args);
+    return RegexReplace(args, status);
   }
 
   std::string e = "sub-command REGEX does not recognize mode " + mode;
-  this->SetError(e);
+  status.SetError(e);
   return false;
 }
 
-bool cmStringCommand::RegexMatch(std::vector<std::string> const& args)
+bool RegexMatch(std::vector<std::string> const& args,
+                cmExecutionStatus& status)
 {
   //"STRING(REGEX MATCH <regular_expression> <output variable>
   // <input> [<input>...])\n";
   std::string const& regex = args[2];
   std::string const& outvar = args[3];
 
-  this->Makefile->ClearMatches();
+  status.GetMakefile().ClearMatches();
   // 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);
+    status.SetError(e);
     return false;
   }
 
@@ -283,38 +342,39 @@ bool cmStringCommand::RegexMatch(std::vector<std::string> const& args)
   // Scan through the input for all matches.
   std::string output;
   if (re.find(input)) {
-    this->Makefile->StoreMatches(re);
+    status.GetMakefile().StoreMatches(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);
+      status.SetError(e);
       return false;
     }
     output = input.substr(l, r - l);
   }
 
   // Store the output in the provided variable.
-  this->Makefile->AddDefinition(outvar, output);
+  status.GetMakefile().AddDefinition(outvar, output);
   return true;
 }
 
-bool cmStringCommand::RegexMatchAll(std::vector<std::string> const& args)
+bool RegexMatchAll(std::vector<std::string> const& args,
+                   cmExecutionStatus& status)
 {
   //"STRING(REGEX MATCHALL <regular_expression> <output variable> <input>
   // [<input>...])\n";
   std::string const& regex = args[2];
   std::string const& outvar = args[3];
 
-  this->Makefile->ClearMatches();
+  status.GetMakefile().ClearMatches();
   // 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);
+    status.SetError(e);
     return false;
   }
 
@@ -325,14 +385,14 @@ bool cmStringCommand::RegexMatchAll(std::vector<std::string> const& args)
   std::string output;
   const char* p = input.c_str();
   while (re.find(p)) {
-    this->Makefile->ClearMatches();
-    this->Makefile->StoreMatches(re);
+    status.GetMakefile().ClearMatches();
+    status.GetMakefile().StoreMatches(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);
+      status.SetError(e);
       return false;
     }
     if (!output.empty()) {
@@ -343,32 +403,33 @@ bool cmStringCommand::RegexMatchAll(std::vector<std::string> const& args)
   }
 
   // Store the output in the provided variable.
-  this->Makefile->AddDefinition(outvar, output);
+  status.GetMakefile().AddDefinition(outvar, output);
   return true;
 }
 
-bool cmStringCommand::RegexReplace(std::vector<std::string> const& args)
+bool RegexReplace(std::vector<std::string> const& args,
+                  cmExecutionStatus& status)
 {
   //"STRING(REGEX REPLACE <regular_expression> <replace_expression>
   // <output variable> <input> [<input>...])\n"
   std::string const& regex = args[2];
   std::string const& replace = args[3];
   std::string const& outvar = args[4];
-  cmStringReplaceHelper replaceHelper(regex, replace, this->Makefile);
+  cmStringReplaceHelper replaceHelper(regex, replace, &status.GetMakefile());
 
   if (!replaceHelper.IsReplaceExpressionValid()) {
-    this->SetError(
+    status.SetError(
       "sub-command REGEX, mode REPLACE: " + replaceHelper.GetError() + ".");
     return false;
   }
 
-  this->Makefile->ClearMatches();
+  status.GetMakefile().ClearMatches();
 
   if (!replaceHelper.IsRegularExpressionValid()) {
     std::string e =
       "sub-command REGEX, mode REPLACE failed to compile regex \"" + regex +
       "\".";
-    this->SetError(e);
+    status.SetError(e);
     return false;
   }
 
@@ -378,21 +439,22 @@ bool cmStringCommand::RegexReplace(std::vector<std::string> const& args)
   std::string output;
 
   if (!replaceHelper.Replace(input, output)) {
-    this->SetError(
+    status.SetError(
       "sub-command REGEX, mode REPLACE: " + replaceHelper.GetError() + ".");
     return false;
   }
 
   // Store the output in the provided variable.
-  this->Makefile->AddDefinition(outvar, output);
+  status.GetMakefile().AddDefinition(outvar, output);
   return true;
 }
 
-bool cmStringCommand::HandleFindCommand(std::vector<std::string> const& args)
+bool HandleFindCommand(std::vector<std::string> const& args,
+                       cmExecutionStatus& status)
 {
   // check if all required parameters were passed
   if (args.size() < 4 || args.size() > 5) {
-    this->SetError("sub-command FIND requires 3 or 4 parameters.");
+    status.SetError("sub-command FIND requires 3 or 4 parameters.");
     return false;
   }
 
@@ -404,7 +466,7 @@ bool cmStringCommand::HandleFindCommand(std::vector<std::string> const& args)
 
   // if we have 5 arguments the last one must be REVERSE
   if (args.size() == 5 && args[4] != "REVERSE") {
-    this->SetError("sub-command FIND: unknown last parameter");
+    status.SetError("sub-command FIND: unknown last parameter");
     return false;
   }
 
@@ -415,9 +477,9 @@ bool cmStringCommand::HandleFindCommand(std::vector<std::string> const& args)
 
   // ensure that the user cannot accidentally specify REVERSE as a variable
   if (outvar == "REVERSE") {
-    this->SetError("sub-command FIND does not allow one to select REVERSE as "
-                   "the output variable.  "
-                   "Maybe you missed the actual output variable?");
+    status.SetError("sub-command FIND does not allow one to select REVERSE as "
+                    "the output variable.  "
+                    "Maybe you missed the actual output variable?");
     return false;
   }
 
@@ -431,20 +493,20 @@ bool cmStringCommand::HandleFindCommand(std::vector<std::string> const& args)
   if (std::string::npos != pos) {
     std::ostringstream s;
     s << pos;
-    this->Makefile->AddDefinition(outvar, s.str());
+    status.GetMakefile().AddDefinition(outvar, s.str());
     return true;
   }
 
   // the character was not found, but this is not really an error
-  this->Makefile->AddDefinition(outvar, "-1");
+  status.GetMakefile().AddDefinition(outvar, "-1");
   return true;
 }
 
-bool cmStringCommand::HandleCompareCommand(
-  std::vector<std::string> const& args)
+bool HandleCompareCommand(std::vector<std::string> const& args,
+                          cmExecutionStatus& status)
 {
   if (args.size() < 2) {
-    this->SetError("sub-command COMPARE requires a mode to be specified.");
+    status.SetError("sub-command COMPARE requires a mode to be specified.");
     return false;
   }
   std::string const& mode = args[1];
@@ -455,7 +517,7 @@ bool cmStringCommand::HandleCompareCommand(
       std::string e = "sub-command COMPARE, mode ";
       e += mode;
       e += " needs at least 5 arguments total to command.";
-      this->SetError(e);
+      status.SetError(e);
       return false;
     }
 
@@ -478,22 +540,22 @@ bool cmStringCommand::HandleCompareCommand(
       result = !(left == right);
     }
     if (result) {
-      this->Makefile->AddDefinition(outvar, "1");
+      status.GetMakefile().AddDefinition(outvar, "1");
     } else {
-      this->Makefile->AddDefinition(outvar, "0");
+      status.GetMakefile().AddDefinition(outvar, "0");
     }
     return true;
   }
   std::string e = "sub-command COMPARE does not recognize mode " + mode;
-  this->SetError(e);
+  status.SetError(e);
   return false;
 }
 
-bool cmStringCommand::HandleReplaceCommand(
-  std::vector<std::string> const& args)
+bool HandleReplaceCommand(std::vector<std::string> const& args,
+                          cmExecutionStatus& status)
 {
   if (args.size() < 5) {
-    this->SetError("sub-command REPLACE requires at least four arguments.");
+    status.SetError("sub-command REPLACE requires at least four arguments.");
     return false;
   }
 
@@ -506,15 +568,15 @@ bool cmStringCommand::HandleReplaceCommand(
   cmsys::SystemTools::ReplaceString(input, matchExpression.c_str(),
                                     replaceExpression.c_str());
 
-  this->Makefile->AddDefinition(variableName, input);
+  status.GetMakefile().AddDefinition(variableName, input);
   return true;
 }
 
-bool cmStringCommand::HandleSubstringCommand(
-  std::vector<std::string> const& args)
+bool HandleSubstringCommand(std::vector<std::string> const& args,
+                            cmExecutionStatus& status)
 {
   if (args.size() != 5) {
-    this->SetError("sub-command SUBSTRING requires four arguments.");
+    status.SetError("sub-command SUBSTRING requires four arguments.");
     return false;
   }
 
@@ -529,24 +591,26 @@ bool cmStringCommand::HandleSubstringCommand(
     std::ostringstream ostr;
     ostr << "begin index: " << begin << " is out of range 0 - "
          << stringLength;
-    this->SetError(ostr.str());
+    status.SetError(ostr.str());
     return false;
   }
   if (end < -1) {
     std::ostringstream ostr;
     ostr << "end index: " << end << " should be -1 or greater";
-    this->SetError(ostr.str());
+    status.SetError(ostr.str());
     return false;
   }
 
-  this->Makefile->AddDefinition(variableName, stringValue.substr(begin, end));
+  status.GetMakefile().AddDefinition(variableName,
+                                     stringValue.substr(begin, end));
   return true;
 }
 
-bool cmStringCommand::HandleLengthCommand(std::vector<std::string> const& args)
+bool HandleLengthCommand(std::vector<std::string> const& args,
+                         cmExecutionStatus& status)
 {
   if (args.size() != 3) {
-    this->SetError("sub-command LENGTH requires two arguments.");
+    status.SetError("sub-command LENGTH requires two arguments.");
     return false;
   }
 
@@ -557,14 +621,15 @@ bool cmStringCommand::HandleLengthCommand(std::vector<std::string> const& args)
   char buffer[1024];
   sprintf(buffer, "%d", static_cast<int>(length));
 
-  this->Makefile->AddDefinition(variableName, buffer);
+  status.GetMakefile().AddDefinition(variableName, buffer);
   return true;
 }
 
-bool cmStringCommand::HandleAppendCommand(std::vector<std::string> const& args)
+bool HandleAppendCommand(std::vector<std::string> const& args,
+                         cmExecutionStatus& status)
 {
   if (args.size() < 2) {
-    this->SetError("sub-command APPEND requires at least one argument.");
+    status.SetError("sub-command APPEND requires at least one argument.");
     return false;
   }
 
@@ -576,20 +641,20 @@ bool cmStringCommand::HandleAppendCommand(std::vector<std::string> const& args)
   const std::string& variable = args[1];
 
   std::string value;
-  const char* oldValue = this->Makefile->GetDefinition(variable);
+  const char* oldValue = status.GetMakefile().GetDefinition(variable);
   if (oldValue) {
     value = oldValue;
   }
   value += cmJoin(cmMakeRange(args).advance(2), std::string());
-  this->Makefile->AddDefinition(variable, value);
+  status.GetMakefile().AddDefinition(variable, value);
   return true;
 }
 
-bool cmStringCommand::HandlePrependCommand(
-  std::vector<std::string> const& args)
+bool HandlePrependCommand(std::vector<std::string> const& args,
+                          cmExecutionStatus& status)
 {
   if (args.size() < 2) {
-    this->SetError("sub-command PREPEND requires at least one argument.");
+    status.SetError("sub-command PREPEND requires at least one argument.");
     return false;
   }
 
@@ -601,67 +666,69 @@ bool cmStringCommand::HandlePrependCommand(
   const std::string& variable = args[1];
 
   std::string value = cmJoin(cmMakeRange(args).advance(2), std::string());
-  const char* oldValue = this->Makefile->GetDefinition(variable);
+  const char* oldValue = status.GetMakefile().GetDefinition(variable);
   if (oldValue) {
     value += oldValue;
   }
-  this->Makefile->AddDefinition(variable, value);
+  status.GetMakefile().AddDefinition(variable, value);
   return true;
 }
 
-bool cmStringCommand::HandleConcatCommand(std::vector<std::string> const& args)
+bool HandleConcatCommand(std::vector<std::string> const& args,
+                         cmExecutionStatus& status)
 {
   if (args.size() < 2) {
-    this->SetError("sub-command CONCAT requires at least one argument.");
+    status.SetError("sub-command CONCAT requires at least one argument.");
     return false;
   }
 
-  return this->joinImpl(args, std::string(), 1);
+  return joinImpl(args, std::string(), 1, status.GetMakefile());
 }
 
-bool cmStringCommand::HandleJoinCommand(std::vector<std::string> const& args)
+bool HandleJoinCommand(std::vector<std::string> const& args,
+                       cmExecutionStatus& status)
 {
   if (args.size() < 3) {
-    this->SetError("sub-command JOIN requires at least two arguments.");
+    status.SetError("sub-command JOIN requires at least two arguments.");
     return false;
   }
 
-  return this->joinImpl(args, args[1], 2);
+  return joinImpl(args, args[1], 2, status.GetMakefile());
 }
 
-bool cmStringCommand::joinImpl(std::vector<std::string> const& args,
-                               std::string const& glue, const size_t varIdx)
+bool joinImpl(std::vector<std::string> const& args, std::string const& glue,
+              const size_t varIdx, cmMakefile& makefile)
 {
   std::string const& variableName = args[varIdx];
   // NOTE Items to concat/join placed right after the variable for
   // both `CONCAT` and `JOIN` sub-commands.
   std::string value = cmJoin(cmMakeRange(args).advance(varIdx + 1), glue);
 
-  this->Makefile->AddDefinition(variableName, value);
+  makefile.AddDefinition(variableName, value);
   return true;
 }
 
-bool cmStringCommand::HandleMakeCIdentifierCommand(
-  std::vector<std::string> const& args)
+bool HandleMakeCIdentifierCommand(std::vector<std::string> const& args,
+                                  cmExecutionStatus& status)
 {
   if (args.size() != 3) {
-    this->SetError("sub-command MAKE_C_IDENTIFIER requires two arguments.");
+    status.SetError("sub-command MAKE_C_IDENTIFIER requires two arguments.");
     return false;
   }
 
   const std::string& input = args[1];
   const std::string& variableName = args[2];
 
-  this->Makefile->AddDefinition(variableName,
-                                cmSystemTools::MakeCidentifier(input));
+  status.GetMakefile().AddDefinition(variableName,
+                                     cmSystemTools::MakeCidentifier(input));
   return true;
 }
 
-bool cmStringCommand::HandleGenexStripCommand(
-  std::vector<std::string> const& args)
+bool HandleGenexStripCommand(std::vector<std::string> const& args,
+                             cmExecutionStatus& status)
 {
   if (args.size() != 3) {
-    this->SetError("sub-command GENEX_STRIP requires two arguments.");
+    status.SetError("sub-command GENEX_STRIP requires two arguments.");
     return false;
   }
 
@@ -672,14 +739,15 @@ bool cmStringCommand::HandleGenexStripCommand(
 
   const std::string& variableName = args[2];
 
-  this->Makefile->AddDefinition(variableName, result);
+  status.GetMakefile().AddDefinition(variableName, result);
   return true;
 }
 
-bool cmStringCommand::HandleStripCommand(std::vector<std::string> const& args)
+bool HandleStripCommand(std::vector<std::string> const& args,
+                        cmExecutionStatus& status)
 {
   if (args.size() != 3) {
-    this->SetError("sub-command STRIP requires two arguments.");
+    status.SetError("sub-command STRIP requires two arguments.");
     return false;
   }
 
@@ -711,12 +779,13 @@ bool cmStringCommand::HandleStripCommand(std::vector<std::string> const& args)
     outLength = endPos - startPos + 1;
   }
 
-  this->Makefile->AddDefinition(variableName,
-                                stringValue.substr(startPos, outLength));
+  status.GetMakefile().AddDefinition(variableName,
+                                     stringValue.substr(startPos, outLength));
   return true;
 }
 
-bool cmStringCommand::HandleRepeatCommand(std::vector<std::string> const& args)
+bool HandleRepeatCommand(std::vector<std::string> const& args,
+                         cmMakefile& makefile)
 {
   // `string(REPEAT "<str>" <times> OUTPUT_VARIABLE)`
   enum ArgPos : std::size_t
@@ -729,16 +798,15 @@ bool cmStringCommand::HandleRepeatCommand(std::vector<std::string> const& args)
   };
 
   if (args.size() != ArgPos::TOTAL_ARGS) {
-    this->Makefile->IssueMessage(
-      MessageType::FATAL_ERROR,
-      "sub-command REPEAT requires three arguments.");
+    makefile.IssueMessage(MessageType::FATAL_ERROR,
+                          "sub-command REPEAT requires three arguments.");
     return true;
   }
 
   unsigned long times;
   if (!cmStrToULong(args[ArgPos::TIMES], &times)) {
-    this->Makefile->IssueMessage(MessageType::FATAL_ERROR,
-                                 "repeat count is not a positive number.");
+    makefile.IssueMessage(MessageType::FATAL_ERROR,
+                          "repeat count is not a positive number.");
     return true;
   }
 
@@ -765,14 +833,15 @@ bool cmStringCommand::HandleRepeatCommand(std::vector<std::string> const& args)
       break;
   }
 
-  this->Makefile->AddDefinition(variableName, result);
+  makefile.AddDefinition(variableName, result);
   return true;
 }
 
-bool cmStringCommand::HandleRandomCommand(std::vector<std::string> const& args)
+bool HandleRandomCommand(std::vector<std::string> const& args,
+                         cmExecutionStatus& status)
 {
   if (args.size() < 2 || args.size() == 3 || args.size() == 5) {
-    this->SetError("sub-command RANDOM requires at least one argument.");
+    status.SetError("sub-command RANDOM requires at least one argument.");
     return false;
   }
 
@@ -809,11 +878,11 @@ bool cmStringCommand::HandleRandomCommand(std::vector<std::string> const& args)
 
   double sizeofAlphabet = static_cast<double>(alphabet.size());
   if (sizeofAlphabet < 1) {
-    this->SetError("sub-command RANDOM invoked with bad alphabet.");
+    status.SetError("sub-command RANDOM invoked with bad alphabet.");
     return false;
   }
   if (length < 1) {
-    this->SetError("sub-command RANDOM invoked with bad length.");
+    status.SetError("sub-command RANDOM invoked with bad length.");
     return false;
   }
   const std::string& variableName = args.back();
@@ -832,19 +901,19 @@ bool cmStringCommand::HandleRandomCommand(std::vector<std::string> const& args)
   }
   result.push_back(0);
 
-  this->Makefile->AddDefinition(variableName, result.data());
+  status.GetMakefile().AddDefinition(variableName, result.data());
   return true;
 }
 
-bool cmStringCommand::HandleTimestampCommand(
-  std::vector<std::string> const& args)
+bool HandleTimestampCommand(std::vector<std::string> const& args,
+                            cmExecutionStatus& status)
 {
   if (args.size() < 2) {
-    this->SetError("sub-command TIMESTAMP requires at least one argument.");
+    status.SetError("sub-command TIMESTAMP requires at least one argument.");
     return false;
   }
   if (args.size() > 4) {
-    this->SetError("sub-command TIMESTAMP takes at most three arguments.");
+    status.SetError("sub-command TIMESTAMP takes at most three arguments.");
     return false;
   }
 
@@ -864,25 +933,26 @@ bool cmStringCommand::HandleTimestampCommand(
     } else {
       std::string e = " TIMESTAMP sub-command does not recognize option " +
         args[argsIndex] + ".";
-      this->SetError(e);
+      status.SetError(e);
       return false;
     }
   }
 
   cmTimestamp timestamp;
   std::string result = timestamp.CurrentTime(formatString, utcFlag);
-  this->Makefile->AddDefinition(outputVariable, result);
+  status.GetMakefile().AddDefinition(outputVariable, result);
 
   return true;
 }
 
-bool cmStringCommand::HandleUuidCommand(std::vector<std::string> const& args)
+bool HandleUuidCommand(std::vector<std::string> const& args,
+                       cmExecutionStatus& status)
 {
 #if !defined(CMAKE_BOOTSTRAP)
   unsigned int argsIndex = 1;
 
   if (args.size() < 2) {
-    this->SetError("UUID sub-command requires an output variable.");
+    status.SetError("UUID sub-command requires an output variable.");
     return false;
   }
 
@@ -897,21 +967,21 @@ bool cmStringCommand::HandleUuidCommand(std::vector<std::string> const& args)
     if (args[argsIndex] == "NAMESPACE") {
       ++argsIndex;
       if (argsIndex >= args.size()) {
-        this->SetError("UUID sub-command, NAMESPACE requires a value.");
+        status.SetError("UUID sub-command, NAMESPACE requires a value.");
         return false;
       }
       uuidNamespaceString = args[argsIndex++];
     } else if (args[argsIndex] == "NAME") {
       ++argsIndex;
       if (argsIndex >= args.size()) {
-        this->SetError("UUID sub-command, NAME requires a value.");
+        status.SetError("UUID sub-command, NAME requires a value.");
         return false;
       }
       uuidName = args[argsIndex++];
     } else if (args[argsIndex] == "TYPE") {
       ++argsIndex;
       if (argsIndex >= args.size()) {
-        this->SetError("UUID sub-command, TYPE requires a value.");
+        status.SetError("UUID sub-command, TYPE requires a value.");
         return false;
       }
       uuidType = args[argsIndex++];
@@ -921,7 +991,7 @@ bool cmStringCommand::HandleUuidCommand(std::vector<std::string> const& args)
     } else {
       std::string e =
         "UUID sub-command does not recognize option " + args[argsIndex] + ".";
-      this->SetError(e);
+      status.SetError(e);
       return false;
     }
   }
@@ -931,7 +1001,7 @@ bool cmStringCommand::HandleUuidCommand(std::vector<std::string> const& args)
 
   std::vector<unsigned char> uuidNamespace;
   if (!uuidGenerator.StringToBinary(uuidNamespaceString, uuidNamespace)) {
-    this->SetError("UUID sub-command, malformed NAMESPACE UUID.");
+    status.SetError("UUID sub-command, malformed NAMESPACE UUID.");
     return false;
   }
 
@@ -941,12 +1011,12 @@ bool cmStringCommand::HandleUuidCommand(std::vector<std::string> const& args)
     uuid = uuidGenerator.FromSha1(uuidNamespace, uuidName);
   } else {
     std::string e = "UUID sub-command, unknown TYPE '" + uuidType + "'.";
-    this->SetError(e);
+    status.SetError(e);
     return false;
   }
 
   if (uuid.empty()) {
-    this->SetError("UUID sub-command, generation failed.");
+    status.SetError("UUID sub-command, generation failed.");
     return false;
   }
 
@@ -954,12 +1024,13 @@ bool cmStringCommand::HandleUuidCommand(std::vector<std::string> const& args)
     uuid = cmSystemTools::UpperCase(uuid);
   }
 
-  this->Makefile->AddDefinition(outputVariable, uuid);
+  status.GetMakefile().AddDefinition(outputVariable, uuid);
   return true;
 #else
   std::ostringstream e;
   e << args[0] << " not available during bootstrap";
-  this->SetError(e.str().c_str());
+  status.SetError(e.str().c_str());
   return false;
 #endif
 }
+}

+ 3 - 54
Source/cmStringCommand.h

@@ -5,67 +5,16 @@
 
 #include "cmConfigure.h" // IWYU pragma: keep
 
-#include <cstddef>
 #include <string>
 #include <vector>
 
-#include "cm_memory.hxx"
-
-#include "cmCommand.h"
-
 class cmExecutionStatus;
 
-/** \class cmStringCommand
+/**
  * \brief Common string operations
  *
  */
-class cmStringCommand : public cmCommand
-{
-public:
-  /**
-   * This is a virtual constructor for the command.
-   */
-  std::unique_ptr<cmCommand> Clone() override
-  {
-    return cm::make_unique<cmStringCommand>();
-  }
-
-  /**
-   * This is called when the command is first encountered in
-   * the CMakeLists.txt file.
-   */
-  bool InitialPass(std::vector<std::string> const& args,
-                   cmExecutionStatus& status) override;
-
-protected:
-  bool HandleConfigureCommand(std::vector<std::string> const& args);
-  bool HandleAsciiCommand(std::vector<std::string> const& args);
-  bool HandleRegexCommand(std::vector<std::string> const& args);
-  bool RegexMatch(std::vector<std::string> const& args);
-  bool RegexMatchAll(std::vector<std::string> const& args);
-  bool RegexReplace(std::vector<std::string> const& args);
-  bool HandleHashCommand(std::vector<std::string> const& args);
-  bool HandleToUpperLowerCommand(std::vector<std::string> const& args,
-                                 bool toUpper);
-  bool HandleCompareCommand(std::vector<std::string> const& args);
-  bool HandleReplaceCommand(std::vector<std::string> const& args);
-  bool HandleLengthCommand(std::vector<std::string> const& args);
-  bool HandleSubstringCommand(std::vector<std::string> const& args);
-  bool HandleAppendCommand(std::vector<std::string> const& args);
-  bool HandlePrependCommand(std::vector<std::string> const& args);
-  bool HandleConcatCommand(std::vector<std::string> const& args);
-  bool HandleJoinCommand(std::vector<std::string> const& args);
-  bool HandleStripCommand(std::vector<std::string> const& args);
-  bool HandleRepeatCommand(std::vector<std::string> const& args);
-  bool HandleRandomCommand(std::vector<std::string> const& args);
-  bool HandleFindCommand(std::vector<std::string> const& args);
-  bool HandleTimestampCommand(std::vector<std::string> const& args);
-  bool HandleMakeCIdentifierCommand(std::vector<std::string> const& args);
-  bool HandleGenexStripCommand(std::vector<std::string> const& args);
-  bool HandleUuidCommand(std::vector<std::string> const& args);
-
-  bool joinImpl(std::vector<std::string> const& args, std::string const& glue,
-                size_t varIdx);
-};
+bool cmStringCommand(std::vector<std::string> const& args,
+                     cmExecutionStatus& status);
 
 #endif