/*============================================================================
  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 "cmAddCustomTargetCommand.h"

#include "cmGeneratorExpression.h"
#include "cmGlobalGenerator.h"

// cmAddCustomTargetCommand
bool cmAddCustomTargetCommand
::InitialPass(std::vector<std::string> const& args,
              cmExecutionStatus&)
{
  if(args.size() < 1 )
    {
    this->SetError("called with incorrect number of arguments");
    return false;
    }

  std::string targetName = args[0];

  // Check the target name.
  if(targetName.find_first_of("/\\") != targetName.npos)
    {
    std::ostringstream e;
    e << "called with invalid target name \"" << targetName
      << "\".  Target names may not contain a slash.  "
      << "Use ADD_CUSTOM_COMMAND to generate files.";
    this->SetError(e.str());
    return false;
    }

  // Accumulate one command line at a time.
  cmCustomCommandLine currentLine;

  // Save all command lines.
  cmCustomCommandLines commandLines;

  // Accumulate dependencies.
  std::vector<std::string> depends, byproducts;
  std::string working_directory;
  bool verbatim = false;
  bool uses_terminal = false;
  std::string comment_buffer;
  const char* comment = 0;
  std::vector<std::string> sources;

  // Keep track of parser state.
  enum tdoing {
    doing_command,
    doing_depends,
    doing_byproducts,
    doing_working_directory,
    doing_comment,
    doing_source,
    doing_nothing
  };
  tdoing doing = doing_command;

  // Look for the ALL option.
  bool excludeFromAll = true;
  unsigned int start = 1;
  if(args.size() > 1)
    {
    if(args[1] == "ALL")
      {
      excludeFromAll = false;
      start = 2;
      }
    }

  // Parse the rest of the arguments.
  for(unsigned int j = start; j < args.size(); ++j)
    {
    std::string const& copy = args[j];

    if(copy == "DEPENDS")
      {
      doing = doing_depends;
      }
    else if(copy == "BYPRODUCTS")
      {
      doing = doing_byproducts;
      }
    else if(copy == "WORKING_DIRECTORY")
      {
      doing = doing_working_directory;
      }
    else if(copy == "VERBATIM")
      {
      doing = doing_nothing;
      verbatim = true;
      }
    else if(copy == "USES_TERMINAL")
      {
      doing = doing_nothing;
      uses_terminal = true;
      }
    else if (copy == "COMMENT")
      {
      doing = doing_comment;
      }
    else if(copy == "COMMAND")
      {
      doing = doing_command;

      // Save the current command before starting the next command.
      if(!currentLine.empty())
        {
        commandLines.push_back(currentLine);
        currentLine.clear();
        }
      }
    else if(copy == "SOURCES")
      {
      doing = doing_source;
      }
    else
      {
      switch (doing)
        {
        case doing_working_directory:
          working_directory = copy;
          break;
        case doing_command:
          currentLine.push_back(copy);
          break;
        case doing_byproducts:
          {
          std::string filename;
          if (!cmSystemTools::FileIsFullPath(copy.c_str()))
            {
            filename = this->Makefile->GetCurrentBinaryDirectory();
            filename += "/";
            }
          filename += copy;
          cmSystemTools::ConvertToUnixSlashes(filename);
          byproducts.push_back(filename);
          }
          break;
        case doing_depends:
          {
          std::string dep = copy;
          cmSystemTools::ConvertToUnixSlashes(dep);
          depends.push_back(dep);
          }
          break;
         case doing_comment:
           comment_buffer = copy;
           comment = comment_buffer.c_str();
           break;
        case doing_source:
          sources.push_back(copy);
          break;
        default:
          this->SetError("Wrong syntax. Unknown type of argument.");
          return false;
        }
      }
    }

  std::string::size_type pos = targetName.find_first_of("#<>");
  if(pos != targetName.npos)
    {
    std::ostringstream msg;
    msg << "called with target name containing a \"" << targetName[pos]
        << "\".  This character is not allowed.";
    this->SetError(msg.str());
    return false;
    }

  // Some requirements on custom target names already exist
  // and have been checked at this point.
  // The following restrictions overlap but depend on policy CMP0037.
  bool nameOk = cmGeneratorExpression::IsValidTargetName(targetName) &&
    !cmGlobalGenerator::IsReservedTarget(targetName);
  if (nameOk)
    {
    nameOk = targetName.find(":") == std::string::npos;
    }
  if (!nameOk)
    {
    cmake::MessageType messageType = cmake::AUTHOR_WARNING;
    std::ostringstream e;
    bool issueMessage = false;
    switch(this->Makefile->GetPolicyStatus(cmPolicies::CMP0037))
      {
      case cmPolicies::WARN:
        e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0037) << "\n";
        issueMessage = true;
      case cmPolicies::OLD:
        break;
      case cmPolicies::NEW:
      case cmPolicies::REQUIRED_IF_USED:
      case cmPolicies::REQUIRED_ALWAYS:
        issueMessage = true;
        messageType = cmake::FATAL_ERROR;
      }
    if (issueMessage)
      {
      e << "The target name \"" << targetName <<
          "\" is reserved or not valid for certain "
          "CMake features, such as generator expressions, and may result "
          "in undefined behavior.";
      this->Makefile->IssueMessage(messageType, e.str());

      if (messageType == cmake::FATAL_ERROR)
        {
        return false;
        }
      }
    }

  // Store the last command line finished.
  if(!currentLine.empty())
    {
    commandLines.push_back(currentLine);
    currentLine.clear();
    }

  // Enforce name uniqueness.
  {
  std::string msg;
  if(!this->Makefile->EnforceUniqueName(targetName, msg, true))
    {
    this->SetError(msg);
    return false;
    }
  }

  // Convert working directory to a full path.
  if(!working_directory.empty())
    {
    const char* build_dir = this->Makefile->GetCurrentBinaryDirectory();
    working_directory =
      cmSystemTools::CollapseFullPath(working_directory, build_dir);
    }

  if (commandLines.empty() && !byproducts.empty())
    {
    this->Makefile->IssueMessage(cmake::FATAL_ERROR,
      "BYPRODUCTS may not be specified without any COMMAND");
    return true;
    }
  if (commandLines.empty() && uses_terminal)
    {
    this->Makefile->IssueMessage(cmake::FATAL_ERROR,
      "USES_TERMINAL may not be specified without any COMMAND");
    return true;
    }

  // Add the utility target to the makefile.
  bool escapeOldStyle = !verbatim;
  cmTarget* target =
    this->Makefile->AddUtilityCommand(targetName, excludeFromAll,
                                      working_directory.c_str(),
                                      byproducts, depends,
                                      commandLines, escapeOldStyle, comment,
                                      uses_terminal);

  // Add additional user-specified source files to the target.
  target->AddSources(sources);

  return true;
}
