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

#include "cmTarget.h"

#include "cmSourceFile.h"

// cmAddCustomCommandCommand
bool cmAddCustomCommandCommand
::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
{
  /* Let's complain at the end of this function about the lack of a particular
     arg. For the moment, let's say that COMMAND, and either TARGET or SOURCE
     are required.
  */
  if (args.size() < 4)
    {
      this->SetError("called with wrong number of arguments.");
      return false;
    }

  std::string source, target, main_dependency, working;
  std::string comment_buffer;
  const char* comment = 0;
  std::vector<std::string> depends, outputs, output;
  bool verbatim = false;
  bool append = false;
  std::string implicit_depends_lang;
  cmCustomCommand::ImplicitDependsList implicit_depends;

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

  // Save all command lines.
  cmCustomCommandLines commandLines;

  cmTarget::CustomCommandType cctype = cmTarget::POST_BUILD;

  enum tdoing {
    doing_source,
    doing_command,
    doing_target,
    doing_depends,
    doing_implicit_depends_lang,
    doing_implicit_depends_file,
    doing_main_dependency,
    doing_output,
    doing_outputs,
    doing_comment,
    doing_working_directory,
    doing_nothing
  };

  tdoing doing = doing_nothing;

  for (unsigned int j = 0; j < args.size(); ++j)
    {
    std::string const& copy = args[j];

    if(copy == "SOURCE")
      {
      doing = doing_source;
      }
    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 == "PRE_BUILD")
      {
      cctype = cmTarget::PRE_BUILD;
      }
    else if(copy == "PRE_LINK")
      {
      cctype = cmTarget::PRE_LINK;
      }
    else if(copy == "POST_BUILD")
      {
      cctype = cmTarget::POST_BUILD;
      }
    else if(copy == "VERBATIM")
      {
      verbatim = true;
      }
    else if(copy == "APPEND")
      {
      append = true;
      }
    else if(copy == "TARGET")
      {
      doing = doing_target;
      }
    else if(copy == "ARGS")
      {
      // Ignore this old keyword.
      }
    else if (copy == "DEPENDS")
      {
      doing = doing_depends;
      }
    else if (copy == "OUTPUTS")
      {
      doing = doing_outputs;
      }
    else if (copy == "OUTPUT")
      {
      doing = doing_output;
      }
    else if (copy == "WORKING_DIRECTORY")
      {
      doing = doing_working_directory;
      }
    else if (copy == "MAIN_DEPENDENCY")
      {
      doing = doing_main_dependency;
      }
    else if (copy == "IMPLICIT_DEPENDS")
      {
      doing = doing_implicit_depends_lang;
      }
    else if (copy == "COMMENT")
      {
      doing = doing_comment;
      }
    else
      {
      std::string filename;
      switch (doing)
        {
        case doing_output:
        case doing_outputs:
          if (!cmSystemTools::FileIsFullPath(copy.c_str()))
            {
            // This is an output to be generated, so it should be
            // under the build tree.  CMake 2.4 placed this under the
            // source tree.  However the only case that this change
            // will break is when someone writes
            //
            //   add_custom_command(OUTPUT out.txt ...)
            //
            // and later references "${CMAKE_CURRENT_SOURCE_DIR}/out.txt".
            // This is fairly obscure so we can wait for someone to
            // complain.
            filename = this->Makefile->GetCurrentOutputDirectory();
            filename += "/";
            }
          filename += copy;
          cmSystemTools::ConvertToUnixSlashes(filename);
          break;
        case doing_source:
          // We do not want to convert the argument to SOURCE because
          // that option is only available for backward compatibility.
          // Old-style use of this command may use the SOURCE==TARGET
          // trick which we must preserve.  If we convert the source
          // to a full path then it will no longer equal the target.
        default:
          break;
        }

      if (cmSystemTools::FileIsFullPath(filename.c_str()))
        {
        filename = cmSystemTools::CollapseFullPath(filename);
        }
       switch (doing)
         {
         case doing_working_directory:
           working = copy;
           break;
         case doing_source:
           source = copy;
           break;
         case doing_output:
           output.push_back(filename);
           break;
         case doing_main_dependency:
           main_dependency = copy;
           break;
         case doing_implicit_depends_lang:
           implicit_depends_lang = copy;
           doing = doing_implicit_depends_file;
           break;
         case doing_implicit_depends_file:
           {
           // An implicit dependency starting point is also an
           // explicit dependency.
           std::string dep = copy;
           cmSystemTools::ConvertToUnixSlashes(dep);
           depends.push_back(dep);

           // Add the implicit dependency language and file.
           cmCustomCommand::ImplicitDependsPair
             entry(implicit_depends_lang, dep);
           implicit_depends.push_back(entry);

           // Switch back to looking for a language.
           doing = doing_implicit_depends_lang;
           }
           break;
         case doing_command:
           currentLine.push_back(copy);
           break;
         case doing_target:
           target = copy;
           break;
         case doing_depends:
           {
           std::string dep = copy;
           cmSystemTools::ConvertToUnixSlashes(dep);
           depends.push_back(dep);
           }
           break;
         case doing_outputs:
           outputs.push_back(filename);
           break;
         case doing_comment:
           comment_buffer = copy;
           comment = comment_buffer.c_str();
           break;
         default:
           this->SetError("Wrong syntax. Unknown type of argument.");
           return false;
         }
      }
    }

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

  // At this point we could complain about the lack of arguments.  For
  // the moment, let's say that COMMAND, TARGET are always required.
  if(output.empty() && target.empty())
    {
    this->SetError("Wrong syntax. A TARGET or OUTPUT must be specified.");
    return false;
    }

  if(source.empty() && !target.empty() && !output.empty())
    {
    this->SetError(
      "Wrong syntax. A TARGET and OUTPUT can not both be specified.");
    return false;
    }
  if(append && output.empty())
    {
    this->SetError("given APPEND option with no OUTPUT.");
    return false;
    }

  // Make sure the output names and locations are safe.
  if(!this->CheckOutputs(output) || !this->CheckOutputs(outputs))
    {
    return false;
    }

  // Check for an append request.
  if(append)
    {
    // Lookup an existing command.
    if(cmSourceFile* sf =
       this->Makefile->GetSourceFileWithOutput(output[0]))
      {
      if(cmCustomCommand* cc = sf->GetCustomCommand())
        {
        cc->AppendCommands(commandLines);
        cc->AppendDepends(depends);
        cc->AppendImplicitDepends(implicit_depends);
        return true;
        }
      }

    // No command for this output exists.
    cmOStringStream e;
    e << "given APPEND option with output \"" << output[0]
      << "\" which is not already a custom command output.";
    this->SetError(e.str());
    return false;
    }

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

  // Choose which mode of the command to use.
  bool escapeOldStyle = !verbatim;
  if(source.empty() && output.empty())
    {
    // Source is empty, use the target.
    std::vector<std::string> no_depends;
    this->Makefile->AddCustomCommandToTarget(target, no_depends,
                                             commandLines, cctype,
                                             comment, working.c_str(),
                                             escapeOldStyle);
    }
  else if(target.empty())
    {
    // Target is empty, use the output.
    this->Makefile->AddCustomCommandToOutput(output, depends,
                                             main_dependency,
                                             commandLines, comment,
                                             working.c_str(), false,
                                             escapeOldStyle);

    // Add implicit dependency scanning requests if any were given.
    if(!implicit_depends.empty())
      {
      bool okay = false;
      if(cmSourceFile* sf =
         this->Makefile->GetSourceFileWithOutput(output[0]))
        {
        if(cmCustomCommand* cc = sf->GetCustomCommand())
          {
          okay = true;
          cc->SetImplicitDepends(implicit_depends);
          }
        }
      if(!okay)
        {
        cmOStringStream e;
        e << "could not locate source file with a custom command producing \""
          << output[0] << "\" even though this command tried to create it!";
        this->SetError(e.str());
        return false;
        }
      }
    }
  else
    {
    bool issueMessage = true;
    cmOStringStream e;
    cmake::MessageType messageType = cmake::AUTHOR_WARNING;
    switch(this->Makefile->GetPolicyStatus(cmPolicies::CMP0050))
    {
    case cmPolicies::WARN:
      e << (this->Makefile->GetPolicies()
                ->GetPolicyWarning(cmPolicies::CMP0050)) << "\n";
      break;
    case cmPolicies::OLD:
      issueMessage = false;
      break;
    case cmPolicies::REQUIRED_ALWAYS:
    case cmPolicies::REQUIRED_IF_USED:
    case cmPolicies::NEW:
      messageType = cmake::FATAL_ERROR;
      break;
    }

    if (issueMessage)
      {
      e << "The SOURCE signatures of add_custom_command are no longer "
           "supported.";
      this->Makefile->IssueMessage(messageType, e.str());
      if (messageType == cmake::FATAL_ERROR)
        {
        return false;
        }
      }

    // Use the old-style mode for backward compatibility.
    this->Makefile->AddCustomCommandOldStyle(target, outputs, depends,
                                             source, commandLines,
                                             comment);
    }

  return true;
}

//----------------------------------------------------------------------------
bool
cmAddCustomCommandCommand
::CheckOutputs(const std::vector<std::string>& outputs)
{
  for(std::vector<std::string>::const_iterator o = outputs.begin();
      o != outputs.end(); ++o)
    {
    // Make sure the file will not be generated into the source
    // directory during an out of source build.
    if(!this->Makefile->CanIWriteThisFile(o->c_str()))
      {
      std::string e = "attempted to have a file \"" + *o +
        "\" in a source directory as an output of custom command.";
      this->SetError(e);
      cmSystemTools::SetFatalErrorOccured();
      return false;
      }

    // Make sure the output file name has no invalid characters.
    std::string::size_type pos = o->find_first_of("#<>");
    if(pos != o->npos)
      {
      cmOStringStream msg;
      msg << "called with OUTPUT containing a \"" << (*o)[pos]
          << "\".  This character is not allowed.";
      this->SetError(msg.str());
      return false;
      }
    }
  return true;
}
