00001 #include <iostream>
00002
00003 #include "FWCore/ParameterSet/src/PythonFormWriter.h"
00004 #include "FWCore/ParameterSet/interface/Nodes.h"
00005 #include "FWCore/ParameterSet/interface/PSetNode.h"
00006 #include "FWCore/ParameterSet/interface/VPSetNode.h"
00007 #include "FWCore/ParameterSet/interface/EntryNode.h"
00008 #include "FWCore/ParameterSet/interface/ImplicitIncludeNode.h"
00009 #include "FWCore/ParameterSet/interface/VEntryNode.h"
00010 #include "FWCore/ParameterSet/interface/WrapperNode.h"
00011 #include "FWCore/ParameterSet/interface/OperatorNode.h"
00012 #include "FWCore/ParameterSet/interface/OperandNode.h"
00013 #include "FWCore/Utilities/interface/DebugMacros.h"
00014 #include "FWCore/Utilities/interface/EDMException.h"
00015 #include "FWCore/ParameterSet/interface/ParseTree.h"
00016 #include "FWCore/ParameterSet/interface/parse.h"
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #define MYDEBUG(n) FDEBUG(n) << "DBG----- "
00035
00036 namespace edm
00037 {
00038 namespace pset
00039 {
00040
00041
00042
00043
00044 typedef void (*writer_func)(std::ostream&, std::string const&);
00045
00046 void
00047 write_string_value(std::ostream& os, std::string const& val)
00048 {
00049
00050
00051 std::string quotes("'");
00052 if( quotes == val.substr(0,1)) {
00053 quotes = "\"";
00054 }
00055
00056 os <<"r"<<quotes<<val<<quotes;
00057 }
00058
00059 void
00060 write_other_value(std::ostream& os, std::string const& val)
00061 {
00062 os << "'" << val << "'";
00063 }
00064
00065 void
00066 write_trackedness(std::ostream& os, bool trackedval)
00067 {
00068 if (trackedval)
00069 os << "'tracked'";
00070 else
00071 os << "'untracked'";
00072 }
00073
00074
00075
00076
00077
00078 bool
00079 looks_like_an_output_module(std::string const& classname)
00080 {
00081 std::string::size_type pos = classname.find("OutputModule");
00082
00083
00084 if ( pos == std::string::npos ) return false;
00085
00086
00087
00088
00089
00090 return (pos + 12) == classname.size();
00091 }
00092
00093
00094
00095
00096 PythonFormWriter::PythonFormWriter() :
00097 procname_(),
00098 moduleStack_(),
00099 modules_(),
00100 outputModuleNames_(),
00101 modulesWithSecSources_(),
00102 triggerPaths_(),
00103 endPaths_()
00104 {
00105 std::list<std::string> emptylist;
00106 modules_.insert(make_pair(std::string("es_module"), emptylist));
00107 modules_.insert(make_pair(std::string("es_source"), emptylist));
00108 modules_.insert(make_pair(std::string("es_prefer"), emptylist));
00109 modules_.insert(make_pair(std::string("module"), emptylist));
00110 modules_.insert(make_pair(std::string("source"), emptylist));
00111 modules_.insert(make_pair(std::string("looper"), emptylist));
00112 modules_.insert(make_pair(std::string("sequence"),emptylist));
00113 modules_.insert(make_pair(std::string("path"),emptylist));
00114 modules_.insert(make_pair(std::string("endpath"),emptylist));
00115 modules_.insert(make_pair(std::string("schedule"), emptylist));
00116 modules_.insert(make_pair(std::string("service"),emptylist));
00117 modules_.insert(make_pair(std::string("pset"), emptylist));
00118 }
00119
00120 PythonFormWriter::~PythonFormWriter()
00121 { }
00122
00123 void
00124 PythonFormWriter::visitUsing(const UsingNode&)
00125 {
00126 MYDEBUG(5) << "Saw a UsingNode\n";
00127 }
00128
00129 void
00130 PythonFormWriter::visitString(const StringNode&)
00131 {
00132 MYDEBUG(5) << "Saw a StringNode\n";
00133 }
00134
00135
00136
00137 void
00138 PythonFormWriter::visitEntry(const EntryNode& n)
00139 {
00140 MYDEBUG(5) << "Saw an EntryNode\n";
00141 std::ostringstream tuple;
00142
00143 tuple << "'"
00144 << n.name() << "': ('"
00145 << n.type() << "', ";
00146 write_trackedness(tuple, n.isTracked());
00147 tuple << ", ";
00148
00149 if (n.type() == "string")
00150 {
00151 write_string_value(tuple, n.value());
00152 }
00153 else
00154 {
00155 write_other_value(tuple, n.value());
00156 }
00157
00158 tuple << ')';
00159
00160 moduleStack_.top() += tuple.str();
00161 }
00162
00163
00164 void
00165 PythonFormWriter::visitVEntry(const VEntryNode& n)
00166 {
00167 MYDEBUG(5) << "Saw a VEntryNode\n";
00168 std::ostringstream tuple;
00169
00170 tuple << "'"
00171 << n.name() << "': ('"
00172 << n.type() << "', ";
00173
00174 write_trackedness(tuple, n.isTracked());
00175 tuple << ", ";
00176
00177
00178 StringList::const_iterator i = n.value()->begin();
00179 StringList::const_iterator e = n.value()->end();
00180
00181
00182
00183 writer_func writer_to_call =
00184 ( n.type() == "vstring" )
00185 ? &write_string_value
00186 : &write_other_value;
00187
00188 tuple << "[ ";
00189 for ( bool first = true; i != e; ++i, first = false)
00190 {
00191 if (!first) tuple << ", ";
00192 writer_to_call(tuple, *i);
00193 }
00194
00195 tuple << " ])";
00196
00197 moduleStack_.top() += tuple.str();
00198 }
00199
00200 void
00201 PythonFormWriter::visitContents(const ContentsNode& n)
00202 {
00203 MYDEBUG(5) << "Saw a ContentsNode\n";
00204 writeCompositeNode(n);
00205 }
00206
00207
00208 void PythonFormWriter::writeCompositeNode(const CompositeNode &n)
00209 {
00210
00211
00212
00213
00214 if(moduleStack_.empty() )
00215 {
00216
00217 n.acceptForChildren(*this);
00218 }
00219 else
00220 {
00221 moduleStack_.top() += "{";
00222 writeCommaSeparated(n);
00223 moduleStack_.top() += "}";
00224 }
00225 }
00226
00227 void
00228 PythonFormWriter::writeCommaSeparated(const CompositeNode & n)
00229 {
00230 assert(!moduleStack_.empty());
00231 NodePtrList::const_iterator i = n.nodes()->begin();
00232 NodePtrList::const_iterator e = n.nodes()->end();
00233 for ( bool first = true; i != e; first = false, ++i)
00234 {
00235 if (!first)
00236 {
00237 moduleStack_.top() += ", ";
00238 }
00239 (*i)->accept(*this);
00240 }
00241 }
00242
00243 void
00244 PythonFormWriter::visitInclude(const IncludeNode &n)
00245 {
00246 if(moduleStack_.empty() )
00247 {
00248
00249 n.acceptForChildren(*this);
00250 }
00251 else
00252 {
00253 writeCommaSeparated(n);
00254 }
00255 }
00256
00257
00258 void
00259 PythonFormWriter:: visitPSet(const PSetNode& n)
00260 {
00261 MYDEBUG(5) << "Saw a PSetNode\n";
00262 if ( "process" == n.type() )
00263 {
00264 procname_ = n.name();
00265 n.acceptForChildren(*this);
00266
00267 MYDEBUG(4) << "\nprocess name: " << procname_
00268 << "\nstack size? " << moduleStack_.size()
00269 << "\nnumber of module types? " << modules_.size()
00270 << '\n';
00271 }
00272 else if ( "PSet" == n.type() )
00273 {
00274
00275
00276
00277 std::ostringstream out;
00278 out << "'"
00279 << n.name()
00280 << "': ('PSet', ";
00281 write_trackedness(out, n.isTracked());
00282 out << ", ";
00283
00284 bool atTopLevel = (moduleStack_.empty());
00285 if(atTopLevel)
00286 {
00287 moduleStack_.push(std::string());
00288 }
00289 moduleStack_.top() += out.str();
00290 writeCompositeNode(n);
00291
00292
00293
00294 moduleStack_.top() += ")";
00295
00296 if(atTopLevel)
00297 {
00298 modules_["pset"].push_back(moduleStack_.top());
00299 moduleStack_.pop();
00300 }
00301 }
00302 else
00303 {
00304 MYDEBUG(5) << "weird thing: "
00305 << n.type() << " " << n.name() << '\n';
00306 }
00307
00308 }
00309
00310 void
00311 PythonFormWriter::visitVPSet(const VPSetNode& n)
00312 {
00313 MYDEBUG(5) << "Saw a VPSetNode\n";
00314 std::ostringstream out;
00315 out << "'"
00316 << n.name()
00317 << "': ('VPSet', ";
00318 write_trackedness(out, n.isTracked());
00319 out << ", [";
00320 moduleStack_.top() += out.str();
00321
00322 writeCommaSeparated(n);
00323
00324 moduleStack_.top() += "])";
00325 }
00326
00327 void
00328 PythonFormWriter::visitModule(const ModuleNode& n)
00329 {
00330 MYDEBUG(5) << "Saw a ModuleNode, name: "
00331 << n.name() << '\n';
00332
00333 std::ostringstream header;
00334
00335
00336
00337
00338
00339 if ( (n.type() == "es_module") ||
00340 (n.type() == "es_source") ||
00341 (n.type() == "es_prefer") )
00342 {
00343
00344 std::string prefix("");
00345 std::string label("");
00346 std::string name("@");
00347 if((n.type() == "es_module" && n.name()!="nameless" ||
00348 n.type() == "es_source" && n.name()!="main_es_input") ||
00349 n.type() == "es_prefer" && n.name()!="nameless")
00350 {
00351 label = n.name();
00352 name += n.name();
00353 }
00354 if(n.type() =="es_prefer") {
00355 prefix = "esprefer_";
00356 }
00357 header <<"'"<< prefix << n.className() <<name<<"': { '@label': ('string','tracked', '" <<label<<"'), ";
00358 }
00359 else if (n.type() == "source" && n.name().empty())
00360 {
00361
00362 }
00363 else if (n.type() == "looper" && n.name().empty())
00364 {
00365
00366 }
00367 else if(n.type()=="service")
00368 {
00369 header<<"'"<<n.className()<<"': {";
00370 }
00371 else if(n.type()=="secsource")
00372 {
00373
00374
00375
00376 assert( moduleStack_.size() > 0);
00377 std::vector<std::string> tokens = tokenize(moduleStack_.top(), ":");
00378 assert(!tokens.empty());
00379 modulesWithSecSources_.push_back(*(tokens.begin()));
00380
00381 header<<"'"<<n.name() <<"': ('secsource', 'tracked', {";
00382 }
00383 else
00384 {
00385 header << "'" << n.name() << "': {";
00386 }
00387
00388 header << "'@classname': ('string', 'tracked', '"
00389 << n.className()
00390 << "')";
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402 if ( n.type() == "module" &&
00403 looks_like_an_output_module(n.className()) )
00404 {
00405 outputModuleNames_.push_back(n.name());
00406 }
00407
00408
00409 if(n.type() == "secsource")
00410 {
00411 assert(!moduleStack_.empty());
00412 moduleStack_.top() += header.str();
00413 }
00414 else
00415 {
00416 moduleStack_.push(header.str());
00417 }
00418
00419
00420
00421
00422
00423 NodePtrList::const_iterator i(n.nodes()->begin());
00424 NodePtrList::const_iterator e(n.nodes()->end());
00425
00426 for ( ; i!=e; ++i)
00427 {
00428
00429
00430
00431
00432 if (!moduleStack_.empty()) moduleStack_.top() += ", ";
00433 (*i)->accept(*this);
00434 }
00435
00436 moduleStack_.top() += '}';
00437
00438 std::string section_label = n.type();
00439
00440
00441 if(section_label == "secsource")
00442 {
00443 moduleStack_.top() += ')';
00444 }
00445 else
00446 {
00447 modules_[section_label].push_back(moduleStack_.top());
00448 moduleStack_.pop();
00449 }
00450 }
00451
00452
00453
00454 void
00455 PythonFormWriter::visitWrapper(const WrapperNode& n)
00456 {
00457 std::ostringstream header;
00458 header << "'";
00459 if(n.type() != "schedule")
00460 {
00461 header<<n.name()<<"' : '";
00462 }
00463 moduleStack_.push(header.str());
00464
00465
00466 n.wrapped()->accept(*this);
00467
00468 moduleStack_.top()+="'";
00469 modules_[n.type()].push_back(moduleStack_.top());
00470 moduleStack_.pop();
00471 MYDEBUG(5) << "Saw a WrapperNode, name: "
00472 << n.name() << '\n';
00473
00474 if(n.type() == "path")
00475 {
00476 triggerPaths_.push_back(n.name());
00477 }
00478 else if(n.type() == "endpath")
00479 {
00480 endPaths_.push_back(n.name());
00481 }
00482 }
00483
00484 void
00485 PythonFormWriter::visitOperator(const OperatorNode& n)
00486 {
00487 moduleStack_.top()+="(";
00488 n.left()->accept(*this);
00489 moduleStack_.top()+=n.type();
00490 n.right()->accept(*this);
00491 moduleStack_.top()+=")";
00492 }
00493 void
00494 PythonFormWriter::visitOperand(const OperandNode& n)
00495 {
00496 moduleStack_.top()+=n.name();
00497 }
00498
00499
00500 void
00501 PythonFormWriter::write(ParseTree& parsetree, std::ostream& out)
00502 {
00503
00504 parsetree.top()->accept(*this);
00505
00506
00507 out << "{\n'procname': '"
00508 << procname_
00509 << "'\n";
00510
00511 out << ", 'main_input': {\n";
00512 {
00513 std::list<std::string> const& input = modules_["source"];
00514 if(input.empty()){
00515 out << "}";
00516 }
00517 else {
00518 out << *(input.begin()) << '\n';
00519 }
00520
00521 }
00522
00523 out << " # end of main_input\n";
00524
00525 out << ", 'looper': {\n";
00526 {
00527 std::list<std::string> const& input = modules_["looper"];
00528 if(input.empty()){
00529 out << "}";
00530 }
00531 else {
00532 out << *(input.begin()) << '\n';
00533 }
00534
00535 }
00536
00537 out << " # end of looper\n";
00538
00539
00540 writeType("pset", out);
00541 writeType("module", out);
00542 writeType("es_module", out);
00543 writeType("es_source", out);
00544 writeType("es_prefer", out);
00545
00546 out << "# output modules (names)\n";
00547 {
00548 out << ", 'output_modules': [ ";
00549 writeCommaSeparated(outputModuleNames_, true, out);
00550 out << " ]\n" ;
00551 }
00552
00553 out << "# modules with secsources (names)\n";
00554 {
00555 out << ", 'modules_with_secsources': [ ";
00556 writeCommaSeparated(modulesWithSecSources_, false, out);
00557 out << " ]\n" ;
00558 }
00559
00560 writeType("sequence", out);
00561 writeType("path", out);
00562 writeType("endpath", out);
00563 writeType("service", out);
00564 doSchedule(out);
00565
00566 out << '}';
00567 }
00568
00569 void PythonFormWriter::writeType(const std::string & type, std::ostream & out)
00570 {
00571
00572 out << "# " << type << "s\n";
00573 {
00574 out << ", '" << type << "s': {\n";
00575 writeCommaSeparated(modules_[type], false, out);
00576 out << "} #end of " << type << "s\n";
00577 }
00578 }
00579
00580 void PythonFormWriter::writeCommaSeparated(const std::list<std::string> & input,
00581 bool addQuotes, std::ostream & out)
00582 {
00583 std::list<std::string>::const_iterator i = input.begin();
00584 std::list<std::string>::const_iterator e = input.end();
00585 for ( bool first = true; i!=e; first=false,++i)
00586 {
00587 if (!first) out << ',';
00588 if(addQuotes) out << "'";
00589 out << *i ;
00590 if(addQuotes) out << "'";
00591 out << '\n';
00592 }
00593 }
00594
00595
00596 void PythonFormWriter::doSchedule(std::ostream & out)
00597 {
00598 int nSchedules = modules_["schedule"].size();
00599 if(nSchedules > 1)
00600 {
00601 throw edm::Exception(errors::Configuration)
00602 << "More than one schedule defined in this config file";
00603 }
00604
00605 else if(nSchedules == 1)
00606 {
00607 writeSchedule(out);
00608 }
00609
00610
00611 else
00612 {
00613
00614 std::string schedule = "'";
00615 std::list<std::string> parts(triggerPaths_);
00616 parts.insert(parts.end(), endPaths_.begin(), endPaths_.end());
00617 std::list<std::string>::const_iterator i = parts.begin();
00618 std::list<std::string>::const_iterator e = parts.end();
00619 for ( bool first = true; i!=e; first=false,++i)
00620 {
00621 if (!first) schedule += ',';
00622 schedule += *i ;
00623 }
00624 schedule += "'";
00625 modules_["schedule"].push_back(schedule);
00626 writeSchedule(out);
00627 }
00628 }
00629
00630
00631
00632 void PythonFormWriter::writeSchedule(std::ostream & out)
00633 {
00634 out << "# schedule\n";
00635 out << ", 'schedule': " << modules_["schedule"].front() << "\n";
00636 }
00637
00638 }
00639 }