[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