00001 #include "FWCore/ParameterSet/interface/IncludeNode.h"
00002 #include "FWCore/Utilities/interface/EDMException.h"
00003 #include "FWCore/Utilities/interface/Algorithms.h"
00004 #include "FWCore/ParameterSet/interface/Visitor.h"
00005 #include "FWCore/ParameterSet/interface/parse.h"
00006 #include "FWCore/ParameterSet/interface/FileInPath.h"
00007
00008 #include "FWCore/ParameterSet/interface/ModuleNode.h"
00009
00010 namespace edm {
00011 namespace pset {
00012
00013
00014 IncludeNode::IncludeNode(const std::string & type, const std::string & name, int line)
00015 : CompositeNode(withoutQuotes(name), NodePtrListPtr(new NodePtrList), line),
00016 type_(type),
00017 fullPath_(""),
00018 isResolved_(false)
00019 {
00020 }
00021
00022
00023 void IncludeNode::accept(Visitor& v) const
00024 {
00025 v.visitInclude(*this);
00026 }
00027
00028
00029 void IncludeNode::dotDelimitedPath(std::string & path) const
00030 {
00031
00032 Node * parent = getParent();
00033 if(parent != 0)
00034 {
00035 parent->dotDelimitedPath(path);
00036 }
00037 }
00038
00039
00040 void IncludeNode::print(std::ostream & ost, Node::PrintOptions options) const
00041 {
00042
00043 if(options == COMPRESSED && !isModified())
00044 {
00045 ost << "include \"" << name() << "\"\n";
00046 }
00047 else
00048 {
00049
00050
00051 NodePtrList::const_iterator i(nodes_->begin()),e(nodes_->end());
00052 for(;i!=e;++i)
00053 {
00054 (**i).print(ost, options);
00055 ost << "\n";
00056 }
00057 }
00058 }
00059
00060
00061 void IncludeNode::printTrace(std::ostream & ost) const
00062 {
00063 if(isResolved())
00064 {
00065 ost << "Line " << line() << " includes " << fullPath_ << "\n";
00066 }
00067
00068 Node::printTrace(ost);
00069 }
00070
00071
00072 void IncludeNode::resolve(std::list<std::string> & openFiles,
00073 std::list<std::string> & sameLevelIncludes,
00074 bool strict)
00075 {
00076
00077 if(search_all(openFiles, name()))
00078 {
00079 throw edm::Exception(errors::Configuration, "IncludeError")
00080 << "Circular inclusion of file " << name()
00081 << "\nfrom " << traceback();
00082 }
00083
00084
00085 bool ignore = false;
00086 if(checkMultipleIncludes())
00087 {
00088 if(search_all(sameLevelIncludes, name()))
00089 {
00090
00091 CompositeNode * parent = dynamic_cast<CompositeNode *>(getParent());
00092 assert(parent != 0);
00093 parent->removeChild(this);
00094 ignore = true;
00095 }
00096 else
00097 {
00098 sameLevelIncludes.push_back(name());
00099 }
00100 }
00101
00102 if(!ignore)
00103 {
00104 openFiles.push_back(name());
00105 try
00106 {
00107 FileInPath fip(name());
00108 fullPath_ = fip.fullPath();
00109 }
00110 catch(const edm::Exception & e)
00111 {
00112
00113 throw edm::Exception(errors::Configuration, "IncludeError")
00114 << "Exception found trying to include " << name() << ":\n"
00115 << e.what() << "\nIncluded from:\n" << traceback();
00116 }
00117
00118 isResolved_ = true;
00119 std::string configuration = read_whole_file(fullPath_);
00120
00121 extern std::string currentFile;
00122 std::string oldFile = currentFile;
00123 currentFile = fullPath_;
00124 nodes_ = parse(configuration.c_str());
00125
00126 setAsChildrensParent();
00127
00128 CompositeNode::resolve(openFiles, sameLevelIncludes, strict);
00129
00130 currentFile = oldFile;
00131
00132 assert(openFiles.back() == name());
00133 openFiles.pop_back();
00134 check(strict);
00135 }
00136 }
00137
00138 void IncludeNode::insertInto(edm::ProcessDesc & procDesc) const
00139 {
00140
00141
00142 NodePtrList::const_iterator i(nodes_->begin()),e(nodes_->end());
00143 for(;i!=e;++i)
00144 {
00145 (**i).insertInto(procDesc);
00146 }
00147 }
00148
00149
00150 bool IncludeNode::check(bool strict) const
00151 {
00152 bool ok = true;
00153 int nletters = name().length();
00154 assert(nletters >= 3);
00155 std::string lastThreeLetters = name().substr(nletters-3);
00156
00157 int nModules = 0;
00158
00159 if(lastThreeLetters == "cfi")
00160 {
00161 NodePtrList::const_iterator i(nodes_->begin()),e(nodes_->end());
00162 for(;i!=e;++i)
00163 {
00164 if(dynamic_cast<const ModuleNode *>((*i).get()) != 0)
00165 {
00166 ++nModules;
00167 }
00168 }
00169
00170 if(nModules > 1)
00171 {
00172 ok = false;
00173 std::ostringstream message;
00174
00175 message
00176 << nModules << " modules were defined in "
00177 << name() << ".\nOnly one module should be defined per .cfi."
00178 <<"\nfrom: " << traceback();
00179
00180 if(strict)
00181 {
00182 throw edm::Exception(errors::Configuration) << message.str();
00183 }
00184
00185 }
00186 }
00187
00188
00189 if(includeParentSuffix() == "cfi")
00190 {
00191 if(strict)
00192 {
00193
00194
00195
00196
00197 NodePtrListPtr kids = children();
00198 ok = (kids->size()==1 && kids->front()->type() == "block");
00199
00200 if(!ok)
00201 {
00202 std::ostringstream message;
00203 message << "include statements should not be used in a .cfi file."
00204 << "\nfrom:" << traceback();
00205 throw edm::Exception(errors::Configuration) << message.str();
00206 }
00207 }
00208 }
00209
00210 return ok;
00211 }
00212
00213
00214 }
00215 }
00216