/*=========================================================================

  Program:   CMake - Cross-Platform Makefile Generator
  Module:    $RCSfile$
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 2002 Kitware, Inc., Insight Consortium.  All rights reserved.
  See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.

     This software is distributed WITHOUT ANY WARRANTY; without even 
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
     PURPOSE.  See the above copyright notices 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);

  /**
   * 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();

  /**
   * The name of the command as specified in CMakeList.txt.
   */
  virtual const char* GetName() { return info.Name; }
  
  /**
   * Succinct documentation.
   */
  virtual const char* GetTerseDocumentation() 
    {
      if (this->info.GetTerseDocumentation)
        {
        cmLoadedCommand::InstallSignalHandlers(info.Name);
        const char* ret = info.GetTerseDocumentation(); 
        cmLoadedCommand::InstallSignalHandlers(info.Name, 1);
        return ret;
        }
      else
        {
        return "LoadedCommand without any additional documentation";
        }
    }
  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);
        }
    }
  
  /**
   * More documentation.
   */
  virtual const char* GetFullDocumentation()
    {
      if (this->info.GetFullDocumentation)
        {
        cmLoadedCommand::InstallSignalHandlers(info.Name);
        const char* ret = info.GetFullDocumentation();
        cmLoadedCommand::InstallSignalHandlers(info.Name, 1);
        return ret;
        }
      else
        {
        return "LoadedCommand without any additional documentation";
        }
    }
  
  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)
{
  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)
{
  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.c_str());

  // 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.c_str(), 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().c_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.c_str());
    return false;
    }

  // Report what file was loaded for this command.
  this->Makefile->AddDefinition(reportVar.c_str(), 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;
}

