[asterisk-scf-commits] asterisk-scf/integration/slice-plugins.git branch "master" created.
Commits to the Asterisk SCF project code repositories
asterisk-scf-commits at lists.digium.com
Tue Jan 4 02:10:33 UTC 2011
branch "master" has been created
at 4640e586f45e3fe06c33e0972f1bad13db8efb78 (commit)
- Log -----------------------------------------------------------------
commit 4640e586f45e3fe06c33e0972f1bad13db8efb78
Author: Kevin P. Fleming <kpfleming at digium.com>
Date: Mon Jan 3 17:46:16 2011 -0600
Remove debug message.
diff --git a/src/SliceVisitorPattern.cpp b/src/SliceVisitorPattern.cpp
index 7eb07c6..96d950a 100644
--- a/src/SliceVisitorPattern.cpp
+++ b/src/SliceVisitorPattern.cpp
@@ -289,7 +289,6 @@ extern "C"
ICE_DECLSPEC_EXPORT PluginVisitorList*
create(Plugin::Language language)
{
- cout << "PluginVisitor being created" << endl;
PluginVisitorList* result = new PluginVisitorList();
result->push_back(new CPPVisitorPatternVisitor);
return result;
commit c28e97bd01ecaa10f06ac9b3353c77262137e1ad
Author: Kevin P. Fleming <kpfleming at digium.com>
Date: Mon Jan 3 17:44:58 2011 -0600
Update to use Slice/Plugin header and provide factory function.
Add installation to CMake script.
diff --git a/CMakeLists.txt b/CMakeLists.txt
index cab23f5..cf65d40 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -157,8 +157,8 @@ if(WIN32)
endif()
find_ICE(3.4)
-
find_ICE_CXX()
+find_ICE_CXX_library(Ice)
message(STATUS "Include directories ${ICE_CXX_INCLUDE_DIR}")
include_directories("${ICE_CXX_INCLUDE_DIR}")
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index f133ff5..facbcf7 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1 +1,4 @@
add_library(SliceVisitorPattern SHARED SliceVisitorPattern.cpp)
+
+get_filename_component(library_path ${ICE_CXX_LIB_Ice} PATH)
+install(TARGETS SliceVisitorPattern LIBRARY DESTINATION ${library_path})
diff --git a/src/SliceVisitorPattern.cpp b/src/SliceVisitorPattern.cpp
index 1edc664..7eb07c6 100644
--- a/src/SliceVisitorPattern.cpp
+++ b/src/SliceVisitorPattern.cpp
@@ -1,8 +1,10 @@
#include <Slice/Parser.h>
#include <Slice/Util.h>
+#include <Slice/Plugin.h>
using namespace std;
using namespace Slice;
+using namespace Slice::Plugin;
// This Visitor iterates over the parse tree looking for 'visitor'
// metadata directives; after validation, it uses these directives
@@ -25,7 +27,7 @@ using namespace Slice;
// where FOO is the name of the class to be visited. The operation
// receives the visited class object as a parameter.
-class VisitorPatternVisitor : public ParserVisitor
+class VisitorPatternVisitor : public PluginVisitor
{
public:
virtual bool visitClassDefStart(const ClassDefPtr&);
@@ -241,7 +243,7 @@ VisitorPatternVisitor::visitClassDefStart(const ClassDefPtr& p)
return false;
}
-class CPPVisitorPatternVisitor : public VisitorPatternVisitor
+class ICE_DECLSPEC_EXPORT CPPVisitorPatternVisitor : public VisitorPatternVisitor
{
protected:
StringList generateVisitFunctionBody(const std::string&, const ClassDefPtr&, const ClassDefPtr&, const std::string&);
@@ -281,3 +283,15 @@ CPPVisitorPatternVisitor::generateVisitFunctionBody(const string& paramName,
return body;
}
+
+extern "C"
+{
+ ICE_DECLSPEC_EXPORT PluginVisitorList*
+ create(Plugin::Language language)
+ {
+ cout << "PluginVisitor being created" << endl;
+ PluginVisitorList* result = new PluginVisitorList();
+ result->push_back(new CPPVisitorPatternVisitor);
+ return result;
+ }
+}
commit 990fda591a845534e6a655d285dbd08beed2d59c
Author: Kevin P. Fleming <kpfleming at digium.com>
Date: Mon Jan 3 13:35:31 2011 -0600
Import more of the needed code.
diff --git a/src/SliceVisitorPattern.cpp b/src/SliceVisitorPattern.cpp
index 40ff3de..1edc664 100644
--- a/src/SliceVisitorPattern.cpp
+++ b/src/SliceVisitorPattern.cpp
@@ -28,35 +28,35 @@ using namespace Slice;
class VisitorPatternVisitor : public ParserVisitor
{
public:
- virtual bool visitClassDefStart(const ClassDefPtr&);
+ virtual bool visitClassDefStart(const ClassDefPtr&);
protected:
- // This function generates the function body for the 'visit' functions
- // in the visited classes. Its parameters are:
- // 1 - the name assigned to the parameter this function will receive (the visitor object)
- // 2 - the base visitor class (the parameter's type)
- // 3 - the derived visitor class (where the visit<FOO> operation is defined)
- // 4 - the name of the operation that should be called on the visitor
- //
- // The function returns a StringList; each string in the list will be placed into the
- // function body in a language-appropriate manner.
- virtual StringList generateVisitFunctionBody(const string&, const ClassDefPtr&, const ClassDefPtr&, const string&) = 0;
+ // This function generates the function body for the 'visit' functions
+ // in the visited classes. Its parameters are:
+ // 1 - the name assigned to the parameter this function will receive (the visitor object)
+ // 2 - the base visitor class (the parameter's type)
+ // 3 - the derived visitor class (where the visit<FOO> operation is defined)
+ // 4 - the name of the operation that should be called on the visitor
+ //
+ // The function returns a StringList; each string in the list will be placed into the
+ // function body in a language-appropriate manner.
+ virtual StringList generateVisitFunctionBody(const string&, const ClassDefPtr&, const ClassDefPtr&, const string&) = 0;
private:
- // This map contains the list of classes known to be visitors;
- // the key is the fully-scoped named of the class, and the value
- // is a pointer to the class definition.
- map<string, ClassDefPtr> _visitorClasses;
- // This map contains the list of base classes that can be visited;
- // the key is the fully scoped named of the class, and the value
- // is a pair consisting of pointers to the class definitions for
- // the visiting classes. The first element is the base visitor class,
- // which defines the type of the parameter to the 'visit' operation
- // generated in the visited class. The second element is the derived
- // visitor class (which might be the same as the base visitor class),
- // which defines the type the parameter must be cast to in order to
- // invoke the visit<FOO> operation on the visitor as described above.
- map<string, pair<ClassDefPtr, ClassDefPtr> > _visitableBases;
+ // This map contains the list of classes known to be visitors;
+ // the key is the fully-scoped named of the class, and the value
+ // is a pointer to the class definition.
+ map<string, ClassDefPtr> _visitorClasses;
+ // This map contains the list of base classes that can be visited;
+ // the key is the fully scoped named of the class, and the value
+ // is a pair consisting of pointers to the class definitions for
+ // the visiting classes. The first element is the base visitor class,
+ // which defines the type of the parameter to the 'visit' operation
+ // generated in the visited class. The second element is the derived
+ // visitor class (which might be the same as the base visitor class),
+ // which defines the type the parameter must be cast to in order to
+ // invoke the visit<FOO> operation on the visitor as described above.
+ map<string, pair<ClassDefPtr, ClassDefPtr> > _visitableBases;
};
// This function attempts to locate a base of the specified class that has been marked
@@ -68,175 +68,216 @@ findVisitableBase(const map<string, pair<ClassDefPtr, ClassDefPtr> >& visitableB
const ClassDefPtr& p, ClassDefPtr& baseVisitor,
ClassDefPtr& derivedVisitor)
{
- ClassList bases = p->allBases();
- for(ClassList::const_iterator q = bases.begin(); q != bases.end(); q++)
- {
- map<string, pair<ClassDefPtr, ClassDefPtr> >::const_iterator it = visitableBases.find((*q)->scoped());
- if(it != visitableBases.end())
- {
- baseVisitor = it->second.first;
- derivedVisitor = it->second.second;
- return *q;
- }
- }
- return 0;
+ ClassList bases = p->allBases();
+ for(ClassList::const_iterator q = bases.begin(); q != bases.end(); q++)
+ {
+ map<string, pair<ClassDefPtr, ClassDefPtr> >::const_iterator it = visitableBases.find((*q)->scoped());
+ if(it != visitableBases.end())
+ {
+ baseVisitor = it->second.first;
+ derivedVisitor = it->second.second;
+ return *q;
+ }
+ }
+ return 0;
}
bool
VisitorPatternVisitor::visitClassDefStart(const ClassDefPtr& p)
{
- ostringstream ostr;
+ ostringstream ostr;
- // First, search for classes tagged with the 'visitor' or 'visitor:XYZ'
- // metadata directives. If they are found, validate the conditions they
- // are used in and report warnings if the conditions are not appropriate.
- StringList metaData = p->getMetaData();
- for(StringList::const_iterator q = metaData.begin(); q != metaData.end(); q++)
- {
- if(*q == "visitor")
- {
- if(!p->isLocal())
- {
- ostr << "ignoring invalid metadata `visitor`: directive can only be applied "
- << "to local classes but `" << p->name() << "` is not local";
- emitWarning(p->file(), p->line(), ostr.str());
- return false;
- }
- else if(p->isInterface())
- {
- ostr << "ignoring invalid metadata `visitor`: directive can only be applied "
- << "to local classes but `" << p->name() << "` is an interface";
- emitWarning(p->file(), p->line(), ostr.str());
- return false;
- }
- else
- {
- // Remember this class as a visiting class.
- _visitorClasses[p->scoped()] = p;
- return false;
- }
- }
- else if(q->find("visitor:", 0) == 0)
- {
- if(p->isInterface())
- {
- ostr << "ignoring invalid `" << *q << "` metadata: directive can only be applied "
- << "to classes, but `" << p->name() << "` is an interface";
- emitWarning(p->file(), p->line(), ostr.str());
- return false;
- }
- else if(p->isAbstract())
- {
- ostr << "ignoring invalid `" << *q << "` metadata: directive can only be applied "
- << "to concrete classes, but `" << p->name() << "` is abstract";
- emitWarning(p->file(), p->line(), ostr.str());
- return false;
- }
- else
- {
- // Attempt to find the specified visiting class in the list of known
- // visiting classes.
- const string visitor = (*q).substr(8);
- map<string, ClassDefPtr>::const_iterator it = _visitorClasses.find(visitor);
- if(it != _visitorClasses.end())
- {
- // Initially, assume the base visitor class will be the specified class.
- ClassDefPtr baseVisitor = it->second, derivedVisitor;
- // Note that the return value of this function is ignored; because this
- // class has been directly marked with the 'visitor' metadata, we already
- // know it must support a visitor; the function is being called
- // to determine if there is a different base visitor class that must be
- // supported.
- findVisitableBase(_visitableBases, p, baseVisitor, derivedVisitor);
- // We know our derived visitor class is the one specified in the directive.
- derivedVisitor = it->second;
- // Remember this class as a visitable base, so that any classes that extend
- // it will automatically be visitable as well.
- _visitableBases[p->scoped()] = make_pair(baseVisitor, derivedVisitor);
- // There is no need to actually generate operations into the visitor
- // class if it was defined in an include file, since the translator
- // won't actually produce output for the include file.
- if(derivedVisitor->includeLevel() == 0)
- {
- // it is necessary to provide a non-empty body for the operation
- // to keep it from being abstract
- StringList body;
- body.push_back("");
- GeneratedOperationPtr gop = derivedVisitor->createGeneratedOperation("visit" + p->name(), 0, body);
- gop->createParamDecl("item", p->declaration(), false);
- }
- // There is no need to actually generate operations into the visited
- // class if it was defined in an include file, since the translator
- // won't actually produce output for the include file.
- if(p->includeLevel() == 0)
- {
- GeneratedOperationPtr gop = p->createGeneratedOperation("visit", 0,
- generateVisitFunctionBody("visitor", baseVisitor, derivedVisitor, "visit" + p->name()));
- gop->createParamDecl("visitor", baseVisitor->declaration(), false);
- }
- return false;
- }
- else
- {
- ostr << "ignoring invalid `" << *q << "` metadata: directive specified on "
- << "class `" << p->name() << "` but specified interface '" << visitor << "` was "
- << "not marked with `visitor` metadata directive";
- emitWarning(p->file(), p->line(), ostr.str());
- return false;
- }
- }
- }
- }
+ // First, search for classes tagged with the 'visitor' or 'visitor:XYZ'
+ // metadata directives. If they are found, validate the conditions they
+ // are used in and report warnings if the conditions are not appropriate.
+ StringList metaData = p->getMetaData();
+ for(StringList::const_iterator q = metaData.begin(); q != metaData.end(); q++)
+ {
+ if(*q == "visitor")
+ {
+ if(!p->isLocal())
+ {
+ ostr << "ignoring invalid metadata `visitor`: directive can only be applied "
+ << "to local classes but `" << p->name() << "` is not local";
+ emitWarning(p->file(), p->line(), ostr.str());
+ return false;
+ }
+ else if(p->isInterface())
+ {
+ ostr << "ignoring invalid metadata `visitor`: directive can only be applied "
+ << "to local classes but `" << p->name() << "` is an interface";
+ emitWarning(p->file(), p->line(), ostr.str());
+ return false;
+ }
+ else
+ {
+ // Remember this class as a visiting class.
+ _visitorClasses[p->scoped()] = p;
+ return false;
+ }
+ }
+ else if(q->find("visitor:", 0) == 0)
+ {
+ if(p->isInterface())
+ {
+ ostr << "ignoring invalid `" << *q << "` metadata: directive can only be applied "
+ << "to classes, but `" << p->name() << "` is an interface";
+ emitWarning(p->file(), p->line(), ostr.str());
+ return false;
+ }
+ else if(p->isAbstract())
+ {
+ ostr << "ignoring invalid `" << *q << "` metadata: directive can only be applied "
+ << "to concrete classes, but `" << p->name() << "` is abstract";
+ emitWarning(p->file(), p->line(), ostr.str());
+ return false;
+ }
+ else
+ {
+ // Attempt to find the specified visiting class in the list of known
+ // visiting classes.
+ const string visitor = (*q).substr(8);
+ map<string, ClassDefPtr>::const_iterator it = _visitorClasses.find(visitor);
+ if(it != _visitorClasses.end())
+ {
+ // Initially, assume the base visitor class will be the specified class.
+ ClassDefPtr baseVisitor = it->second, derivedVisitor;
+ // Note that the return value of this function is ignored; because this
+ // class has been directly marked with the 'visitor' metadata, we already
+ // know it must support a visitor; the function is being called
+ // to determine if there is a different base visitor class that must be
+ // supported.
+ findVisitableBase(_visitableBases, p, baseVisitor, derivedVisitor);
+ // We know our derived visitor class is the one specified in the directive.
+ derivedVisitor = it->second;
+ // Remember this class as a visitable base, so that any classes that extend
+ // it will automatically be visitable as well.
+ _visitableBases[p->scoped()] = make_pair(baseVisitor, derivedVisitor);
+ // There is no need to actually generate operations into the visitor
+ // class if it was defined in an include file, since the translator
+ // won't actually produce output for the include file.
+ if(derivedVisitor->includeLevel() == 0)
+ {
+ // it is necessary to provide a non-empty body for the operation
+ // to keep it from being abstract
+ StringList body;
+ body.push_back("");
+ GeneratedOperationPtr gop = derivedVisitor->createGeneratedOperation("visit" + p->name(), 0, body);
+ gop->createParamDecl("item", p->declaration(), false);
+ }
+ // There is no need to actually generate operations into the visited
+ // class if it was defined in an include file, since the translator
+ // won't actually produce output for the include file.
+ if(p->includeLevel() == 0)
+ {
+ GeneratedOperationPtr gop = p->createGeneratedOperation("visit", 0,
+ generateVisitFunctionBody("visitor", baseVisitor, derivedVisitor, "visit" + p->name()));
+ gop->createParamDecl("visitor", baseVisitor->declaration(), false);
+ }
+ return false;
+ }
+ else
+ {
+ ostr << "ignoring invalid `" << *q << "` metadata: directive specified on "
+ << "class `" << p->name() << "` but specified interface '" << visitor << "` was "
+ << "not marked with `visitor` metadata directive";
+ emitWarning(p->file(), p->line(), ostr.str());
+ return false;
+ }
+ }
+ }
+ }
- // Only classes are supported by 'visitor' metadata inheritance.
- if(p->isInterface())
- {
- return false;
- }
+ // Only classes are supported by 'visitor' metadata inheritance.
+ if(p->isInterface())
+ {
+ return false;
+ }
+
+ // For concrete classes that aren't marked with the 'visitor' metadata,
+ // try to locate a visitable base class that they extend; if one is found,
+ // generate the appropriate operations to support the visitable class.
+ if(!p->isAbstract())
+ {
+ ClassDefPtr baseVisitor, derivedVisitor;
+ if (findVisitableBase(_visitableBases, p, baseVisitor, derivedVisitor))
+ {
+ if(derivedVisitor->includeLevel() == 0)
+ {
+ // it is necessary to provide a non-empty body for the operation
+ // to keep it from being abstract
+ StringList body;
+ body.push_back("");
+ GeneratedOperationPtr gop = derivedVisitor->createGeneratedOperation("visit" + p->name(), 0, body);
+ gop->createParamDecl("item", p->declaration(), false);
+ }
+ if(p->includeLevel() == 0)
+ {
+ GeneratedOperationPtr gop = p->createGeneratedOperation("visit", 0,
+ generateVisitFunctionBody("visitor", baseVisitor, derivedVisitor, "visit" + p->name()));
+ gop->createParamDecl("visitor", baseVisitor->declaration(), false);
+ }
+ }
+ return false;
+ }
- // For concrete classes that aren't marked with the 'visitor' metadata,
- // try to locate a visitable base class that they extend; if one is found,
- // generate the appropriate operations to support the visitable class.
- if(!p->isAbstract())
+ // For abstract classes that aren't marked with 'visitor' metadata,
+ // try to locate a visiting base class that they extend; if one is found,
+ // remember the derived class as a visiting class.
+ if(p->isAbstract())
+ {
+ ClassList bases = p->allBases();
+ for(ClassList::const_iterator q = bases.begin(); q != bases.end(); q++)
+ {
+ map<string, ClassDefPtr>::const_iterator it = _visitorClasses.find((*q)->scoped());
+ if(it != _visitorClasses.end())
+ {
+ _visitorClasses[p->scoped()] = p;
+ return false;
+ }
+ }
+ }
+
+ return false;
+}
+
+class CPPVisitorPatternVisitor : public VisitorPatternVisitor
+{
+protected:
+ StringList generateVisitFunctionBody(const std::string&, const ClassDefPtr&, const ClassDefPtr&, const std::string&);
+};
+
+// This function is fairly straightforward; see VisitorPatternVisitor above for a description
+// of its parameters and return value.
+StringList
+CPPVisitorPatternVisitor::generateVisitFunctionBody(const string& paramName,
+ const ClassDefPtr& baseVisitor,
+ const ClassDefPtr& derivedVisitor,
+ const string& operationName)
+{
+ ostringstream ostr;
+ StringList body;
+
+ if(baseVisitor != derivedVisitor)
{
- ClassDefPtr baseVisitor, derivedVisitor;
- if (findVisitableBase(_visitableBases, p, baseVisitor, derivedVisitor))
- {
- if(derivedVisitor->includeLevel() == 0)
- {
- // it is necessary to provide a non-empty body for the operation
- // to keep it from being abstract
- StringList body;
- body.push_back("");
- GeneratedOperationPtr gop = derivedVisitor->createGeneratedOperation("visit" + p->name(), 0, body);
- gop->createParamDecl("item", p->declaration(), false);
- }
- if(p->includeLevel() == 0)
- {
- GeneratedOperationPtr gop = p->createGeneratedOperation("visit", 0,
- generateVisitFunctionBody("visitor", baseVisitor, derivedVisitor, "visit" + p->name()));
- gop->createParamDecl("visitor", baseVisitor->declaration(), false);
- }
- }
- return false;
+ // The visitor object will be passed by value, which for C++ means it will be an
+ // IceUtil::Handle-derived shared pointer. Since that is the case, we can use
+ // the dynamicCast() operation defined by IceUtil::Handle to convert the pointer
+ // into a derived visitor class pointer.
+ ostr << derivedVisitor->scoped() << "Ptr v = " << derivedVisitor->scoped() << "Ptr::dynamicCast(" << paramName << ");";
+ body.push_back(ostr.str());
+ ostr.str("");
+ ostr << "if (!v) return;";
+ body.push_back(ostr.str());
+ ostr.str("");
+ ostr << "v";
}
-
- // For abstract classes that aren't marked with 'visitor' metadata,
- // try to locate a visiting base class that they extend; if one is found,
- // remember the derived class as a visiting class.
- if(p->isAbstract())
+ else
{
- ClassList bases = p->allBases();
- for(ClassList::const_iterator q = bases.begin(); q != bases.end(); q++)
- {
- map<string, ClassDefPtr>::const_iterator it = _visitorClasses.find((*q)->scoped());
- if(it != _visitorClasses.end())
- {
- _visitorClasses[p->scoped()] = p;
- return false;
- }
- }
+ ostr << paramName;
}
+ ostr << "->" << operationName << "(this);";
+ body.push_back(ostr.str());
- return false;
+ return body;
}
commit fb4fcc7e1a9209605278ae4ce66ab9e204b7d34e
Author: Kevin P. Fleming <kpfleming at digium.com>
Date: Mon Jan 3 13:35:19 2011 -0600
Ignore build subdirectory.
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..378eac2
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+build
commit 9c1d5c95100e9d5d5046c0d52b4b6f17783ef912
Author: Kevin P. Fleming <kpfleming at digium.com>
Date: Mon Jan 3 13:31:23 2011 -0600
Initial import of VisitorPattern stuff to be built as a plugin.
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..cab23f5
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,166 @@
+cmake_minimum_required(VERSION 2.6)
+
+# If a build type has not been explicitly specified then use debug
+if(NOT CMAKE_BUILD_TYPE)
+ set(CMAKE_BUILD_TYPE Debug CACHE STRING
+ "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel Profile."
+ FORCE)
+endif()
+
+# since Debug, debug and DeBuG all mean the same thing to cmake, tolower it
+# for consistency
+string(TOLOWER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE)
+
+if(CMAKE_COMPILER_IS_GNUCXX)
+ set(CMAKE_CXX_FLAGS_DEBUG "-Werror -Wall -g3"
+ CACHE STRING "Flags used by the compiler during debug builds." FORCE)
+endif()
+
+if(WIN32 AND ${CMAKE_BUILD_TYPE} STREQUAL profile)
+ message(FATAL_ERROR "Profile builds not supported")
+endif()
+
+macro(set_cache_var)
+ set(${ARGV} CACHE INTERNAL Bob FORCE)
+endmacro()
+
+# Function which scans a path for matching files or directories,
+# whose names end with a standard version number string, and
+# returns the one with the 'highest' version found, or NOTFOUND
+# if there were no matches. Single-character globs (?) can
+# be used in the base string, but not multi-character globs (*).
+function(find_best_version output base)
+ get_filename_component(base_full "${base}" ABSOLUTE)
+ file(GLOB path_list "${base_full}*")
+ string(LENGTH "${base_full}" base_length)
+ foreach(path ${path_list})
+ get_filename_component(path_full "${path}" ABSOLUTE)
+ string(LENGTH "${path_full}" path_length)
+ math(EXPR get "${path_length} - ${base_length}")
+ string(SUBSTRING "${path_full}" ${base_length} ${get} ver)
+ if(NOT DEFINED best_ver)
+ set(best_ver ${ver})
+ set(best_path "${path_full}")
+ elseif(best_ver VERSION_LESS ver)
+ set(best_ver ${ver})
+ set(best_path "${path_full}")
+ endif()
+ endforeach()
+ if(DEFINED best_ver)
+ set(${output} "${best_path}" PARENT_SCOPE)
+ else()
+ set(${output} "NOTFOUND" PARENT_SCOPE)
+ endif()
+endfunction()
+
+# Find Ice installation for a specific major/minor version
+function(find_ICE version)
+ set(ice "$ENV{ICE_HOME}")
+ if(NOT ice)
+ if(WIN32)
+ find_best_version(ice "C:/Ice-${version}")
+ elseif(UNIX)
+ find_best_version(ice "/opt/Ice-${version}")
+ endif()
+ endif()
+
+ if(NOT ice)
+ message(FATAL_ERROR "Could not find an installation of Ice with version ${version}")
+ endif()
+ find_path(ICE_SLICE_DIR Ice/Current.ice PATHS "${ice}/../slice" "${ice}/slice" NO_DEFAULT_PATH)
+ if(ICE_SLICE_DIR)
+ message(STATUS "Found Ice Slice definitions in ${ICE_SLICE_DIR}")
+ else()
+ message(FATAL_ERROR "Ice installation located at ${ice} is incomplete or broken (missing 'slice' directory)")
+ endif()
+ file(TO_CMAKE_PATH "${ice}" ice_cmake_path)
+ set_cache_var(ICE_DIR "${ice_cmake_path}")
+
+ # find icebox executable
+ # XXX Need to look for iceboxd.exe for debug windows builds
+ find_program(ICEBOX icebox PATHS "${ICE_DIR}/bin" NO_DEFAULT_PATH)
+
+ if(ICEBOX)
+ message(STATUS "Found icebox at ${ICEBOX}")
+ else()
+ message(WARNING "Failed to find icebox ${ICE_DIR}")
+ endif()
+endfunction()
+
+# Find Ice headers and libraries for CXX components
+function(find_ICE_CXX)
+ find_path(ICE_CXX_INCLUDE_DIR Ice/Ice.h PATHS "${ICE_DIR}/include" NO_DEFAULT_PATH)
+ if(ICE_CXX_INCLUDE_DIR)
+ message(STATUS "Found Ice headers for CXX in ${ICE_CXX_INCLUDE_DIR}")
+ else()
+ message(FATAL_ERROR "Failed to find Ice headers for CXX")
+ endif()
+ # This block essentially tricks the GNU compiler into treating the Ice header files as system headers. This has
+ # the benefit of having warnings emitted by the headers NOT treated as errors, even if the compiler has been told
+ # to do so. This is currently being utilized by the C++0x support in this file so that Ice itself does not have to
+ # be updated to be C++0x safe.
+ if(CMAKE_COMPILER_IS_GNUCXX)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem ${ICE_CXX_INCLUDE_DIR}"
+ CACHE STRING "Flags used by the compiler during release builds." FORCE)
+ endif()
+endfunction()
+
+# Find an Ice library for CXX components
+function(find_ICE_CXX_library LIBRARY)
+ if(NOT ICE_CXX_LIB_${LIBRARY})
+ if(WIN32)
+ string(TOLOWER ${LIBRARY} lib)
+ find_library(ICE_CXX_LIB_RELEASE_${LIBRARY} ${lib} PATHS "${ICE_DIR}/lib" NO_DEFAULT_PATH)
+ if(ICE_CXX_LIB_RELEASE_${LIBRARY})
+ message(STATUS "Found Ice ${LIBRARY} library for CXX (release build) at ${ICE_CXX_LIB_RELEASE_${LIBRARY}}")
+ list(APPEND ficxxl_libs optimized "${ICE_CXX_LIB_RELEASE_${LIBRARY}}")
+ endif()
+ find_library(ICE_CXX_LIB_DEBUG_${LIBRARY} ${lib}d PATHS "${ICE_DIR}/lib" NO_DEFAULT_PATH)
+ if(ICE_CXX_LIB_DEBUG_${LIBRARY})
+ message(STATUS "Found Ice ${LIBRARY} library for CXX (debug build) at ${ICE_CXX_LIB_DEBUG_${LIBRARY}}")
+ list(APPEND ficxxl_libs debug "${ICE_CXX_LIB_DEBUG_${LIBRARY}}")
+ endif()
+ if(ficxxl_libs)
+ set_cache_var(ICE_CXX_LIB_${LIBRARY} ${ficxxl_libs})
+ else()
+ message(FATAL_ERROR "Failed to find Ice ${LIBRARY} library for CXX")
+ endif()
+ elseif(UNIX)
+ find_library(ICE_CXX_LIB_${LIBRARY} ${LIBRARY} PATHS "${ICE_DIR}/lib" "${ICE_DIR}/lib32" "${ICE_DIR}/lib64" NO_DEFAULT_PATH)
+ if(ICE_CXX_LIB_${LIBRARY})
+ message(STATUS "Found Ice ${LIBRARY} library for CXX at ${ICE_CXX_LIB_${LIBRARY}}")
+ else()
+ message(FATAL_ERROR "Failed to find Ice ${LIBRARY} library for CXX")
+ endif()
+ endif()
+ endif()
+
+ if(UNIX)
+ get_filename_component(library_path ${ICE_CXX_LIB_${LIBRARY}} PATH)
+ link_directories(${library_path})
+ endif()
+endfunction()
+
+project("Digium Slice Translator Plugins" CXX)
+
+if(WIN32)
+ message(STATUS "Setting SLICE_EXPORT definition for Windows plugins")
+ add_definitions(-DSLICE_EXPORT=__declspec\(dllexport\))
+else()
+ add_definitions(-DSLICE_EXPORT=)
+endif()
+
+# On Windows, 'debug' libraries should have a "d" suffix to indicate that they
+# are debug libraries
+if(WIN32)
+ set(CMAKE_DEBUG_POSTFIX "d" PARENT_SCOPE)
+endif()
+
+find_ICE(3.4)
+
+find_ICE_CXX()
+
+message(STATUS "Include directories ${ICE_CXX_INCLUDE_DIR}")
+include_directories("${ICE_CXX_INCLUDE_DIR}")
+
+add_subdirectory(src)
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
new file mode 100644
index 0000000..f133ff5
--- /dev/null
+++ b/src/CMakeLists.txt
@@ -0,0 +1 @@
+add_library(SliceVisitorPattern SHARED SliceVisitorPattern.cpp)
diff --git a/src/SliceVisitorPattern.cpp b/src/SliceVisitorPattern.cpp
new file mode 100644
index 0000000..40ff3de
--- /dev/null
+++ b/src/SliceVisitorPattern.cpp
@@ -0,0 +1,242 @@
+#include <Slice/Parser.h>
+#include <Slice/Util.h>
+
+using namespace std;
+using namespace Slice;
+
+// This Visitor iterates over the parse tree looking for 'visitor'
+// metadata directives; after validation, it uses these directives
+// to generate operations in both the visiting and visited classes.
+// The 'visitor' metadata is inherited into classes that extend
+// the classes where the directive appears.
+//
+// In the visited classes, an operation called 'visit' is generated
+// which accepts a visitor object as a parameter, and calls a
+// visit<FOO> operation on that object, where FOO is the name of the
+// visited class. If the visited class has been marked to be visited
+// by a derived visitor class, then the 'visit' operation will cast
+// the received visitor object to that derived type so it can call
+// the visit<FOO> operation (which will only exist in the derived
+// visitor class).
+//
+// In the visiting classes, an operation is generated for each class
+// that has been marked with that class' name as its visitor (or
+// has inherited that marking). The operation's name is 'visit<FOO>',
+// where FOO is the name of the class to be visited. The operation
+// receives the visited class object as a parameter.
+
+class VisitorPatternVisitor : public ParserVisitor
+{
+public:
+ virtual bool visitClassDefStart(const ClassDefPtr&);
+
+protected:
+ // This function generates the function body for the 'visit' functions
+ // in the visited classes. Its parameters are:
+ // 1 - the name assigned to the parameter this function will receive (the visitor object)
+ // 2 - the base visitor class (the parameter's type)
+ // 3 - the derived visitor class (where the visit<FOO> operation is defined)
+ // 4 - the name of the operation that should be called on the visitor
+ //
+ // The function returns a StringList; each string in the list will be placed into the
+ // function body in a language-appropriate manner.
+ virtual StringList generateVisitFunctionBody(const string&, const ClassDefPtr&, const ClassDefPtr&, const string&) = 0;
+
+private:
+ // This map contains the list of classes known to be visitors;
+ // the key is the fully-scoped named of the class, and the value
+ // is a pointer to the class definition.
+ map<string, ClassDefPtr> _visitorClasses;
+ // This map contains the list of base classes that can be visited;
+ // the key is the fully scoped named of the class, and the value
+ // is a pair consisting of pointers to the class definitions for
+ // the visiting classes. The first element is the base visitor class,
+ // which defines the type of the parameter to the 'visit' operation
+ // generated in the visited class. The second element is the derived
+ // visitor class (which might be the same as the base visitor class),
+ // which defines the type the parameter must be cast to in order to
+ // invoke the visit<FOO> operation on the visitor as described above.
+ map<string, pair<ClassDefPtr, ClassDefPtr> > _visitableBases;
+};
+
+// This function attempts to locate a base of the specified class that has been marked
+// with the 'visitor:<XYZ>' metadata directive. If it finds one, sets two output
+// parameters to indicate the base visitor class and derived visitor class that this
+// visitable class should support.
+static bool
+findVisitableBase(const map<string, pair<ClassDefPtr, ClassDefPtr> >& visitableBases,
+ const ClassDefPtr& p, ClassDefPtr& baseVisitor,
+ ClassDefPtr& derivedVisitor)
+{
+ ClassList bases = p->allBases();
+ for(ClassList::const_iterator q = bases.begin(); q != bases.end(); q++)
+ {
+ map<string, pair<ClassDefPtr, ClassDefPtr> >::const_iterator it = visitableBases.find((*q)->scoped());
+ if(it != visitableBases.end())
+ {
+ baseVisitor = it->second.first;
+ derivedVisitor = it->second.second;
+ return *q;
+ }
+ }
+ return 0;
+}
+
+bool
+VisitorPatternVisitor::visitClassDefStart(const ClassDefPtr& p)
+{
+ ostringstream ostr;
+
+ // First, search for classes tagged with the 'visitor' or 'visitor:XYZ'
+ // metadata directives. If they are found, validate the conditions they
+ // are used in and report warnings if the conditions are not appropriate.
+ StringList metaData = p->getMetaData();
+ for(StringList::const_iterator q = metaData.begin(); q != metaData.end(); q++)
+ {
+ if(*q == "visitor")
+ {
+ if(!p->isLocal())
+ {
+ ostr << "ignoring invalid metadata `visitor`: directive can only be applied "
+ << "to local classes but `" << p->name() << "` is not local";
+ emitWarning(p->file(), p->line(), ostr.str());
+ return false;
+ }
+ else if(p->isInterface())
+ {
+ ostr << "ignoring invalid metadata `visitor`: directive can only be applied "
+ << "to local classes but `" << p->name() << "` is an interface";
+ emitWarning(p->file(), p->line(), ostr.str());
+ return false;
+ }
+ else
+ {
+ // Remember this class as a visiting class.
+ _visitorClasses[p->scoped()] = p;
+ return false;
+ }
+ }
+ else if(q->find("visitor:", 0) == 0)
+ {
+ if(p->isInterface())
+ {
+ ostr << "ignoring invalid `" << *q << "` metadata: directive can only be applied "
+ << "to classes, but `" << p->name() << "` is an interface";
+ emitWarning(p->file(), p->line(), ostr.str());
+ return false;
+ }
+ else if(p->isAbstract())
+ {
+ ostr << "ignoring invalid `" << *q << "` metadata: directive can only be applied "
+ << "to concrete classes, but `" << p->name() << "` is abstract";
+ emitWarning(p->file(), p->line(), ostr.str());
+ return false;
+ }
+ else
+ {
+ // Attempt to find the specified visiting class in the list of known
+ // visiting classes.
+ const string visitor = (*q).substr(8);
+ map<string, ClassDefPtr>::const_iterator it = _visitorClasses.find(visitor);
+ if(it != _visitorClasses.end())
+ {
+ // Initially, assume the base visitor class will be the specified class.
+ ClassDefPtr baseVisitor = it->second, derivedVisitor;
+ // Note that the return value of this function is ignored; because this
+ // class has been directly marked with the 'visitor' metadata, we already
+ // know it must support a visitor; the function is being called
+ // to determine if there is a different base visitor class that must be
+ // supported.
+ findVisitableBase(_visitableBases, p, baseVisitor, derivedVisitor);
+ // We know our derived visitor class is the one specified in the directive.
+ derivedVisitor = it->second;
+ // Remember this class as a visitable base, so that any classes that extend
+ // it will automatically be visitable as well.
+ _visitableBases[p->scoped()] = make_pair(baseVisitor, derivedVisitor);
+ // There is no need to actually generate operations into the visitor
+ // class if it was defined in an include file, since the translator
+ // won't actually produce output for the include file.
+ if(derivedVisitor->includeLevel() == 0)
+ {
+ // it is necessary to provide a non-empty body for the operation
+ // to keep it from being abstract
+ StringList body;
+ body.push_back("");
+ GeneratedOperationPtr gop = derivedVisitor->createGeneratedOperation("visit" + p->name(), 0, body);
+ gop->createParamDecl("item", p->declaration(), false);
+ }
+ // There is no need to actually generate operations into the visited
+ // class if it was defined in an include file, since the translator
+ // won't actually produce output for the include file.
+ if(p->includeLevel() == 0)
+ {
+ GeneratedOperationPtr gop = p->createGeneratedOperation("visit", 0,
+ generateVisitFunctionBody("visitor", baseVisitor, derivedVisitor, "visit" + p->name()));
+ gop->createParamDecl("visitor", baseVisitor->declaration(), false);
+ }
+ return false;
+ }
+ else
+ {
+ ostr << "ignoring invalid `" << *q << "` metadata: directive specified on "
+ << "class `" << p->name() << "` but specified interface '" << visitor << "` was "
+ << "not marked with `visitor` metadata directive";
+ emitWarning(p->file(), p->line(), ostr.str());
+ return false;
+ }
+ }
+ }
+ }
+
+ // Only classes are supported by 'visitor' metadata inheritance.
+ if(p->isInterface())
+ {
+ return false;
+ }
+
+ // For concrete classes that aren't marked with the 'visitor' metadata,
+ // try to locate a visitable base class that they extend; if one is found,
+ // generate the appropriate operations to support the visitable class.
+ if(!p->isAbstract())
+ {
+ ClassDefPtr baseVisitor, derivedVisitor;
+ if (findVisitableBase(_visitableBases, p, baseVisitor, derivedVisitor))
+ {
+ if(derivedVisitor->includeLevel() == 0)
+ {
+ // it is necessary to provide a non-empty body for the operation
+ // to keep it from being abstract
+ StringList body;
+ body.push_back("");
+ GeneratedOperationPtr gop = derivedVisitor->createGeneratedOperation("visit" + p->name(), 0, body);
+ gop->createParamDecl("item", p->declaration(), false);
+ }
+ if(p->includeLevel() == 0)
+ {
+ GeneratedOperationPtr gop = p->createGeneratedOperation("visit", 0,
+ generateVisitFunctionBody("visitor", baseVisitor, derivedVisitor, "visit" + p->name()));
+ gop->createParamDecl("visitor", baseVisitor->declaration(), false);
+ }
+ }
+ return false;
+ }
+
+ // For abstract classes that aren't marked with 'visitor' metadata,
+ // try to locate a visiting base class that they extend; if one is found,
+ // remember the derived class as a visiting class.
+ if(p->isAbstract())
+ {
+ ClassList bases = p->allBases();
+ for(ClassList::const_iterator q = bases.begin(); q != bases.end(); q++)
+ {
+ map<string, ClassDefPtr>::const_iterator it = _visitorClasses.find((*q)->scoped());
+ if(it != _visitorClasses.end())
+ {
+ _visitorClasses[p->scoped()] = p;
+ return false;
+ }
+ }
+ }
+
+ return false;
+}
-----------------------------------------------------------------------
--
asterisk-scf/integration/slice-plugins.git
More information about the asterisk-scf-commits
mailing list