/*============================================================================
  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 "cmLoadCommandCommand.h"
#include "cmCPluginAPI.h"
#include "cmCPluginAPI.cxx"
#include "cmDynamicLoader.h"

#include <cmsys/DynamicLoader.hxx>

#include <stdlib.h>

#ifdef __QNX__
# include <malloc.h> /* for malloc/free on QNX */
#endif

#include <signal.h>
extern "C" void TrapsForSignalsCFunction(int sig);


// a class for loadabple commands
class cmLoadedCommand : public cmCommand
{
public:
  cmLoadedCommand() {
    memset(&this->info,0,sizeof(this->info));
    this->info.CAPI = &cmStaticCAPI;
  }

  ///! clean up any memory allocated by the plugin
  ~cmLoadedCommand();

  /**
   * This is a virtual constructor for the command.
   */
  virtual cmCommand* Clone()
    {
      cmLoadedCommand *newC = new cmLoadedCommand;
      // we must copy when we clone
      memcpy(&newC->info,&this->info,sizeof(info));
      return newC;
    }

  /**
   * This is called when the command is first encountered in
   * the CMakeLists.txt file.
   */
  virtual bool InitialPass(std::vector<std::string> const& args,
                           cmExecutionStatus &);

  /**
   * This is called at the end after all the information
   * specified by the command is accumulated. Most commands do
   * not implement this method.  At this point, reading and
   * writing to the cache can be done.
   */
  virtual void FinalPass();
  virtual bool HasFinalPass() const
    { return this->info.FinalPass? true:false; }

  /**
   * The name of the command as specified in CMakeList.txt.
   */
  virtual std::string GetName() const { return info.Name; }

  static const char* LastName;
  static void TrapsForSignals(int sig)
    {
      fprintf(stderr, "CMake loaded command %s crashed with signal: %d.\n",
              cmLoadedCommand::LastName, sig);
    }
  static void InstallSignalHandlers(const char* name, int remove = 0)
    {
      cmLoadedCommand::LastName = name;
      if(!name)
        {
        cmLoadedCommand::LastName = "????";
        }

      if(!remove)
        {
        signal(SIGSEGV, TrapsForSignalsCFunction);
#ifdef SIGBUS
        signal(SIGBUS,  TrapsForSignalsCFunction);
#endif
        signal(SIGILL,  TrapsForSignalsCFunction);
        }
      else
        {
        signal(SIGSEGV, 0);
#ifdef SIGBUS
        signal(SIGBUS,  0);
#endif
        signal(SIGILL,  0);
        }
    }

  cmTypeMacro(cmLoadedCommand, cmCommand);

  cmLoadedCommandInfo info;
};

extern "C" void TrapsForSignalsCFunction(int sig)
{
  cmLoadedCommand::TrapsForSignals(sig);
}


const char* cmLoadedCommand::LastName = 0;

bool cmLoadedCommand::InitialPass(std::vector<std::string> const& args,
                                  cmExecutionStatus &)
{
  if (!info.InitialPass)
    {
    return true;
    }

  // clear the error string
  if (this->info.Error)
    {
    free(this->info.Error);
    }

  // create argc and argv and then invoke the command
  int argc = static_cast<int> (args.size());
  char **argv = 0;
  if (argc)
    {
    argv = (char **)malloc(argc*sizeof(char *));
    }
  int i;
  for (i = 0; i < argc; ++i)
    {
    argv[i] = strdup(args[i].c_str());
    }
  cmLoadedCommand::InstallSignalHandlers(info.Name);
  int result = info.InitialPass((void *)&info,
                                (void *)this->Makefile,argc,argv);
  cmLoadedCommand::InstallSignalHandlers(info.Name, 1);
  cmFreeArguments(argc,argv);

  if (result)
    {
    return true;
    }

  /* Initial Pass must have failed so set the error string */
  if (this->info.Error)
    {
    this->SetError(this->info.Error);
    }
  return false;
}

void cmLoadedCommand::FinalPass()
{
  if (this->info.FinalPass)
    {
    cmLoadedCommand::InstallSignalHandlers(info.Name);
    this->info.FinalPass((void *)&this->info,(void *)this->Makefile);
    cmLoadedCommand::InstallSignalHandlers(info.Name, 1);
    }
}

cmLoadedCommand::~cmLoadedCommand()
{
  if (this->info.Destructor)
    {
    cmLoadedCommand::InstallSignalHandlers(info.Name);
    this->info.Destructor((void *)&this->info);
    cmLoadedCommand::InstallSignalHandlers(info.Name, 1);
    }
  if (this->info.Error)
    {
    free(this->info.Error);
    }
}

// cmLoadCommandCommand
bool cmLoadCommandCommand
::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
{
  if(this->Disallowed(cmPolicies::CMP0031,
      "The load_command command should not be called; see CMP0031."))
    { return true; }
  if(args.size() < 1 )
    {
    return true;
    }

  // Construct a variable to report what file was loaded, if any.
  // Start by removing the definition in case of failure.
  std::string reportVar = "CMAKE_LOADED_COMMAND_";
  reportVar += args[0];
  this->Makefile->RemoveDefinition(reportVar);

  // the file must exist
  std::string moduleName =
    this->Makefile->GetRequiredDefinition("CMAKE_SHARED_MODULE_PREFIX");
  moduleName += "cm" + args[0];
  moduleName +=
    this->Makefile->GetRequiredDefinition("CMAKE_SHARED_MODULE_SUFFIX");

  // search for the file
  std::vector<std::string> path;
  for (unsigned int j = 1; j < args.size(); j++)
    {
    // expand variables
    std::string exp = args[j];
    cmSystemTools::ExpandRegistryValues(exp);

    // Glob the entry in case of wildcards.
    cmSystemTools::GlobDirs(exp, path);
    }

  // Try to find the program.
  std::string fullPath = cmSystemTools::FindFile(moduleName.c_str(), path);
  if (fullPath == "")
    {
    cmOStringStream e;
    e << "Attempt to load command failed from file \""
      << moduleName << "\"";
    this->SetError(e.str());
    return false;
    }

  // try loading the shared library / dll
  cmsys::DynamicLoader::LibraryHandle lib
    = cmDynamicLoader::OpenLibrary(fullPath.c_str());
  if(!lib)
    {
    std::string err = "Attempt to load the library ";
    err += fullPath + " failed.";
    const char* error = cmsys::DynamicLoader::LastError();
    if ( error )
      {
      err += " Additional error info is:\n";
      err += error;
      }
    this->SetError(err);
    return false;
    }

  // Report what file was loaded for this command.
  this->Makefile->AddDefinition(reportVar, fullPath.c_str());

  // find the init function
  std::string initFuncName = args[0] + "Init";
  CM_INIT_FUNCTION initFunction
    = (CM_INIT_FUNCTION)
    cmsys::DynamicLoader::GetSymbolAddress(lib, initFuncName.c_str());
  if ( !initFunction )
    {
    initFuncName = "_";
    initFuncName += args[0];
    initFuncName += "Init";
    initFunction = (CM_INIT_FUNCTION)(
      cmsys::DynamicLoader::GetSymbolAddress(lib, initFuncName.c_str()));
    }
  // if the symbol is found call it to set the name on the
  // function blocker
  if(initFunction)
    {
    // create a function blocker and set it up
    cmLoadedCommand *f = new cmLoadedCommand();
    (*initFunction)(&f->info);
    this->Makefile->AddCommand(f);
    return true;
    }
  this->SetError("Attempt to load command failed. "
                 "No init function found.");
  return false;
}

