CMS 3D CMS Logo

IncludeNode.cc

Go to the documentation of this file.
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 // circular dependence here
00008 #include "FWCore/ParameterSet/interface/ModuleNode.h"
00009 
00010 namespace edm {
00011   namespace pset {
00012 
00013     //make an empty CompositeNode
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       // don't add your name
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       // if it's modified, we have to print out everything
00043       if(options == COMPRESSED && !isModified())
00044       {
00045          ost << "include \"" << name() << "\"\n";
00046       }
00047       else 
00048       {
00049         // we can't just take CompositeNode's print, since we don't want the 
00050         // curly braces around everything
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       // and pass it up
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       // we don't allow circular opening of already-open files,
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       // ignore second includes at the same level
00085       bool ignore = false;
00086       if(checkMultipleIncludes())
00087       {
00088         if(search_all(sameLevelIncludes, name()))
00089         {
00090           // duplicate.  Remove this one.
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           // re-throw with the traceback info
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         // save the name of the file
00121         extern std::string currentFile;
00122         std::string oldFile = currentFile;
00123         currentFile = fullPath_;
00124         nodes_ = parse(configuration.c_str());
00125         // put in the backwards links right away
00126         setAsChildrensParent();
00127         // resolve the includes in any subnodes
00128         CompositeNode::resolve(openFiles, sameLevelIncludes, strict);
00129       
00130         currentFile = oldFile;
00131         // make sure the openFiles list isn't corrupted
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       // maybe refactor this down to CompositeNode, if another
00141       // CompositeNode needs it
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       // count the number of module nodes
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       // now check if this is included from a .cfi
00189       if(includeParentSuffix() == "cfi")
00190       {
00191         if(strict) 
00192         {
00193           // the only object that can be included within a .cfi is a block.
00194           // see if this include file has only one node, a block.
00195           // tolerate further nesting for now, as long as the result
00196           // is just one block
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 

Generated on Tue Jun 9 17:36:28 2009 for CMSSW by  doxygen 1.5.4