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