diff options
Diffstat (limited to 'Source/cmCableClassSet.cxx')
-rw-r--r-- | Source/cmCableClassSet.cxx | 752 |
1 files changed, 0 insertions, 752 deletions
diff --git a/Source/cmCableClassSet.cxx b/Source/cmCableClassSet.cxx deleted file mode 100644 index b8fcd38..0000000 --- a/Source/cmCableClassSet.cxx +++ /dev/null @@ -1,752 +0,0 @@ -/*========================================================================= - - Program: Insight Segmentation & Registration Toolkit - Module: $RCSfile$ - Language: C++ - Date: $Date$ - Version: $Revision$ - - Copyright (c) 2002 Insight Consortium. All rights reserved. - See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. - - This software is distributed WITHOUT ANY WARRANTY; without even - the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - PURPOSE. See the above copyright notices for more information. - -=========================================================================*/ -#include "cmCableClassSet.h" - - -/** - * Add to the set of required sources to define the class. - */ -void cmCableClass::AddSources(const Sources& sources) -{ - for(Sources::const_iterator s = sources.begin(); s != sources.end(); ++s) - { - m_Sources.insert(*s); - } -} - - -/** - * Add to the set of required sources to define the class. - */ -void cmCableClass::AddSource(const char* source) -{ - m_Sources.insert(source); -} - - -/** - * The destructor frees all the cmCableClass instances in the set. - */ -cmCableClassSet::~cmCableClassSet() -{ - for(CableClassMap::const_iterator i = m_CableClassMap.begin(); - i != m_CableClassMap.end(); ++i) - { - delete i->second; - } -} - - -/** - * Add a class to the set. - * Automatically replace ">>" with "> >" to prevent template class name - * problems after replacements. - */ -void cmCableClassSet::AddClass(const char* in_name, - cmCableClass* cableClass) -{ - cmStdString name = in_name; - for(cmStdString::size_type pos = name.find(">>"); - pos != cmStdString::npos; pos = name.find(">>", pos+2)) - { - name.replace(pos, 2, "> >"); - } - m_CableClassMap.insert(CableClassMap::value_type(name, cableClass)); -} - - -/** - * Add a source to every class in the set. This should only be done after - * all classes have been inserted. - */ -void cmCableClassSet::AddSource(const char* name) -{ - for(CableClassMap::iterator c = m_CableClassMap.begin(); - c != m_CableClassMap.end(); ++c) - { - c->second->AddSource(name); - } -} - - -/** - * Get the size of the internal CableClassMap used to store the set. - */ -size_t cmCableClassSet::Size() const -{ - return m_CableClassMap.size(); -} - - -/** - * Get a begin iterator to the internal CableClassMap used to store the - * set. - */ -cmCableClassSet::CableClassMap::const_iterator cmCableClassSet::Begin() const -{ - return m_CableClassMap.begin(); -} - - -/** - * Get an end iterator to the internal CableClassMap used to store the - * set. - */ -cmCableClassSet::CableClassMap::const_iterator cmCableClassSet::End() const -{ - return m_CableClassMap.end(); -} - - -/** - * A utility class to generate element combinations from all possible - * substitutions of set members into a $ token. - */ -class ElementCombinationGenerator -{ -public: - ElementCombinationGenerator(const char* in_element, cmMakefile* in_makefile, - cmCableClassSet* out_set): - m_Makefile(in_makefile), m_OutputSet(out_set) - { - this->ParseInputElement(in_element); - } - ~ElementCombinationGenerator(); - - void Generate(); - -public: - /** - * Represent a substitution. - */ - class Substitution - { - public: - Substitution() {} - void Bind(const cmStdString& in_code, const cmCableClass* in_class) - { - m_Code = in_code; - m_Class = in_class; - } - const cmCableClass* GetClass() const - { return m_Class; } - const cmStdString& GetCode() const - { return m_Code; } - - private: - /** - * The cmCableClass associated with this substitution. - */ - const cmCableClass* m_Class; - - /** - * The code to be used for the substitution. - */ - cmStdString m_Code; - }; - - - /** - * Interface to the parts of an input string of code, possibly with - * $SomeSetName tokens in it. An indivitual Portion will be either - * a StringPortion, which has no substitutions, or a ReplacePortion, - * which has only a substitution, and no hard-coded text. - * - * This is used by cmCableClassSet::GenerateElementCombinations() to - * hold the pieces of a string after the set substitution tokens - * have been extracted. - */ - class Portion - { - public: - /** - * Get the C++ code corresponding to this Portion of a string. - */ - virtual cmStdString GetCode() const =0; - /** - * Get the class corresponding to this Portion of a string. This is NULL - * for StringPortion, and points to a cmCableClass for ReplacePortion. - */ - virtual const cmCableClass* GetClass() const - { return NULL; } - virtual ~Portion() {} - }; - - - /** - * Represent a hard-coded part of an input string, that has no substitutions - * in it. The tag for this part of a string is always empty. - */ - class StringPortion: public Portion - { - public: - StringPortion(const cmStdString& in_code): m_Code(in_code) {} - virtual cmStdString GetCode() const - { return m_Code; } - virtual const cmCableClass* GetClass() const - { return NULL; } - virtual ~StringPortion() {} - private: - /** - * Hold this Portion's contribution to the output string. - */ - cmStdString m_Code; - }; - - - /** - * Represent the "$SomeSetName" portion of an input string. This has a - * reference to the Substitution holding the real output to generate. - */ - class ReplacePortion; - friend class ReplacePortion; - class ReplacePortion: public Portion - { - public: - ReplacePortion(const Substitution& in_substitution): - m_Substitution(in_substitution) {} - virtual cmStdString GetCode() const - { return m_Substitution.GetCode(); } - virtual const cmCableClass* GetClass() const - { return m_Substitution.GetClass(); } - virtual ~ReplacePortion() {} - private: - /** - * Refer to the real Substitution for this Portion's contribution. - */ - const Substitution& m_Substitution; - }; - - typedef std::list<Portion*> Portions; - typedef std::map<const cmCableClassSet*, Substitution*> Substitutions; - - /** - * The makefile in which to lookup set names. - */ - cmMakefile* m_Makefile; - - /** - * The cmCableClassSet instance to be filled with combinations. - */ - cmCableClassSet* m_OutputSet; - - /** - * The class name parsed out for this element, before set expansion. - */ - cmStdString m_ClassName; - - /** - * The tag name parsed out or generated for this element. - */ - cmStdString m_Tag; - - /** - * The set of sources parsed out for this element. - */ - cmCableClass::Sources m_Sources; - - /** - * The parts of the input string after parsing of the tokens. - */ - Portions m_Portions; - - /** - * Map from substitution's Set to actual Substitution. - */ - Substitutions m_Substitutions; - -private: - void Generate(Substitutions::const_iterator); - void ParseInputElement(const char*); - void SplitClassName(); - cmStdString ParseSetName(cmStdString::const_iterator&, - cmStdString::const_iterator) const; - void FindTagSource(); - bool GenerateTag(const cmStdString&); -}; - - -/** - * Destructor frees portions and substitutions that were allocated by - * constructor. - */ -ElementCombinationGenerator -::~ElementCombinationGenerator() -{ - // Free the string portions that were allocated. - for(Portions::iterator portion = m_Portions.begin(); - portion != m_Portions.end(); ++portion) - { - delete *portion; - } - - // Free the substitutions that were allocated. - for(Substitutions::iterator sub = m_Substitutions.begin(); - sub != m_Substitutions.end(); ++sub) - { - delete sub->second; - } -} - - -/** - * Generate all element combinations possible with the set of - * substitutions available. The given output set is filled with - * all the combinations. - */ -void -ElementCombinationGenerator -::Generate() -{ - // If there are no substitutions to be made, just generate this - // single combination. - if(m_Substitutions.empty()) - { - cmCableClass* cableClass = new cmCableClass(m_Tag); - cableClass->AddSources(m_Sources); - m_OutputSet->AddClass(m_ClassName.c_str(), cableClass); - return; - } - - // We must generate all combinations of substitutions. - // Begin the recursion with the first substitution. - this->Generate(m_Substitutions.begin()); -} - - -/** - * Internal helper to Generate() which generates all - * combinations in a recursive, depth-first order. - */ -void -ElementCombinationGenerator -::Generate(Substitutions::const_iterator substitution) -{ - // Test our position in the list of substitutions to be bound. - if(substitution == m_Substitutions.end()) - { - // All substitutions have been prepared. Generate this combination. - cmStdString tag = m_Tag; - cmStdString code = ""; - - // The set of sources for the generated combination. It will - // always include the sources parsed from the original element - // string. - cmCableClass::Sources sources = m_Sources; - - // Put together all the pieces, with substitutions. - for(Portions::const_iterator i = m_Portions.begin(); - i != Portions::const_iterator(m_Portions.end()); ++i) - { - // See if there is a class associated with this portion. - const cmCableClass* curClassPortion = (*i)->GetClass(); - if(curClassPortion) - { - // Append the tag from the class portion. - tag.append(curClassPortion->GetTag()); - - // Include any sources needed by the class in this combination's set. - for(cmCableClass::Sources::const_iterator - s = curClassPortion->SourcesBegin(); - s != curClassPortion->SourcesEnd(); ++s) - { - sources.insert(*s); - } - } - - // Append the portion's code to this combination's code. - code.append((*i)->GetCode()); - } - - // Add this combination to the output set. - cmCableClass* cableClass = new cmCableClass(tag); - cableClass->AddSources(sources); - m_OutputSet->AddClass(code.c_str(), cableClass); - } - else - { - // Get the set for this substitution. - const cmCableClassSet* set = substitution->first; - if(set == m_OutputSet) - { - // We cannot iterate over the set currently being defined. - cmSystemTools::Error("CABLE class set self-reference!"); - return; - } - - // Prepare an iterator to the next substitution. - Substitutions::const_iterator nextSubstitution = substitution; - ++nextSubstitution; - - // We must iterate over all possible values for this substitution. - for(cmCableClassSet::CableClassMap::const_iterator element = set->Begin(); - element != set->End(); ++element) - { - // Bind the substitution to this element. - substitution->second->Bind(element->first, element->second); - - // Move on to the next substitution. - this->Generate(nextSubstitution); - } - } -} - - -/** - * Called from constructor. Parses the given string to extract the - * class information specified. - * - * The format of the string is - * [tag:]class_name[;source1;source2;...] - */ -void -ElementCombinationGenerator -::ParseInputElement(const char* in_element) -{ - // A regular expression to match the tagged element specification. - cmRegularExpression taggedElement = - "^([A-Za-z_0-9]*)[ \t]*:[ \t]*([^:].*|::.*)$"; - - // A regular expression to match the element when more source files are given. - cmRegularExpression sourcesRemain("^([^;]*);(.*)$"); - - cmStdString elementWithoutTag; - cmStdString sourceString; - bool tagGiven = false; - - // See if the element was tagged, and if so, pull off the tag. - if(taggedElement.find(in_element)) - { - // A tag was given. Use it. - tagGiven = true; - m_Tag = taggedElement.match(1); - elementWithoutTag = taggedElement.match(2); - } - else - { - // No tag was given. We will try to generate it later. - elementWithoutTag = in_element; - } - - // Separate the class name. - if(sourcesRemain.find(elementWithoutTag.c_str())) - { - m_ClassName = sourcesRemain.match(1); - sourceString = sourcesRemain.match(2); - } - else - { - m_ClassName = elementWithoutTag; - } - - // Find any source files specified with the ";source" syntax. - while(sourcesRemain.find(sourceString.c_str())) - { - m_Sources.insert(sourcesRemain.match(1)); - sourceString = sourcesRemain.match(2); - } - if(sourceString != "") - { - m_Sources.insert(sourceString); - } - - // If no tag was given, try to generate one. - if(!tagGiven) - { - if(!this->GenerateTag(m_ClassName)) - { - cmSystemTools::Error("Cannot generate tag for class name: ", - m_ClassName.c_str(), - "\nPlease supply one with the \"tag:..\" syntax."); - } - } - - // If there is a .h with the name of the tag, add it as a source. - this->FindTagSource(); - - // Split the class name up into portions for the combination - // generation method. - this->SplitClassName(); -} - - -/** - * Parses the class name into portions. Plain text in the string is - * held by a StringPortion, and a $ token for replacement is - * represented by a ReplacePortion. - */ -void -ElementCombinationGenerator -::SplitClassName() -{ - // Break the input code into blocks alternating between literal code and - // set-substitution tokens (like $SomeSetName). - cmStdString currentPortion = ""; - for(cmStdString::const_iterator c=m_ClassName.begin(); - c != m_ClassName.end(); ++c) - { - // Look for the '$' to mark the beginning of a token. - if(*c != '$') - { - currentPortion.insert(currentPortion.end(), *c); - } - else - { - // If there is a portion of the string, record it. - if(currentPortion.length() > 0) - { - m_Portions.push_back(new StringPortion(currentPortion)); - currentPortion = ""; - } - // Skip over the '$' character. - ++c; - // Get element set name token. - cmStdString setName = this->ParseSetName(c, m_ClassName.end()); - - // We have a complete set name. Look it up in makefile's data - // collection. - cmData* d = m_Makefile->LookupData(setName.c_str()); - // This should be a dynamic_cast, but we don't want to require RTTI. - cmCableClassSet* set = static_cast<cmCableClassSet*>(d); - if(set) - { - // We have a valid set name. Prepare the substitution entry - // for it. - Substitution* sub; - if(m_Substitutions.count(set) == 0) - { - sub = new Substitution(); - m_Substitutions[set] = sub; - } - else - { - sub = m_Substitutions[set]; - } - m_Portions.push_back(new ReplacePortion(*sub)); - setName = ""; - } - else - { - // Invalid set name. Complain. - cmSystemTools::Error("Unknown name of CABLE class set: ", - setName.c_str()); - } - - // Let the loop look at this character again. - --c; - } - } - - // If there is a final portion of the string, record it. - if(currentPortion.length() > 0) - { - m_Portions.push_back(new StringPortion(currentPortion)); - } -} - - -/** - * Parse out the name of a Set specified after a $ in the element's string. - * This is called with "c" pointing to the first character after the $, - * and "end" equal to the string's end iterator. - * - * Returns the set name after parsing. "c" will point to the first - * character after the end of the set name. - */ -cmStdString -ElementCombinationGenerator -::ParseSetName(cmStdString::const_iterator& c, cmStdString::const_iterator end) const -{ - cmStdString setName = ""; - - // Check for the $(setName) syntax. - // If the first character after the '$' is a left paren, we scan for the - // matching paren, and take everything in-between as the set name. - if((c != end) && (*c == '(')) - { - unsigned int depth = 1; - ++c; - while(c != end) - { - char ch = *c++; - if(ch == '(') { ++depth; } - else if(ch == ')') { --depth; } - if(depth == 0) { break; } - setName.insert(setName.end(), ch); - } - return setName; - } - - // The $(setName) syntax was not used. - // Look for all characters that can be part of a qualified C++ - // identifier. - while(c != end) - { - char ch = *c; - if(((ch >= 'a') && (ch <= 'z')) - || ((ch >= 'A') && (ch <= 'Z')) - || ((ch >= '0') && (ch <= '9')) - || (ch == '_') || (ch == ':')) - { - setName.insert(setName.end(), ch); - ++c; - } - else - { - break; - } - } - return setName; -} - - -/** - * After the tag for an element has been determined, but before - * combination expansion is done, this is called to search for a - * header file in the makefile's include path with the name of the - * tag. This makes specifying lists of classes that are declared in - * header files with their own name very convenient. - */ -void ElementCombinationGenerator::FindTagSource() -{ - // If there is no tag, don't bother with this step. - if(m_Tag == "") - { - return; - } - - // Get the makefile's include path. - const std::vector<std::string>& includePath = - m_Makefile->GetIncludeDirectories(); - - // Search the path for a file called "(m_Tag).h". - for(std::vector<std::string>::const_iterator dir = includePath.begin(); - dir != includePath.end(); ++dir) - { - cmStdString filePath = *dir; - m_Makefile->ExpandVariablesInString(filePath); - filePath += "/"+m_Tag+".h"; - if(cmSystemTools::FileExists(filePath.c_str())) - { - m_Sources.insert(m_Tag+".h"); - return; - } - } -} - - -/** - * Given the string representing a set element, automatically generate - * the element tag for it. This function determines how the output - * language of all CABLE-generated wrappers will look. - */ -bool ElementCombinationGenerator::GenerateTag(const cmStdString& element) -{ - // Hold the regular expressions for matching against the element. - cmRegularExpression regex; - - // If the element's code begins in a $, it is referring to a set name. - // The set's elements have their own tags, so we don't need one. - regex.compile("^[ \t]*\\$"); - if(regex.find(element)) - { m_Tag = ""; return true; } - - // Test for simple integer - regex.compile("^[ \t]*([0-9]*)[ \t]*$"); - if(regex.find(element)) - { - m_Tag = "_"; - m_Tag.append(regex.match(1)); - return true; - } - - // Test for basic integer type - regex.compile("^[ \t]*(unsigned[ ]|signed[ ])?[ \t]*(char|short|int|long|long[ ]long)[ \t]*$"); - if(regex.find(element)) - { - m_Tag = "_"; - if(regex.match(1) == "unsigned ") - { m_Tag.append("u"); } - if(regex.match(2) == "long long") - { m_Tag.append("llong"); } - else - { m_Tag.append(regex.match(2)); } - return true; - } - - // Test for basic floating-point type - regex.compile("^[ \t]*(long[ ])?[ \t]*(float|double)[ \t]*$"); - if(regex.find(element)) - { - m_Tag = "_"; - if(static_cast<int>(regex.start(1)) > 0 && regex.match(1) == "long ") - { - m_Tag.append("l"); - } - m_Tag.append(regex.match(2)); - return true; - } - - // Test for basic wide-character type - regex.compile("^[ \t]*(wchar_t)[ \t]*$"); - if(regex.find(element)) - { - m_Tag = "_wchar"; - return true; - } - - // Test for type name (possibly with template arguments). - regex.compile("^[ \t]*([A-Za-z_][A-Za-z0-9_]*)(<.*)?[ \t]*$"); - if(regex.find(element)) - { - // The tag is the same as the type. If there were template arguments, - // they are ignored since they may have their own tags. - m_Tag = regex.match(1); - return true; - } - - // Test for a name with a single namespace qualifier. - regex.compile("^[ \t]*([A-Za-z_][A-Za-z0-9_]*)::([A-Za-z_][A-Za-z0-9_]*)(<.*)?[ \t]*$"); - if(regex.find(element)) - { - // The tag is the same as the namespace and type concatenated together. - m_Tag = regex.match(1); - m_Tag.append(regex.match(2)); - return true; - } - - // We can't generate a tag. - m_Tag = ""; - return false; -} - - -/** - * Given an element in string form, parse out the information from it, - * generate the combinations of set substitutions, and add all the - * elements that result. - */ -void cmCableClassSet::ParseAndAddElement(const char* in_element, - cmMakefile* makefile) -{ - // Create an object to handle the generation. - ElementCombinationGenerator combinationGenerator(in_element, makefile, this); - - // Generate the combinations. - combinationGenerator.Generate(); -} - |