|
|
@@ -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();
|
|
|
-}
|
|
|
-
|