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