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