00001 #include <iostream>
00002 #include <sstream>
00003 #include <cstdlib>
00004 #include <cstring>
00005 #include <cctype>
00006 #include <string>
00007 #include <cassert>
00008
00009 #ifdef _POSIX_C_SOURCE
00010 # include <sys/time.h>
00011 # include <signal.h>
00012 # include <setjmp.h>
00013 #endif
00014
00015 #include <CLHEP/Random/RandomEngine.h>
00016
00017 #include <HepMC/HerwigWrapper.h>
00018
00019 #include "FWCore/ParameterSet/interface/FileInPath.h"
00020 #include "FWCore/Utilities/interface/Exception.h"
00021 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00022
00023 #include "GeneratorInterface/Core/interface/RNDMEngineAccess.h"
00024
00025 #include "GeneratorInterface/Herwig6Interface/interface/herwig.h"
00026 #include "GeneratorInterface/Herwig6Interface/interface/Herwig6Instance.h"
00027
00028 #include "params.inc"
00029
00030 extern "C" void jminit_();
00031 __attribute__((visibility("hidden"))) void dummy()
00032 {
00033 int dummyInt = 0;
00034 jminit_();
00035 jimmin_();
00036 jminit_();
00037 hwmsct_(&dummyInt);
00038 jmefin_();
00039 }
00040
00041
00042 extern "C" void lunread_(const char filename[], const int length);
00043
00044 using namespace gen;
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054 double gen::hwrgen_(int *idummy)
00055 {
00056 Herwig6Instance *instance = FortranInstance::getInstance<Herwig6Instance>();
00057 assert(instance != 0);
00058 assert(instance->randomEngine != 0);
00059 return instance->randomEngine->flat();
00060 }
00061
00062 void gen::cms_hwwarn_(char fn[6], int *code, int *exit)
00063 {
00064 std::string function(fn, fn + sizeof fn);
00065 *exit = FortranInstance::getInstance<Herwig6Instance>()->hwwarn(function, *code);
00066 }
00067
00068 extern "C" {
00069 void hwaend_()
00070 {}
00071
00072 void cmsending_(int *ecode)
00073 {
00074 throw cms::Exception("Herwig6Error")
00075 << "Herwig6 stopped run with error code " << *ecode
00076 << "." << std::endl;
00077 }
00078 }
00079
00080
00081
00082 Herwig6Instance::Herwig6Instance(CLHEP::HepRandomEngine *randomEngine) :
00083 randomEngine(randomEngine ? randomEngine : &getEngineReference()),
00084 timeoutPrivate(0)
00085 {
00086 }
00087
00088 Herwig6Instance::Herwig6Instance(int dummy) :
00089 randomEngine(0),
00090 timeoutPrivate(0)
00091 {
00092 }
00093
00094 Herwig6Instance::~Herwig6Instance()
00095 {
00096 }
00097
00098
00099
00100 #ifdef _POSIX_C_SOURCE
00101
00102
00103
00104 void Herwig6Instance::_timeout_sighandler(int signr)
00105 {
00106 Herwig6Instance *instance = FortranInstance::getInstance<Herwig6Instance>();
00107 assert(instance != 0);
00108 assert(instance->timeoutPrivate != 0);
00109 siglongjmp(*(sigjmp_buf*)instance->timeoutPrivate, 1);
00110 }
00111
00112 bool Herwig6Instance::timeout(unsigned int secs, void (*fn)())
00113 {
00114 if (timeoutPrivate)
00115 throw cms::Exception("ReentrancyProblem")
00116 << "Herwig6Instance::timeout() called recursively."
00117 << std::endl;
00118 struct sigaction saOld;
00119 std::memset(&saOld, 0, sizeof saOld);
00120
00121 struct itimerval itv;
00122 timerclear(&itv.it_value);
00123 timerclear(&itv.it_interval);
00124 itv.it_value.tv_sec = 0;
00125 itv.it_interval.tv_sec = 0;
00126 setitimer(ITIMER_VIRTUAL, &itv, NULL);
00127
00128 sigset_t ss;
00129 sigemptyset(&ss);
00130 sigaddset(&ss, SIGVTALRM);
00131
00132 sigprocmask(SIG_UNBLOCK, &ss, NULL);
00133 sigprocmask(SIG_BLOCK, &ss, NULL);
00134
00135 timeoutPrivate = new sigjmp_buf;
00136 if (sigsetjmp(*(sigjmp_buf*)timeoutPrivate, 1)) {
00137 delete (sigjmp_buf*)timeoutPrivate;
00138 timeoutPrivate = 0;
00139
00140 itv.it_value.tv_sec = 0;
00141 itv.it_interval.tv_sec = 0;
00142 setitimer(ITIMER_VIRTUAL, &itv, NULL);
00143 sigprocmask(SIG_UNBLOCK, &ss, NULL);
00144 return true;
00145 }
00146
00147 itv.it_value.tv_sec = secs;
00148 itv.it_interval.tv_sec = secs;
00149 setitimer(ITIMER_VIRTUAL, &itv, NULL);
00150
00151 struct sigaction sa;
00152 std::memset(&sa, 0, sizeof sa);
00153 sa.sa_handler = &Herwig6Instance::_timeout_sighandler;
00154 sa.sa_flags = SA_ONESHOT;
00155 sigemptyset(&sa.sa_mask);
00156
00157 sigaction(SIGVTALRM, &sa, &saOld);
00158 sigprocmask(SIG_UNBLOCK, &ss, NULL);
00159
00160 try {
00161 fn();
00162 } catch(...) {
00163 delete (sigjmp_buf*)timeoutPrivate;
00164 timeoutPrivate = 0;
00165
00166 itv.it_value.tv_sec = 0;
00167 itv.it_interval.tv_sec = 0;
00168 setitimer(ITIMER_VIRTUAL, &itv, NULL);
00169
00170 sigaction(SIGVTALRM, &saOld, NULL);
00171
00172 throw;
00173 }
00174
00175 delete (sigjmp_buf*)timeoutPrivate;
00176 timeoutPrivate = 0;
00177
00178 itv.it_value.tv_sec = 0;
00179 itv.it_interval.tv_sec = 0;
00180 setitimer(ITIMER_VIRTUAL, &itv, NULL);
00181
00182 sigaction(SIGVTALRM, &saOld, NULL);
00183
00184 return false;
00185 }
00186 #else
00187 bool Herwig6Instance::timeout(unsigned int secs, void (*fn)())
00188 {
00189 fn();
00190 return false;
00191 }
00192 #endif
00193
00194 bool Herwig6Instance::hwwarn(const std::string &fn, int code)
00195 {
00196 return false;
00197 }
00198
00199
00200
00201 bool Herwig6Instance::give(const std::string &line)
00202 {
00203 typedef std::istringstream::traits_type traits;
00204
00205 const char *p = line.c_str(), *q;
00206 p += std::strspn(p, " \t\r\n");
00207
00208 for(q = p; std::isalnum(*q); q++);
00209 std::string name(p, q - p);
00210
00211 const ConfigParam *param;
00212 for(param = configParams; param->name; param++)
00213 if (name == param->name)
00214 break;
00215 if (!param->name)
00216 return false;
00217
00218 p = q + std::strspn(q, " \t\r\n");
00219
00220 std::size_t pos = 0;
00221 std::size_t mult = 1;
00222 for(unsigned int i = 0; i < 3; i++) {
00223 if (!param->dim[i].size)
00224 break;
00225
00226 if (*p++ != (i ? ',' : '('))
00227 return false;
00228
00229 p += std::strspn(p, " \t\r\n");
00230
00231 for(q = p; std::isdigit(*q); q++);
00232 std::istringstream ss(std::string(p, q - p));
00233 std::size_t index;
00234 ss >> index;
00235 if (ss.bad() || ss.peek() != traits::eof())
00236 return false;
00237
00238 if (index < param->dim[i].offset)
00239 return false;
00240 index -= param->dim[i].offset;
00241 if (index >= param->dim[i].size)
00242 return false;
00243
00244 p = q + std::strspn(q, " \t\r\n");
00245
00246 pos += mult * index;
00247 mult *= param->dim[i].size;
00248 }
00249
00250 if (param->dim[0].size) {
00251 if (*p++ != ')')
00252 return false;
00253 p += std::strspn(p, " \t\r\n");
00254 }
00255
00256 if (*p++ != '=')
00257 return false;
00258 p += std::strspn(p, " \t\r\n");
00259
00260 for(q = p; *q && (std::isalnum(*q) || std::strchr(".-+", *q)); q++);
00261 std::istringstream ss(std::string(p, q - p));
00262
00263 p = q + std::strspn(q, " \t\r\n");
00264 if (*p && *p != '!')
00265 return false;
00266
00267 switch(param->type) {
00268 case kInt: {
00269 int value;
00270 ss >> value;
00271 if (ss.bad() || ss.peek() != traits::eof())
00272 return false;
00273
00274 ((int*)param->ptr)[pos] = value;
00275 break;
00276 }
00277 case kDouble: {
00278 double value;
00279 ss >> value;
00280 if (ss.bad() || ss.peek() != traits::eof())
00281 return false;
00282
00283 ((double*)param->ptr)[pos] = value;
00284 break;
00285 }
00286 case kLogical: {
00287 std::string value_;
00288 ss >> value_;
00289 if (ss.bad() || ss.peek() != traits::eof())
00290 return false;
00291
00292 for(std::string::iterator iter = value_.begin();
00293 iter != value_.end(); ++iter)
00294 *iter = std::tolower(*iter);
00295 bool value;
00296 if (value_ == "yes" || value_ == "true" || value_ == "1")
00297 value = true;
00298 else if (value_ == "no" || value_ == "false" || value_ == "0")
00299 value = false;
00300 else
00301 return false;
00302
00303 ((int*)param->ptr)[pos] = value;
00304 break;
00305 }
00306 }
00307
00308 return true;
00309 }
00310
00311 void Herwig6Instance::openParticleSpecFile(const std::string fileName) {
00312
00313 edm::FileInPath fileAndPath( fileName );
00314
00315 lunread_( fileAndPath.fullPath().c_str(),strlen(fileAndPath.fullPath().c_str()) );
00316
00317 return;
00318 }
00319
00320