summaryrefslogtreecommitdiff
path: root/cpp/src/slice2cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cpp/src/slice2cpp')
-rw-r--r--cpp/src/slice2cpp/.depend2
-rw-r--r--cpp/src/slice2cpp/.depend.mak2
-rw-r--r--cpp/src/slice2cpp/Gen.cpp7087
-rw-r--r--cpp/src/slice2cpp/Gen.h493
-rw-r--r--cpp/src/slice2cpp/Main.cpp337
-rw-r--r--cpp/src/slice2cpp/Makefile32
-rw-r--r--cpp/src/slice2cpp/Makefile.mak61
-rw-r--r--cpp/src/slice2cpp/Slice2Cpp.rc34
8 files changed, 8048 insertions, 0 deletions
diff --git a/cpp/src/slice2cpp/.depend b/cpp/src/slice2cpp/.depend
new file mode 100644
index 00000000000..9ac6f06151b
--- /dev/null
+++ b/cpp/src/slice2cpp/.depend
@@ -0,0 +1,2 @@
+Gen$(OBJEXT): Gen.cpp $(includedir)/IceUtil/DisableWarnings.h Gen.h $(includedir)/Slice/Parser.h $(includedir)/IceUtil/Shared.h $(includedir)/IceUtil/Config.h $(includedir)/IceUtil/Handle.h $(includedir)/IceUtil/Exception.h $(includedir)/IceUtil/OutputUtil.h $(includedir)/Slice/Util.h $(includedir)/Slice/CPlusPlusUtil.h $(includedir)/IceUtil/Functional.h $(includedir)/IceUtil/Iterator.h $(includedir)/Slice/Checksum.h $(includedir)/Slice/FileTracker.h
+Main$(OBJEXT): Main.cpp $(includedir)/IceUtil/Options.h $(includedir)/IceUtil/Config.h $(includedir)/IceUtil/RecMutex.h $(includedir)/IceUtil/Lock.h $(includedir)/IceUtil/ThreadException.h $(includedir)/IceUtil/Exception.h $(includedir)/IceUtil/Time.h $(includedir)/IceUtil/MutexProtocol.h $(includedir)/IceUtil/Shared.h $(includedir)/IceUtil/Handle.h $(includedir)/IceUtil/CtrlCHandler.h $(includedir)/IceUtil/Mutex.h $(includedir)/IceUtil/MutexPtrLock.h $(includedir)/Slice/Preprocessor.h $(includedir)/Slice/FileTracker.h $(includedir)/Slice/Parser.h $(includedir)/Slice/Util.h $(includedir)/IceUtil/OutputUtil.h Gen.h
diff --git a/cpp/src/slice2cpp/.depend.mak b/cpp/src/slice2cpp/.depend.mak
new file mode 100644
index 00000000000..595c48191d3
--- /dev/null
+++ b/cpp/src/slice2cpp/.depend.mak
@@ -0,0 +1,2 @@
+Gen$(OBJEXT): Gen.cpp "$(includedir)/IceUtil/DisableWarnings.h" Gen.h "$(includedir)/Slice/Parser.h" "$(includedir)/IceUtil/Shared.h" "$(includedir)/IceUtil/Config.h" "$(includedir)/IceUtil/Handle.h" "$(includedir)/IceUtil/Exception.h" "$(includedir)/IceUtil/OutputUtil.h" "$(includedir)/Slice/Util.h" "$(includedir)/Slice/CPlusPlusUtil.h" "$(includedir)/IceUtil/Functional.h" "$(includedir)/IceUtil/Iterator.h" "$(includedir)/Slice/Checksum.h" "$(includedir)/Slice/FileTracker.h"
+Main$(OBJEXT): Main.cpp "$(includedir)/IceUtil/Options.h" "$(includedir)/IceUtil/Config.h" "$(includedir)/IceUtil/RecMutex.h" "$(includedir)/IceUtil/Lock.h" "$(includedir)/IceUtil/ThreadException.h" "$(includedir)/IceUtil/Exception.h" "$(includedir)/IceUtil/Time.h" "$(includedir)/IceUtil/MutexProtocol.h" "$(includedir)/IceUtil/Shared.h" "$(includedir)/IceUtil/Handle.h" "$(includedir)/IceUtil/CtrlCHandler.h" "$(includedir)/IceUtil/Mutex.h" "$(includedir)/IceUtil/MutexPtrLock.h" "$(includedir)/Slice/Preprocessor.h" "$(includedir)/Slice/FileTracker.h" "$(includedir)/Slice/Parser.h" "$(includedir)/Slice/Util.h" "$(includedir)/IceUtil/OutputUtil.h" Gen.h
diff --git a/cpp/src/slice2cpp/Gen.cpp b/cpp/src/slice2cpp/Gen.cpp
new file mode 100644
index 00000000000..dfceb00e3d6
--- /dev/null
+++ b/cpp/src/slice2cpp/Gen.cpp
@@ -0,0 +1,7087 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+#include <IceUtil/DisableWarnings.h>
+#include <Gen.h>
+#include <Slice/Util.h>
+#include <Slice/CPlusPlusUtil.h>
+#include <IceUtil/Functional.h>
+#include <IceUtil/Iterator.h>
+#include <Slice/Checksum.h>
+#include <Slice/FileTracker.h>
+
+#include <limits>
+
+#include <sys/stat.h>
+#include <string.h>
+
+using namespace std;
+using namespace Slice;
+using namespace IceUtil;
+using namespace IceUtilInternal;
+
+static string
+getDeprecateSymbol(const ContainedPtr& p1, const ContainedPtr& p2)
+{
+ string deprecateMetadata, deprecateSymbol;
+ if(p1->findMetaData("deprecate", deprecateMetadata) ||
+ (p2 != 0 && p2->findMetaData("deprecate", deprecateMetadata)))
+ {
+ deprecateSymbol = "ICE_DEPRECATED_API ";
+ }
+ return deprecateSymbol;
+}
+
+static void
+writeConstantValue(IceUtilInternal::Output& out, const TypePtr& type, const SyntaxTreeBasePtr& valueType,
+ const string& value, int useWstring, const StringList& metaData)
+{
+ ConstPtr constant = ConstPtr::dynamicCast(valueType);
+ if(constant)
+ {
+ out << fixKwd(constant->scoped());
+ }
+ else
+ {
+ BuiltinPtr bp = BuiltinPtr::dynamicCast(type);
+ if(bp && bp->kind() == Builtin::KindString)
+ {
+ //
+ // Expand strings into the basic source character set. We can't use isalpha() and the like
+ // here because they are sensitive to the current locale.
+ //
+ static const string basicSourceChars = "abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789"
+ "_{}[]#()<>%:;.?*+-/^&|~!=,\\\"' ";
+ static const set<char> charSet(basicSourceChars.begin(), basicSourceChars.end());
+
+ if((useWstring & TypeContextUseWstring) || findMetaData(metaData) == "wstring")
+ {
+ out << 'L';
+ }
+ out << "\""; // Opening "
+
+ for(string::const_iterator c = value.begin(); c != value.end(); ++c)
+ {
+ if(charSet.find(*c) == charSet.end())
+ {
+ unsigned char uc = *c; // char may be signed, so make it positive
+ ostringstream s;
+ s << "\\"; // Print as octal if not in basic source character set
+ s.width(3);
+ s.fill('0');
+ s << oct;
+ s << static_cast<unsigned>(uc);
+ out << s.str();
+ }
+ else
+ {
+ switch(*c)
+ {
+ case '\\':
+ case '"':
+ {
+ out << "\\";
+ break;
+ }
+ }
+ out << *c; // Print normally if in basic source character set
+ }
+ }
+
+ out << "\""; // Closing "
+ }
+ else if(bp && bp->kind() == Builtin::KindLong)
+ {
+ out << "ICE_INT64(" << value << ")";
+ }
+ else if(bp && bp->kind() == Builtin::KindFloat)
+ {
+ out << value << "F";
+ }
+ else
+ {
+ EnumPtr ep = EnumPtr::dynamicCast(type);
+ if(ep)
+ {
+ out << fixKwd(value);
+ }
+ else
+ {
+ out << value;
+ }
+ }
+ }
+}
+
+static void
+writeDataMemberInitializers(IceUtilInternal::Output& C, const DataMemberList& members, int useWstring)
+{
+ bool first = true;
+ for(DataMemberList::const_iterator p = members.begin(); p != members.end(); ++p)
+ {
+ if((*p)->defaultValueType())
+ {
+ string memberName = fixKwd((*p)->name());
+
+ if(first)
+ {
+ first = false;
+ }
+ else
+ {
+ C << ',';
+ }
+ C << nl << memberName << '(';
+ writeConstantValue(C, (*p)->type(), (*p)->defaultValueType(), (*p)->defaultValue(), useWstring,
+ (*p)->getMetaData());
+ C << ')';
+ }
+ }
+}
+
+Slice::Gen::Gen(const string& base, const string& headerExtension, const string& sourceExtension,
+ const vector<string>& extraHeaders, const string& include,
+ const vector<string>& includePaths, const string& dllExport, const string& dir,
+ bool imp, bool checksum, bool stream, bool ice) :
+ _base(base),
+ _headerExtension(headerExtension),
+ _implHeaderExtension(headerExtension),
+ _sourceExtension(sourceExtension),
+ _extraHeaders(extraHeaders),
+ _include(include),
+ _includePaths(includePaths),
+ _dllExport(dllExport),
+ _dir(dir),
+ _impl(imp),
+ _checksum(checksum),
+ _stream(stream),
+ _ice(ice)
+{
+ for(vector<string>::iterator p = _includePaths.begin(); p != _includePaths.end(); ++p)
+ {
+ *p = fullPath(*p);
+ }
+
+ string::size_type pos = _base.find_last_of("/\\");
+ if(pos != string::npos)
+ {
+ _base.erase(0, pos + 1);
+ }
+}
+
+Slice::Gen::~Gen()
+{
+ H << "\n\n#endif\n";
+ C << '\n';
+
+ if(_impl)
+ {
+ implH << "\n\n#endif\n";
+ implC << '\n';
+ }
+}
+
+void
+Slice::Gen::generate(const UnitPtr& p)
+{
+ string file = p->topLevelFile();
+
+ //
+ // Give precedence to header-ext global metadata.
+ //
+ string headerExtension = getHeaderExt(file, p);
+ if(!headerExtension.empty())
+ {
+ _headerExtension = headerExtension;
+ }
+
+ if(_impl)
+ {
+ string fileImplH = _base + "I." + _implHeaderExtension;
+ string fileImplC = _base + "I." + _sourceExtension;
+ if(!_dir.empty())
+ {
+ fileImplH = _dir + '/' + fileImplH;
+ fileImplC = _dir + '/' + fileImplC;
+ }
+
+ struct stat st;
+ if(stat(fileImplH.c_str(), &st) == 0)
+ {
+ ostringstream os;
+ os << fileImplH << "' already exists - will not overwrite";
+ throw FileException(__FILE__, __LINE__, os.str());
+ }
+ if(stat(fileImplC.c_str(), &st) == 0)
+ {
+ ostringstream os;
+ os << fileImplC << "' already exists - will not overwrite";
+ throw FileException(__FILE__, __LINE__, os.str());
+ }
+
+ implH.open(fileImplH.c_str());
+ if(!implH)
+ {
+ ostringstream os;
+ os << "cannot open `" << fileImplH << "': " << strerror(errno);
+ throw FileException(__FILE__, __LINE__, os.str());
+ }
+ FileTracker::instance()->addFile(fileImplH);
+
+ implC.open(fileImplC.c_str());
+ if(!implC)
+ {
+ ostringstream os;
+ os << "cannot open `" << fileImplC << "': " << strerror(errno);
+ throw FileException(__FILE__, __LINE__, os.str());
+ }
+ FileTracker::instance()->addFile(fileImplC);
+
+ string s = fileImplH;
+ if(_include.size())
+ {
+ s = _include + '/' + s;
+ }
+ transform(s.begin(), s.end(), s.begin(), ToIfdef());
+ implH << "#ifndef __" << s << "__";
+ implH << "\n#define __" << s << "__";
+ implH << '\n';
+ }
+
+ string fileH = _base + "." + _headerExtension;
+ string fileC = _base + "." + _sourceExtension;
+ if(!_dir.empty())
+ {
+ fileH = _dir + '/' + fileH;
+ fileC = _dir + '/' + fileC;
+ }
+
+ H.open(fileH.c_str());
+ if(!H)
+ {
+ ostringstream os;
+ os << "cannot open `" << fileH << "': " << strerror(errno);
+ throw FileException(__FILE__, __LINE__, os.str());
+ }
+ FileTracker::instance()->addFile(fileH);
+
+ C.open(fileC.c_str());
+ if(!C)
+ {
+ ostringstream os;
+ os << "cannot open `" << fileC << "': " << strerror(errno);
+ throw FileException(__FILE__, __LINE__, os.str());
+ }
+ FileTracker::instance()->addFile(fileC);
+
+ printHeader(H);
+ printGeneratedHeader(H, _base + ".ice");
+ printHeader(C);
+ printGeneratedHeader(C, _base + ".ice");
+
+
+ string s = fileH;
+ if(_include.size())
+ {
+ s = _include + '/' + s;
+ }
+ transform(s.begin(), s.end(), s.begin(), ToIfdef());
+ H << "\n#ifndef __" << s << "__";
+ H << "\n#define __" << s << "__";
+ H << '\n';
+
+ validateMetaData(p);
+
+ writeExtraHeaders(C);
+
+ if(_dllExport.size())
+ {
+ C << "\n#ifndef " << _dllExport << "_EXPORTS";
+ C << "\n# define " << _dllExport << "_EXPORTS";
+ C << "\n#endif";
+ }
+
+ C << "\n#include <";
+ if(_include.size())
+ {
+ C << _include << '/';
+ }
+ C << _base << "." << _headerExtension << ">";
+
+
+ H << "\n#include <Ice/LocalObjectF.h>";
+ H << "\n#include <Ice/ProxyF.h>";
+ H << "\n#include <Ice/ObjectF.h>";
+ H << "\n#include <Ice/Exception.h>";
+ H << "\n#include <Ice/LocalObject.h>";
+
+ if(p->usesProxies())
+ {
+ H << "\n#include <Ice/Proxy.h>";
+ }
+
+ if(p->hasNonLocalClassDefs())
+ {
+ H << "\n#include <Ice/Object.h>";
+ H << "\n#include <Ice/Outgoing.h>";
+ H << "\n#include <Ice/OutgoingAsync.h>";
+ H << "\n#include <Ice/Incoming.h>";
+ if(p->hasContentsWithMetaData("amd"))
+ {
+ H << "\n#include <Ice/IncomingAsync.h>";
+ }
+ H << "\n#include <Ice/Direct.h>";
+
+ C << "\n#include <Ice/LocalException.h>";
+ C << "\n#include <Ice/ObjectFactory.h>";
+ }
+ else if(p->hasNonLocalClassDecls())
+ {
+
+ H << "\n#include <Ice/Object.h>";
+ }
+
+ if(p->hasNonLocalDataOnlyClasses() || p->hasNonLocalExceptions())
+ {
+ H << "\n#include <Ice/FactoryTableInit.h>";
+ }
+ H << "\n#include <IceUtil/ScopedArray.h>";
+
+ if(p->usesNonLocals())
+ {
+ C << "\n#include <Ice/BasicStream.h>";
+
+ if(!p->hasNonLocalClassDefs() && !p->hasNonLocalClassDecls())
+ {
+ C << "\n#include <Ice/Object.h>";
+ }
+ }
+
+ if(_stream || p->hasNonLocalClassDefs() || p->hasNonLocalExceptions())
+ {
+ if(!p->hasNonLocalClassDefs())
+ {
+ C << "\n#include <Ice/LocalException.h>";
+ }
+
+ if(_stream)
+ {
+ H << "\n#include <Ice/Stream.h>";
+ }
+ else
+ {
+ H << "\n#include <Ice/StreamF.h>";
+ }
+ }
+
+ if(_checksum)
+ {
+ C << "\n#include <Ice/SliceChecksums.h>";
+ }
+
+ C << "\n#include <IceUtil/Iterator.h>";
+
+ StringList includes = p->includeFiles();
+
+ for(StringList::const_iterator q = includes.begin(); q != includes.end(); ++q)
+ {
+ string extension = getHeaderExt((*q), p);
+ if(extension.empty())
+ {
+ extension = _headerExtension;
+ }
+ H << "\n#include <" << changeInclude(*q, _includePaths) << "." << extension << ">";
+ }
+
+ H << "\n#include <Ice/UndefSysMacros.h>";
+
+ if(_ice)
+ {
+ C << "\n#include <IceUtil/DisableWarnings.h>";
+ }
+
+ //
+ // Emit #include statements for any cpp:include metadata directives
+ // in the top-level Slice file.
+ //
+ {
+ DefinitionContextPtr dc = p->findDefinitionContext(file);
+ assert(dc);
+ StringList globalMetaData = dc->getMetaData();
+ for(StringList::const_iterator q = globalMetaData.begin(); q != globalMetaData.end(); ++q)
+ {
+ string s = *q;
+ static const string includePrefix = "cpp:include:";
+ if(s.find(includePrefix) == 0 && s.size() > includePrefix.size())
+ {
+ H << nl << "#include <" << s.substr(includePrefix.size()) << ">";
+ }
+ }
+ }
+
+ printVersionCheck(H);
+ printVersionCheck(C);
+
+ printDllExportStuff(H, _dllExport);
+ if(_dllExport.size())
+ {
+ _dllExport += " ";
+ }
+
+ ProxyDeclVisitor proxyDeclVisitor(H, C, _dllExport);
+ p->visit(&proxyDeclVisitor, false);
+
+ ObjectDeclVisitor objectDeclVisitor(H, C, _dllExport);
+ p->visit(&objectDeclVisitor, false);
+
+ IceInternalVisitor iceInternalVisitor(H, C, _dllExport);
+ p->visit(&iceInternalVisitor, false);
+
+ HandleVisitor handleVisitor(H, C, _dllExport, _stream);
+ p->visit(&handleVisitor, false);
+
+ TypesVisitor typesVisitor(H, C, _dllExport, _stream);
+ p->visit(&typesVisitor, false);
+
+ AsyncVisitor asyncVisitor(H, C, _dllExport);
+ p->visit(&asyncVisitor, false);
+
+ AsyncImplVisitor asyncImplVisitor(H, C, _dllExport);
+ p->visit(&asyncImplVisitor, false);
+
+ //
+ // The templates are emitted before the proxy definition
+ // so the derivation hierarchy is known to the proxy:
+ // the proxy relies on knowing the hierarchy to make the begin_
+ // methods type-safe.
+ //
+ AsyncCallbackVisitor asyncCallbackVisitor(H, C, _dllExport);
+ p->visit(&asyncCallbackVisitor, false);
+
+ ProxyVisitor proxyVisitor(H, C, _dllExport);
+ p->visit(&proxyVisitor, false);
+
+ DelegateVisitor delegateVisitor(H, C, _dllExport);
+ p->visit(&delegateVisitor, false);
+
+ DelegateMVisitor delegateMVisitor(H, C, _dllExport);
+ p->visit(&delegateMVisitor, false);
+
+ DelegateDVisitor delegateDVisitor(H, C, _dllExport);
+ p->visit(&delegateDVisitor, false);
+
+ ObjectVisitor objectVisitor(H, C, _dllExport, _stream);
+ p->visit(&objectVisitor, false);
+
+ if(_stream)
+ {
+ StreamVisitor streamVistor(H, C);
+ p->visit(&streamVistor, false);
+ }
+
+ //
+ // We need to delay generating the template after the proxy
+ // definition, because __completed calls the begin_ method in the
+ // proxy.
+ //
+ AsyncCallbackTemplateVisitor asyncCallbackTemplateVisitor(H, C, _dllExport);
+ p->visit(&asyncCallbackTemplateVisitor, false);
+
+ if(_impl)
+ {
+ implH << "\n#include <";
+ if(_include.size())
+ {
+ implH << _include << '/';
+ }
+ implH << _base << "." << _headerExtension << ">";
+
+ writeExtraHeaders(implC);
+
+ implC << "\n#include <";
+ if(_include.size())
+ {
+ implC << _include << '/';
+ }
+ implC << _base << "I." << _implHeaderExtension << ">";
+
+ ImplVisitor implVisitor(implH, implC, _dllExport);
+ p->visit(&implVisitor, false);
+ }
+
+ if(_checksum)
+ {
+ ChecksumMap map = createChecksums(p);
+ if(!map.empty())
+ {
+ C << sp << nl << "static const char* __sliceChecksums[] =";
+ C << sb;
+ for(ChecksumMap::const_iterator q = map.begin(); q != map.end(); ++q)
+ {
+ C << nl << "\"" << q->first << "\", \"";
+ ostringstream str;
+ str.flags(ios_base::hex);
+ str.fill('0');
+ for(vector<unsigned char>::const_iterator r = q->second.begin(); r != q->second.end(); ++r)
+ {
+ str << (int)(*r);
+ }
+ C << str.str() << "\",";
+ }
+ C << nl << "0";
+ C << eb << ';';
+ C << nl << "static IceInternal::SliceChecksumInit __sliceChecksumInit(__sliceChecksums);";
+ }
+ }
+}
+
+void
+Slice::Gen::closeOutput()
+{
+ H.close();
+ C.close();
+ implH.close();
+ implC.close();
+}
+
+void
+Slice::Gen::writeExtraHeaders(IceUtilInternal::Output& out)
+{
+ for(vector<string>::const_iterator i = _extraHeaders.begin(); i != _extraHeaders.end(); ++i)
+ {
+ string hdr = *i;
+ string guard;
+ string::size_type pos = hdr.rfind(',');
+ if(pos != string::npos)
+ {
+ hdr = i->substr(0, pos);
+ guard = i->substr(pos + 1);
+ }
+ if(!guard.empty())
+ {
+ out << "\n#ifndef " << guard;
+ out << "\n#define " << guard;
+ }
+ out << "\n#include <";
+ if(!_include.empty())
+ {
+ out << _include << '/';
+ }
+ out << hdr << '>';
+ if(!guard.empty())
+ {
+ out << "\n#endif";
+ }
+ }
+}
+
+Slice::Gen::TypesVisitor::TypesVisitor(Output& h, Output& c, const string& dllExport, bool stream) :
+ H(h), C(c), _dllExport(dllExport), _stream(stream), _doneStaticSymbol(false), _useWstring(false)
+{
+}
+
+bool
+Slice::Gen::TypesVisitor::visitModuleStart(const ModulePtr& p)
+{
+ if(!p->hasOtherConstructedOrExceptions())
+ {
+ return false;
+ }
+
+ _useWstring = setUseWstring(p, _useWstringHist, _useWstring);
+
+ H << sp << nl << "namespace " << fixKwd(p->name()) << nl << '{';
+
+ return true;
+}
+
+void
+Slice::Gen::TypesVisitor::visitModuleEnd(const ModulePtr& p)
+{
+ H << sp << nl << '}';
+
+ _useWstring = resetUseWstring(_useWstringHist);
+}
+
+bool
+Slice::Gen::TypesVisitor::visitClassDefStart(const ClassDefPtr& p)
+{
+ return false;
+}
+
+bool
+Slice::Gen::TypesVisitor::visitExceptionStart(const ExceptionPtr& p)
+{
+ _useWstring = setUseWstring(p, _useWstringHist, _useWstring);
+
+ string name = fixKwd(p->name());
+ string scoped = fixKwd(p->scoped());
+ ExceptionPtr base = p->base();
+ DataMemberList dataMembers = p->dataMembers();
+ DataMemberList allDataMembers = p->allDataMembers();
+ DataMemberList::const_iterator q;
+
+ vector<string> params;
+ vector<string> allTypes;
+ vector<string> allParamDecls;
+ vector<string> baseParams;
+ vector<string>::const_iterator pi;
+
+ for(q = dataMembers.begin(); q != dataMembers.end(); ++q)
+ {
+ params.push_back(fixKwd((*q)->name()));
+ }
+
+ for(q = allDataMembers.begin(); q != allDataMembers.end(); ++q)
+ {
+ string typeName = inputTypeToString((*q)->type(), (*q)->getMetaData(), _useWstring);
+ allTypes.push_back(typeName);
+ allParamDecls.push_back(typeName + " __ice_" + fixKwd((*q)->name()));
+ }
+
+ if(base)
+ {
+ DataMemberList baseDataMembers = base->allDataMembers();
+ for(q = baseDataMembers.begin(); q != baseDataMembers.end(); ++q)
+ {
+ baseParams.push_back("__ice_" + fixKwd((*q)->name()));
+ }
+ }
+
+ H << sp << nl << "class " << _dllExport << name << " : ";
+ H.useCurrentPosAsIndent();
+ H << "public ";
+ if(!base)
+ {
+ H << (p->isLocal() ? "::Ice::LocalException" : "::Ice::UserException");
+ }
+ else
+ {
+ H << fixKwd(base->scoped());
+ }
+ H.restoreIndent();
+ H << sb;
+
+ H.dec();
+ H << nl << "public:";
+ H.inc();
+
+ H << sp << nl << name << spar;
+ if(p->isLocal())
+ {
+ H << "const char*" << "int";
+ }
+ H << epar;
+ if(!p->isLocal() && !p->hasDefaultValues())
+ {
+ H << " {}";
+ }
+ else
+ {
+ H << ';';
+ }
+ if(!allTypes.empty())
+ {
+ H << nl;
+ if(!p->isLocal() && allTypes.size() == 1)
+ {
+ H << "explicit ";
+ }
+ H << name << spar;
+ if(p->isLocal())
+ {
+ H << "const char*" << "int";
+ }
+ H << allTypes << epar << ';';
+ }
+ H << nl << "virtual ~" << name << "() throw();";
+ H << sp;
+
+ if(p->isLocal())
+ {
+ C << sp << nl << scoped.substr(2) << "::" << name << spar << "const char* __file" << "int __line" << epar
+ << " :";
+ C.inc();
+ emitUpcall(base, "(__file, __line)", true);
+ if(p->hasDefaultValues())
+ {
+ C << nl << ", ";
+ writeDataMemberInitializers(C, dataMembers, _useWstring);
+ }
+ C.dec();
+ C << sb;
+ C << eb;
+ }
+ else if(p->hasDefaultValues())
+ {
+ C << sp << nl << scoped.substr(2) << "::" << name << "() :";
+ C.inc();
+ writeDataMemberInitializers(C, dataMembers, _useWstring);
+ C.dec();
+ C << sb;
+ C << eb;
+ }
+
+ if(!allTypes.empty())
+ {
+ C << sp << nl;
+ C << scoped.substr(2) << "::" << name << spar;
+ if(p->isLocal())
+ {
+ C << "const char* __file" << "int __line";
+ }
+ C << allParamDecls << epar;
+ if(p->isLocal() || !baseParams.empty() || !params.empty())
+ {
+ C << " :";
+ C.inc();
+ string upcall;
+ if(!allParamDecls.empty())
+ {
+ upcall = "(";
+ if(p->isLocal())
+ {
+ upcall += "__file, __line";
+ }
+ for(pi = baseParams.begin(); pi != baseParams.end(); ++pi)
+ {
+ if(p->isLocal() || pi != baseParams.begin())
+ {
+ upcall += ", ";
+ }
+ upcall += *pi;
+ }
+ upcall += ")";
+ }
+ if(!params.empty())
+ {
+ upcall += ",";
+ }
+ emitUpcall(base, upcall, p->isLocal());
+ }
+ for(pi = params.begin(); pi != params.end(); ++pi)
+ {
+ if(pi != params.begin())
+ {
+ C << ",";
+ }
+ C << nl << *pi << "(__ice_" << *pi << ')';
+ }
+ if(p->isLocal() || !baseParams.empty() || !params.empty())
+ {
+ C.dec();
+ }
+ C << sb;
+ C << eb;
+ }
+
+ C << sp << nl;
+ C << scoped.substr(2) << "::~" << name << "() throw()";
+ C << sb;
+ C << eb;
+
+ H << nl << "virtual ::std::string ice_name() const;";
+
+ string flatName = p->flattenedScope() + p->name() + "_name";
+
+ C << sp << nl << "static const char* " << flatName << " = \"" << p->scoped().substr(2) << "\";";
+ C << sp << nl << "::std::string" << nl << scoped.substr(2) << "::ice_name() const";
+ C << sb;
+ C << nl << "return " << flatName << ';';
+ C << eb;
+
+ if(p->isLocal())
+ {
+ H << nl << "virtual void ice_print(::std::ostream&) const;";
+ }
+
+ H << nl << "virtual ::Ice::Exception* ice_clone() const;";
+ C << sp << nl << "::Ice::Exception*" << nl << scoped.substr(2) << "::ice_clone() const";
+ C << sb;
+ C << nl << "return new " << name << "(*this);";
+ C << eb;
+
+ H << nl << "virtual void ice_throw() const;";
+ C << sp << nl << "void" << nl << scoped.substr(2) << "::ice_throw() const";
+ C << sb;
+ C << nl << "throw *this;";
+ C << eb;
+
+ if(!p->isLocal())
+ {
+ H << sp << nl << "static const ::IceInternal::UserExceptionFactoryPtr& ice_factory();";
+ }
+ if(!dataMembers.empty())
+ {
+ H << sp;
+ }
+ return true;
+}
+
+void
+Slice::Gen::TypesVisitor::visitExceptionEnd(const ExceptionPtr& p)
+{
+ string name = fixKwd(p->name());
+ string scope = fixKwd(p->scope());
+ string scoped = fixKwd(p->scoped());
+ DataMemberList dataMembers = p->dataMembers();
+ DataMemberList::const_iterator q;
+
+ string factoryName;
+
+ if(!p->isLocal())
+ {
+ ExceptionPtr base = p->base();
+
+ H << sp << nl << "virtual void __write(::IceInternal::BasicStream*) const;";
+ H << nl << "virtual void __read(::IceInternal::BasicStream*, bool);";
+
+ H.zeroIndent();
+ H << nl << "// COMPILERFIX: Stream API is not supported with VC++ 6";
+ H << nl << "#if !defined(_MSC_VER) || (_MSC_VER >= 1300)";
+ H.restoreIndent();
+ H << nl << "virtual void __write(const ::Ice::OutputStreamPtr&) const;";
+ H << nl << "virtual void __read(const ::Ice::InputStreamPtr&, bool);";
+ H.zeroIndent();
+ H << nl << "#endif";
+ H.restoreIndent();
+
+ C << sp << nl << "void" << nl << scoped.substr(2) << "::__write(::IceInternal::BasicStream* __os) const";
+ C << sb;
+ C << nl << "__os->write(::std::string(\"" << p->scoped() << "\"), false);";
+ C << nl << "__os->startWriteSlice();";
+ for(q = dataMembers.begin(); q != dataMembers.end(); ++q)
+ {
+ writeMarshalUnmarshalCode(C, (*q)->type(), fixKwd((*q)->name()), true, "", true, (*q)->getMetaData());
+ }
+ C << nl << "__os->endWriteSlice();";
+ if(base)
+ {
+ emitUpcall(base, "::__write(__os);");
+ }
+ C << eb;
+
+ C << sp << nl << "void" << nl << scoped.substr(2) << "::__read(::IceInternal::BasicStream* __is, bool __rid)";
+ C << sb;
+ C << nl << "if(__rid)";
+ C << sb;
+ C << nl << "::std::string myId;";
+ C << nl << "__is->read(myId, false);";
+ C << eb;
+ C << nl << "__is->startReadSlice();";
+ for(q = dataMembers.begin(); q != dataMembers.end(); ++q)
+ {
+ writeMarshalUnmarshalCode(C, (*q)->type(), fixKwd((*q)->name()), false, "", true, (*q)->getMetaData());
+ }
+ C << nl << "__is->endReadSlice();";
+ if(base)
+ {
+ emitUpcall(base, "::__read(__is, true);");
+ }
+ C << eb;
+
+ if(_stream)
+ {
+ C << sp;
+ C.zeroIndent();
+ C << nl << "// COMPILERFIX: Stream API is not supported with VC++ 6";
+ C << nl << "#if !defined(_MSC_VER) || (_MSC_VER >= 1300)";
+ C.restoreIndent();
+ C << nl << "void" << nl << scoped.substr(2)
+ << "::__write(const ::Ice::OutputStreamPtr& __outS) const";
+ C << sb;
+ C << nl << "__outS->write(::std::string(\"" << p->scoped() << "\"));";
+ C << nl << "__outS->startSlice();";
+ for(q = dataMembers.begin(); q != dataMembers.end(); ++q)
+ {
+ writeStreamMarshalUnmarshalCode(C, (*q)->type(), (*q)->name(), true, "", (*q)->getMetaData(),
+ _useWstring);
+ }
+ C << nl << "__outS->endSlice();";
+ if(base)
+ {
+ emitUpcall(base, "::__write(__outS);");
+ }
+ C << eb;
+
+ C << sp << nl << "void" << nl << scoped.substr(2)
+ << "::__read(const ::Ice::InputStreamPtr& __inS, bool __rid)";
+ C << sb;
+ C << nl << "if(__rid)";
+ C << sb;
+ C << nl << "std::string s;";
+ C << nl << "__inS->read(s);";
+ C << eb;
+ C << nl << "__inS->startSlice();";
+ for(q = dataMembers.begin(); q != dataMembers.end(); ++q)
+ {
+ writeStreamMarshalUnmarshalCode(C, (*q)->type(), (*q)->name(), false, "", (*q)->getMetaData(),
+ _useWstring);
+ }
+ C << nl << "__inS->endSlice();";
+ if(base)
+ {
+ emitUpcall(base, "::__read(__inS, true);");
+ }
+ C << eb;
+ C.zeroIndent();
+ C << nl << "#endif";
+ C.restoreIndent();
+ }
+ else
+ {
+ //
+ // Emit placeholder functions to catch errors.
+ //
+ C << sp;
+ C.zeroIndent();
+ C << nl << "// COMPILERFIX: Stream API is not supported with VC++ 6";
+ C << nl << "#if !defined(_MSC_VER) || (_MSC_VER >= 1300)";
+ C.restoreIndent();
+ C << nl << "void" << nl << scoped.substr(2) << "::__write(const ::Ice::OutputStreamPtr&) const";
+ C << sb;
+ C << nl << "Ice::MarshalException ex(__FILE__, __LINE__);";
+ C << nl << "ex.reason = \"exception " << scoped.substr(2) << " was not generated with stream support\";";
+ C << nl << "throw ex;";
+ C << eb;
+
+ C << sp << nl << "void" << nl << scoped.substr(2) << "::__read(const ::Ice::InputStreamPtr&, bool)";
+ C << sb;
+ C << nl << "Ice::MarshalException ex(__FILE__, __LINE__);";
+ C << nl << "ex.reason = \"exception " << scoped .substr(2)<< " was not generated with stream support\";";
+ C << nl << "throw ex;";
+ C << eb;
+
+ C.zeroIndent();
+ C << nl << "#endif";
+ C.restoreIndent();
+ }
+
+ if(p->usesClasses())
+ {
+ if(!base || (base && !base->usesClasses()))
+ {
+ H << nl << "virtual bool __usesClasses() const;";
+
+ C << sp << nl << "bool";
+ C << nl << scoped.substr(2) << "::__usesClasses() const";
+ C << sb;
+ C << nl << "return true;";
+ C << eb;
+ }
+ }
+
+ factoryName = "__F" + p->flattenedScope() + p->name();
+
+ C << sp << nl << "struct " << factoryName << " : public ::IceInternal::UserExceptionFactory";
+ C << sb;
+ C << sp << nl << "virtual void";
+ C << nl << "createAndThrow()";
+ C << sb;
+ C << nl << "throw " << scoped << "();";
+ C << eb;
+ C << eb << ';';
+
+ C << sp << nl << "static ::IceInternal::UserExceptionFactoryPtr " << factoryName
+ << "__Ptr = new " << factoryName << ';';
+
+ C << sp << nl << "const ::IceInternal::UserExceptionFactoryPtr&";
+ C << nl << scoped.substr(2) << "::ice_factory()";
+ C << sb;
+ C << nl << "return " << factoryName << "__Ptr;";
+ C << eb;
+
+ C << sp << nl << "class " << factoryName << "__Init";
+ C << sb;
+ C.dec();
+ C << nl << "public:";
+ C.inc();
+ C << sp << nl << factoryName << "__Init()";
+ C << sb;
+ C << nl << "::IceInternal::factoryTable->addExceptionFactory(\"" << p->scoped() << "\", " << scoped
+ << "::ice_factory());";
+ C << eb;
+ C << sp << nl << "~" << factoryName << "__Init()";
+ C << sb;
+ C << nl << "::IceInternal::factoryTable->removeExceptionFactory(\"" << p->scoped() << "\");";
+ C << eb;
+ C << eb << ';';
+ C << sp << nl << "static " << factoryName << "__Init "<< factoryName << "__i;";
+ C << sp << nl << "#ifdef __APPLE__";
+
+ string initfuncname = "__F" + p->flattenedScope() + p->name() + "__initializer";
+ C << nl << "extern \"C\" { void " << initfuncname << "() {} }";
+ C << nl << "#endif";
+ }
+ H << eb << ';';
+
+ if(!p->isLocal())
+ {
+ //
+ // We need an instance here to trigger initialization if the implementation is in a shared libarry.
+ // But we do this only once per source file, because a single instance is sufficient to initialize
+ // all of the globals in a shared library.
+ //
+ if(!_doneStaticSymbol)
+ {
+ _doneStaticSymbol = true;
+ H << sp << nl << "static " << name << " __" << p->name() << "_init;";
+ }
+ }
+
+ _useWstring = resetUseWstring(_useWstringHist);
+}
+
+bool
+Slice::Gen::TypesVisitor::visitStructStart(const StructPtr& p)
+{
+ DataMemberList dataMembers = p->dataMembers();
+ _useWstring = setUseWstring(p, _useWstringHist, _useWstring);
+
+ string name = fixKwd(p->name());
+
+ bool classMetaData = findMetaData(p->getMetaData()) == "class";
+ if(classMetaData)
+ {
+ H << sp << nl << "class " << _dllExport << name << " : public IceUtil::Shared";
+ H << sb;
+ H.dec();
+ H << nl << "public:";
+ H.inc();
+ H << nl;
+ if(p->hasDefaultValues())
+ {
+ H << nl << name << "();";
+
+ C << sp << nl << fixKwd(p->scoped()).substr(2) << "::" << fixKwd(p->name()) << "() :";
+ C.inc();
+ writeDataMemberInitializers(C, dataMembers, _useWstring);
+ C.dec();
+ C << sb;
+ C << eb;
+ }
+ else
+ {
+ H << nl << name << "() {}";
+ }
+ }
+ else
+ {
+ H << sp << nl << "struct " << name;
+ H << sb;
+ if(p->hasDefaultValues())
+ {
+ H << nl << _dllExport << name << "();";
+
+ C << sp << nl << fixKwd(p->scoped()).substr(2) << "::" << fixKwd(p->name()) << "() :";
+ C.inc();
+ writeDataMemberInitializers(C, dataMembers, _useWstring);
+ C.dec();
+ C << sb;
+ C << eb;
+ }
+ }
+
+ //
+ // Generate a one-shot constructor if the struct uses the class mapping, or if at least
+ // one of its members has a default value.
+ //
+ if(!dataMembers.empty() && (findMetaData(p->getMetaData()) == "class" || p->hasDefaultValues()))
+ {
+ DataMemberList::const_iterator q;
+ vector<string> paramDecls;
+ vector<string> types;
+ for(q = dataMembers.begin(); q != dataMembers.end(); ++q)
+ {
+ string typeName = inputTypeToString((*q)->type(), (*q)->getMetaData(), _useWstring);
+ types.push_back(typeName);
+ paramDecls.push_back(typeName + " __ice_" + (*q)->name());
+ }
+
+ H << nl;
+ if(!classMetaData)
+ {
+ H << _dllExport;
+ }
+ if(paramDecls.size() == 1)
+ {
+ H << "explicit ";
+ }
+ H << name << spar << types << epar << ';';
+
+ C << sp << nl << fixKwd(p->scoped()).substr(2) << "::"
+ << fixKwd(p->name()) << spar << paramDecls << epar << " :";
+ C.inc();
+
+ for(q = dataMembers.begin(); q != dataMembers.end(); ++q)
+ {
+ if(q != dataMembers.begin())
+ {
+ C << ',';
+ }
+ string memberName = fixKwd((*q)->name());
+ C << nl << memberName << '(' << "__ice_" << (*q)->name() << ')';
+ }
+
+ C.dec();
+ C << sb;
+ C << eb;
+ }
+
+ H << sp;
+
+ return true;
+}
+
+void
+Slice::Gen::TypesVisitor::visitStructEnd(const StructPtr& p)
+{
+ string name = fixKwd(p->name());
+ string scoped = fixKwd(p->scoped());
+ string scope = fixKwd(p->scope());
+
+ DataMemberList dataMembers = p->dataMembers();
+ DataMemberList::const_iterator q;
+
+ vector<string> params;
+ vector<string>::const_iterator pi;
+
+ for(q = dataMembers.begin(); q != dataMembers.end(); ++q)
+ {
+ params.push_back(fixKwd((*q)->name()));
+ }
+
+ string dllExport;
+ if(findMetaData(p->getMetaData()) != "class")
+ {
+ dllExport = _dllExport;
+ }
+
+ H << sp << nl << "bool operator==(const " << name << "& __rhs) const";
+ H << sb;
+ H << nl << "if(this == &__rhs)";
+ H << sb;
+ H << nl << "return true;";
+ H << eb;
+ for(pi = params.begin(); pi != params.end(); ++pi)
+ {
+ H << nl << "if(" << *pi << " != __rhs." << *pi << ')';
+ H << sb;
+ H << nl << "return false;";
+ H << eb;
+ }
+ H << nl << "return true;";
+ H << eb;
+ H << sp << nl << "bool operator<(const " << name << "& __rhs) const";
+ H << sb;
+ H << nl << "if(this == &__rhs)";
+ H << sb;
+ H << nl << "return false;";
+ H << eb;
+ for(pi = params.begin(); pi != params.end(); ++pi)
+ {
+ H << nl << "if(" << *pi << " < __rhs." << *pi << ')';
+ H << sb;
+ H << nl << "return true;";
+ H << eb;
+ H << nl << "else if(__rhs." << *pi << " < " << *pi << ')';
+ H << sb;
+ H << nl << "return false;";
+ H << eb;
+ }
+ H << nl << "return false;";
+ H << eb;
+
+ H << sp << nl << "bool operator!=(const " << name << "& __rhs) const";
+ H << sb;
+ H << nl << "return !operator==(__rhs);";
+ H << eb;
+ H << nl << "bool operator<=(const " << name << "& __rhs) const";
+ H << sb;
+ H << nl << "return operator<(__rhs) || operator==(__rhs);";
+ H << eb;
+ H << nl << "bool operator>(const " << name << "& __rhs) const";
+ H << sb;
+ H << nl << "return !operator<(__rhs) && !operator==(__rhs);";
+ H << eb;
+ H << nl << "bool operator>=(const " << name << "& __rhs) const";
+ H << sb;
+ H << nl << "return !operator<(__rhs);";
+ H << eb;
+
+ if(!p->isLocal())
+ {
+ //
+ // None of these member functions is virtual!
+ //
+ H << sp << nl << dllExport << "void __write(::IceInternal::BasicStream*) const;";
+ H << nl << dllExport << "void __read(::IceInternal::BasicStream*);";
+
+ if(_stream)
+ {
+ H.zeroIndent();
+ H << nl << "// COMPILERFIX: Stream API is not supported with VC++ 6";
+ H << nl << "#if !defined(_MSC_VER) || (_MSC_VER >= 1300)";
+ H.restoreIndent();
+ H << nl << dllExport << "void ice_write(const ::Ice::OutputStreamPtr&) const;";
+ H << nl << dllExport << "void ice_read(const ::Ice::InputStreamPtr&);";
+ H.zeroIndent();
+ H << nl << "#endif";
+ H.restoreIndent();
+ }
+
+ C << sp << nl << "void" << nl << scoped.substr(2) << "::__write(::IceInternal::BasicStream* __os) const";
+ C << sb;
+ for(q = dataMembers.begin(); q != dataMembers.end(); ++q)
+ {
+ writeMarshalUnmarshalCode(C, (*q)->type(), fixKwd((*q)->name()), true, "", true, (*q)->getMetaData());
+ }
+ C << eb;
+
+ C << sp << nl << "void" << nl << scoped.substr(2) << "::__read(::IceInternal::BasicStream* __is)";
+ C << sb;
+ for(q = dataMembers.begin(); q != dataMembers.end(); ++q)
+ {
+ writeMarshalUnmarshalCode(C, (*q)->type(), fixKwd((*q)->name()), false, "", true, (*q)->getMetaData());
+ }
+ C << eb;
+
+ if(_stream)
+ {
+ C << sp;
+ C.zeroIndent();
+ C << nl << "// COMPILERFIX: Stream API is not supported with VC++ 6";
+ C << nl << "#if !defined(_MSC_VER) || (_MSC_VER >= 1300)";
+ C.restoreIndent();
+ C << nl << "void" << nl << scoped.substr(2)
+ << "::ice_write(const ::Ice::OutputStreamPtr& __outS) const";
+ C << sb;
+ for(q = dataMembers.begin(); q != dataMembers.end(); ++q)
+ {
+ writeStreamMarshalUnmarshalCode(C, (*q)->type(), (*q)->name(), true, "", (*q)->getMetaData(),
+ _useWstring);
+ }
+ C << eb;
+
+ C << sp << nl << "void" << nl << scoped.substr(2) << "::ice_read(const ::Ice::InputStreamPtr& __inS)";
+ C << sb;
+ for(q = dataMembers.begin(); q != dataMembers.end(); ++q)
+ {
+ writeStreamMarshalUnmarshalCode(C, (*q)->type(), (*q)->name(), false, "", (*q)->getMetaData(),
+ _useWstring);
+ }
+ C << eb;
+ C.zeroIndent();
+ C << nl << "#endif";
+ C.restoreIndent();
+ }
+ }
+
+ H << eb << ';';
+ if(findMetaData(p->getMetaData()) == "class")
+ {
+ H << sp << nl << "typedef ::IceUtil::Handle< " << scoped << "> " << p->name() + "Ptr;";
+
+ if(!p->isLocal() && _stream)
+ {
+ H << sp;
+ H.zeroIndent();
+ H << nl << "// COMPILERFIX: Stream API is not supported with VC++ 6";
+ H << nl << "#if !defined(_MSC_VER) || (_MSC_VER >= 1300)";
+ H.restoreIndent();
+ H << nl << "void ice_write" << p->name() << "(const ::Ice::OutputStreamPtr&, const "
+ << p->name() << "Ptr&);";
+ H << nl << "void ice_read" << p->name() << "(const ::Ice::InputStreamPtr&, " << p->name()
+ << "Ptr&);";
+ H.zeroIndent();
+ H << nl << "#endif";
+ H.restoreIndent();
+
+ C << sp;
+ C.zeroIndent();
+ C << nl << "// COMPILERFIX: Stream API is not supported with VC++ 6";
+ C << nl << "#if !defined(_MSC_VER) || (_MSC_VER >= 1300)";
+ C.restoreIndent();
+ C << nl << "void" << nl << scope.substr(2) << "ice_write" << p->name()
+ << "(const ::Ice::OutputStreamPtr& __outS, const " << fixKwd(p->scoped() + "Ptr") << "& __v)";
+ C << sb;
+ C << nl << "__v->ice_write(__outS);";
+ C << eb;
+
+ C << sp << nl << "void" << nl << scope.substr(2) << "ice_read" << p->name()
+ << "(const ::Ice::InputStreamPtr& __inS, " << fixKwd(p->scoped() + "Ptr") << "& __v)";
+ C << sb;
+ C << nl << "__v->ice_read(__inS);";
+ C << eb;
+ C.zeroIndent();
+ C << nl << "#endif";
+ C.restoreIndent();
+ }
+ }
+ else
+ {
+ if(!p->isLocal() && _stream)
+ {
+ H << sp;
+ H.zeroIndent();
+ H << nl << "// COMPILERFIX: Stream API is not supported with VC++ 6";
+ H << nl << "#if !defined(_MSC_VER) || (_MSC_VER >= 1300)";
+ H.restoreIndent();
+ H << nl << dllExport << "void ice_write" << p->name() << "(const ::Ice::OutputStreamPtr&, const "
+ << name << "&);";
+ H << nl << dllExport << "void ice_read" << p->name() << "(const ::Ice::InputStreamPtr&, " << name << "&);";
+ H.zeroIndent();
+ H << nl << "#endif";
+ H.restoreIndent();
+
+ C << sp;
+ C.zeroIndent();
+ C << nl << "// COMPILERFIX: Stream API is not supported with VC++ 6";
+ C << nl << "#if !defined(_MSC_VER) || (_MSC_VER >= 1300)";
+ C.restoreIndent();
+ C << nl << "void" << nl << scope.substr(2) << "ice_write" << p->name()
+ << "(const ::Ice::OutputStreamPtr& __outS, const " << scoped << "& __v)";
+ C << sb;
+ C << nl << "__v.ice_write(__outS);";
+ C << eb;
+
+ C << sp << nl << "void" << nl << scope.substr(2) << "ice_read" << p->name()
+ << "(const ::Ice::InputStreamPtr& __inS, " << scoped << "& __v)";
+ C << sb;
+ C << nl << "__v.ice_read(__inS);";
+ C << eb;
+ C.zeroIndent();
+ C << nl << "#endif";
+ C.restoreIndent();
+ }
+ }
+
+ _useWstring = resetUseWstring(_useWstringHist);
+}
+
+void
+Slice::Gen::TypesVisitor::visitDataMember(const DataMemberPtr& p)
+{
+ string name = fixKwd(p->name());
+ TypePtr type = p->type();
+ if(p->container() != 0 && (StructPtr::dynamicCast(p->container()) || ExceptionPtr::dynamicCast(p->container())) &&
+ SequencePtr::dynamicCast(type))
+ {
+ SequencePtr s = SequencePtr::dynamicCast(type);
+ BuiltinPtr builtin = BuiltinPtr::dynamicCast(s->type());
+ if(builtin && builtin->kind() == Builtin::KindByte)
+ {
+ StringList metaData = s->getMetaData();
+ bool protobuf;
+ findMetaData(s, metaData, protobuf);
+ if(protobuf)
+ {
+ emitWarning(p->file(), p->line(), string("protobuf cannot be used as a ") +
+ (StructPtr::dynamicCast(p->container()) ? "struct" : "exception") +
+ " member in C++");
+ }
+ }
+ }
+
+ string s = typeToString(p->type(), p->getMetaData(), _useWstring);
+ H << nl << s << ' ' << name << ';';
+}
+
+void
+Slice::Gen::TypesVisitor::visitSequence(const SequencePtr& p)
+{
+ string name = fixKwd(p->name());
+ TypePtr type = p->type();
+ string s = typeToString(type, p->typeMetaData(), _useWstring);
+ StringList metaData = p->getMetaData();
+
+ bool protobuf;
+ string seqType = findMetaData(p, metaData, protobuf);
+ H << sp;
+ if(!protobuf)
+ {
+ if(!seqType.empty())
+ {
+ H << nl << "typedef " << seqType << ' ' << name << ';';
+ }
+ else
+ {
+ H << nl << "typedef ::std::vector<" << (s[0] == ':' ? " " : "") << s << "> " << name << ';';
+ }
+ }
+
+ BuiltinPtr builtin = BuiltinPtr::dynamicCast(type);
+ if(!p->isLocal())
+ {
+ string scoped = fixKwd(p->scoped());
+ string scope = fixKwd(p->scope());
+
+ if(protobuf || !seqType.empty())
+ {
+ string typeName = name;
+ string scopedName = scoped;
+ if(protobuf && !seqType.empty())
+ {
+ typeName = seqType;
+ scopedName = seqType;
+ }
+ H << nl << _dllExport << "void __write" << name << "(::IceInternal::BasicStream*, const "
+ << typeName << "&);";
+ H << nl << _dllExport << "void __read" << name << "(::IceInternal::BasicStream*, "
+ << typeName << "&);";
+
+ if(_stream)
+ {
+ H.zeroIndent();
+ H << nl << "// COMPILERFIX: Stream API is not supported with VC++ 6";
+ H << nl << "#if !defined(_MSC_VER) || (_MSC_VER >= 1300)";
+ H.restoreIndent();
+ H << nl << _dllExport << "ICE_DEPRECATED_API void ice_write" << p->name() << "(const ::Ice::OutputStreamPtr&, const "
+ << typeName << "&);";
+ H << nl << _dllExport << "ICE_DEPRECATED_API void ice_read" << p->name() << "(const ::Ice::InputStreamPtr&, " << typeName
+ << "&);";
+ H.zeroIndent();
+ H << nl << "#endif";
+ H.restoreIndent();
+ }
+
+ C << sp << nl << "void" << nl << scope.substr(2) << "__write" << name <<
+ "(::IceInternal::BasicStream* __os, const " << scopedName << "& v)";
+ C << sb;
+ if(protobuf)
+ {
+ C << nl << "std::vector< ::Ice::Byte> data(v.ByteSize());";
+ C << nl << "if(!v.IsInitialized())";
+ C << sb;
+ C << nl << "throw ::Ice::MarshalException(__FILE__, __LINE__, \"type not fully initialized: \" + v.InitializationErrorString());";
+ C << eb;
+ C << nl << "if(!v.SerializeToArray(&data[0], data.size()))";
+ C << sb;
+ C << nl << "throw ::Ice::MarshalException(__FILE__, __LINE__, \"SerializeToArray failed\");";
+ C << eb;
+ C << nl << "__os->write(&data[0], &data[0] + data.size());";
+ }
+ else
+ {
+ C << nl << "::Ice::Int size = static_cast< ::Ice::Int>(v.size());";
+ C << nl << "__os->writeSize(size);";
+ C << nl << "for(" << name << "::const_iterator p = v.begin(); p != v.end(); ++p)";
+ C << sb;
+ writeMarshalUnmarshalCode(C, type, "(*p)", true);
+ C << eb;
+ }
+ C << eb;
+
+ C << sp << nl << "void" << nl << scope.substr(2) << "__read" << name
+ << "(::IceInternal::BasicStream* __is, " << scopedName << "& v)";
+ C << sb;
+ if(protobuf)
+ {
+ C << nl << "::std::pair<const ::Ice::Byte*, const ::Ice::Byte*> data;";
+ C << nl << "__is->read(data);";
+ C << nl << "if(!v.ParseFromArray(data.first, data.second - data.first))";
+ C << sb;
+ C << nl << "throw ::Ice::MarshalException(__FILE__, __LINE__, \"ParseFromArray failed\");";
+ C << eb;
+ }
+ else
+ {
+ C << nl << "::Ice::Int sz;";
+ C << nl << "__is->readAndCheckSeqSize(" << type->minWireSize() << ", sz);";
+ C << nl << name << "(sz).swap(v);";
+ C << nl << "for(" << name << "::iterator p = v.begin(); p != v.end(); ++p)";
+ C << sb;
+ writeMarshalUnmarshalCode(C, type, "(*p)", false);
+ C << eb;
+ }
+ C << eb;
+
+ if(_stream)
+ {
+ C << sp;
+ C.zeroIndent();
+ C << nl << "// COMPILERFIX: Stream API is not supported with VC++ 6";
+ C << nl << "#if !defined(_MSC_VER) || (_MSC_VER >= 1300)";
+ C.restoreIndent();
+ C << nl << "void" << nl << scope.substr(2) << "ice_write" << p->name()
+ << "(const ::Ice::OutputStreamPtr& __outS, const " << scopedName << "& v)";
+ C << sb;
+ if(protobuf)
+ {
+ C << nl << "std::vector< ::Ice::Byte> data(v.ByteSize());";
+ C << nl << "if(!v.IsInitialized())";
+ C << sb;
+ C << nl << "throw ::Ice::MarshalException(__FILE__, __LINE__, \"type not fully initialized: \" + v.InitializationErrorString());";
+ C << eb;
+ C << nl << "v.SerializeToArray(&data[0], data.size());";
+
+ C << nl << "__outS->write(data);";
+ }
+ else
+ {
+ C << nl << "__outS->writeSize(::Ice::Int(v.size()));";
+ C << nl << scopedName << "::const_iterator p;";
+ C << nl << "for(p = v.begin(); p != v.end(); ++p)";
+ C << sb;
+ writeStreamMarshalUnmarshalCode(C, type, "(*p)", true, "", StringList(), _useWstring);
+ C << eb;
+ }
+ C << eb;
+
+ C << sp << nl << "void" << nl << scope.substr(2) << "ice_read" << p->name()
+ << "(const ::Ice::InputStreamPtr& __inS, " << scopedName << "& v)";
+ C << sb;
+ if(protobuf)
+ {
+ C << nl << "std::pair<const ::Ice::Byte*, const ::Ice::Byte*> data;";
+ C << nl << "__inS->readByteSeq(data);";
+ C << nl << "if(!v.ParseFromArray(data.first, data.second - data.first))";
+ C << sb;
+ C << nl << "throw ::Ice::MarshalException(__FILE__, __LINE__, \"ParseFromArray failed\");";
+ C << eb;
+ }
+ else
+ {
+ C << nl << "::Ice::Int sz = __inS->readAndCheckSeqSize(" << type->minWireSize() << ");";
+ C << nl << scopedName << "(sz).swap(v);";
+ C << nl << scopedName << "::iterator p;";
+ C << nl << "for(p = v.begin(); p != v.end(); ++p)";
+ C << sb;
+ writeStreamMarshalUnmarshalCode(C, type, "(*p)", false, "", StringList(), _useWstring);
+ C << eb;
+ }
+ C << eb;
+ C.zeroIndent();
+ C << nl << "#endif";
+ C.restoreIndent();
+ }
+ }
+ else if(!builtin || builtin->kind() == Builtin::KindObject || builtin->kind() == Builtin::KindObjectProxy)
+ {
+ H << nl << _dllExport << "void __write" << name << "(::IceInternal::BasicStream*, const " << s
+ << "*, const " << s << "*);";
+ H << nl << _dllExport << "void __read" << name << "(::IceInternal::BasicStream*, " << name << "&);";
+
+ if(_stream)
+ {
+ H.zeroIndent();
+ H << nl << "// COMPILERFIX: Stream API is not supported with VC++ 6";
+ H << nl << "#if !defined(_MSC_VER) || (_MSC_VER >= 1300)";
+ H.restoreIndent();
+ H << nl << _dllExport << "ICE_DEPRECATED_API void ice_write" << p->name() << "(const ::Ice::OutputStreamPtr&, const "
+ << name << "&);";
+ H << nl << _dllExport << "ICE_DEPRECATED_API void ice_read" << p->name() << "(const ::Ice::InputStreamPtr&, " << name
+ << "&);";
+ H.zeroIndent();
+ H << nl << "#endif";
+ H.restoreIndent();
+ }
+
+ C << sp << nl << "void" << nl << scope.substr(2) << "__write" << name
+ << "(::IceInternal::BasicStream* __os, const " << s << "* begin, const " << s << "* end)";
+ C << sb;
+ C << nl << "::Ice::Int size = static_cast< ::Ice::Int>(end - begin);";
+ C << nl << "__os->writeSize(size);";
+ C << nl << "for(int i = 0; i < size; ++i)";
+ C << sb;
+ writeMarshalUnmarshalCode(C, type, "begin[i]", true);
+ C << eb;
+ C << eb;
+
+ C << sp << nl << "void" << nl << scope.substr(2) << "__read" << name
+ << "(::IceInternal::BasicStream* __is, " << scoped << "& v)";
+ C << sb;
+ C << nl << "::Ice::Int sz;";
+ C << nl << "__is->readAndCheckSeqSize(" << type->minWireSize() << ", sz);";
+ C << nl << "v.resize(sz);";
+ C << nl << "for(int i = 0; i < sz; ++i)";
+ C << sb;
+ writeMarshalUnmarshalCode(C, type, "v[i]", false);
+ C << eb;
+ C << eb;
+
+ if(_stream)
+ {
+ C << sp;
+ C.zeroIndent();
+ C << nl << "// COMPILERFIX: Stream API is not supported with VC++ 6";
+ C << nl << "#if !defined(_MSC_VER) || (_MSC_VER >= 1300)";
+ C.restoreIndent();
+ C << nl << "void" << nl << scope.substr(2) << "ice_write" << p->name()
+ << "(const ::Ice::OutputStreamPtr& __outS, const " << scoped << "& v)";
+ C << sb;
+ C << nl << "__outS->writeSize(::Ice::Int(v.size()));";
+ C << nl << scoped << "::const_iterator p;";
+ C << nl << "for(p = v.begin(); p != v.end(); ++p)";
+ C << sb;
+ writeStreamMarshalUnmarshalCode(C, type, "(*p)", true, "", StringList(), _useWstring);
+ C << eb;
+ C << eb;
+
+ C << sp << nl << "void" << nl << scope.substr(2) << "ice_read" << p->name()
+ << "(const ::Ice::InputStreamPtr& __inS, " << scoped << "& v)";
+ C << sb;
+ C << nl << "::Ice::Int sz = __inS->readAndCheckSeqSize(" << type->minWireSize() << ");";
+ C << nl << "v.resize(sz);";
+ C << nl << "for(int i = 0; i < sz; ++i)";
+ C << sb;
+ writeStreamMarshalUnmarshalCode(C, type, "v[i]", false, "", StringList(), _useWstring);
+ C << eb;
+ C << eb;
+ C.zeroIndent();
+ C << nl << "#endif";
+ C.restoreIndent();
+ }
+ }
+ }
+}
+
+void
+Slice::Gen::TypesVisitor::visitDictionary(const DictionaryPtr& p)
+{
+ string name = fixKwd(p->name());
+ TypePtr keyType = p->keyType();
+ if(SequencePtr::dynamicCast(keyType))
+ {
+ SequencePtr s = SequencePtr::dynamicCast(keyType);
+ BuiltinPtr builtin = BuiltinPtr::dynamicCast(s->type());
+ if(builtin && builtin->kind() == Builtin::KindByte)
+ {
+ StringList metaData = s->getMetaData();
+ bool protobuf;
+ findMetaData(s, metaData, protobuf);
+ if(protobuf)
+ {
+ emitWarning(p->file(), p->line(), "protobuf cannot be used as a dictionary key in C++");
+ }
+ }
+ }
+
+ TypePtr valueType = p->valueType();
+ string ks = typeToString(keyType, p->keyMetaData(), _useWstring);
+ if(ks[0] == ':')
+ {
+ ks.insert(0, " ");
+ }
+ string vs = typeToString(valueType, p->valueMetaData(), _useWstring);
+ H << sp << nl << "typedef ::std::map<" << ks << ", " << vs << "> " << name << ';';
+
+ if(!p->isLocal())
+ {
+ string scoped = fixKwd(p->scoped());
+ string scope = fixKwd(p->scope());
+
+ H << nl << _dllExport << "void __write" << name << "(::IceInternal::BasicStream*, const " << name << "&);";
+ H << nl << _dllExport << "void __read" << name << "(::IceInternal::BasicStream*, " << name << "&);";
+
+ if(_stream)
+ {
+ H.zeroIndent();
+ H << nl << "// COMPILERFIX: Stream API is not supported with VC++ 6";
+ H << nl << "#if !defined(_MSC_VER) || (_MSC_VER >= 1300)";
+ H.restoreIndent();
+ H << nl << _dllExport << "ICE_DEPRECATED_API void ice_write" << p->name() << "(const ::Ice::OutputStreamPtr&, const " << name
+ << "&);";
+ H << nl << _dllExport << "ICE_DEPRECATED_API void ice_read" << p->name() << "(const ::Ice::InputStreamPtr&, " << name << "&);";
+ H.zeroIndent();
+ H << nl << "#endif";
+ H.restoreIndent();
+ }
+
+ C << sp << nl << "void" << nl << scope.substr(2) << "__write" << name
+ << "(::IceInternal::BasicStream* __os, const " << scoped << "& v)";
+ C << sb;
+ C << nl << "__os->writeSize(::Ice::Int(v.size()));";
+ C << nl << scoped << "::const_iterator p;";
+ C << nl << "for(p = v.begin(); p != v.end(); ++p)";
+ C << sb;
+ writeMarshalUnmarshalCode(C, keyType, "p->first", true);
+ writeMarshalUnmarshalCode(C, valueType, "p->second", true);
+ C << eb;
+ C << eb;
+
+ C << sp << nl << "void" << nl << scope.substr(2) << "__read" << name
+ << "(::IceInternal::BasicStream* __is, " << scoped << "& v)";
+ C << sb;
+ C << nl << "::Ice::Int sz;";
+ C << nl << "__is->readSize(sz);";
+ C << nl << "while(sz--)";
+ C << sb;
+ C << nl << "::std::pair<const " << ks << ", " << vs << "> pair;";
+ const string pf = string("const_cast<") + ks + "&>(pair.first)";
+ writeMarshalUnmarshalCode(C, keyType, pf, false);
+ C << nl << scoped << "::iterator __i = v.insert(v.end(), pair);";
+ writeMarshalUnmarshalCode(C, valueType, "__i->second", false);
+ C << eb;
+ C << eb;
+
+ if(_stream)
+ {
+ C << sp;
+ C.zeroIndent();
+ C << nl << "// COMPILERFIX: Stream API is not supported with VC++ 6";
+ C << nl << "#if !defined(_MSC_VER) || (_MSC_VER >= 1300)";
+ C.restoreIndent();
+ C << nl << "void" << nl << scope.substr(2) << "ice_write" << p->name()
+ << "(const ::Ice::OutputStreamPtr& __outS, const " << scoped << "& v)";
+ C << sb;
+ C << nl << "__outS->writeSize(::Ice::Int(v.size()));";
+ C << nl << scoped << "::const_iterator p;";
+ C << nl << "for(p = v.begin(); p != v.end(); ++p)";
+ C << sb;
+ writeStreamMarshalUnmarshalCode(C, keyType, "p->first", true, "", p->keyMetaData(), _useWstring);
+ writeStreamMarshalUnmarshalCode(C, valueType, "p->second", true, "", p->valueMetaData(), _useWstring);
+ C << eb;
+ C << eb;
+
+ C << sp << nl << "void" << nl << scope.substr(2) << "ice_read" << p->name()
+ << "(const ::Ice::InputStreamPtr& __inS, " << scoped << "& v)";
+ C << sb;
+ C << nl << "::Ice::Int sz = __inS->readSize();";
+ C << nl << "while(sz--)";
+ C << sb;
+ C << nl << "::std::pair<const " << ks << ", " << vs << "> pair;";
+ writeStreamMarshalUnmarshalCode(C, keyType, pf, false, "", p->keyMetaData(), _useWstring);
+ C << nl << scoped << "::iterator __i = v.insert(v.end(), pair);";
+ writeStreamMarshalUnmarshalCode(C, valueType, "__i->second", false, "", p->valueMetaData(), _useWstring);
+ C << eb;
+ C << eb;
+ C.zeroIndent();
+ C << nl << "#endif";
+ C.restoreIndent();
+ }
+ }
+}
+
+void
+Slice::Gen::TypesVisitor::visitEnum(const EnumPtr& p)
+{
+ string name = fixKwd(p->name());
+ EnumeratorList enumerators = p->getEnumerators();
+ H << sp << nl << "enum " << name;
+ H << sb;
+ EnumeratorList::const_iterator en = enumerators.begin();
+ while(en != enumerators.end())
+ {
+ H << nl << fixKwd((*en)->name());
+ if(++en != enumerators.end())
+ {
+ H << ',';
+ }
+ }
+ H << eb << ';';
+
+ if(!p->isLocal())
+ {
+ string scoped = fixKwd(p->scoped());
+ string scope = fixKwd(p->scope());
+
+ size_t sz = enumerators.size();
+ assert(sz <= 0x7fffffff); // 64-bit enums are not supported
+
+ H << sp << nl << _dllExport << "void __write(::IceInternal::BasicStream*, " << name << ");";
+ H << nl << _dllExport << "void __read(::IceInternal::BasicStream*, " << name << "&);";
+
+ if(_stream)
+ {
+ H.zeroIndent();
+ H << nl << "// COMPILERFIX: Stream API is not supported with VC++ 6";
+ H << nl << "#if !defined(_MSC_VER) || (_MSC_VER >= 1300)";
+ H << nl << _dllExport << "ICE_DEPRECATED_API void ice_write" << p->name()
+ << "(const ::Ice::OutputStreamPtr&, " << name << ");";
+ H << nl << _dllExport << "ICE_DEPRECATED_API void ice_read" << p->name() << "(const ::Ice::InputStreamPtr&, " << name << "&);";
+ H.zeroIndent();
+ H << nl << "#endif";
+ H.restoreIndent();
+ }
+
+ C << sp << nl << "void" << nl << scope.substr(2) << "__write(::IceInternal::BasicStream* __os, " << scoped
+ << " v)";
+ C << sb;
+ if(sz <= 0x7f)
+ {
+ C << nl << "__os->write(static_cast< ::Ice::Byte>(v), " << sz << ");";
+ }
+ else if(sz <= 0x7fff)
+ {
+ C << nl << "__os->write(static_cast< ::Ice::Short>(v), " << sz << ");";
+ }
+ else
+ {
+ C << nl << "__os->write(static_cast< ::Ice::Int>(v), " << sz << ");";
+ }
+ C << eb;
+
+ C << sp << nl << "void" << nl << scope.substr(2) << "__read(::IceInternal::BasicStream* __is, " << scoped
+ << "& v)";
+ C << sb;
+ if(sz <= 0x7f)
+ {
+ C << nl << "::Ice::Byte val;";
+ }
+ else if(sz <= 0x7fff)
+ {
+ C << nl << "::Ice::Short val;";
+ }
+ else
+ {
+ C << nl << "::Ice::Int val;";
+ }
+ C << nl << "__is->read(val, " << sz << ");";
+ C << nl << "v = static_cast< " << scoped << ">(val);";
+ C << eb;
+
+ if(_stream)
+ {
+ C << sp;
+ C.zeroIndent();
+ C << nl << "// COMPILERFIX: Stream API is not supported with VC++ 6";
+ C << nl << "#if !defined(_MSC_VER) || (_MSC_VER >= 1300)";
+ C << nl << "void" << nl << scope.substr(2) << "ice_write" << p->name()
+ << "(const ::Ice::OutputStreamPtr& __outS, " << scoped << " v)";
+ C << sb;
+ C << nl << "__outS->write(v);";
+ C << eb;
+
+ C << sp << nl << "void" << nl << scope.substr(2) << "ice_read" << p->name()
+ << "(const ::Ice::InputStreamPtr& __inS, " << scoped << "& v)";
+ C << sb;
+ C << nl << "__inS->read(v);";
+ C << eb;
+ C.zeroIndent();
+ C << nl << "#endif";
+ C.restoreIndent();
+ }
+ }
+}
+
+void
+Slice::Gen::TypesVisitor::visitConst(const ConstPtr& p)
+{
+ H << sp;
+ H << nl << "const " << typeToString(p->type(), p->typeMetaData(), _useWstring) << " " << fixKwd(p->name())
+ << " = ";
+ writeConstantValue(H, p->type(), p->valueType(), p->value(), _useWstring, p->typeMetaData());
+ H << ';';
+}
+
+void
+Slice::Gen::TypesVisitor::emitUpcall(const ExceptionPtr& base, const string& call, bool isLocal)
+{
+ C.zeroIndent();
+ C << nl << "#if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug"; // COMPILERFIX
+ C.restoreIndent();
+ C << nl << (base ? fixKwd(base->name()) : string(isLocal ? "LocalException" : "UserException")) << call;
+ C.zeroIndent();
+ C << nl << "#else";
+ C.restoreIndent();
+ C << nl << (base ? fixKwd(base->scoped()) : string(isLocal ? "::Ice::LocalException" : "::Ice::UserException"))
+ << call;
+ C.zeroIndent();
+ C << nl << "#endif";
+ C.restoreIndent();
+}
+
+Slice::Gen::ProxyDeclVisitor::ProxyDeclVisitor(Output& h, Output& c, const string& dllExport) :
+ H(h), C(c), _dllExport(dllExport)
+{
+}
+
+bool
+Slice::Gen::ProxyDeclVisitor::visitUnitStart(const UnitPtr& p)
+{
+ if(!p->hasNonLocalClassDecls())
+ {
+ return false;
+ }
+
+ H << sp << nl << "namespace IceProxy" << nl << '{';
+
+ return true;
+}
+
+void
+Slice::Gen::ProxyDeclVisitor::visitUnitEnd(const UnitPtr& p)
+{
+ H << sp << nl << '}';
+}
+
+bool
+Slice::Gen::ProxyDeclVisitor::visitModuleStart(const ModulePtr& p)
+{
+ if(!p->hasNonLocalClassDecls())
+ {
+ return false;
+ }
+
+ string name = fixKwd(p->name());
+
+ H << sp << nl << "namespace " << name << nl << '{';
+
+ return true;
+}
+
+void
+Slice::Gen::ProxyDeclVisitor::visitModuleEnd(const ModulePtr& p)
+{
+ H << sp << nl << '}';
+}
+
+void
+Slice::Gen::ProxyDeclVisitor::visitClassDecl(const ClassDeclPtr& p)
+{
+ if(p->isLocal())
+ {
+ return;
+ }
+
+ string name = fixKwd(p->name());
+
+ H << sp << nl << "class " << name << ';';
+}
+
+Slice::Gen::ProxyVisitor::ProxyVisitor(Output& h, Output& c, const string& dllExport) :
+ H(h), C(c), _dllExport(dllExport), _useWstring(false)
+{
+}
+
+bool
+Slice::Gen::ProxyVisitor::visitUnitStart(const UnitPtr& p)
+{
+ if(!p->hasNonLocalClassDefs())
+ {
+ return false;
+ }
+
+ H << sp << nl << "namespace IceProxy" << nl << '{';
+
+ return true;
+}
+
+void
+Slice::Gen::ProxyVisitor::visitUnitEnd(const UnitPtr& p)
+{
+ H << sp << nl << '}';
+}
+
+bool
+Slice::Gen::ProxyVisitor::visitModuleStart(const ModulePtr& p)
+{
+ if(!p->hasNonLocalClassDefs())
+ {
+ return false;
+ }
+
+ _useWstring = setUseWstring(p, _useWstringHist, _useWstring);
+
+ string name = fixKwd(p->name());
+
+ H << sp << nl << "namespace " << name << nl << '{';
+
+ return true;
+}
+
+void
+Slice::Gen::ProxyVisitor::visitModuleEnd(const ModulePtr& p)
+{
+ H << sp << nl << '}';
+
+ _useWstring = resetUseWstring(_useWstringHist);
+}
+
+bool
+Slice::Gen::ProxyVisitor::visitClassDefStart(const ClassDefPtr& p)
+{
+ if(p->isLocal())
+ {
+ return false;
+ }
+
+ _useWstring = setUseWstring(p, _useWstringHist, _useWstring);
+
+ string name = fixKwd(p->name());
+ string scoped = fixKwd(p->scoped());
+ ClassList bases = p->bases();
+
+ H << sp << nl << "class " << name << " : ";
+ if(bases.empty())
+ {
+ H << "virtual public ::IceProxy::Ice::Object";
+ }
+ else
+ {
+ H.useCurrentPosAsIndent();
+ ClassList::const_iterator q = bases.begin();
+ while(q != bases.end())
+ {
+ H << "virtual public ::IceProxy" << fixKwd((*q)->scoped());
+ if(++q != bases.end())
+ {
+ H << ',' << nl;
+ }
+ }
+ H.restoreIndent();
+ }
+
+ H << sb;
+ H.dec();
+ H << nl << "public:";
+ H.inc();
+
+ if(_dllExport != "")
+ {
+ //
+ // To export the virtual table
+ //
+ C << nl << "#ifdef __SUNPRO_CC";
+ C << nl << "class "
+ << (_dllExport.empty() ? "" : "ICE_DECLSPEC_EXPORT ")
+ << "IceProxy" << scoped << ";";
+ C << nl << "#endif";
+ }
+
+ return true;
+}
+
+void
+Slice::Gen::ProxyVisitor::visitClassDefEnd(const ClassDefPtr& p)
+{
+ string name = fixKwd(p->name());
+ string scoped = fixKwd(p->scoped());
+ string scope = fixKwd(p->scope());
+
+ //
+ // "Overwrite" various non-virtual functions in ::IceProxy::Ice::Object that return an ObjectPrx and
+ // are more usable when they return a <name>Prx
+ //
+
+ //
+ // No identity!
+ //
+
+ H << nl << nl << "::IceInternal::ProxyHandle<" << name << "> ice_context(const ::Ice::Context& __context) const";
+ H << sb;
+ H.dec();
+ H << nl << "#if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug"; // COMPILERFIX
+ H.inc();
+ H << nl << "typedef ::IceProxy::Ice::Object _Base;";
+ H << nl << "return dynamic_cast<" << name << "*>(_Base::ice_context(__context).get());";
+ H.dec();
+ H << nl << "#else";
+ H.inc();
+ H << nl << "return dynamic_cast<" << name << "*>(::IceProxy::Ice::Object::ice_context(__context).get());";
+ H.dec();
+ H << nl << "#endif";
+ H.inc();
+ H << eb;
+
+ //
+ // No facet!
+ //
+
+ H << nl << nl << "::IceInternal::ProxyHandle<" << name << "> ice_adapterId(const std::string& __id) const";
+ H << sb;
+ H.dec();
+ H << nl << "#if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug"; // COMPILERFIX
+ H.inc();
+ H << nl << "typedef ::IceProxy::Ice::Object _Base;";
+ H << nl << "return dynamic_cast<" << name << "*>(_Base::ice_adapterId(__id).get());";
+ H.dec();
+ H << nl << "#else";
+ H.inc();
+ H << nl << "return dynamic_cast<" << name << "*>(::IceProxy::Ice::Object::ice_adapterId(__id).get());";
+ H.dec();
+ H << nl << "#endif";
+ H.inc();
+ H << eb;
+
+ H << nl << nl << "::IceInternal::ProxyHandle<" << name << "> ice_endpoints(const ::Ice::EndpointSeq& __endpoints) const";
+ H << sb;
+ H.dec();
+ H << nl << "#if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug"; // COMPILERFIX
+ H.inc();
+ H << nl << "typedef ::IceProxy::Ice::Object _Base;";
+ H << nl << "return dynamic_cast<" << name << "*>(_Base::ice_endpoints(__endpoints).get());";
+ H.dec();
+ H << nl << "#else";
+ H.inc();
+ H << nl << "return dynamic_cast<" << name << "*>(::IceProxy::Ice::Object::ice_endpoints(__endpoints).get());";
+ H.dec();
+ H << nl << "#endif";
+ H.inc();
+ H << eb;
+
+ H << nl << nl << "::IceInternal::ProxyHandle<" << name << "> ice_locatorCacheTimeout(int __timeout) const";
+ H << sb;
+ H.dec();
+ H << nl << "#if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug"; // COMPILERFIX
+ H.inc();
+ H << nl << "typedef ::IceProxy::Ice::Object _Base;";
+ H << nl << "return dynamic_cast<" << name << "*>(_Base::ice_locatorCacheTimeout(__timeout).get());";
+ H.dec();
+ H << nl << "#else";
+ H.inc();
+ H << nl << "return dynamic_cast<" << name << "*>(::IceProxy::Ice::Object::ice_locatorCacheTimeout(__timeout).get());";
+ H.dec();
+ H << nl << "#endif";
+ H.inc();
+ H << eb;
+
+ H << nl << nl << "::IceInternal::ProxyHandle<" << name << "> ice_connectionCached(bool __cached) const";
+ H << sb;
+ H.dec();
+ H << nl << "#if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug"; // COMPILERFIX
+ H.inc();
+ H << nl << "typedef ::IceProxy::Ice::Object _Base;";
+ H << nl << "return dynamic_cast<" << name << "*>(_Base::ice_connectionCached(__cached).get());";
+ H.dec();
+ H << nl << "#else";
+ H.inc();
+ H << nl << "return dynamic_cast<" << name << "*>(::IceProxy::Ice::Object::ice_connectionCached(__cached).get());";
+ H.dec(); H << nl << "#endif"; H.inc();
+ H << eb;
+
+ H << nl << nl << "::IceInternal::ProxyHandle<" << name << "> ice_endpointSelection(::Ice::EndpointSelectionType __est) const";
+ H << sb;
+ H.dec();
+ H << nl << "#if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug"; // COMPILERFIX
+ H.inc();
+ H << nl << "typedef ::IceProxy::Ice::Object _Base;";
+ H << nl << "return dynamic_cast<" << name << "*>(_Base::ice_endpointSelection(__est).get());";
+ H.dec();
+ H << nl << "#else";
+ H.inc();
+ H << nl << "return dynamic_cast<" << name << "*>(::IceProxy::Ice::Object::ice_endpointSelection(__est).get());";
+ H.dec();
+ H << nl << "#endif";
+ H.inc();
+ H << eb;
+
+ H << nl << nl << "::IceInternal::ProxyHandle<" << name << "> ice_secure(bool __secure) const";
+ H << sb;
+ H.dec();
+ H << nl << "#if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug"; // COMPILERFIX
+ H.inc();
+ H << nl << "typedef ::IceProxy::Ice::Object _Base;";
+ H << nl << "return dynamic_cast<" << name << "*>(_Base::ice_secure(__secure).get());";
+ H.dec();
+ H << nl << "#else";
+ H.inc();
+ H << nl << "return dynamic_cast<" << name << "*>(::IceProxy::Ice::Object::ice_secure(__secure).get());";
+ H.dec();
+ H << nl << "#endif";
+ H.inc();
+ H << eb;
+
+ H << nl << nl << "::IceInternal::ProxyHandle<" << name << "> ice_preferSecure(bool __preferSecure) const";
+ H << sb;
+ H.dec();
+ H << nl << "#if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug"; // COMPILERFIX
+ H.inc();
+ H << nl << "typedef ::IceProxy::Ice::Object _Base;";
+ H << nl << "return dynamic_cast<" << name << "*>(_Base::ice_preferSecure(__preferSecure).get());";
+ H.dec();
+ H << nl << "#else";
+ H.inc();
+ H << nl << "return dynamic_cast<" << name << "*>(::IceProxy::Ice::Object::ice_preferSecure(__preferSecure).get());";
+ H.dec();
+ H << nl << "#endif";
+ H.inc();
+ H << eb;
+
+ H << nl << nl << "::IceInternal::ProxyHandle<" << name << "> ice_router(const ::Ice::RouterPrx& __router) const";
+ H << sb;
+ H.dec();
+ H << nl << "#if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug"; // COMPILERFIX
+ H.inc();
+ H << nl << "typedef ::IceProxy::Ice::Object _Base;";
+ H << nl << "return dynamic_cast<" << name << "*>(_Base::ice_router(__router).get());";
+ H.dec();
+ H << nl << "#else";
+ H.inc();
+ H << nl << "return dynamic_cast<" << name << "*>(::IceProxy::Ice::Object::ice_router(__router).get());";
+ H.dec();
+ H << nl << "#endif";
+ H.inc();
+ H << eb;
+
+ H << nl << nl << "::IceInternal::ProxyHandle<" << name << "> ice_locator(const ::Ice::LocatorPrx& __locator) const";
+ H << sb;
+ H.dec(); H << nl << "#if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug"; // COMPILERFIX
+ H.inc();
+ H << nl << "typedef ::IceProxy::Ice::Object _Base;";
+ H << nl << "return dynamic_cast<" << name << "*>(_Base::ice_locator(__locator).get());";
+ H.dec();
+ H << nl << "#else";
+ H.inc();
+ H << nl << "return dynamic_cast<" << name << "*>(::IceProxy::Ice::Object::ice_locator(__locator).get());";
+ H.dec();
+ H << nl << "#endif";
+ H.inc();
+ H << eb;
+
+ H << nl << nl << "::IceInternal::ProxyHandle<" << name << "> ice_collocationOptimized(bool __co) const";
+ H << sb;
+ H.dec(); H << nl << "#if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug"; // COMPILERFIX
+ H.inc();
+ H << nl << "typedef ::IceProxy::Ice::Object _Base;";
+ H << nl << "return dynamic_cast<" << name << "*>(_Base::ice_collocationOptimized(__co).get());";
+ H.dec(); H << nl << "#else"; H.inc();
+ H << nl << "return dynamic_cast<" << name << "*>(::IceProxy::Ice::Object::ice_collocationOptimized(__co).get());";
+ H.dec(); H << nl << "#endif"; H.inc();
+ H << eb;
+
+ H << nl << nl << "::IceInternal::ProxyHandle<" << name << "> ice_twoway() const";
+ H << sb;
+ H.dec();
+ H << nl << "#if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug"; // COMPILERFIX
+ H.inc();
+ H << nl << "typedef ::IceProxy::Ice::Object _Base;";
+ H << nl << "return dynamic_cast<" << name << "*>(_Base::ice_twoway().get());";
+ H.dec();
+ H << nl << "#else";
+ H.inc();
+ H << nl << "return dynamic_cast<" << name << "*>(::IceProxy::Ice::Object::ice_twoway().get());";
+ H.dec();
+ H << nl << "#endif";
+ H.inc();
+ H << eb;
+
+ H << nl << nl << "::IceInternal::ProxyHandle<" << name << "> ice_oneway() const";
+ H << sb;
+ H.dec();
+ H << nl << "#if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug"; // COMPILERFIX
+ H.inc();
+ H << nl << "typedef ::IceProxy::Ice::Object _Base;";
+ H << nl << "return dynamic_cast<" << name << "*>(_Base::ice_oneway().get());";
+ H.dec();
+ H << nl << "#else"; H.inc();
+ H << nl << "return dynamic_cast<" << name << "*>(::IceProxy::Ice::Object::ice_oneway().get());";
+ H.dec();
+ H << nl << "#endif";
+ H.inc();
+ H << eb;
+
+ H << nl << nl << "::IceInternal::ProxyHandle<" << name << "> ice_batchOneway() const";
+ H << sb;
+ H.dec();
+ H << nl << "#if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug"; // COMPILERFIX
+ H.inc();
+ H << nl << "typedef ::IceProxy::Ice::Object _Base;";
+ H << nl << "return dynamic_cast<" << name << "*>(_Base::ice_batchOneway().get());";
+ H.dec();
+ H << nl << "#else";
+ H.inc();
+ H << nl << "return dynamic_cast<" << name << "*>(::IceProxy::Ice::Object::ice_batchOneway().get());";
+ H.dec();
+ H << nl << "#endif";
+ H.inc();
+ H << eb;
+
+ H << nl << nl << "::IceInternal::ProxyHandle<" << name << "> ice_datagram() const";
+ H << sb;
+ H.dec();
+ H << nl << "#if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug"; // COMPILERFIX
+ H.inc();
+ H << nl << "typedef ::IceProxy::Ice::Object _Base;";
+ H << nl << "return dynamic_cast<" << name << "*>(_Base::ice_datagram().get());";
+ H.dec();
+ H << nl << "#else";
+ H.inc();
+ H << nl << "return dynamic_cast<" << name << "*>(::IceProxy::Ice::Object::ice_datagram().get());";
+ H.dec();
+ H << nl << "#endif";
+ H.inc();
+ H << eb;
+
+ H << nl << nl << "::IceInternal::ProxyHandle<" << name << "> ice_batchDatagram() const";
+ H << sb;
+ H.dec();
+ H << nl << "#if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug"; // COMPILERFIX
+ H.inc();
+ H << nl << "typedef ::IceProxy::Ice::Object _Base;";
+ H << nl << "return dynamic_cast<" << name << "*>(_Base::ice_batchDatagram().get());";
+ H.dec();
+ H << nl << "#else";
+ H.inc();
+ H << nl << "return dynamic_cast<" << name << "*>(::IceProxy::Ice::Object::ice_batchDatagram().get());";
+ H.dec();
+ H << nl << "#endif";
+ H.inc();
+ H << eb;
+
+ H << nl << nl << "::IceInternal::ProxyHandle<" << name << "> ice_compress(bool __compress) const";
+ H << sb;
+ H.dec();
+ H << nl << "#if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug"; // COMPILERFIX
+ H.inc();
+ H << nl << "typedef ::IceProxy::Ice::Object _Base;";
+ H << nl << "return dynamic_cast<" << name << "*>(_Base::ice_compress(__compress).get());";
+ H.dec();
+ H << nl << "#else";
+ H.inc();
+ H << nl << "return dynamic_cast<" << name << "*>(::IceProxy::Ice::Object::ice_compress(__compress).get());";
+ H.dec();
+ H << nl << "#endif";
+ H.inc();
+ H << eb;
+
+ H << nl << nl << "::IceInternal::ProxyHandle<" << name << "> ice_timeout(int __timeout) const";
+ H << sb;
+ H.dec();
+ H << nl << "#if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug"; // COMPILERFIX
+ H.inc();
+ H << nl << "typedef ::IceProxy::Ice::Object _Base;";
+ H << nl << "return dynamic_cast<" << name << "*>(_Base::ice_timeout(__timeout).get());";
+ H.dec();
+ H << nl << "#else";
+ H.inc();
+ H << nl << "return dynamic_cast<" << name << "*>(::IceProxy::Ice::Object::ice_timeout(__timeout).get());";
+ H.dec();
+ H << nl << "#endif";
+ H.inc();
+ H << eb;
+
+ H << nl << nl << "::IceInternal::ProxyHandle<" << name << "> ice_connectionId(const std::string& __id) const";
+ H << sb;
+ H.dec();
+ H << nl << "#if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug"; // COMPILERFIX
+ H.inc();
+ H << nl << "typedef ::IceProxy::Ice::Object _Base;";
+ H << nl << "return dynamic_cast<" << name << "*>(_Base::ice_connectionId(__id).get());";
+ H.dec();
+ H << nl << "#else";
+ H.inc();
+ H << nl << "return dynamic_cast<" << name << "*>(::IceProxy::Ice::Object::ice_connectionId(__id).get());";
+ H.dec();
+ H << nl << "#endif";
+ H.inc();
+ H << eb;
+
+ H << nl << nl << _dllExport << "static const ::std::string& ice_staticId();";
+
+ H.dec();
+ H << sp << nl << "private: ";
+ H.inc();
+ H << sp << nl << _dllExport << "virtual ::IceInternal::Handle< ::IceDelegateM::Ice::Object> __createDelegateM();";
+ H << nl << _dllExport << "virtual ::IceInternal::Handle< ::IceDelegateD::Ice::Object> __createDelegateD();";
+ H << nl << _dllExport << "virtual ::IceProxy::Ice::Object* __newInstance() const;";
+ H << eb << ';';
+
+ C << sp;
+ C << nl << "const ::std::string&" << nl << "IceProxy" << scoped << "::ice_staticId()";
+ C << sb;
+ C << nl << "return "<< scoped << "::ice_staticId();";
+ C << eb;
+
+ C << sp << nl << "::IceInternal::Handle< ::IceDelegateM::Ice::Object>";
+ C << nl << "IceProxy" << scoped << "::__createDelegateM()";
+ C << sb;
+ C << nl << "return ::IceInternal::Handle< ::IceDelegateM::Ice::Object>(new ::IceDelegateM" << scoped << ");";
+ C << eb;
+ C << sp << nl << "::IceInternal::Handle< ::IceDelegateD::Ice::Object>";
+ C << nl << "IceProxy" << scoped << "::__createDelegateD()";
+ C << sb;
+ C << nl << "return ::IceInternal::Handle< ::IceDelegateD::Ice::Object>(new ::IceDelegateD" << scoped << ");";
+ C << eb;
+ C << sp << nl << "::IceProxy::Ice::Object*";
+ C << nl << "IceProxy" << scoped << "::__newInstance() const";
+ C << sb;
+ C << nl << "return new " << name << ";";
+ C << eb;
+
+ _useWstring = resetUseWstring(_useWstringHist);
+}
+
+void
+Slice::Gen::ProxyVisitor::visitOperation(const OperationPtr& p)
+{
+ string name = p->name();
+ string scoped = fixKwd(p->scoped());
+ string scope = fixKwd(p->scope());
+
+ TypePtr ret = p->returnType();
+ string retS = returnTypeToString(ret, p->getMetaData(), _useWstring | TypeContextAMIEnd);
+ string retSEndAMI = returnTypeToString(ret, p->getMetaData(), _useWstring | TypeContextAMIPrivateEnd);
+
+ ContainerPtr container = p->container();
+ ClassDefPtr cl = ClassDefPtr::dynamicCast(container);
+ string clScope = fixKwd(cl->scope());
+ string delName = "Callback_" + cl->name() + "_" + name;
+ string delNameScoped = clScope + delName;
+
+ vector<string> params;
+ vector<string> paramsDecl;
+ vector<string> args;
+
+ vector<string> paramsAMI;
+ vector<string> paramsDeclAMI;
+ vector<string> argsAMI;
+ vector<string> outParamsAMI;
+ vector<string> outParamsDeclAMI;
+ vector<string> outParamsDeclEndAMI;
+
+ ParamDeclList paramList = p->parameters();
+ ParamDeclList inParams;
+ ParamDeclList outParams;
+ for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q)
+ {
+ string paramName = fixKwd((*q)->name());
+
+ StringList metaData = (*q)->getMetaData();
+ string typeString;
+ string typeStringEndAMI;
+ if((*q)->isOutParam())
+ {
+ typeString = outputTypeToString((*q)->type(), metaData, _useWstring | TypeContextAMIEnd);
+ typeStringEndAMI = outputTypeToString((*q)->type(), metaData, _useWstring | TypeContextAMIPrivateEnd);
+ }
+ else
+ {
+ typeString = inputTypeToString((*q)->type(), metaData, _useWstring);
+ }
+
+ params.push_back(typeString);
+ paramsDecl.push_back(typeString + ' ' + paramName);
+ args.push_back(paramName);
+
+ if(!(*q)->isOutParam())
+ {
+ paramsAMI.push_back(typeString);
+ paramsDeclAMI.push_back(typeString + ' ' + paramName);
+ argsAMI.push_back(paramName);
+ inParams.push_back(*q);
+ }
+ else
+ {
+ outParamsAMI.push_back(typeString);
+ outParamsDeclAMI.push_back(typeString + ' ' + paramName);
+ outParamsDeclEndAMI.push_back(typeStringEndAMI + ' ' + paramName);
+ outParams.push_back(*q);
+ }
+ }
+
+ //
+ // Check if we need to generate a private ___end_ method. This is the case if the
+ // when using certain mapping features such as cpp:array or cpp:range:array. While
+ // the regular end_ method can't return pair<const TYPE*, const TYPE*> because the
+ // pointers would be invalid once end_ returns, we still want to allow using this
+ // alternate mapping with AMI response callbacks (to allow zero-copy for instance).
+ // For this purpose, we generate a special ___end method which is used by the
+ // __completed implementation of the generated Callback_Inft_opName operation
+ // delegate.
+ //
+ bool generatePrivateEnd = retS != retSEndAMI || outParamsDeclAMI != outParamsDeclEndAMI;
+ if(ret && generatePrivateEnd)
+ {
+ string typeStringEndAMI = outputTypeToString(ret, p->getMetaData(), _useWstring | TypeContextAMIPrivateEnd);
+ outParamsDeclEndAMI.push_back(typeStringEndAMI + ' ' + "__ret");
+ }
+
+ string thisPointer = fixKwd(scope.substr(0, scope.size() - 2)) + "*";
+
+ string deprecateSymbol = getDeprecateSymbol(p, cl);
+ H << sp << nl << deprecateSymbol << retS << ' ' << fixKwd(name) << spar << paramsDecl << epar;
+ H << sb;
+ H << nl;
+ if(ret)
+ {
+ H << "return ";
+ }
+ H << fixKwd(name) << spar << args << "0" << epar << ';';
+ H << eb;
+ H << nl << deprecateSymbol << retS << ' ' << fixKwd(name) << spar << paramsDecl << "const ::Ice::Context& __ctx"
+ << epar;
+ H << sb;
+ H << nl;
+ if(ret)
+ {
+ H << "return ";
+ }
+ H << fixKwd(name) << spar << args << "&__ctx" << epar << ';';
+ H << eb;
+
+ H << sp << nl << "::Ice::AsyncResultPtr begin_" << name << spar << paramsDeclAMI << epar;
+ H << sb;
+ H << nl << "return begin_" << name << spar << argsAMI << "0" << "::IceInternal::__dummyCallback" << "0"
+ << epar << ';';
+ H << eb;
+
+ H << sp << nl << "::Ice::AsyncResultPtr begin_" << name << spar << paramsDeclAMI
+ << "const ::Ice::Context& __ctx" << epar;
+ H << sb;
+ H << nl << "return begin_" << name << spar << argsAMI << "&__ctx" << "::IceInternal::__dummyCallback" << "0"
+ << epar << ';';
+ H << eb;
+
+ H << sp << nl << "::Ice::AsyncResultPtr begin_" << name << spar << paramsDeclAMI
+ << "const ::Ice::CallbackPtr& __del"
+ << "const ::Ice::LocalObjectPtr& __cookie = 0" << epar;
+ H << sb;
+ H << nl << "return begin_" << name << spar << argsAMI << "0" << "__del" << "__cookie" << epar << ';';
+ H << eb;
+
+ H << sp << nl << "::Ice::AsyncResultPtr begin_" << name << spar << paramsDeclAMI
+ << "const ::Ice::Context& __ctx"
+ << "const ::Ice::CallbackPtr& __del"
+ << "const ::Ice::LocalObjectPtr& __cookie = 0" << epar;
+ H << sb;
+ H << nl << "return begin_" << name << spar << argsAMI << "&__ctx" << "__del" << "__cookie" << epar << ';';
+ H << eb;
+
+ H << sp << nl << "::Ice::AsyncResultPtr begin_" << name << spar << paramsDeclAMI
+ << "const " + delNameScoped + "Ptr& __del"
+ << "const ::Ice::LocalObjectPtr& __cookie = 0" << epar;
+ H << sb;
+ H << nl << "return begin_" << name << spar << argsAMI << "0" << "__del" << "__cookie" << epar << ';';
+ H << eb;
+
+ H << sp << nl << "::Ice::AsyncResultPtr begin_" << name << spar << paramsDeclAMI
+ << "const ::Ice::Context& __ctx"
+ << "const " + delNameScoped + "Ptr& __del"
+ << "const ::Ice::LocalObjectPtr& __cookie = 0" << epar;
+ H << sb;
+ H << nl << "return begin_" << name << spar << argsAMI << "&__ctx" << "__del" << "__cookie" << epar << ';';
+ H << eb;
+
+ H << sp << nl << _dllExport << retS << " end_" << name << spar << outParamsDeclAMI
+ << "const ::Ice::AsyncResultPtr&" << epar << ';';
+ if(generatePrivateEnd)
+ {
+ H << sp << nl << "void ___end_" << name << spar << outParamsDeclEndAMI;
+ H << "const ::Ice::AsyncResultPtr&" << epar << ';';
+ }
+
+ H << nl;
+ H.dec();
+ H << nl << "private:";
+ H.inc();
+ H << sp << nl << _dllExport << retS << ' ' << fixKwd(name) << spar << params << "const ::Ice::Context*" << epar
+ << ';';
+ H << nl << _dllExport << "::Ice::AsyncResultPtr begin_" << name << spar << paramsAMI << "const ::Ice::Context*"
+ << "const ::IceInternal::CallbackBasePtr&"
+ << "const ::Ice::LocalObjectPtr& __cookie = 0" << epar << ';';
+ H << nl;
+ H.dec();
+ H << nl << "public:";
+ H.inc();
+
+ C << sp << nl << retS << nl << "IceProxy" << scoped << spar << paramsDecl << "const ::Ice::Context* __ctx" << epar;
+ C << sb;
+ C << nl << "int __cnt = 0;";
+ C << nl << "while(true)";
+ C << sb;
+ C << nl << "::IceInternal::Handle< ::IceDelegate::Ice::Object> __delBase;";
+ C << nl << "try";
+ C << sb;
+
+ if(p->returnsData())
+ {
+ C << nl << "__checkTwowayOnly(" << p->flattenedScope() + p->name() + "_name);";
+ }
+ C << nl << "__delBase = __getDelegate(false);";
+ C << nl << "::IceDelegate" << thisPointer << " __del = dynamic_cast< ::IceDelegate"
+ << thisPointer << ">(__delBase.get());";
+ C << nl;
+ if(ret)
+ {
+ C << "return ";
+ }
+ C << "__del->" << fixKwd(name) << spar << args << "__ctx" << epar << ';';
+ if(!ret)
+ {
+ C << nl << "return;";
+ }
+ C << eb;
+ C << nl << "catch(const ::IceInternal::LocalExceptionWrapper& __ex)";
+ C << sb;
+ if(p->mode() == Operation::Idempotent || p->mode() == Operation::Nonmutating)
+ {
+ C << nl << "__handleExceptionWrapperRelaxed(__delBase, __ex, true, __cnt);";
+ }
+ else
+ {
+ C << nl << "__handleExceptionWrapper(__delBase, __ex);";
+ }
+ C << eb;
+ C << nl << "catch(const ::Ice::LocalException& __ex)";
+ C << sb;
+ C << nl << "__handleException(__delBase, __ex, true, __cnt);";
+ C << eb;
+ C << eb;
+ C << eb;
+
+ C << sp << nl << "::Ice::AsyncResultPtr" << nl << "IceProxy" << scope << "begin_" << name << spar << paramsDeclAMI
+ << "const ::Ice::Context* __ctx" << "const ::IceInternal::CallbackBasePtr& __del"
+ << "const ::Ice::LocalObjectPtr& __cookie" << epar;
+ C << sb;
+ string flatName = p->flattenedScope() + name + "_name";
+ if(p->returnsData())
+ {
+ C << nl << "__checkAsyncTwowayOnly(" << flatName << ");";
+ }
+ C << nl << "::IceInternal::OutgoingAsyncPtr __result = new ::IceInternal::OutgoingAsync(this, ";
+ C << flatName << ", __del, __cookie);";
+ C << nl << "try";
+ C << sb;
+ C << nl << "__result->__prepare(" << flatName << ", " << operationModeToString(p->sendMode()) << ", __ctx);";
+ C << nl << "::IceInternal::BasicStream* __os = __result->__getOs();";
+ writeMarshalCode(C, inParams, 0, StringList(), true);
+ if(p->sendsClasses())
+ {
+ C << nl << "__os->writePendingObjects();";
+ }
+ C << nl << "__os->endWriteEncaps();";
+ C << nl << "__result->__send(true);";
+ C << eb;
+ C << nl << "catch(const ::Ice::LocalException& __ex)";
+ C << sb;
+ C << nl << "__result->__exceptionAsync(__ex);";
+ C << eb;
+ C << nl << "return __result;";
+ C << eb;
+
+ C << sp << nl << retS << nl << "IceProxy" << scope << "end_" << name << spar << outParamsDeclAMI
+ << "const ::Ice::AsyncResultPtr& __result" << epar;
+ C << sb;
+ if(p->returnsData())
+ {
+ C << nl << "::Ice::AsyncResult::__check(__result, this, " << flatName << ");";
+
+ //
+ // COMPILERFIX: It's necessary to generate the allocate code here before
+ // this if(!__result->wait()). If generated after this if block, we get
+ // access violations errors with the test/Ice/slicing/objects test on VC9
+ // and Windows 64 bits when compiled with optimization (see bug 4400).
+ //
+ writeAllocateCode(C, ParamDeclList(), ret, p->getMetaData(), _useWstring | TypeContextAMIEnd);
+
+ C << nl << "if(!__result->__wait())";
+ C << sb;
+ C << nl << "try";
+ C << sb;
+ C << nl << "__result->__throwUserException();";
+ C << eb;
+ //
+ // Generate a catch block for each legal user exception.
+ // (See comment in DelegateMVisitor::visitOperation() for details.)
+ //
+ ExceptionList throws = p->throws();
+ throws.sort();
+ throws.unique();
+#if defined(__SUNPRO_CC)
+ throws.sort(derivedToBaseCompare);
+#else
+ throws.sort(Slice::DerivedToBaseCompare());
+#endif
+ for(ExceptionList::const_iterator i = throws.begin(); i != throws.end(); ++i)
+ {
+ string scoped = (*i)->scoped();
+ C << nl << "catch(const " << fixKwd((*i)->scoped()) << "&)";
+ C << sb;
+ C << nl << "throw;";
+ C << eb;
+ }
+ C << nl << "catch(const ::Ice::UserException& __ex)";
+ C << sb;
+ C << nl << "throw ::Ice::UnknownUserException(__FILE__, __LINE__, __ex.ice_name());";
+ C << eb;
+ C << eb;
+ C << nl << "::IceInternal::BasicStream* __is = __result->__getIs();";
+ if(ret || !outParams.empty())
+ {
+ C << nl << "__is->startReadEncaps();";
+ writeUnmarshalCode(C, outParams, ret, p->getMetaData(), _useWstring | TypeContextAMIEnd);
+ if(p->returnsClasses())
+ {
+ C << nl << "__is->readPendingObjects();";
+ }
+ C << nl << "__is->endReadEncaps();";
+ }
+ else
+ {
+ C << nl << "__is->skipEmptyEncaps();";
+ }
+ if(ret)
+ {
+ C << nl << "return __ret;";
+ }
+ }
+ else
+ {
+ C << nl << "__end(__result, " << flatName << ");";
+ }
+ C << eb;
+
+ if(generatePrivateEnd)
+ {
+ assert(p->returnsData());
+
+ C << sp << nl << "void IceProxy" << scope << "___end_" << name << spar << outParamsDeclEndAMI
+ << "const ::Ice::AsyncResultPtr& __result" << epar;
+ C << sb;
+ C << nl << "::Ice::AsyncResult::__check(__result, this, " << flatName << ");";
+ C << nl << "if(!__result->__wait())";
+ C << sb;
+ C << nl << "try";
+ C << sb;
+ C << nl << "__result->__throwUserException();";
+ C << eb;
+ //
+ // Generate a catch block for each legal user exception.
+ // (See comment in DelegateMVisitor::visitOperation() for details.)
+ //
+ ExceptionList throws = p->throws();
+ throws.sort();
+ throws.unique();
+#if defined(__SUNPRO_CC)
+ throws.sort(derivedToBaseCompare);
+#else
+ throws.sort(Slice::DerivedToBaseCompare());
+#endif
+ for(ExceptionList::const_iterator i = throws.begin(); i != throws.end(); ++i)
+ {
+ string scoped = (*i)->scoped();
+ C << nl << "catch(const " << fixKwd((*i)->scoped()) << "&)";
+ C << sb;
+ C << nl << "throw;";
+ C << eb;
+ }
+ C << nl << "catch(const ::Ice::UserException& __ex)";
+ C << sb;
+ C << nl << "throw ::Ice::UnknownUserException(__FILE__, __LINE__, __ex.ice_name());";
+ C << eb;
+ C << eb;
+ C << nl << "::IceInternal::BasicStream* __is = __result->__getIs();";
+ if(ret || !outParams.empty())
+ {
+ C << nl << "__is->startReadEncaps();";
+ writeUnmarshalCode(C, outParams, ret, p->getMetaData(), _useWstring | TypeContextAMIPrivateEnd);
+ if(p->returnsClasses())
+ {
+ C << nl << "__is->readPendingObjects();";
+ }
+ C << nl << "__is->endReadEncaps();";
+ }
+ else
+ {
+ C << nl << "__is->skipEmptyEncaps();";
+ }
+ C << eb;
+ }
+
+ if(cl->hasMetaData("ami") || p->hasMetaData("ami"))
+ {
+ string classNameAMI = "AMI_" + cl->name();
+ string classScope = fixKwd(cl->scope());
+ string classScopedAMI = classScope + classNameAMI;
+ string opScopedAMI = classScopedAMI + "_" + name;
+
+ H << nl << _dllExport << "bool " << name << "_async" << spar << ("const " + opScopedAMI + "Ptr&")
+ << paramsAMI << epar << ';';
+ H << nl << _dllExport << "bool " << name << "_async" << spar << ("const " + opScopedAMI + "Ptr&")
+ << paramsAMI << "const ::Ice::Context&" << epar << ';';
+
+ C << sp << nl << "bool" << nl << "IceProxy" << scope << name << "_async" << spar
+ << ("const " + opScopedAMI + "Ptr& __cb") << paramsDeclAMI << epar;
+ C << sb;
+ if(p->returnsData())
+ {
+ C << nl << delNameScoped << "Ptr __del;";
+ C << nl << "if(dynamic_cast< ::Ice::AMISentCallback*>(__cb.get()))";
+ C << sb;
+ C << nl << " __del = " << classScope << "new" << delName << "(__cb, &" << opScopedAMI << "::__response, &"
+ << opScopedAMI << "::__exception, &" << opScopedAMI << "::__sent);";
+ C << eb;
+ C << nl << "else";
+ C << sb;
+ C << nl << " __del = " << classScope << "new" << delName << "(__cb, &" << opScopedAMI << "::__response, &"
+ << opScopedAMI << "::__exception);";
+ C << eb;
+ }
+ else
+ {
+ C << nl << "::IceInternal::CallbackBasePtr __del;";
+ C << nl << "if(dynamic_cast< ::Ice::AMISentCallback*>(__cb.get()))";
+ C << sb;
+ C << nl << " __del = " << classScope << "new" << delName << "(__cb, &" << opScopedAMI << "::__response, &"
+ << opScopedAMI << "::__exception, &" << opScopedAMI << "::__sent);";
+ C << eb;
+ C << nl << "else";
+ C << sb;
+ C << nl << " __del = " << classScope << "new" << delName << "(__cb, &" << opScopedAMI << "::__response, &"
+ << opScopedAMI << "::__exception);";
+ C << eb;
+ }
+
+ if(p->returnsData())
+ {
+ C << nl << "::Ice::AsyncResultPtr __ar;";
+ C << nl << "try";
+ C << sb;
+ C << nl << "__checkTwowayOnly(" << flatName << ");";
+ C << nl << "__ar = begin_" << name << spar << argsAMI << "0, __del" << epar << ';';
+ C << eb;
+ C << nl << "catch(const ::Ice::TwowayOnlyException& ex)";
+ C << sb;
+ C << nl << "__ar = new ::IceInternal::OutgoingAsync(this, " << flatName << ", __del, 0);";
+ C << nl << "__ar->__exceptionAsync(ex);";
+ C << eb;
+ }
+ else
+ {
+ C << nl << "::Ice::AsyncResultPtr __ar = begin_" << name << spar << argsAMI << "0, __del" << epar << ';';
+ }
+ C << nl << "return __ar->sentSynchronously();";
+ C << eb;
+
+ C << sp << nl << "bool" << nl << "IceProxy" << scope << name << "_async" << spar
+ << ("const " + opScopedAMI + "Ptr& __cb") << paramsDeclAMI << "const ::Ice::Context& __ctx"
+ << epar;
+ C << sb;
+ if(p->returnsData())
+ {
+ C << nl << delNameScoped << "Ptr __del;";
+ C << nl << "if(dynamic_cast< ::Ice::AMISentCallback*>(__cb.get()))";
+ C << sb;
+ C << nl << " __del = " << classScope << "new" << delName << "(__cb, &" << opScopedAMI << "::__response, &"
+ << opScopedAMI << "::__exception, &" << opScopedAMI << "::__sent);";
+ C << eb;
+ C << nl << "else";
+ C << sb;
+ C << nl << " __del = " << classScope << "new" << delName << "(__cb, &" << opScopedAMI << "::__response, &"
+ << opScopedAMI << "::__exception);";
+ C << eb;
+ }
+ else
+ {
+ C << nl << "::IceInternal::CallbackBasePtr __del;";
+ C << nl << "if(dynamic_cast< ::Ice::AMISentCallback*>(__cb.get()))";
+ C << sb;
+ C << nl << " __del = " << classScope << "new" << delName << "(__cb, &" << opScopedAMI << "::__response, &"
+ << opScopedAMI << "::__exception, &" << opScopedAMI << "::__sent);";
+ C << eb;
+ C << nl << "else";
+ C << sb;
+ C << nl << " __del = " << classScope << "new" << delName << "(__cb, &" << opScopedAMI << "::__response, &"
+ << opScopedAMI << "::__exception);";
+ C << eb;
+ }
+
+ if(p->returnsData())
+ {
+ C << nl << "::Ice::AsyncResultPtr __ar;";
+ C << nl << "try";
+ C << sb;
+ C << nl << "__checkTwowayOnly(" << flatName << ");";
+ C << nl << "__ar = begin_" << name << spar << argsAMI << "&__ctx" << "__del" << epar << ';';
+ C << eb;
+ C << nl << "catch(const ::Ice::TwowayOnlyException& ex)";
+ C << sb;
+ C << nl << "__ar = new ::IceInternal::OutgoingAsync(this, " << flatName << ", __del, 0);";
+ C << nl << "__ar->__exceptionAsync(ex);";
+ C << eb;
+ }
+ else
+ {
+ C << nl << "::Ice::AsyncResultPtr __ar = begin_" << name << spar << argsAMI << "&__ctx" << "__del" << epar
+ << ';';
+ }
+ C << nl << "return __ar->sentSynchronously();";
+ C << eb;
+ }
+}
+
+Slice::Gen::DelegateVisitor::DelegateVisitor(Output& h, Output& c, const string& dllExport) :
+ H(h), C(c), _dllExport(dllExport), _useWstring(false)
+{
+}
+
+bool
+Slice::Gen::DelegateVisitor::visitUnitStart(const UnitPtr& p)
+{
+ if(!p->hasNonLocalClassDefs())
+ {
+ return false;
+ }
+
+ H << sp << nl << "namespace IceDelegate" << nl << '{';
+
+ return true;
+}
+
+void
+Slice::Gen::DelegateVisitor::visitUnitEnd(const UnitPtr& p)
+{
+ H << sp << nl << '}';
+}
+
+bool
+Slice::Gen::DelegateVisitor::visitModuleStart(const ModulePtr& p)
+{
+ if(!p->hasNonLocalClassDefs())
+ {
+ return false;
+ }
+
+ _useWstring = setUseWstring(p, _useWstringHist, _useWstring);
+
+ string name = fixKwd(p->name());
+
+ H << sp << nl << "namespace " << name << nl << '{';
+
+ return true;
+}
+
+void
+Slice::Gen::DelegateVisitor::visitModuleEnd(const ModulePtr& p)
+{
+ H << sp << nl << '}';
+
+ _useWstring = resetUseWstring(_useWstringHist);
+}
+
+bool
+Slice::Gen::DelegateVisitor::visitClassDefStart(const ClassDefPtr& p)
+{
+ if(p->isLocal())
+ {
+ return false;
+ }
+
+ _useWstring = setUseWstring(p, _useWstringHist, _useWstring);
+
+ string name = fixKwd(p->name());
+ ClassList bases = p->bases();
+
+ H << sp << nl << "class " << _dllExport << name << " : ";
+ if(bases.empty())
+ {
+ H << "virtual public ::IceDelegate::Ice::Object";
+ }
+ else
+ {
+ H.useCurrentPosAsIndent();
+ ClassList::const_iterator q = bases.begin();
+ while(q != bases.end())
+ {
+ H << "virtual public ::IceDelegate" << fixKwd((*q)->scoped());
+ if(++q != bases.end())
+ {
+ H << ',' << nl;
+ }
+ }
+ H.restoreIndent();
+ }
+ H << sb;
+ H.dec();
+ H << nl << "public:";
+ H.inc();
+
+ return true;
+}
+
+void
+Slice::Gen::DelegateVisitor::visitClassDefEnd(const ClassDefPtr& p)
+{
+ H << eb << ';';
+
+ _useWstring = resetUseWstring(_useWstringHist);
+}
+
+void
+Slice::Gen::DelegateVisitor::visitOperation(const OperationPtr& p)
+{
+ string name = fixKwd(p->name());
+
+ TypePtr ret = p->returnType();
+ string retS = returnTypeToString(ret, p->getMetaData(), _useWstring);
+
+ vector<string> params;
+
+ ParamDeclList paramList = p->parameters();
+ for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q)
+ {
+ StringList metaData = (*q)->getMetaData();
+#if defined(__SUNPRO_CC) && (__SUNPRO_CC==0x550)
+ //
+ // Work around for Sun CC 5.5 bug #4853566
+ //
+ string typeString;
+ if((*q)->isOutParam())
+ {
+ typeString = outputTypeToString((*q)->type(), metaData, _useWstring);
+ }
+ else
+ {
+ typeString = inputTypeToString((*q)->type(), metaData, _useWstring);
+ }
+#else
+ string typeString = (*q)->isOutParam() ? outputTypeToString((*q)->type(), metaData, _useWstring)
+ : inputTypeToString((*q)->type(), metaData, _useWstring);
+#endif
+
+ params.push_back(typeString);
+ }
+
+ params.push_back("const ::Ice::Context*");
+
+ H << sp << nl << "virtual " << retS << ' ' << name << spar << params << epar << " = 0;";
+}
+
+Slice::Gen::DelegateMVisitor::DelegateMVisitor(Output& h, Output& c, const string& dllExport) :
+ H(h), C(c), _dllExport(dllExport), _useWstring(false)
+{
+}
+
+bool
+Slice::Gen::DelegateMVisitor::visitUnitStart(const UnitPtr& p)
+{
+ if(!p->hasNonLocalClassDefs())
+ {
+ return false;
+ }
+
+ H << sp << nl << "namespace IceDelegateM" << nl << '{';
+
+ return true;
+}
+
+void
+Slice::Gen::DelegateMVisitor::visitUnitEnd(const UnitPtr& p)
+{
+ H << sp << nl << '}';
+}
+
+bool
+Slice::Gen::DelegateMVisitor::visitModuleStart(const ModulePtr& p)
+{
+ if(!p->hasNonLocalClassDefs())
+ {
+ return false;
+ }
+
+ _useWstring = setUseWstring(p, _useWstringHist, _useWstring);
+
+ string name = fixKwd(p->name());
+
+ H << sp << nl << "namespace " << name << nl << '{';
+
+ return true;
+}
+
+void
+Slice::Gen::DelegateMVisitor::visitModuleEnd(const ModulePtr& p)
+{
+ H << sp << nl << '}';
+
+ _useWstring = resetUseWstring(_useWstringHist);
+}
+
+bool
+Slice::Gen::DelegateMVisitor::visitClassDefStart(const ClassDefPtr& p)
+{
+ if(p->isLocal())
+ {
+ return false;
+ }
+
+ _useWstring = setUseWstring(p, _useWstringHist, _useWstring);
+
+ string name = fixKwd(p->name());
+ string scoped = fixKwd(p->scoped());
+ ClassList bases = p->bases();
+
+ H << sp << nl << "class " << _dllExport << name << " : ";
+ H.useCurrentPosAsIndent();
+ H << "virtual public ::IceDelegate" << scoped << ',';
+ if(bases.empty())
+ {
+ H << nl << "virtual public ::IceDelegateM::Ice::Object";
+ }
+ else
+ {
+ ClassList::const_iterator q = bases.begin();
+ while(q != bases.end())
+ {
+ H << nl << "virtual public ::IceDelegateM" << fixKwd((*q)->scoped());
+ if(++q != bases.end())
+ {
+ H << ',';
+ }
+ }
+ }
+ H.restoreIndent();
+ H << sb;
+ H.dec();
+ H << nl << "public:";
+ H.inc();
+
+ return true;
+}
+
+void
+Slice::Gen::DelegateMVisitor::visitClassDefEnd(const ClassDefPtr& p)
+{
+ H << eb << ';';
+
+ _useWstring = resetUseWstring(_useWstringHist);
+}
+
+void
+Slice::Gen::DelegateMVisitor::visitOperation(const OperationPtr& p)
+{
+ string name = fixKwd(p->name());
+ string scoped = fixKwd(p->scoped());
+
+ TypePtr ret = p->returnType();
+ string retS = returnTypeToString(ret, p->getMetaData(), _useWstring);
+
+ vector<string> params;
+ vector<string> paramsDecl;
+
+ ParamDeclList inParams;
+ ParamDeclList outParams;
+ ParamDeclList paramList = p->parameters();
+ for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q)
+ {
+ string paramName = fixKwd((*q)->name());
+ TypePtr type = (*q)->type();
+ bool isOutParam = (*q)->isOutParam();
+ StringList metaData = (*q)->getMetaData();
+ string typeString;
+ if(isOutParam)
+ {
+ outParams.push_back(*q);
+ typeString = outputTypeToString(type, metaData, _useWstring);
+ }
+ else
+ {
+ inParams.push_back(*q);
+ typeString = inputTypeToString(type, metaData, _useWstring);
+ }
+
+ params.push_back(typeString);
+ paramsDecl.push_back(typeString + ' ' + paramName);
+ }
+
+ params.push_back("const ::Ice::Context*");
+ paramsDecl.push_back("const ::Ice::Context* __context");
+
+ string flatName = p->flattenedScope() + p->name() + "_name";
+
+ H << sp << nl << "virtual " << retS << ' ' << name << spar << params << epar << ';';
+ C << sp << nl << retS << nl << "IceDelegateM" << scoped << spar << paramsDecl << epar;
+ C << sb;
+ C << nl << "::IceInternal::Outgoing __og(__handler.get(), " << flatName << ", "
+ << operationModeToString(p->sendMode()) << ", __context);";
+ if(!inParams.empty())
+ {
+ C << nl << "try";
+ C << sb;
+ C << nl << "::IceInternal::BasicStream* __os = __og.os();";
+ writeMarshalCode(C, inParams, 0, StringList(), true);
+ if(p->sendsClasses())
+ {
+ C << nl << "__os->writePendingObjects();";
+ }
+ C << eb;
+ C << nl << "catch(const ::Ice::LocalException& __ex)";
+ C << sb;
+ C << nl << "__og.abort(__ex);";
+ C << eb;
+ }
+
+ C << nl << "bool __ok = __og.invoke();";
+
+ //
+ // Declare the return __ret variable at the top-level scope to
+ // enable NRVO with GCC (see also bug #3619).
+ //
+ writeAllocateCode(C, ParamDeclList(), ret, p->getMetaData(), _useWstring);
+ if(!p->returnsData())
+ {
+ C << nl << "if(!__og.is()->b.empty())";
+ C << sb;
+ }
+ C << nl << "try";
+ C << sb;
+ C << nl << "if(!__ok)";
+ C << sb;
+ C << nl << "try";
+ C << sb;
+ C << nl << "__og.throwUserException();";
+ C << eb;
+
+ //
+ // Generate a catch block for each legal user exception. This is necessary
+ // to prevent an "impossible" user exception to be thrown if client and
+ // and server use different exception specifications for an operation. For
+ // example:
+ //
+ // Client compiled with:
+ // exception A {};
+ // exception B {};
+ // interface I {
+ // void op() throws A;
+ // };
+ //
+ // Server compiled with:
+ // exception A {};
+ // exception B {};
+ // interface I {
+ // void op() throws B; // Differs from client
+ // };
+ //
+ // We need the catch blocks so, if the server throws B from op(), the
+ // client receives UnknownUserException instead of B.
+ //
+ ExceptionList throws = p->throws();
+ throws.sort();
+ throws.unique();
+#if defined(__SUNPRO_CC)
+ throws.sort(derivedToBaseCompare);
+#else
+ throws.sort(Slice::DerivedToBaseCompare());
+#endif
+ for(ExceptionList::const_iterator i = throws.begin(); i != throws.end(); ++i)
+ {
+ C << nl << "catch(const " << fixKwd((*i)->scoped()) << "&)";
+ C << sb;
+ C << nl << "throw;";
+ C << eb;
+ }
+ C << nl << "catch(const ::Ice::UserException& __ex)";
+ C << sb;
+ //
+ // COMPILERFIX: Don't throw UnknownUserException directly. This is causing access
+ // violation errors with Visual C++ 64bits optimized builds. See bug #2962.
+ //
+ C << nl << "::Ice::UnknownUserException __uue(__FILE__, __LINE__, __ex.ice_name());";
+ C << nl << "throw __uue;";
+ C << eb;
+ C << eb;
+
+ for(ParamDeclList::const_iterator opi = outParams.begin(); opi != outParams.end(); ++opi)
+ {
+ StructPtr st = StructPtr::dynamicCast((*opi)->type());
+ if(st && findMetaData(st->getMetaData()) == "class")
+ {
+ C << nl << fixKwd((*opi)->name()) << " = new " << fixKwd(st->scoped()) << ";";
+ }
+ }
+
+ if(ret || !outParams.empty())
+ {
+ C << nl << "::IceInternal::BasicStream* __is = __og.is();";
+ C << nl << "__is->startReadEncaps();";
+ writeUnmarshalCode(C, outParams, ret, p->getMetaData());
+ if(p->returnsClasses())
+ {
+ C << nl << "__is->readPendingObjects();";
+ }
+ C << nl << "__is->endReadEncaps();";
+ }
+ else
+ {
+ C << nl << "__og.is()->skipEmptyEncaps();";
+ }
+
+ if(ret)
+ {
+ C << nl << "return __ret;";
+ }
+ C << eb;
+ C << nl << "catch(const ::Ice::LocalException& __ex)";
+ C << sb;
+ C << nl << "throw ::IceInternal::LocalExceptionWrapper(__ex, false);";
+ C << eb;
+ if(!p->returnsData())
+ {
+ C << eb;
+ }
+ C << eb;
+}
+
+Slice::Gen::DelegateDVisitor::DelegateDVisitor(Output& h, Output& c, const string& dllExport) :
+ H(h), C(c), _dllExport(dllExport), _useWstring(false)
+{
+}
+
+bool
+Slice::Gen::DelegateDVisitor::visitUnitStart(const UnitPtr& p)
+{
+ if(!p->hasNonLocalClassDefs())
+ {
+ return false;
+ }
+
+ H << sp << nl << "namespace IceDelegateD" << nl << '{';
+
+ return true;
+}
+
+void
+Slice::Gen::DelegateDVisitor::visitUnitEnd(const UnitPtr& p)
+{
+ H << sp << nl << '}';
+}
+
+bool
+Slice::Gen::DelegateDVisitor::visitModuleStart(const ModulePtr& p)
+{
+ if(!p->hasNonLocalClassDefs())
+ {
+ return false;
+ }
+
+ _useWstring = setUseWstring(p, _useWstringHist, _useWstring);
+
+ string name = fixKwd(p->name());
+
+ H << sp << nl << "namespace " << name << nl << '{';
+
+ return true;
+}
+
+void
+Slice::Gen::DelegateDVisitor::visitModuleEnd(const ModulePtr& p)
+{
+ H << sp << nl << '}';
+
+ _useWstring = resetUseWstring(_useWstringHist);
+}
+
+bool
+Slice::Gen::DelegateDVisitor::visitClassDefStart(const ClassDefPtr& p)
+{
+ if(p->isLocal())
+ {
+ return false;
+ }
+
+ _useWstring = setUseWstring(p, _useWstringHist, _useWstring);
+
+ string name = fixKwd(p->name());
+ string scoped = fixKwd(p->scoped());
+ ClassList bases = p->bases();
+
+ H << sp << nl << "class " << _dllExport << name << " : ";
+ H.useCurrentPosAsIndent();
+ H << "virtual public ::IceDelegate" << scoped << ',';
+ if(bases.empty())
+ {
+ H << nl << "virtual public ::IceDelegateD::Ice::Object";
+ }
+ else
+ {
+ ClassList::const_iterator q = bases.begin();
+ while(q != bases.end())
+ {
+ H << nl << "virtual public ::IceDelegateD" << fixKwd((*q)->scoped());
+ if(++q != bases.end())
+ {
+ H << ',';
+ }
+ }
+ }
+ H.restoreIndent();
+ H << sb;
+ H.dec();
+ H << nl << "public:";
+ H.inc();
+
+ return true;
+}
+
+void
+Slice::Gen::DelegateDVisitor::visitClassDefEnd(const ClassDefPtr& p)
+{
+ H << eb << ';';
+
+ _useWstring = resetUseWstring(_useWstringHist);
+}
+
+void
+Slice::Gen::DelegateDVisitor::visitOperation(const OperationPtr& p)
+{
+ string name = fixKwd(p->name());
+ string scoped = fixKwd(p->scoped());
+
+ TypePtr ret = p->returnType();
+ string retS = returnTypeToString(ret, p->getMetaData(), _useWstring);
+
+ vector<string> params;
+ vector<string> paramsDecl;
+ vector<string> args;
+ vector<string> argMembers;
+
+ ParamDeclList paramList = p->parameters();
+ for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q)
+ {
+ string paramName = fixKwd((*q)->name());
+
+ StringList metaData = (*q)->getMetaData();
+#if defined(__SUNPRO_CC) && (__SUNPRO_CC==0x550)
+ //
+ // Work around for Sun CC 5.5 bug #4853566
+ //
+ string typeString;
+ if((*q)->isOutParam())
+ {
+ typeString = outputTypeToString((*q)->type(), metaData, _useWstring);
+ }
+ else
+ {
+ typeString = inputTypeToString((*q)->type(), metaData, _useWstring);
+ }
+#else
+ string typeString = (*q)->isOutParam() ? outputTypeToString((*q)->type(), metaData, _useWstring)
+ : inputTypeToString((*q)->type(), metaData, _useWstring);
+#endif
+
+ params.push_back(typeString);
+ paramsDecl.push_back(typeString + ' ' + paramName);
+ args.push_back(paramName);
+ argMembers.push_back("_m_" + paramName);
+ }
+
+ params.push_back("const ::Ice::Context*");
+ args.push_back("__current");
+ argMembers.push_back("_current");
+
+ ContainerPtr container = p->container();
+ ClassDefPtr cl = ClassDefPtr::dynamicCast(container);
+ string thisPointer = fixKwd(cl->scoped()) + "*";
+
+ H << sp;
+
+ H << nl << "virtual " << retS << ' ' << name << spar << params << epar << ';';
+ bool amd = !cl->isLocal() && (cl->hasMetaData("amd") || p->hasMetaData("amd"));
+ if(amd)
+ {
+ C << sp << nl << retS << nl << "IceDelegateD" << scoped << spar << params << epar;
+ C << sb;
+ C << nl << "throw ::Ice::CollocationOptimizationException(__FILE__, __LINE__);";
+ if(ret != 0)
+ {
+ C << nl << "return " << retS << "(); // to avoid a warning with some compilers;";
+ }
+ C << eb;
+ }
+ else
+ {
+ C << sp << nl << retS << nl << "IceDelegateD" << scoped << spar << paramsDecl
+ << "const ::Ice::Context* __context" << epar;
+ C << sb;
+ C << nl << "class _DirectI : public ::IceInternal::Direct";
+ C << sb;
+ C.dec();
+ C << nl << "public:";
+ C.inc();
+
+ //
+ // Constructor
+ //
+ C << sp << nl << "_DirectI" << spar;
+ if(ret)
+ {
+ string resultRef = outputTypeToString(ret, p->getMetaData(), _useWstring);
+ C << resultRef + " __result";
+ }
+ C << paramsDecl << "const ::Ice::Current& __current" << epar << " : ";
+ C.inc();
+ C << nl << "::IceInternal::Direct(__current)";
+
+ if(ret)
+ {
+ C << "," << nl << "_result(__result)";
+ }
+
+ for(size_t i = 0; i < args.size(); ++i)
+ {
+ if(args[i] != "__current")
+ {
+ C << "," << nl << argMembers[i] + "(" + args[i] + ")";
+ }
+ }
+ C.dec();
+ C << sb;
+ C << eb;
+
+ //
+ // run
+ //
+ C << nl << nl << "virtual ::Ice::DispatchStatus";
+ C << nl << "run(::Ice::Object* object)";
+ C << sb;
+ C << nl << thisPointer << " servant = dynamic_cast< " << thisPointer << ">(object);";
+ C << nl << "if(!servant)";
+ C << sb;
+ C << nl << "throw ::Ice::OperationNotExistException(__FILE__, __LINE__, _current.id, _current.facet, _current.operation);";
+ C << eb;
+
+ ExceptionList throws = p->throws();
+
+ if(!throws.empty())
+ {
+ C << nl << "try";
+ C << sb;
+ }
+ C << nl;
+ if(ret)
+ {
+ C << "_result = ";
+ }
+ C << "servant->" << name << spar << argMembers << epar << ';';
+ C << nl << "return ::Ice::DispatchOK;";
+
+ if(!throws.empty())
+ {
+ C << eb;
+ C << nl << "catch(const ::Ice::UserException& __ex)";
+ C << sb;
+ C << nl << "setUserException(__ex);";
+ C << nl << "return ::Ice::DispatchUserException;";
+ C << eb;
+ throws.sort();
+ throws.unique();
+#if defined(__SUNPRO_CC)
+ throws.sort(derivedToBaseCompare);
+#else
+ throws.sort(Slice::DerivedToBaseCompare());
+#endif
+
+ }
+
+ C << eb;
+ C << nl;
+
+ C.dec();
+ C << nl << "private:";
+ C.inc();
+ C << nl;
+ if(ret)
+ {
+ string resultRef= outputTypeToString(ret, p->getMetaData(), _useWstring);
+ C << nl << resultRef << " _result;";
+ }
+
+ for(size_t j = 0; j < argMembers.size(); ++j)
+ {
+ if(argMembers[j] != "_current")
+ {
+ C << nl << params[j] + " " + argMembers[j] << ";";
+ }
+ }
+
+ C << eb << ";";
+
+ C << nl << nl << "::Ice::Current __current;";
+ C << nl << "__initCurrent(__current, " << p->flattenedScope() + p->name() + "_name, "
+ << operationModeToString(p->sendMode()) << ", __context);";
+
+ if(ret)
+ {
+ C << nl << retS << " __result;";
+ }
+
+ C << nl << "try";
+ C << sb;
+
+ C << nl << "_DirectI __direct" << spar;
+ if(ret)
+ {
+ C << "__result";
+ }
+ C << args << epar << ";";
+
+ C << nl << "try";
+ C << sb;
+ C << nl << "__direct.servant()->__collocDispatch(__direct);";
+ C << eb;
+#if 0
+ C << nl << "catch(const ::std::exception& __ex)";
+ C << sb;
+ C << nl << "__direct.destroy();";
+ C << nl << "::IceInternal::LocalExceptionWrapper::throwWrapper(__ex);";
+ C << eb;
+ C << nl << "catch(...)";
+ C << sb;
+ C << nl << "__direct.destroy();";
+ C << nl << "throw ::Ice::UnknownException(__FILE__, __LINE__, \"unknown c++ exception\");";
+ C << eb;
+#else
+ C << nl << "catch(...)";
+ C << sb;
+ C << nl << "__direct.destroy();";
+ C << nl << "throw;";
+ C << eb;
+#endif
+ C << nl << "__direct.destroy();";
+ C << eb;
+ for(ExceptionList::const_iterator k = throws.begin(); k != throws.end(); ++k)
+ {
+ C << nl << "catch(const " << fixKwd((*k)->scoped()) << "&)";
+ C << sb;
+ C << nl << "throw;";
+ C << eb;
+ }
+ C << nl << "catch(const ::Ice::SystemException&)";
+ C << sb;
+ C << nl << "throw;";
+ C << eb;
+ C << nl << "catch(const ::IceInternal::LocalExceptionWrapper&)";
+ C << sb;
+ C << nl << "throw;";
+ C << eb;
+ C << nl << "catch(const ::std::exception& __ex)";
+ C << sb;
+ C << nl << "::IceInternal::LocalExceptionWrapper::throwWrapper(__ex);";
+ C << eb;
+ C << nl << "catch(...)";
+ C << sb;
+ C << nl << "throw ::IceInternal::LocalExceptionWrapper("
+ << "::Ice::UnknownException(__FILE__, __LINE__, \"unknown c++ exception\"), false);";
+ C << eb;
+ if(ret)
+ {
+ C << nl << "return __result;";
+ }
+
+ C << eb;
+ }
+}
+
+Slice::Gen::ObjectDeclVisitor::ObjectDeclVisitor(Output& h, Output& c, const string& dllExport) :
+ H(h), C(c), _dllExport(dllExport)
+{
+}
+
+bool
+Slice::Gen::ObjectDeclVisitor::visitModuleStart(const ModulePtr& p)
+{
+ if(!p->hasClassDecls())
+ {
+ return false;
+ }
+
+ string name = fixKwd(p->name());
+
+ H << sp << nl << "namespace " << name << nl << '{';
+
+ return true;
+}
+
+void
+Slice::Gen::ObjectDeclVisitor::visitModuleEnd(const ModulePtr& p)
+{
+ H << sp << nl << '}';
+}
+
+void
+Slice::Gen::ObjectDeclVisitor::visitClassDecl(const ClassDeclPtr& p)
+{
+ string name = fixKwd(p->name());
+
+ H << sp << nl << "class " << name << ';';
+ H << nl << "bool operator==(const " << name << "&, const " << name << "&);";
+ H << nl << "bool operator<(const " << name << "&, const " << name << "&);";
+}
+
+void
+Slice::Gen::ObjectDeclVisitor::visitOperation(const OperationPtr& p)
+{
+ string flatName = p->flattenedScope() + p->name() + "_name";
+ C << sp << nl << "static const ::std::string " << flatName << " = \"" << p->name() << "\";";
+}
+
+Slice::Gen::ObjectVisitor::ObjectVisitor(Output& h, Output& c, const string& dllExport, bool stream) :
+ H(h), C(c), _dllExport(dllExport), _stream(stream), _doneStaticSymbol(false), _useWstring(false)
+{
+}
+
+bool
+Slice::Gen::ObjectVisitor::visitModuleStart(const ModulePtr& p)
+{
+ if(!p->hasClassDefs())
+ {
+ return false;
+ }
+
+ _useWstring = setUseWstring(p, _useWstringHist, _useWstring);
+
+ string name = fixKwd(p->name());
+
+ H << sp << nl << "namespace " << name << nl << '{';
+
+ return true;
+}
+
+void
+Slice::Gen::ObjectVisitor::visitModuleEnd(const ModulePtr& p)
+{
+ H << sp;
+ H << nl << '}';
+
+ _useWstring = resetUseWstring(_useWstringHist);
+}
+
+bool
+Slice::Gen::ObjectVisitor::visitClassDefStart(const ClassDefPtr& p)
+{
+ _useWstring = setUseWstring(p, _useWstringHist, _useWstring);
+
+ string name = fixKwd(p->name());
+ string scoped = fixKwd(p->scoped());
+ ClassList bases = p->bases();
+ ClassDefPtr base;
+ if(!bases.empty() && !bases.front()->isInterface())
+ {
+ base = bases.front();
+ }
+ DataMemberList dataMembers = p->dataMembers();
+ DataMemberList allDataMembers = p->allDataMembers();
+
+
+ H << sp << nl << "class " << _dllExport << name << " : ";
+ H.useCurrentPosAsIndent();
+ if(bases.empty())
+ {
+ if(p->isLocal())
+ {
+ H << "virtual public ::Ice::LocalObject";
+ }
+ else
+ {
+ H << "virtual public ::Ice::Object";
+ }
+ }
+ else
+ {
+ ClassList::const_iterator q = bases.begin();
+ bool virtualInheritance = p->hasMetaData("cpp:virtual") || p->isInterface();
+ while(q != bases.end())
+ {
+ if(virtualInheritance || (*q)->isInterface())
+ {
+ H << "virtual ";
+ }
+
+ H << "public " << fixKwd((*q)->scoped());
+ if(++q != bases.end())
+ {
+ H << ',' << nl;
+ }
+ }
+ }
+
+ bool hasBaseClass = !bases.empty() && !bases.front()->isInterface();
+ bool override = p->canBeCyclic() && (!hasBaseClass || !bases.front()->canBeCyclic());
+ if(override)
+ {
+ H << ", private IceInternal::GCShared";
+ }
+
+ H.restoreIndent();
+ H << sb;
+ H.dec();
+ H << nl << "public:" << sp;
+ H.inc();
+
+ if(!p->isLocal())
+ {
+ H << nl << "typedef " << p->name() << "Prx ProxyType;";
+ }
+ H << nl << "typedef " << p->name() << "Ptr PointerType;";
+ H << nl;
+
+ vector<string> params;
+ vector<string> allTypes;
+ vector<string> allParamDecls;
+ DataMemberList::const_iterator q;
+
+ for(q = dataMembers.begin(); q != dataMembers.end(); ++q)
+ {
+ params.push_back(fixKwd((*q)->name()));
+ }
+
+ for(q = allDataMembers.begin(); q != allDataMembers.end(); ++q)
+ {
+ string typeName = inputTypeToString((*q)->type(), (*q)->getMetaData(), _useWstring);
+ allTypes.push_back(typeName);
+ allParamDecls.push_back(typeName + " __ice_" + (*q)->name());
+ }
+
+ if(!p->isInterface())
+ {
+ if(p->hasDefaultValues())
+ {
+ H << nl << name << "();";
+
+ C << sp << nl << scoped.substr(2) << "::" << name << "() :";
+ C.inc();
+ writeDataMemberInitializers(C, dataMembers, _useWstring);
+ C.dec();
+ C << sb;
+ C << eb;
+ }
+ else
+ {
+ H << nl << name << "() {}";
+ }
+ if(!allParamDecls.empty())
+ {
+ H << nl;
+ if(allParamDecls.size() == 1)
+ {
+ H << "explicit ";
+ }
+ H << name << spar << allTypes << epar << ';';
+ }
+
+ /*
+ * Strong guarantee: commented-out code marked "Strong guarantee" generates
+ * a copy-assignment operator that provides the strong exception guarantee.
+ * For now, this is commented out, and we use the compiler-generated
+ * copy-assignment operator. However, that one does not provide the strong
+ * guarantee.
+
+ H << ';';
+ if(!p->isAbstract())
+ {
+ H << nl << name << "& operator=(const " << name << "&)";
+ if(allDataMembers.empty())
+ {
+ H << " { return *this; }";
+ }
+ H << ';';
+ }
+
+ //
+ // __swap() is static because classes may be abstract, so we
+ // can't use a non-static member function when we do an upcall
+ // from a non-abstract derived __swap to the __swap in an abstract base.
+ //
+ H << sp << nl << "static void __swap(" << name << "&, " << name << "&) throw()";
+ if(allDataMembers.empty())
+ {
+ H << " {}";
+ }
+ H << ';';
+ H << nl << "void swap(" << name << "& rhs) throw()";
+ H << sb;
+ if(!allDataMembers.empty())
+ {
+ H << nl << "__swap(*this, rhs);";
+ }
+ H << eb;
+
+ * Strong guarantee
+ */
+
+ emitOneShotConstructor(p);
+
+ /*
+ * Strong guarantee
+
+ if(!allDataMembers.empty())
+ {
+ C << sp << nl << "void";
+ C << nl << scoped.substr(2) << "::__swap(" << name << "& __lhs, " << name << "& __rhs) throw()";
+ C << sb;
+
+ if(base)
+ {
+ emitUpcall(base, "::__swap(__lhs, __rhs);");
+ }
+
+ //
+ // We use a map to remember for which types we have already declared
+ // a temporary variable and reuse that variable if a class has
+ // more than one member of the same type. That way, we don't use more
+ // temporaries than necessary. (::std::swap() instantiates a new temporary
+ // each time it is used.)
+ //
+ map<string, int> tmpMap;
+ map<string, int>::iterator pos;
+ int tmpCount = 0;
+
+ for(q = dataMembers.begin(); q != dataMembers.end(); ++q)
+ {
+ string memberName = fixKwd((*q)->name());
+ TypePtr type = (*q)->type();
+ BuiltinPtr builtin = BuiltinPtr::dynamicCast(type);
+ if(builtin && builtin->kind() != Builtin::KindString
+ || EnumPtr::dynamicCast(type) || ProxyPtr::dynamicCast(type)
+ || ClassDeclPtr::dynamicCast(type) || StructPtr::dynamicCast(type))
+ {
+ //
+ // For built-in types (except string), enums, proxies, structs, and classes,
+ // do the swap via a temporary variable.
+ //
+ string typeName = typeToString(type);
+ pos = tmpMap.find(typeName);
+ if(pos == tmpMap.end())
+ {
+ pos = tmpMap.insert(pos, make_pair(typeName, tmpCount));
+ C << nl << typeName << " __tmp" << tmpCount << ';';
+ tmpCount++;
+ }
+ C << nl << "__tmp" << pos->second << " = __rhs." << memberName << ';';
+ C << nl << "__rhs." << memberName << " = __lhs." << memberName << ';';
+ C << nl << "__lhs." << memberName << " = __tmp" << pos->second << ';';
+ }
+ else
+ {
+ //
+ // For dictionaries, vectors, and maps, use the standard container's
+ // swap() (which is usually optimized).
+ //
+ C << nl << "__lhs." << memberName << ".swap(__rhs." << memberName << ");";
+ }
+ }
+ C << eb;
+
+ if(!p->isAbstract())
+ {
+ C << sp << nl << scoped << "&";
+ C << nl << scoped.substr(2) << "::operator=(const " << name << "& __rhs)";
+ C << sb;
+ C << nl << name << " __tmp(__rhs);";
+ C << nl << "__swap(*this, __tmp);";
+ C << nl << "return *this;";
+ C << eb;
+ }
+ }
+
+ * Strong guarantee
+ */
+ }
+
+ if(!p->isLocal())
+ {
+ H << nl << "virtual ::Ice::ObjectPtr ice_clone() const;";
+
+ C << sp;
+ C << nl << "::Ice::ObjectPtr";
+ C << nl << scoped.substr(2) << "::ice_clone() const";
+ C << sb;
+ if(!p->isAbstract())
+ {
+ C << nl << fixKwd(p->scope()) << p->name() << "Ptr __p = new " << scoped << "(*this);";
+ C << nl << "return __p;";
+ }
+ else
+ {
+ C << nl << "throw ::Ice::CloneNotImplementedException(__FILE__, __LINE__);";
+ C << nl << "return 0; // to avoid a warning with some compilers";
+ }
+ C << eb;
+
+ ClassList allBases = p->allBases();
+ StringList ids;
+#if defined(__IBMCPP__) && defined(NDEBUG)
+//
+// VisualAge C++ 6.0 does not see that ClassDef is a Contained,
+// when inlining is on. The code below issues a warning: better
+// than an error!
+//
+ transform(allBases.begin(), allBases.end(), back_inserter(ids), ::IceUtil::constMemFun<string,ClassDef>(&Contained::scoped));
+#else
+ transform(allBases.begin(), allBases.end(), back_inserter(ids), ::IceUtil::constMemFun(&Contained::scoped));
+#endif
+ StringList other;
+ other.push_back(p->scoped());
+ other.push_back("::Ice::Object");
+ other.sort();
+ ids.merge(other);
+ ids.unique();
+ StringList::const_iterator firstIter = ids.begin();
+ StringList::const_iterator scopedIter = find(ids.begin(), ids.end(), p->scoped());
+ assert(scopedIter != ids.end());
+ StringList::difference_type scopedPos = IceUtilInternal::distance(firstIter, scopedIter);
+
+ H << sp;
+ H << nl << "virtual bool ice_isA"
+ << "(const ::std::string&, const ::Ice::Current& = ::Ice::Current()) const;";
+ H << nl << "virtual ::std::vector< ::std::string> ice_ids"
+ << "(const ::Ice::Current& = ::Ice::Current()) const;";
+ H << nl << "virtual const ::std::string& ice_id(const ::Ice::Current& = ::Ice::Current()) const;";
+ H << nl << "static const ::std::string& ice_staticId();";
+ if(!dataMembers.empty())
+ {
+ H << sp;
+ }
+
+ string flatName = p->flattenedScope() + p->name() + "_ids";
+
+ C << sp;
+ C << nl << "static const ::std::string " << flatName << '[' << ids.size() << "] =";
+ C << sb;
+
+ StringList::const_iterator r = ids.begin();
+ while(r != ids.end())
+ {
+ C << nl << '"' << *r << '"';
+ if(++r != ids.end())
+ {
+ C << ',';
+ }
+ }
+ C << eb << ';';
+
+ C << sp;
+ C << nl << "bool" << nl << scoped.substr(2)
+ << "::ice_isA(const ::std::string& _s, const ::Ice::Current&) const";
+ C << sb;
+ C << nl << "return ::std::binary_search(" << flatName << ", " << flatName << " + " << ids.size() << ", _s);";
+ C << eb;
+
+ C << sp;
+ C << nl << "::std::vector< ::std::string>" << nl << scoped.substr(2)
+ << "::ice_ids(const ::Ice::Current&) const";
+ C << sb;
+ C << nl << "return ::std::vector< ::std::string>(&" << flatName << "[0], &" << flatName
+ << '[' << ids.size() << "]);";
+ C << eb;
+
+ C << sp;
+ C << nl << "const ::std::string&" << nl << scoped.substr(2)
+ << "::ice_id(const ::Ice::Current&) const";
+ C << sb;
+ C << nl << "return " << flatName << '[' << scopedPos << "];";
+ C << eb;
+
+ C << sp;
+ C << nl << "const ::std::string&" << nl << scoped.substr(2) << "::ice_staticId()";
+ C << sb;
+ C << nl << "return " << flatName << '[' << scopedPos << "];";
+ C << eb;
+
+ emitGCFunctions(p);
+ }
+
+ return true;
+}
+
+void
+Slice::Gen::ObjectVisitor::visitClassDefEnd(const ClassDefPtr& p)
+{
+ string scoped = fixKwd(p->scoped());
+ string scope = fixKwd(p->scope());
+
+ if(!p->isLocal())
+ {
+ ClassList bases = p->bases();
+ ClassDefPtr base;
+ if(!bases.empty() && !bases.front()->isInterface())
+ {
+ base = bases.front();
+ }
+
+ OperationList allOps = p->allOperations();
+ if(!allOps.empty())
+ {
+ StringList allOpNames;
+#if defined(__IBMCPP__) && defined(NDEBUG)
+//
+// See comment for transform above
+//
+ transform(allOps.begin(), allOps.end(), back_inserter(allOpNames),
+ ::IceUtil::constMemFun<string,Operation>(&Contained::name));
+#else
+ transform(allOps.begin(), allOps.end(), back_inserter(allOpNames),
+ ::IceUtil::constMemFun(&Contained::name));
+#endif
+ allOpNames.push_back("ice_id");
+ allOpNames.push_back("ice_ids");
+ allOpNames.push_back("ice_isA");
+ allOpNames.push_back("ice_ping");
+ allOpNames.sort();
+ allOpNames.unique();
+
+ StringList::const_iterator q;
+
+ H << sp;
+ H << nl
+ << "virtual ::Ice::DispatchStatus __dispatch(::IceInternal::Incoming&, const ::Ice::Current&);";
+
+ string flatName = p->flattenedScope() + p->name() + "_all";
+ C << sp;
+ C << nl << "static ::std::string " << flatName << "[] =";
+ C << sb;
+ q = allOpNames.begin();
+ while(q != allOpNames.end())
+ {
+ C << nl << '"' << *q << '"';
+ if(++q != allOpNames.end())
+ {
+ C << ',';
+ }
+ }
+ C << eb << ';';
+ C << sp;
+ C << nl << "::Ice::DispatchStatus" << nl << scoped.substr(2)
+ << "::__dispatch(::IceInternal::Incoming& in, const ::Ice::Current& current)";
+ C << sb;
+
+ C << nl << "::std::pair< ::std::string*, ::std::string*> r = "
+ << "::std::equal_range(" << flatName << ", " << flatName << " + " << allOpNames.size()
+ << ", current.operation);";
+ C << nl << "if(r.first == r.second)";
+ C << sb;
+ C << nl << "throw ::Ice::OperationNotExistException(__FILE__, __LINE__, current.id, "
+ << "current.facet, current.operation);";
+ C << eb;
+ C << sp;
+ C << nl << "switch(r.first - " << flatName << ')';
+ C << sb;
+ int i = 0;
+ for(q = allOpNames.begin(); q != allOpNames.end(); ++q)
+ {
+ C << nl << "case " << i++ << ':';
+ C << sb;
+ C << nl << "return ___" << *q << "(in, current);";
+ C << eb;
+ }
+ C << eb;
+ C << sp;
+ C << nl << "assert(false);";
+ C << nl << "throw ::Ice::OperationNotExistException(__FILE__, __LINE__, current.id, "
+ << "current.facet, current.operation);";
+ C << eb;
+
+
+ //
+ // Check if we need to generate ice_operationAttributes()
+ //
+ map<string, int> attributesMap;
+ for(OperationList::iterator r = allOps.begin(); r != allOps.end(); ++r)
+ {
+ int attributes = (*r)->attributes();
+ if(attributes != 0)
+ {
+ attributesMap.insert(map<string, int>::value_type((*r)->name(), attributes));
+ }
+ }
+
+ if(!attributesMap.empty())
+ {
+ H << sp;
+ H << nl
+ << "virtual ::Ice::Int ice_operationAttributes(const ::std::string&) const;";
+
+ string opAttrFlatName = p->flattenedScope() + p->name() + "_operationAttributes";
+
+ C << sp;
+ C << nl << "static int " << opAttrFlatName << "[] = ";
+ C << sb;
+
+ q = allOpNames.begin();
+ while(q != allOpNames.end())
+ {
+ int attributes = 0;
+ string opName = *q;
+ map<string, int>::iterator it = attributesMap.find(opName);
+ if(it != attributesMap.end())
+ {
+ attributes = it->second;
+ }
+ C << nl << attributes;
+
+ if(++q != allOpNames.end())
+ {
+ C << ',';
+ }
+ C << " // " << opName;
+ }
+
+ C << eb << ';';
+ C << sp;
+
+ C << nl << "::Ice::Int" << nl << scoped.substr(2)
+ << "::ice_operationAttributes(const ::std::string& opName) const";
+ C << sb;
+
+ C << nl << "::std::pair< ::std::string*, ::std::string*> r = "
+ << "::std::equal_range(" << flatName << ", " << flatName << " + " << allOpNames.size()
+ << ", opName);";
+ C << nl << "if(r.first == r.second)";
+ C << sb;
+ C << nl << "return -1;";
+ C << eb;
+
+ C << nl << "return " << opAttrFlatName << "[r.first - " << flatName << "];";
+ C << eb;
+ }
+ }
+
+ H << sp;
+ H << nl << "virtual void __write(::IceInternal::BasicStream*) const;";
+ H << nl << "virtual void __read(::IceInternal::BasicStream*, bool);";
+
+
+ H.zeroIndent();
+ H << nl << "// COMPILERFIX: Stream API is not supported with VC++ 6";
+ H << nl << "#if !defined(_MSC_VER) || (_MSC_VER >= 1300)";
+ H.restoreIndent();
+ H << nl << "virtual void __write(const ::Ice::OutputStreamPtr&) const;";
+ H << nl << "virtual void __read(const ::Ice::InputStreamPtr&, bool);";
+ H.zeroIndent();
+ H << nl << "#endif";
+ H.restoreIndent();
+
+ C << sp;
+ C << nl << "void" << nl << scoped.substr(2)
+ << "::__write(::IceInternal::BasicStream* __os) const";
+ C << sb;
+ C << nl << "__os->writeTypeId(ice_staticId());";
+ C << nl << "__os->startWriteSlice();";
+ DataMemberList dataMembers = p->dataMembers();
+ DataMemberList::const_iterator q;
+ for(q = dataMembers.begin(); q != dataMembers.end(); ++q)
+ {
+ writeMarshalUnmarshalCode(C, (*q)->type(), fixKwd((*q)->name()), true, "", true, (*q)->getMetaData());
+ }
+ C << nl << "__os->endWriteSlice();";
+ emitUpcall(base, "::__write(__os);");
+ C << eb;
+ C << sp;
+ C << nl << "void" << nl << scoped.substr(2) << "::__read(::IceInternal::BasicStream* __is, bool __rid)";
+ C << sb;
+ C << nl << "if(__rid)";
+ C << sb;
+ C << nl << "::std::string myId;";
+ C << nl << "__is->readTypeId(myId);";
+ C << eb;
+ C << nl << "__is->startReadSlice();";
+ for(q = dataMembers.begin(); q != dataMembers.end(); ++q)
+ {
+ writeMarshalUnmarshalCode(C, (*q)->type(), fixKwd((*q)->name()), false, "", true, (*q)->getMetaData());
+ }
+ C << nl << "__is->endReadSlice();";
+ emitUpcall(base, "::__read(__is, true);");
+ C << eb;
+
+ if(_stream)
+ {
+ C << sp;
+ C.zeroIndent();
+ C << nl << "// COMPILERFIX: Stream API is not supported with VC++ 6";
+ C << nl << "#if !defined(_MSC_VER) || (_MSC_VER >= 1300)";
+ C.restoreIndent();
+ C << nl << "void" << nl << scoped.substr(2) << "::__write(const ::Ice::OutputStreamPtr& __outS) const";
+ C << sb;
+ C << nl << "__outS->writeTypeId(ice_staticId());";
+ C << nl << "__outS->startSlice();";
+ for(q = dataMembers.begin(); q != dataMembers.end(); ++q)
+ {
+ writeStreamMarshalUnmarshalCode(C, (*q)->type(), (*q)->name(), true, "", (*q)->getMetaData(),
+ _useWstring);
+ }
+ C << nl << "__outS->endSlice();";
+ emitUpcall(base, "::__write(__outS);");
+ C << eb;
+ C << sp;
+ C << nl << "void" << nl << scoped.substr(2) << "::__read(const ::Ice::InputStreamPtr& __inS, bool __rid)";
+ C << sb;
+ C << nl << "if(__rid)";
+ C << sb;
+ C << nl << "__inS->readTypeId();";
+ C << eb;
+ C << nl << "__inS->startSlice();";
+ for(q = dataMembers.begin(); q != dataMembers.end(); ++q)
+ {
+ writeStreamMarshalUnmarshalCode(C, (*q)->type(), (*q)->name(), false, "", (*q)->getMetaData(),
+ _useWstring);
+ }
+ C << nl << "__inS->endSlice();";
+ emitUpcall(base, "::__read(__inS, true);");
+ C << eb;
+ C.zeroIndent();
+ C << nl << "#endif";
+ C.restoreIndent();
+ }
+ else
+ {
+ C << sp;
+ C.zeroIndent();
+ C << nl << "// COMPILERFIX: Stream API is not supported with VC++ 6";
+ C << nl << "#if !defined(_MSC_VER) || (_MSC_VER >= 1300)";
+ C.restoreIndent();
+ //
+ // Emit placeholder functions to catch errors.
+ //
+ C << nl << "void" << nl << scoped.substr(2) << "::__write(const ::Ice::OutputStreamPtr&) const";
+ C << sb;
+ C << nl << "Ice::MarshalException ex(__FILE__, __LINE__);";
+ C << nl << "ex.reason = \"type " << scoped.substr(2) << " was not generated with stream support\";";
+ C << nl << "throw ex;";
+ C << eb;
+ C << sp;
+ C << nl << "void" << nl << scoped.substr(2) << "::__read(const ::Ice::InputStreamPtr&, bool)";
+ C << sb;
+ C << nl << "Ice::MarshalException ex(__FILE__, __LINE__);";
+ C << nl << "ex.reason = \"type " << scoped.substr(2) << " was not generated with stream support\";";
+ C << nl << "throw ex;";
+ C << eb;
+ C.zeroIndent();
+ C << nl << "#endif";
+ C.restoreIndent();
+ }
+
+ if(!p->isAbstract())
+ {
+ H << sp << nl << "static const ::Ice::ObjectFactoryPtr& ice_factory();";
+
+ string factoryName = "__F" + p->flattenedScope() + p->name();
+ C << sp;
+ C << nl << "class " << factoryName << " : public ::Ice::ObjectFactory";
+ C << sb;
+ C.dec();
+ C << nl << "public:";
+ C.inc();
+ C << sp << nl << "virtual ::Ice::ObjectPtr" << nl << "create(const ::std::string& type)";
+ C << sb;
+ C << nl << "assert(type == " << scoped << "::ice_staticId());";
+ C << nl << "return new " << scoped << ';';
+ C << eb;
+ C << sp << nl << "virtual void" << nl << "destroy()";
+ C << sb;
+ C << eb;
+ C << eb << ';';
+
+ string flatName = factoryName + "_Ptr";
+ C << sp;
+ C << nl << "static ::Ice::ObjectFactoryPtr " << flatName << " = new " << factoryName << ';';
+
+ C << sp << nl << "const ::Ice::ObjectFactoryPtr&" << nl << scoped.substr(2) << "::ice_factory()";
+ C << sb;
+ C << nl << "return " << flatName << ';';
+ C << eb;
+
+ C << sp;
+ C << nl << "class " << factoryName << "__Init";
+ C << sb;
+ C.dec();
+ C << nl << "public:";
+ C.inc();
+ C << sp << nl << factoryName << "__Init()";
+ C << sb;
+ C << nl << "::IceInternal::factoryTable->addObjectFactory(" << scoped << "::ice_staticId(), "
+ << scoped << "::ice_factory());";
+ C << eb;
+ C << sp << nl << "~" << factoryName << "__Init()";
+ C << sb;
+ C << nl << "::IceInternal::factoryTable->removeObjectFactory(" << scoped << "::ice_staticId());";
+ C << eb;
+ C << eb << ';';
+
+ C << sp;
+ C << nl << "static " << factoryName << "__Init " << factoryName << "__i;";
+ C << sp << nl << "#ifdef __APPLE__";
+ std::string initfuncname = "__F" + p->flattenedScope() + p->name() + "__initializer";
+ C << nl << "extern \"C\" { void " << initfuncname << "() {} }";
+ C << nl << "#endif";
+ }
+ }
+
+ bool inProtected = false;
+
+ if(!p->isAbstract())
+ {
+ //
+ // We add a protected destructor to force heap instantiation of the class.
+ //
+ H.dec();
+ H << sp << nl << "protected:";
+ H.inc();
+ H << sp << nl << "virtual ~" << fixKwd(p->name()) << "() {}";
+
+ if(!_doneStaticSymbol)
+ {
+ H << sp << nl << "friend class " << p->name() << "__staticInit;";
+ }
+
+ inProtected = true;
+ }
+
+ //
+ // Emit data members. Access visibility may be specified by metadata.
+ //
+ DataMemberList dataMembers = p->dataMembers();
+ DataMemberList::const_iterator q;
+ bool prot = p->hasMetaData("protected");
+ for(q = dataMembers.begin(); q != dataMembers.end(); ++q)
+ {
+ TypePtr type = (*q)->type();
+ if(SequencePtr::dynamicCast(type))
+ {
+ SequencePtr s = SequencePtr::dynamicCast(type);
+ BuiltinPtr builtin = BuiltinPtr::dynamicCast(s->type());
+ if(builtin && builtin->kind() == Builtin::KindByte)
+ {
+ StringList metaData = s->getMetaData();
+ bool protobuf;
+ findMetaData(s, metaData, protobuf);
+ if(protobuf)
+ {
+ emitWarning((*q)->file(), (*q)->line(), "protobuf cannot be used as a class member in C++");
+ }
+ }
+ }
+
+ if(prot || (*q)->hasMetaData("protected"))
+ {
+ if(!inProtected)
+ {
+ H.dec();
+ H << sp << nl << "protected:";
+ H.inc();
+ inProtected = true;
+ }
+ }
+ else
+ {
+ if(inProtected)
+ {
+ H.dec();
+ H << sp << nl << "public:";
+ H.inc();
+ inProtected = false;
+ }
+ }
+
+ string name = fixKwd((*q)->name());
+ string s = typeToString((*q)->type(), (*q)->getMetaData(), _useWstring);
+ H << sp << nl << s << ' ' << name << ';';
+ }
+
+ H << eb << ';';
+
+ if(!p->isAbstract() && !_doneStaticSymbol)
+ {
+ //
+ // We need an instance here to trigger initialization if the implementation is in a shared library.
+ // But we do this only once per source file, because a single instance is sufficient to initialize
+ // all of the globals in a shared library.
+ //
+ // For a Slice class Foo, we instantiate a dummy class Foo__staticInit instead of using a static
+ // Foo instance directly because Foo has a protected destructor.
+ //
+ H << sp << nl << "class " << p->name() << "__staticInit";
+ H << sb;
+ H.dec();
+ H << nl << "public:";
+ H.inc();
+ H << sp << nl << scoped << " _init;";
+ H << eb << ';';
+ _doneStaticSymbol = true;
+ H << sp << nl << "static " << p->name() << "__staticInit _" << p->name() << "_init;";
+ }
+
+ if(p->isLocal())
+ {
+ H << sp;
+ H << nl << "inline bool operator==(const " << fixKwd(p->name()) << "& l, const " << fixKwd(p->name()) << "& r)";
+ H << sb;
+ H << nl << "return static_cast<const ::Ice::LocalObject&>(l) == static_cast<const ::Ice::LocalObject&>(r);";
+ H << eb;
+ H << sp;
+ H << nl << "inline bool operator<(const " << fixKwd(p->name()) << "& l, const " << fixKwd(p->name()) << "& r)";
+ H << sb;
+ H << nl << "return static_cast<const ::Ice::LocalObject&>(l) < static_cast<const ::Ice::LocalObject&>(r);";
+ H << eb;
+ }
+ else
+ {
+ C << sp << nl << "void "
+ << (_dllExport.empty() ? "" : "ICE_DECLSPEC_EXPORT ");
+ C << nl << scope.substr(2) << "__patch__" << p->name() << "Ptr(void* __addr, ::Ice::ObjectPtr& v)";
+ C << sb;
+ C << nl << scope << p->name() << "Ptr* p = static_cast< " << scope << p->name() << "Ptr*>(__addr);";
+ C << nl << "assert(p);";
+ C << nl << "*p = " << scope << p->name() << "Ptr::dynamicCast(v);";
+ C << nl << "if(v && !*p)";
+ C << sb;
+ C << nl << "IceInternal::Ex::throwUOE(" << scoped << "::ice_staticId(), v->ice_id());";
+ C << eb;
+ C << eb;
+
+ H << sp;
+ H << nl << "inline bool operator==(const " << fixKwd(p->name()) << "& l, const " << fixKwd(p->name()) << "& r)";
+ H << sb;
+ H << nl << "return static_cast<const ::Ice::Object&>(l) == static_cast<const ::Ice::Object&>(r);";
+ H << eb;
+ H << sp;
+ H << nl << "inline bool operator<(const " << fixKwd(p->name()) << "& l, const " << fixKwd(p->name()) << "& r)";
+ H << sb;
+ H << nl << "return static_cast<const ::Ice::Object&>(l) < static_cast<const ::Ice::Object&>(r);";
+ H << eb;
+ }
+
+ _useWstring = resetUseWstring(_useWstringHist);
+}
+
+bool
+Slice::Gen::ObjectVisitor::visitExceptionStart(const ExceptionPtr&)
+{
+ return false;
+}
+
+bool
+Slice::Gen::ObjectVisitor::visitStructStart(const StructPtr&)
+{
+ return false;
+}
+
+void
+Slice::Gen::ObjectVisitor::visitOperation(const OperationPtr& p)
+{
+ string name = p->name();
+ string scoped = fixKwd(p->scoped());
+ string scope = fixKwd(p->scope());
+
+ TypePtr ret = p->returnType();
+ string retS = returnTypeToString(ret, p->getMetaData(), _useWstring);
+
+ string params = "(";
+ string paramsDecl = "(";
+ string args = "(";
+
+ ContainerPtr container = p->container();
+ ClassDefPtr cl = ClassDefPtr::dynamicCast(container);
+ string classNameAMD = "AMD_" + cl->name();
+ string classScope = fixKwd(cl->scope());
+ string classScopedAMD = classScope + classNameAMD;
+
+ string paramsAMD = "(const " + classScopedAMD + '_' + name + "Ptr&, ";
+ string paramsDeclAMD = "(const " + classScopedAMD + '_' + name + "Ptr& __cb, ";
+ string argsAMD = "(__cb, ";
+
+ ParamDeclList inParams;
+ ParamDeclList outParams;
+ ParamDeclList paramList = p->parameters();
+ for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q)
+ {
+ string paramName = fixKwd((*q)->name());
+ TypePtr type = (*q)->type();
+ bool isOutParam = (*q)->isOutParam();
+ string typeString;
+ if(isOutParam)
+ {
+ outParams.push_back(*q);
+ typeString = outputTypeToString(type, (*q)->getMetaData(), _useWstring);
+ }
+ else
+ {
+ inParams.push_back(*q);
+ typeString = inputTypeToString((*q)->type(), (*q)->getMetaData(), _useWstring);
+ }
+
+ if(q != paramList.begin())
+ {
+ params += ", ";
+ paramsDecl += ", ";
+ args += ", ";
+ }
+
+ params += typeString;
+ paramsDecl += typeString;
+ paramsDecl += ' ';
+ paramsDecl += paramName;
+ args += paramName;
+
+ if(!isOutParam)
+ {
+ paramsAMD += typeString;
+ paramsAMD += ", ";
+ paramsDeclAMD += typeString;
+ paramsDeclAMD += ' ';
+ paramsDeclAMD += paramName;
+ paramsDeclAMD += ", ";
+ argsAMD += paramName;
+ argsAMD += ", ";
+ }
+ }
+
+ if(!cl->isLocal())
+ {
+ if(!paramList.empty())
+ {
+ params += ", ";
+ paramsDecl += ", ";
+ args += ", ";
+ }
+
+ params += "const ::Ice::Current& = ::Ice::Current())";
+ paramsDecl += "const ::Ice::Current& __current)";
+ args += "__current)";
+ }
+ else
+ {
+ params += ')';
+ paramsDecl += ')';
+ args += ')';
+ }
+
+ paramsAMD += "const ::Ice::Current& = ::Ice::Current())";
+ paramsDeclAMD += "const ::Ice::Current& __current)";
+ argsAMD += "__current)";
+
+ bool isConst = (p->mode() == Operation::Nonmutating) || p->hasMetaData("cpp:const");
+ bool amd = !cl->isLocal() && (cl->hasMetaData("amd") || p->hasMetaData("amd"));
+
+ string deprecateSymbol = getDeprecateSymbol(p, cl);
+
+ H << sp;
+ if(!amd)
+ {
+ H << nl << deprecateSymbol << "virtual " << retS << ' ' << fixKwd(name) << params
+ << (isConst ? " const" : "") << " = 0;";
+ }
+ else
+ {
+ H << nl << deprecateSymbol << "virtual void " << name << "_async" << paramsAMD
+ << (isConst ? " const" : "") << " = 0;";
+ }
+
+ if(!cl->isLocal())
+ {
+ H << nl << "::Ice::DispatchStatus ___" << name
+ << "(::IceInternal::Incoming&, const ::Ice::Current&)" << (isConst ? " const" : "") << ';';
+
+ C << sp;
+ C << nl << "::Ice::DispatchStatus" << nl << scope.substr(2) << "___" << name
+ << "(::IceInternal::Incoming& __inS";
+ C << ", const ::Ice::Current& __current)" << (isConst ? " const" : "");
+ C << sb;
+ if(!amd)
+ {
+ ExceptionList throws = p->throws();
+ throws.sort();
+ throws.unique();
+
+ //
+ // Arrange exceptions into most-derived to least-derived order. If we don't
+ // do this, a base exception handler can appear before a derived exception
+ // handler, causing compiler warnings and resulting in the base exception
+ // being marshaled instead of the derived exception.
+ //
+
+#if defined(__SUNPRO_CC)
+ throws.sort(derivedToBaseCompare);
+#else
+ throws.sort(Slice::DerivedToBaseCompare());
+#endif
+
+ C << nl << "__checkMode(" << operationModeToString(p->mode()) << ", __current.mode);";
+
+ if(!inParams.empty())
+ {
+ C << nl << "::IceInternal::BasicStream* __is = __inS.is();";
+ C << nl << "__is->startReadEncaps();";
+ writeAllocateCode(C, inParams, 0, StringList(), _useWstring | TypeContextInParam);
+ writeUnmarshalCode(C, inParams, 0, StringList(), TypeContextInParam);
+ if(p->sendsClasses())
+ {
+ C << nl << "__is->readPendingObjects();";
+ }
+ C << nl << "__is->endReadEncaps();";
+ }
+ else
+ {
+ C << nl << "__inS.is()->skipEmptyEncaps();";
+ }
+
+ if(ret || !outParams.empty() || !throws.empty())
+ {
+ C << nl << "::IceInternal::BasicStream* __os = __inS.os();";
+ }
+ writeAllocateCode(C, outParams, 0, StringList(), _useWstring);
+ if(!throws.empty())
+ {
+ C << nl << "try";
+ C << sb;
+ }
+ C << nl;
+ if(ret)
+ {
+ C << retS << " __ret = ";
+ }
+ C << fixKwd(name) << args << ';';
+ writeMarshalCode(C, outParams, ret, p->getMetaData());
+ if(p->returnsClasses())
+ {
+ C << nl << "__os->writePendingObjects();";
+ }
+ if(!throws.empty())
+ {
+ C << eb;
+ ExceptionList::const_iterator r;
+ for(r = throws.begin(); r != throws.end(); ++r)
+ {
+ C << nl << "catch(const " << fixKwd((*r)->scoped()) << "& __ex)";
+ C << sb;
+ C << nl << "__os->write(__ex);";
+ C << nl << "return ::Ice::DispatchUserException;";
+ C << eb;
+ }
+ }
+
+ C << nl << "return ::Ice::DispatchOK;";
+ }
+ else
+ {
+ C << nl << "__checkMode(" << operationModeToString(p->mode()) << ", __current.mode);";
+
+ if(!inParams.empty())
+ {
+ C << nl << "::IceInternal::BasicStream* __is = __inS.is();";
+ C << nl << "__is->startReadEncaps();";
+ writeAllocateCode(C, inParams, 0, StringList(), _useWstring | TypeContextInParam);
+ writeUnmarshalCode(C, inParams, 0, StringList(), TypeContextInParam);
+ if(p->sendsClasses())
+ {
+ C << nl << "__is->readPendingObjects();";
+ }
+ C << nl << "__is->endReadEncaps();";
+ }
+ else
+ {
+ C << nl << "__inS.is()->skipEmptyEncaps();";
+ }
+
+ C << nl << classScopedAMD << '_' << name << "Ptr __cb = new IceAsync" << classScopedAMD << '_' << name
+ << "(__inS);";
+ C << nl << "try";
+ C << sb;
+ C << nl << name << "_async" << argsAMD << ';';
+ C << eb;
+ C << nl << "catch(const ::std::exception& __ex)";
+ C << sb;
+ C << nl << "__cb->ice_exception(__ex);";
+ C << eb;
+ C << nl << "catch(...)";
+ C << sb;
+ C << nl << "__cb->ice_exception();";
+ C << eb;
+ C << nl << "return ::Ice::DispatchAsync;";
+ }
+ C << eb;
+ }
+
+ if(cl->isLocal() && (cl->hasMetaData("async") || p->hasMetaData("async")))
+ {
+ vector<string> paramsDeclAMI;
+ vector<string> outParamsDeclAMI;
+
+ ParamDeclList paramList = p->parameters();
+ for(ParamDeclList::const_iterator r = paramList.begin(); r != paramList.end(); ++r)
+ {
+ string paramName = fixKwd((*r)->name());
+
+ StringList metaData = (*r)->getMetaData();
+ string typeString;
+ if((*r)->isOutParam())
+ {
+ typeString = outputTypeToString((*r)->type(), metaData, _useWstring | TypeContextAMIEnd);
+ }
+ else
+ {
+ typeString = inputTypeToString((*r)->type(), metaData, _useWstring);
+ }
+
+ if(!(*r)->isOutParam())
+ {
+ paramsDeclAMI.push_back(typeString + ' ' + paramName);
+ }
+ else
+ {
+ outParamsDeclAMI.push_back(typeString + ' ' + paramName);
+ }
+ }
+
+ H << sp << nl << "virtual ::Ice::AsyncResultPtr begin_" << name << spar << paramsDeclAMI << epar << " = 0;";
+
+ H << sp << nl << "virtual ::Ice::AsyncResultPtr begin_" << name << spar << paramsDeclAMI
+ << "const ::Ice::CallbackPtr& __del"
+ << "const ::Ice::LocalObjectPtr& __cookie = 0" << epar << " = 0;";
+
+ string clScope = fixKwd(cl->scope());
+ string delName = "Callback_" + cl->name() + "_" + name;
+ string delNameScoped = clScope + delName;
+
+ H << sp << nl << "virtual ::Ice::AsyncResultPtr begin_" << name << spar << paramsDeclAMI
+ << "const " + delNameScoped + "Ptr& __del"
+ << "const ::Ice::LocalObjectPtr& __cookie = 0" << epar << " = 0;";
+
+ H << sp << nl << "virtual " << retS << " end_" << name << spar << outParamsDeclAMI
+ << "const ::Ice::AsyncResultPtr&" << epar << " = 0;";
+ }
+}
+
+void
+Slice::Gen::ObjectVisitor::emitGCFunctions(const ClassDefPtr& p)
+{
+ string scoped = fixKwd(p->scoped());
+ ClassList bases = p->bases();
+ DataMemberList dataMembers = p->dataMembers();
+
+ //
+ // A class can potentially be part of a cycle if it (recursively) contains class
+ // members. If so, we override __incRef(), __decRef(), and __addObject() and, hence, consider
+ // instances of the class as candidates for collection by the garbage collector.
+ // We override __incRef(), __decRef(), and __addObject() only once, in the basemost potentially
+ // cyclic class in an inheritance hierarchy.
+ //
+ bool hasBaseClass = !bases.empty() && !bases.front()->isInterface();
+ bool canBeCyclic = p->canBeCyclic();
+ bool override = canBeCyclic && (!hasBaseClass || !bases.front()->canBeCyclic());
+
+ if(override)
+ {
+ H << nl << "virtual void __addObject(::IceInternal::GCCountMap&);";
+
+ C << sp << nl << "void" << nl << scoped.substr(2) << "::__addObject(::IceInternal::GCCountMap& _c)";
+ C << sb;
+ C << nl << "::IceInternal::GCCountMap::iterator pos = _c.find(this);";
+ C << nl << "if(pos == _c.end())";
+ C << sb;
+ C << nl << "_c[this] = 1;";
+ C << eb;
+ C << nl << "else";
+ C << sb;
+ C << nl << "++pos->second;";
+ C << eb;
+ C << eb;
+
+ H << nl << "virtual bool __usesClasses();";
+
+ C << sp << nl << "bool" << nl << scoped.substr(2) << "::__usesClasses()";
+ C << sb;
+ C << nl << "return true;";
+ C << eb;
+ }
+
+ //
+ // __gcReachable() and __gcClear() are overridden by the basemost class that
+ // can be cyclic, plus all classes derived from that class.
+ //
+ if(canBeCyclic)
+ {
+ H << nl << "virtual void __gcReachable(::IceInternal::GCCountMap&) const;";
+
+ C << sp << nl << "void" << nl << scoped.substr(2) << "::__gcReachable(::IceInternal::GCCountMap& _c) const";
+ C << sb;
+
+ bool hasCyclicBase = hasBaseClass && bases.front()->canBeCyclic();
+ if(hasCyclicBase)
+ {
+ emitUpcall(bases.front(), "::__gcReachable(_c);");
+ }
+ for(DataMemberList::const_iterator i = dataMembers.begin(); i != dataMembers.end(); ++i)
+ {
+ if((*i)->type()->usesClasses())
+ {
+ emitGCInsertCode((*i)->type(), fixKwd((*i)->name()), "", 0);
+ }
+ }
+ C << eb;
+
+ H << nl << "virtual void __gcClear();";
+
+ C << sp << nl << "void" << nl << scoped.substr(2) << "::__gcClear()";
+ C << sb;
+ if(hasCyclicBase)
+ {
+ emitUpcall(bases.front(), "::__gcClear();");
+ }
+ for(DataMemberList::const_iterator j = dataMembers.begin(); j != dataMembers.end(); ++j)
+ {
+ if((*j)->type()->usesClasses())
+ {
+ emitGCClearCode((*j)->type(), fixKwd((*j)->name()), "", 0);
+ }
+ }
+ C << eb;
+ }
+}
+
+void
+Slice::Gen::ObjectVisitor::emitGCInsertCode(const TypePtr& p, const string& prefix, const string& name, int level)
+{
+ if((BuiltinPtr::dynamicCast(p) && BuiltinPtr::dynamicCast(p)->kind() == Builtin::KindObject)
+ || ClassDeclPtr::dynamicCast(p))
+ {
+ C << nl << "if(" << prefix << name << ')';
+ C << sb;
+ ClassDeclPtr decl = ClassDeclPtr::dynamicCast(p);
+ if(decl)
+ {
+ C << nl << "::IceInternal::upCast(" << prefix << name << ".get())->__addObject(_c);";
+ }
+ else
+ {
+ C << nl << prefix << name << "->__addObject(_c);";
+ }
+ C << eb;
+ }
+ else if(StructPtr::dynamicCast(p))
+ {
+ StructPtr s = StructPtr::dynamicCast(p);
+ DataMemberList dml = s->dataMembers();
+ for(DataMemberList::const_iterator i = dml.begin(); i != dml.end(); ++i)
+ {
+ if((*i)->type()->usesClasses())
+ {
+ emitGCInsertCode((*i)->type(), prefix + name + ".", fixKwd((*i)->name()), ++level);
+ }
+ }
+ }
+ else if(DictionaryPtr::dynamicCast(p))
+ {
+ DictionaryPtr d = DictionaryPtr::dynamicCast(p);
+ string scoped = fixKwd(d->scoped());
+ ostringstream tmp;
+ tmp << "_i" << level;
+ string iterName = tmp.str();
+ C << sb;
+ C << nl << "for(" << scoped << "::const_iterator " << iterName << " = " << prefix + name
+ << ".begin(); " << iterName << " != " << prefix + name << ".end(); ++" << iterName << ")";
+ C << sb;
+ emitGCInsertCode(d->valueType(), "", string("(*") + iterName + ").second", ++level);
+ C << eb;
+ C << eb;
+ }
+ else if(SequencePtr::dynamicCast(p))
+ {
+ SequencePtr s = SequencePtr::dynamicCast(p);
+ string scoped = fixKwd(s->scoped());
+ ostringstream tmp;
+ tmp << "_i" << level;
+ string iterName = tmp.str();
+ C << sb;
+ C << nl << "for(" << scoped << "::const_iterator " << iterName << " = " << prefix + name
+ << ".begin(); " << iterName << " != " << prefix + name << ".end(); ++" << iterName << ")";
+ C << sb;
+ emitGCInsertCode(s->type(), string("(*") + iterName + ")", "", ++level);
+ C << eb;
+ C << eb;
+ }
+}
+
+void
+Slice::Gen::ObjectVisitor::emitGCClearCode(const TypePtr& p, const string& prefix, const string& name, int level)
+{
+ if((BuiltinPtr::dynamicCast(p) && BuiltinPtr::dynamicCast(p)->kind() == Builtin::KindObject)
+ || ClassDeclPtr::dynamicCast(p))
+ {
+ C << nl << "if(" << prefix << name << ")";
+ C << sb;
+ ClassDeclPtr decl = ClassDeclPtr::dynamicCast(p);
+ if(decl)
+ {
+ C << nl << "if(" << "::IceInternal::upCast(" << prefix << name << ".get())->__usesClasses())";
+ C << sb;
+ C << nl << "::IceInternal::upCast(" << prefix << name << ".get())->__decRefUnsafe();";
+ C << nl << prefix << name << ".__clearHandleUnsafe();";
+
+ }
+ else
+ {
+ C << nl << "if(" << prefix << name << "->__usesClasses())";
+ C << sb;
+ C << nl << prefix << name << "->__decRefUnsafe();";
+ C << nl << prefix << name << ".__clearHandleUnsafe();";
+ }
+ C << eb;
+ C << nl << "else";
+ C << sb;
+ C << nl << prefix << name << " = 0;";
+ C << eb;
+ C << eb;
+ }
+ else if(StructPtr::dynamicCast(p))
+ {
+ StructPtr s = StructPtr::dynamicCast(p);
+ DataMemberList dml = s->dataMembers();
+ for(DataMemberList::const_iterator i = dml.begin(); i != dml.end(); ++i)
+ {
+ if((*i)->type()->usesClasses())
+ {
+ emitGCClearCode((*i)->type(), prefix + name + ".", fixKwd((*i)->name()), ++level);
+ }
+ }
+ }
+ else if(DictionaryPtr::dynamicCast(p))
+ {
+ DictionaryPtr d = DictionaryPtr::dynamicCast(p);
+ string scoped = fixKwd(d->scoped());
+ ostringstream tmp;
+ tmp << "_i" << level;
+ string iterName = tmp.str();
+ C << sb;
+ C << nl << "for(" << scoped << "::iterator " << iterName << " = " << prefix + name
+ << ".begin(); " << iterName << " != " << prefix + name << ".end(); ++" << iterName << ")";
+ C << sb;
+ emitGCClearCode(d->valueType(), "", string("(*") + iterName + ").second", ++level);
+ C << eb;
+ C << eb;
+ }
+ else if(SequencePtr::dynamicCast(p))
+ {
+ SequencePtr s = SequencePtr::dynamicCast(p);
+ string scoped = fixKwd(s->scoped());
+ ostringstream tmp;
+ tmp << "_i" << level;
+ string iterName = tmp.str();
+ C << sb;
+ C << nl << "for(" << scoped << "::iterator " << iterName << " = " << prefix + name
+ << ".begin(); " << iterName << " != " << prefix + name << ".end(); ++" << iterName << ")";
+ C << sb;
+ emitGCClearCode(s->type(), "", string("(*") + iterName + ")", ++level);
+ C << eb;
+ C << eb;;
+ }
+}
+
+bool
+Slice::Gen::ObjectVisitor::emitVirtualBaseInitializers(const ClassDefPtr& p, bool virtualInheritance)
+{
+ DataMemberList allDataMembers = p->allDataMembers();
+ if(allDataMembers.empty())
+ {
+ return false;
+ }
+
+ if(virtualInheritance)
+ {
+ ClassList bases = p->bases();
+ if(!bases.empty() && !bases.front()->isInterface())
+ {
+ if(emitVirtualBaseInitializers(bases.front(), virtualInheritance))
+ {
+ C << ',';
+ }
+ }
+ }
+
+ string upcall = "(";
+ DataMemberList::const_iterator q;
+ for(q = allDataMembers.begin(); q != allDataMembers.end(); ++q)
+ {
+ if(q != allDataMembers.begin())
+ {
+ upcall += ", ";
+ }
+ upcall += "__ice_" + (*q)->name();
+ }
+ upcall += ")";
+
+ C.zeroIndent();
+ C << nl << "#if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug";
+ C.restoreIndent();
+ C << nl << fixKwd(p->name()) << upcall;
+ C.zeroIndent();
+ C << nl << "#else";
+ C.restoreIndent();
+ C << nl << fixKwd(p->scoped()) << upcall;
+ C.zeroIndent();
+ C << nl << "#endif";
+ C << nl;
+ C.restoreIndent();
+
+ return true;
+}
+
+void
+Slice::Gen::ObjectVisitor::emitOneShotConstructor(const ClassDefPtr& p)
+{
+ DataMemberList allDataMembers = p->allDataMembers();
+ DataMemberList::const_iterator q;
+
+ vector<string> allParamDecls;
+
+ for(q = allDataMembers.begin(); q != allDataMembers.end(); ++q)
+ {
+ string typeName = inputTypeToString((*q)->type(), (*q)->getMetaData(), _useWstring);
+ allParamDecls.push_back(typeName + " __ice_" + (*q)->name());
+ }
+
+ if(!allDataMembers.empty())
+ {
+ C << sp << nl << fixKwd(p->scoped()).substr(2) << "::" << fixKwd(p->name())
+ << spar << allParamDecls << epar << " :";
+ C.inc();
+
+ DataMemberList dataMembers = p->dataMembers();
+
+ ClassList bases = p->bases();
+ ClassDefPtr base;
+ if(!bases.empty() && !bases.front()->isInterface())
+ {
+ if(emitVirtualBaseInitializers(bases.front(), p->hasMetaData("cpp:virtual")))
+ {
+ if(!dataMembers.empty())
+ {
+ C << ',';
+ }
+ }
+ }
+
+ if(!dataMembers.empty())
+ {
+ C << nl;
+ }
+ for(q = dataMembers.begin(); q != dataMembers.end(); ++q)
+ {
+ if(q != dataMembers.begin())
+ {
+ C << ',' << nl;
+ }
+ string memberName = fixKwd((*q)->name());
+ C << memberName << '(' << "__ice_" << (*q)->name() << ')';
+ }
+
+ C.dec();
+ C << sb;
+ C << eb;
+ }
+}
+
+void
+Slice::Gen::ObjectVisitor::emitUpcall(const ClassDefPtr& base, const string& call)
+{
+ C.zeroIndent();
+ C << nl << "#if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug"; // COMPILERFIX
+ C.restoreIndent();
+ C << nl << (base ? fixKwd(base->name()) : string("Object")) << call;
+ C.zeroIndent();
+ C << nl << "#else";
+ C.restoreIndent();
+ C << nl << (base ? fixKwd(base->scoped()) : string("::Ice::Object")) << call;
+ C.zeroIndent();
+ C << nl << "#endif";
+ C.restoreIndent();
+}
+
+Slice::Gen::AsyncCallbackVisitor::AsyncCallbackVisitor(Output& h, Output& c, const string& dllExport) :
+ H(h), C(c), _dllExport(dllExport), _useWstring(false)
+{
+}
+
+bool
+Slice::Gen::AsyncCallbackVisitor::visitModuleStart(const ModulePtr& p)
+{
+ if(!p->hasNonLocalClassDefs() && !p->hasContentsWithMetaData("async"))
+ {
+ return false;
+ }
+
+ _useWstring = setUseWstring(p, _useWstringHist, _useWstring);
+
+ H << sp << nl << "namespace " << fixKwd(p->name()) << nl << '{';
+
+ return true;
+}
+
+void
+Slice::Gen::AsyncCallbackVisitor::visitModuleEnd(const ModulePtr& p)
+{
+ _useWstring = resetUseWstring(_useWstringHist);
+
+ H << sp << nl << '}';
+}
+
+bool
+Slice::Gen::AsyncCallbackVisitor::visitClassDefStart(const ClassDefPtr& p)
+{
+ _useWstring = setUseWstring(p, _useWstringHist, _useWstring);
+ return true;
+}
+
+void
+Slice::Gen::AsyncCallbackVisitor::visitClassDefEnd(const ClassDefPtr& p)
+{
+ _useWstring = resetUseWstring(_useWstringHist);
+}
+
+void
+Slice::Gen::AsyncCallbackVisitor::visitOperation(const OperationPtr& p)
+{
+ ClassDefPtr cl = ClassDefPtr::dynamicCast(p->container());
+
+ if(cl->isLocal() && !(cl->hasMetaData("async") || p->hasMetaData("async")))
+ {
+ return;
+ }
+
+ //
+ // Write the callback base class and callback smart pointer.
+ //
+ string delName = "Callback_" + cl->name() + "_" + p->name();
+ H << sp << nl << "class " << delName << "_Base : virtual public ::IceInternal::CallbackBase { };";
+ H << nl << "typedef ::IceUtil::Handle< " << delName << "_Base> " << delName << "Ptr;";
+}
+
+Slice::Gen::AsyncCallbackTemplateVisitor::AsyncCallbackTemplateVisitor(Output& h,
+ Output& c,
+ const string& dllExport)
+ : H(h), C(c), _dllExport(dllExport), _useWstring(false)
+{
+}
+
+bool
+Slice::Gen::AsyncCallbackTemplateVisitor::visitUnitStart(const UnitPtr& p)
+{
+ return p->hasNonLocalClassDefs();
+}
+
+void
+Slice::Gen::AsyncCallbackTemplateVisitor::visitUnitEnd(const UnitPtr&)
+{
+}
+
+bool
+Slice::Gen::AsyncCallbackTemplateVisitor::visitModuleStart(const ModulePtr& p)
+{
+ if(!p->hasNonLocalClassDefs())
+ {
+ return false;
+ }
+
+ _useWstring = setUseWstring(p, _useWstringHist, _useWstring);
+
+ H << sp << nl << "namespace " << fixKwd(p->name()) << nl << '{';
+ return true;
+}
+
+void
+Slice::Gen::AsyncCallbackTemplateVisitor::visitModuleEnd(const ModulePtr& p)
+{
+ _useWstring = resetUseWstring(_useWstringHist);
+
+ H << sp << nl << '}';
+}
+
+bool
+Slice::Gen::AsyncCallbackTemplateVisitor::visitClassDefStart(const ClassDefPtr& p)
+{
+ _useWstring = setUseWstring(p, _useWstringHist, _useWstring);
+ return true;
+}
+
+void
+Slice::Gen::AsyncCallbackTemplateVisitor::visitClassDefEnd(const ClassDefPtr& p)
+{
+ _useWstring = resetUseWstring(_useWstringHist);
+}
+
+namespace
+{
+
+bool
+usePrivateEnd(const OperationPtr& p)
+{
+ TypePtr ret = p->returnType();
+ string retSEnd = returnTypeToString(ret, p->getMetaData(), TypeContextAMIEnd);
+ string retSPrivateEnd = returnTypeToString(ret, p->getMetaData(), TypeContextAMIPrivateEnd);
+
+ ParamDeclList outParams;
+ vector<string> outDeclsEnd;
+ vector<string> outDeclsPrivateEnd;
+
+ ParamDeclList paramList = p->parameters();
+ for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q)
+ {
+ if((*q)->isOutParam())
+ {
+ outDeclsEnd.push_back(outputTypeToString((*q)->type(), (*q)->getMetaData(), TypeContextAMIEnd));
+ outDeclsPrivateEnd.push_back(outputTypeToString((*q)->type(), (*q)->getMetaData(), TypeContextAMIPrivateEnd));
+ }
+ }
+
+ return retSEnd != retSPrivateEnd || outDeclsEnd != outDeclsPrivateEnd;
+}
+
+}
+
+void
+Slice::Gen::AsyncCallbackTemplateVisitor::visitOperation(const OperationPtr& p)
+{
+ generateOperation(p, false);
+ generateOperation(p, true);
+}
+
+void
+Slice::Gen::AsyncCallbackTemplateVisitor::generateOperation(const OperationPtr& p, bool withCookie)
+{
+ ClassDefPtr cl = ClassDefPtr::dynamicCast(p->container());
+ if(cl->isLocal() || cl->operations().empty())
+ {
+ return;
+ }
+
+ string clName = cl->name();
+ string clScope = fixKwd(cl->scope());
+ string delName = "Callback_" + clName + "_" + p->name();
+ string delTmplName = (withCookie ? "Callback_" : "CallbackNC_") + clName + "_" + p->name();
+
+ TypePtr ret = p->returnType();
+ string retS = inputTypeToString(ret, p->getMetaData(), _useWstring);
+ string retEndArg = getEndArg(ret, p->getMetaData(), "__ret");
+
+ ParamDeclList outParams;
+ vector<string> outArgs;
+ vector<string> outDecls;
+ vector<string> outDeclsEnd;
+ vector<string> outEndArgs;
+
+ ParamDeclList paramList = p->parameters();
+ for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q)
+ {
+ if((*q)->isOutParam())
+ {
+ outParams.push_back(*q);
+ outArgs.push_back(fixKwd((*q)->name()));
+ outEndArgs.push_back(getEndArg((*q)->type(), (*q)->getMetaData(), outArgs.back()));
+ outDecls.push_back(inputTypeToString((*q)->type(), (*q)->getMetaData(), _useWstring));
+ }
+ }
+
+ string baseD;
+ string inheritD;
+ if(withCookie)
+ {
+ baseD = "::IceInternal::Callback<T, CT>";
+ H << sp << nl << "template<class T, typename CT>";
+ inheritD = p->returnsData() ? "::IceInternal::TwowayCallback<T, CT>" : "::IceInternal::OnewayCallback<T, CT>";
+ }
+ else
+ {
+ baseD = "::IceInternal::CallbackNC<T>";
+ H << sp << nl << "template<class T>";
+ inheritD = p->returnsData() ? "::IceInternal::TwowayCallbackNC<T>" : "::IceInternal::OnewayCallbackNC<T>";
+ }
+
+ H << nl << "class " << delTmplName << " : public " << delName << "_Base, public " << inheritD;
+ H << sb;
+ H.dec();
+ H << nl << "public:";
+ H.inc();
+
+ H << sp << nl << "typedef IceUtil::Handle<T> TPtr;";
+
+ string cookieT;
+ string comCookieT;
+ if(withCookie)
+ {
+ cookieT = "const CT&";
+ comCookieT = " , const CT&";
+ }
+
+ H << sp << nl << "typedef void (T::*Exception)(const ::Ice::Exception&" << comCookieT << ");";
+ H << nl << "typedef void (T::*Sent)(bool" << comCookieT << ");";
+ if(p->returnsData())
+ {
+ //
+ // typedefs for callbacks.
+ //
+ H << nl << "typedef void (T::*Response)" << spar;
+ if(ret)
+ {
+ H << retS;
+ }
+ H << outDecls;
+ if(withCookie)
+ {
+ H << cookieT;
+ }
+ H << epar << ';';
+ }
+ else
+ {
+ H << nl << "typedef void (T::*Response)(" << cookieT << ");";
+ }
+
+ //
+ // constructor.
+ //
+ H << sp;
+ H << nl << delTmplName << spar << "const TPtr& obj";
+ H << "Response cb";
+ H << "Exception excb";
+ H << "Sent sentcb" << epar;
+ H.inc();
+ if(p->returnsData())
+ {
+ H << nl << ": " << inheritD + "(obj, cb != 0, excb, sentcb), response(cb)";
+ }
+ else
+ {
+ H << nl << ": " << inheritD + "(obj, cb, excb, sentcb)";
+ }
+ H.dec();
+ H << sb;
+ H << eb;
+
+ if(p->returnsData())
+ {
+ //
+ // completed.
+ //
+ H << sp << nl << "virtual void __completed(const ::Ice::AsyncResultPtr& __result) const";
+ H << sb;
+ H << nl << clScope << clName << "Prx __proxy = " << clScope << clName
+ << "Prx::uncheckedCast(__result->getProxy());";
+ writeAllocateCode(H, outParams, ret, p->getMetaData(),
+ _useWstring | TypeContextInParam | TypeContextAMICallPrivateEnd);
+ H << nl << "try";
+ H << sb;
+ H << nl;
+ if(!usePrivateEnd(p))
+ {
+ if(ret)
+ {
+ H << retEndArg << " = ";
+ }
+ H << "__proxy->end_" << p->name() << spar << outEndArgs << "__result" << epar << ';';
+ }
+ else
+ {
+ H << "__proxy->___end_" << p->name() << spar << outEndArgs;
+ if(ret)
+ {
+ H << retEndArg;
+ }
+ H << "__result" << epar << ';';
+ }
+ writeEndCode(H, outParams, ret, p->getMetaData());
+ H << eb;
+ H << nl << "catch(::Ice::Exception& ex)";
+ H << sb;
+ H.zeroIndent();
+ H << nl << "#if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug"; // COMPILERFIX
+ H.restoreIndent();
+ H << nl << "__exception(__result, ex);";
+ H.zeroIndent();
+ H << nl << "#else";
+ H.restoreIndent();
+ H << nl << "" << baseD << "::__exception(__result, ex);";
+ H.zeroIndent();
+ H << nl << "#endif";
+ H.restoreIndent();
+ H << nl << "return;";
+ H << eb;
+ H << nl << "if(response)";
+ H << sb;
+ H.zeroIndent();
+ H << nl << "#if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug"; // COMPILERFIX
+ H.restoreIndent();
+ H << nl << "(callback.get()->*response)" << spar;
+ if(ret)
+ {
+ H << "__ret";
+ }
+ H << outArgs;
+ if(withCookie)
+ {
+ H << "CT::dynamicCast(__result->getCookie())";
+ }
+ H << epar << ';';
+ H.zeroIndent();
+ H << nl << "#else";
+ H.restoreIndent();
+ H << nl << "(" << baseD << "::callback.get()->*response)" << spar;
+ if(ret)
+ {
+ H << "__ret";
+ }
+ H << outArgs;
+ if(withCookie)
+ {
+ H << "CT::dynamicCast(__result->getCookie())";
+ }
+ H << epar << ';';
+ H.zeroIndent();
+ H << nl << "#endif";
+ H.restoreIndent();
+ H << eb;
+ H << eb;
+
+ H << sp << nl << "Response response;";
+ }
+ H << eb << ';';
+
+ // Factory method
+ for(int i = 0; i < 2; i++)
+ {
+ string callbackT = i == 0 ? "const IceUtil::Handle<T>&" : "T*";
+
+ if(withCookie)
+ {
+ cookieT = "const CT&";
+ comCookieT = ", const CT&";
+ H << sp << nl << "template<class T, typename CT> " << delName << "Ptr";
+ }
+ else
+ {
+ H << sp << nl << "template<class T> " << delName << "Ptr";
+ }
+
+ H << nl << "new" << delName << "(" << callbackT << " instance, ";
+ if(p->returnsData())
+ {
+ H << "void (T::*cb)" << spar;
+ if(ret)
+ {
+ H << retS;
+ }
+ H << outDecls;
+ if(withCookie)
+ {
+ H << cookieT;
+ }
+ H << epar << ", ";
+ }
+ else
+ {
+ H << "void (T::*cb)(" << cookieT << "), ";
+ }
+ H << "void (T::*excb)(" << "const ::Ice::Exception&" << comCookieT << "), ";
+ H << "void (T::*sentcb)(bool" << comCookieT << ") = 0)";
+ H << sb;
+ if(withCookie)
+ {
+ H << nl << "return new " << delTmplName << "<T, CT>(instance, cb, excb, sentcb);";
+ }
+ else
+ {
+ H << nl << "return new " << delTmplName << "<T>(instance, cb, excb, sentcb);";
+ }
+ H << eb;
+
+ if(!ret && outParams.empty())
+ {
+ if(withCookie)
+ {
+ H << sp << nl << "template<class T, typename CT> " << delName << "Ptr";
+ }
+ else
+ {
+ H << sp << nl << "template<class T> " << delName << "Ptr";
+ }
+ H << nl << "new" << delName << "(" << callbackT << " instance, ";
+ H << "void (T::*excb)(" << "const ::Ice::Exception&" << comCookieT << "), ";
+ H << "void (T::*sentcb)(bool" << comCookieT << ") = 0)";
+ H << sb;
+ if(withCookie)
+ {
+ H << nl << "return new " << delTmplName << "<T, CT>(instance, 0, excb, sentcb);";
+ }
+ else
+ {
+ H << nl << "return new " << delTmplName << "<T>(instance, 0, excb, sentcb);";
+ }
+ H << eb;
+ }
+ }
+}
+
+Slice::Gen::IceInternalVisitor::IceInternalVisitor(Output& h, Output& c, const string& dllExport) :
+ H(h), C(c), _dllExport(dllExport)
+{
+}
+
+bool
+Slice::Gen::IceInternalVisitor::visitUnitStart(const UnitPtr& p)
+{
+ if(!p->hasClassDecls())
+ {
+ return false;
+ }
+
+ H << sp;
+ H << nl << "namespace IceInternal" << nl << '{';
+
+ return true;
+}
+
+void
+Slice::Gen::IceInternalVisitor::visitUnitEnd(const UnitPtr& p)
+{
+ H << sp;
+ H << nl << '}';
+}
+
+void
+Slice::Gen::IceInternalVisitor::visitClassDecl(const ClassDeclPtr& p)
+{
+ string scoped = fixKwd(p->scoped());
+
+ H << sp;
+
+ if(!p->isLocal())
+ {
+ H << nl << _dllExport << "::Ice::Object* upCast(" << scoped << "*);";
+ H << nl << _dllExport << "::IceProxy::Ice::Object* upCast(::IceProxy" << scoped << "*);";
+ }
+ else
+ {
+ H << nl << _dllExport << "::Ice::LocalObject* upCast(" << scoped << "*);";
+ }
+}
+
+bool
+Slice::Gen::IceInternalVisitor::visitClassDefStart(const ClassDefPtr& p)
+{
+ string scoped = fixKwd(p->scoped());
+
+ C << sp;
+ if(!p->isLocal())
+ {
+ C << nl
+ << (_dllExport.empty() ? "" : "ICE_DECLSPEC_EXPORT ")
+ << "::Ice::Object* IceInternal::upCast(" << scoped << "* p) { return p; }";
+ C << nl
+ << (_dllExport.empty() ? "" : "ICE_DECLSPEC_EXPORT ")
+ << "::IceProxy::Ice::Object* IceInternal::upCast(::IceProxy" << scoped
+ << "* p) { return p; }";
+ }
+ else
+ {
+ C << nl
+ << (_dllExport.empty() ? "" : "ICE_DECLSPEC_EXPORT ")
+ << "::Ice::LocalObject* IceInternal::upCast(" << scoped << "* p) { return p; }";
+ }
+
+ return true;
+}
+
+Slice::Gen::HandleVisitor::HandleVisitor(Output& h, Output& c, const string& dllExport, bool stream) :
+ H(h), C(c), _dllExport(dllExport), _stream(stream)
+{
+}
+
+bool
+Slice::Gen::HandleVisitor::visitModuleStart(const ModulePtr& p)
+{
+ if(!p->hasClassDecls())
+ {
+ return false;
+ }
+
+ string name = fixKwd(p->name());
+
+ H << sp;
+ H << nl << "namespace " << name << nl << '{';
+
+ return true;
+}
+
+void
+Slice::Gen::HandleVisitor::visitModuleEnd(const ModulePtr& p)
+{
+ H << sp;
+ H << nl << '}';
+}
+
+void
+Slice::Gen::HandleVisitor::visitClassDecl(const ClassDeclPtr& p)
+{
+ string name = p->name();
+ string scoped = fixKwd(p->scoped());
+
+ H << sp;
+ H << nl << "typedef ::IceInternal::Handle< " << scoped << "> " << name << "Ptr;";
+
+ if(!p->isLocal())
+ {
+ H << nl << "typedef ::IceInternal::ProxyHandle< ::IceProxy" << scoped << "> " << name << "Prx;";
+
+ H << sp;
+ H << nl << _dllExport << "void __read(::IceInternal::BasicStream*, " << name << "Prx&);";
+ H << nl << _dllExport << "void __patch__" << name << "Ptr(void*, ::Ice::ObjectPtr&);";
+ if(_stream)
+ {
+ H << sp;
+ H.zeroIndent();
+ H << nl << "// COMPILERFIX: Stream API is not supported with VC++ 6";
+ H << nl << "#if !defined(_MSC_VER) || (_MSC_VER >= 1300)";
+ H.restoreIndent();
+ H << nl << _dllExport << "ICE_DEPRECATED_API void ice_write" << name << "Prx(const ::Ice::OutputStreamPtr&, const " << name
+ << "Prx&);";
+ H << nl << _dllExport << "ICE_DEPRECATED_API void ice_read" << name << "Prx(const ::Ice::InputStreamPtr&, " << name
+ << "Prx&);";
+
+ H << nl << _dllExport << "ICE_DEPRECATED_API void ice_write" << name << "(const ::Ice::OutputStreamPtr&, const "
+ << name << "Ptr&);";
+ H << nl << _dllExport << "ICE_DEPRECATED_API void ice_read" << name << "(const ::Ice::InputStreamPtr&, " << name << "Ptr&);";
+ H.zeroIndent();
+ H << nl << "#endif";
+ H.restoreIndent();
+ }
+ }
+}
+
+bool
+Slice::Gen::HandleVisitor::visitClassDefStart(const ClassDefPtr& p)
+{
+ if(!p->isLocal())
+ {
+ string name = p->name();
+ string scoped = fixKwd(p->scoped());
+ string scope = fixKwd(p->scope());
+
+ string factory;
+ string type;
+ if(!p->isAbstract())
+ {
+ type = scoped + "::ice_staticId()";
+ factory = scoped + "::ice_factory()";
+ }
+ else
+ {
+ type = "\"\"";
+ factory = "0";
+ }
+
+ C << sp;
+ C << nl << "void" << nl << scope.substr(2) << "__read(::IceInternal::BasicStream* __is, "
+ << scope << name << "Prx& v)";
+ C << sb;
+ C << nl << "::Ice::ObjectPrx proxy;";
+ C << nl << "__is->read(proxy);";
+ C << nl << "if(!proxy)";
+ C << sb;
+ C << nl << "v = 0;";
+ C << eb;
+ C << nl << "else";
+ C << sb;
+ C << nl << "v = new ::IceProxy" << scoped << ';';
+ C << nl << "v->__copyFrom(proxy);";
+ C << eb;
+ C << eb;
+
+ if(_stream)
+ {
+ C << sp;
+ C.zeroIndent();
+ C << nl << "// COMPILERFIX: Stream API is not supported with VC++ 6";
+ C << nl << "#if !defined(_MSC_VER) || (_MSC_VER >= 1300)";
+ C.restoreIndent();
+ C << nl << "void" << nl << scope.substr(2) << "ice_write" << name
+ << "Prx(const ::Ice::OutputStreamPtr& __outS, const " << scope << name << "Prx& v)";
+ C << sb;
+ C << nl << "__outS->write(v);";
+ C << eb;
+
+ C << sp;
+ C << nl << "void" << nl << scope.substr(2) << "ice_read" << name
+ << "Prx(const ::Ice::InputStreamPtr& __inS, " << scope << name << "Prx& v)";
+ C << sb;
+ C << nl << "__inS->read(v);";
+ C << eb;
+
+ C << sp;
+ C << nl << "void" << nl << scope.substr(2) << "ice_write" << name
+ << "(const ::Ice::OutputStreamPtr& __outS, const " << scope << name << "Ptr& v)";
+ C << sb;
+ C << nl << "__outS->writeObject(v);";
+ C << eb;
+
+ C << sp;
+ C << nl << "void" << nl << scope.substr(2) << "ice_read" << name << "(const ::Ice::InputStreamPtr& __inS, "
+ << scope << name << "Ptr& __v)";
+ C << sb;
+ C << nl << "__inS->read(__v);";
+ C << eb;
+ C.zeroIndent();
+ C << nl << "#endif";
+ C.restoreIndent();
+ }
+ }
+
+ return true;
+}
+
+Slice::Gen::ImplVisitor::ImplVisitor(Output& h, Output& c,
+ const string& dllExport) :
+ H(h), C(c), _dllExport(dllExport), _useWstring(false)
+{
+}
+
+void
+Slice::Gen::ImplVisitor::writeDecl(Output& out, const string& name, const TypePtr& type, const StringList& metaData)
+{
+ out << nl << typeToString(type, metaData, _useWstring) << ' ' << name;
+
+ BuiltinPtr builtin = BuiltinPtr::dynamicCast(type);
+ if(builtin)
+ {
+ switch(builtin->kind())
+ {
+ case Builtin::KindBool:
+ {
+ out << " = false";
+ break;
+ }
+ case Builtin::KindByte:
+ case Builtin::KindShort:
+ case Builtin::KindInt:
+ case Builtin::KindLong:
+ {
+ out << " = 0";
+ break;
+ }
+ case Builtin::KindFloat:
+ case Builtin::KindDouble:
+ {
+ out << " = 0.0";
+ break;
+ }
+ case Builtin::KindString:
+ case Builtin::KindObject:
+ case Builtin::KindObjectProxy:
+ case Builtin::KindLocalObject:
+ {
+ break;
+ }
+ }
+ }
+
+ EnumPtr en = EnumPtr::dynamicCast(type);
+ if(en)
+ {
+ EnumeratorList enumerators = en->getEnumerators();
+ out << " = " << fixKwd(en->scope()) << fixKwd(enumerators.front()->name());
+ }
+
+ out << ';';
+}
+
+void
+Slice::Gen::ImplVisitor::writeReturn(Output& out, const TypePtr& type, const StringList& metaData)
+{
+ BuiltinPtr builtin = BuiltinPtr::dynamicCast(type);
+ if(builtin)
+ {
+ switch(builtin->kind())
+ {
+ case Builtin::KindBool:
+ {
+ out << nl << "return false;";
+ break;
+ }
+ case Builtin::KindByte:
+ case Builtin::KindShort:
+ case Builtin::KindInt:
+ case Builtin::KindLong:
+ {
+ out << nl << "return 0;";
+ break;
+ }
+ case Builtin::KindFloat:
+ case Builtin::KindDouble:
+ {
+ out << nl << "return 0.0;";
+ break;
+ }
+ case Builtin::KindString:
+ {
+ out << nl << "return ::std::string();";
+ break;
+ }
+ case Builtin::KindObject:
+ case Builtin::KindObjectProxy:
+ case Builtin::KindLocalObject:
+ {
+ out << nl << "return 0;";
+ break;
+ }
+ }
+ }
+ else
+ {
+ ProxyPtr prx = ProxyPtr::dynamicCast(type);
+ if(prx)
+ {
+ out << nl << "return 0;";
+ }
+ else
+ {
+ ClassDeclPtr cl = ClassDeclPtr::dynamicCast(type);
+ if(cl)
+ {
+ out << nl << "return 0;";
+ }
+ else
+ {
+ StructPtr st = StructPtr::dynamicCast(type);
+ if(st)
+ {
+ out << nl << "return " << fixKwd(st->scoped()) << "();";
+ }
+ else
+ {
+ EnumPtr en = EnumPtr::dynamicCast(type);
+ if(en)
+ {
+ EnumeratorList enumerators = en->getEnumerators();
+ out << nl << "return " << fixKwd(en->scope()) << fixKwd(enumerators.front()->name()) << ';';
+ }
+ else
+ {
+ SequencePtr seq = SequencePtr::dynamicCast(type);
+ if(seq)
+ {
+ out << nl << "return " << typeToString(seq, metaData, _useWstring) << "();";
+ }
+ else
+ {
+ DictionaryPtr dict = DictionaryPtr::dynamicCast(type);
+ assert(dict);
+ out << nl << "return " << fixKwd(dict->scoped()) << "();";
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+bool
+Slice::Gen::ImplVisitor::visitModuleStart(const ModulePtr& p)
+{
+ if(!p->hasClassDefs())
+ {
+ return false;
+ }
+
+ _useWstring = setUseWstring(p, _useWstringHist, _useWstring);
+
+ set<string> includes;
+ ClassList classes = p->classes();
+ for(ClassList::const_iterator q = classes.begin(); q != classes.end(); ++q)
+ {
+ ClassList bases = (*q)->bases();
+ for(ClassList::const_iterator r = bases.begin(); r != bases.end(); ++r)
+ {
+ if((*r)->isAbstract())
+ {
+ includes.insert((*r)->name());
+ }
+ }
+ }
+
+ for(set<string>::const_iterator it = includes.begin(); it != includes.end(); ++it)
+ {
+ H << nl << "#include <" << *it << "I.h>";
+ }
+
+ string name = fixKwd(p->name());
+
+ H << sp << nl << "namespace " << name << nl << '{';
+
+ return true;
+}
+
+void
+Slice::Gen::ImplVisitor::visitModuleEnd(const ModulePtr& p)
+{
+ H << sp;
+ H << nl << '}';
+
+ _useWstring = resetUseWstring(_useWstringHist);
+}
+
+bool
+Slice::Gen::ImplVisitor::visitClassDefStart(const ClassDefPtr& p)
+{
+ if(!p->isAbstract())
+ {
+ return false;
+ }
+
+ _useWstring = setUseWstring(p, _useWstringHist, _useWstring);
+
+ string name = p->name();
+ string scope = fixKwd(p->scope());
+ string cls = scope.substr(2) + name + "I";
+ string classScopedAMD = scope + "AMD_" + name;
+ ClassList bases = p->bases();
+
+ H << sp;
+ H << nl << "class " << name << "I : ";
+ H.useCurrentPosAsIndent();
+ H << "virtual public " << fixKwd(name);
+ for(ClassList::const_iterator q = bases.begin(); q != bases.end(); ++q)
+ {
+ H << ',' << nl << "virtual public " << fixKwd((*q)->scope());
+ if((*q)->isAbstract())
+ {
+ H << (*q)->name() << "I";
+ }
+ else
+ {
+ H << fixKwd((*q)->name());
+ }
+ }
+ H.restoreIndent();
+
+ H << sb;
+ H.dec();
+ H << nl << "public:";
+ H.inc();
+
+ OperationList ops = p->operations();
+ OperationList::const_iterator r;
+
+ for(r = ops.begin(); r != ops.end(); ++r)
+ {
+ OperationPtr op = (*r);
+ string opName = op->name();
+
+ TypePtr ret = op->returnType();
+ string retS = returnTypeToString(ret, op->getMetaData(), _useWstring);
+
+ if(!p->isLocal() && (p->hasMetaData("amd") || op->hasMetaData("amd")))
+ {
+ H << sp << nl << "virtual void " << opName << "_async(";
+ H.useCurrentPosAsIndent();
+ H << "const " << classScopedAMD << '_' << opName << "Ptr&";
+ ParamDeclList paramList = op->parameters();
+ ParamDeclList::const_iterator q;
+ for(q = paramList.begin(); q != paramList.end(); ++q)
+ {
+ if(!(*q)->isOutParam())
+ {
+ H << ',' << nl << inputTypeToString((*q)->type(), (*q)->getMetaData(), _useWstring);
+ }
+ }
+ H << ',' << nl << "const Ice::Current&";
+ H.restoreIndent();
+
+ bool isConst = (op->mode() == Operation::Nonmutating) || op->hasMetaData("cpp:const");
+
+ H << ")" << (isConst ? " const" : "") << ';';
+
+ C << sp << nl << "void" << nl << scope << name << "I::" << opName << "_async(";
+ C.useCurrentPosAsIndent();
+ C << "const " << classScopedAMD << '_' << opName << "Ptr& " << opName << "CB";
+ for(q = paramList.begin(); q != paramList.end(); ++q)
+ {
+ if(!(*q)->isOutParam())
+ {
+ C << ',' << nl << inputTypeToString((*q)->type(), (*q)->getMetaData(), _useWstring) << ' '
+ << fixKwd((*q)->name());
+ }
+ }
+ C << ',' << nl << "const Ice::Current& current";
+ C.restoreIndent();
+ C << ")" << (isConst ? " const" : "");
+ C << sb;
+
+ string result = "r";
+ for(q = paramList.begin(); q != paramList.end(); ++q)
+ {
+ if((*q)->name() == result)
+ {
+ result = "_" + result;
+ break;
+ }
+ }
+ if(ret)
+ {
+ writeDecl(C, result, ret, op->getMetaData());
+ }
+ for(q = paramList.begin(); q != paramList.end(); ++q)
+ {
+ if((*q)->isOutParam())
+ {
+ writeDecl(C, fixKwd((*q)->name()), (*q)->type(), (*q)->getMetaData());
+ }
+ }
+
+ C << nl << opName << "CB->ice_response(";
+ if(ret)
+ {
+ C << result;
+ }
+ for(q = paramList.begin(); q != paramList.end(); ++q)
+ {
+ if((*q)->isOutParam())
+ {
+ if(ret || q != paramList.begin())
+ {
+ C << ", ";
+ }
+ C << fixKwd((*q)->name());
+ }
+ }
+ C << ");";
+
+ C << eb;
+ }
+ else
+ {
+ H << sp << nl << "virtual " << retS << ' ' << fixKwd(opName) << '(';
+ H.useCurrentPosAsIndent();
+ ParamDeclList paramList = op->parameters();
+ ParamDeclList::const_iterator q;
+ for(q = paramList.begin(); q != paramList.end(); ++q)
+ {
+ if(q != paramList.begin())
+ {
+ H << ',' << nl;
+ }
+ StringList metaData = (*q)->getMetaData();
+#if defined(__SUNPRO_CC) && (__SUNPRO_CC==0x550)
+ //
+ // Work around for Sun CC 5.5 bug #4853566
+ //
+ string typeString;
+ if((*q)->isOutParam())
+ {
+ typeString = outputTypeToString((*q)->type(), metaData, _useWstring);
+ }
+ else
+ {
+ typeString = inputTypeToString((*q)->type(), metaData, _useWstring);
+ }
+#else
+ string typeString = (*q)->isOutParam() ? outputTypeToString((*q)->type(), metaData, _useWstring)
+ : inputTypeToString((*q)->type(), metaData, _useWstring);
+#endif
+ H << typeString;
+ }
+ if(!p->isLocal())
+ {
+ if(!paramList.empty())
+ {
+ H << ',' << nl;
+ }
+ H << "const Ice::Current&";
+ }
+ H.restoreIndent();
+
+ bool isConst = (op->mode() == Operation::Nonmutating) || op->hasMetaData("cpp:const");
+
+ H << ")" << (isConst ? " const" : "") << ';';
+
+ C << sp << nl << retS << nl;
+ C << scope.substr(2) << name << "I::" << fixKwd(opName) << '(';
+ C.useCurrentPosAsIndent();
+ for(q = paramList.begin(); q != paramList.end(); ++q)
+ {
+ if(q != paramList.begin())
+ {
+ C << ',' << nl;
+ }
+ StringList metaData = (*q)->getMetaData();
+#if defined(__SUNPRO_CC) && (__SUNPRO_CC==0x550)
+ //
+ // Work around for Sun CC 5.5 bug #4853566
+ //
+ string typeString;
+ if((*q)->isOutParam())
+ {
+ typeString = outputTypeToString((*q)->type(), _useWstring, metaData);
+ }
+ else
+ {
+ typeString = inputTypeToString((*q)->type(), _useWstring, metaData);
+ }
+#else
+ string typeString = (*q)->isOutParam() ? outputTypeToString((*q)->type(), metaData, _useWstring)
+ : inputTypeToString((*q)->type(), metaData, _useWstring);
+#endif
+ C << typeString << ' ' << fixKwd((*q)->name());
+ }
+ if(!p->isLocal())
+ {
+ if(!paramList.empty())
+ {
+ C << ',' << nl;
+ }
+ C << "const Ice::Current& current";
+ }
+ C.restoreIndent();
+ C << ')';
+ C << (isConst ? " const" : "");
+ C << sb;
+
+ if(ret)
+ {
+ writeReturn(C, ret, op->getMetaData());
+ }
+
+ C << eb;
+ }
+ }
+
+ H << eb << ';';
+
+ _useWstring = resetUseWstring(_useWstringHist);
+
+ return true;
+}
+
+Slice::Gen::AsyncVisitor::AsyncVisitor(Output& h, Output& c, const string& dllExport) :
+ H(h), C(c), _dllExport(dllExport), _useWstring(false)
+{
+}
+
+bool
+Slice::Gen::AsyncVisitor::visitModuleStart(const ModulePtr& p)
+{
+ if(!p->hasNonLocalClassDecls() || (!p->hasContentsWithMetaData("ami") && !p->hasContentsWithMetaData("amd")))
+ {
+ return false;
+ }
+
+ _useWstring = setUseWstring(p, _useWstringHist, _useWstring);
+
+ string name = fixKwd(p->name());
+
+ H << sp << nl << "namespace " << name << nl << '{';
+
+ return true;
+}
+
+void
+Slice::Gen::AsyncVisitor::visitModuleEnd(const ModulePtr& p)
+{
+ H << sp << nl << '}';
+
+ _useWstring = resetUseWstring(_useWstringHist);
+}
+
+bool
+Slice::Gen::AsyncVisitor::visitClassDefStart(const ClassDefPtr& p)
+{
+ _useWstring = setUseWstring(p, _useWstringHist, _useWstring);
+ return true;
+}
+
+void
+Slice::Gen::AsyncVisitor::visitClassDefEnd(const ClassDefPtr&)
+{
+ _useWstring = resetUseWstring(_useWstringHist);
+}
+
+void
+Slice::Gen::AsyncVisitor::visitOperation(const OperationPtr& p)
+{
+ ContainerPtr container = p->container();
+ ClassDefPtr cl = ClassDefPtr::dynamicCast(container);
+
+ if(cl->isLocal() ||
+ (!cl->hasMetaData("ami") && !p->hasMetaData("ami") && !cl->hasMetaData("amd") && !p->hasMetaData("amd")))
+ {
+ return;
+ }
+
+ string name = p->name();
+
+ string className = cl->name();
+ string classNameAMI = "AMI_" + className;
+ string classNameAMD = "AMD_" + className;
+ string classScope = fixKwd(cl->scope());
+ string classScopedAMI = classScope + classNameAMI;
+ string classScopedAMD = classScope + classNameAMD;
+ string proxyName = classScope + className + "Prx";
+
+ vector<string> params;
+ vector<string> paramsAMD;
+ vector<string> paramsDecl;
+ vector<string> args;
+
+ vector<string> paramsInvoke;
+ vector<string> paramsDeclInvoke;
+
+ paramsInvoke.push_back("const " + proxyName + "&");
+ paramsDeclInvoke.push_back("const " + proxyName + "& __prx");
+
+ TypePtr ret = p->returnType();
+ string retS = inputTypeToString(ret, p->getMetaData(), _useWstring);
+
+ if(ret)
+ {
+ params.push_back(retS);
+ paramsAMD.push_back(inputTypeToString(ret, p->getMetaData(), _useWstring));
+ paramsDecl.push_back(retS + " __ret");
+ args.push_back("__ret");
+ }
+
+ ParamDeclList inParams;
+ ParamDeclList outParams;
+ ParamDeclList paramList = p->parameters();
+ for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q)
+ {
+ string paramName = fixKwd((*q)->name());
+ TypePtr type = (*q)->type();
+ string typeString = inputTypeToString(type, (*q)->getMetaData(), _useWstring);
+
+ if((*q)->isOutParam())
+ {
+ params.push_back(typeString);
+ paramsAMD.push_back(inputTypeToString(type, (*q)->getMetaData(), _useWstring));
+ paramsDecl.push_back(typeString + ' ' + paramName);
+ args.push_back(paramName);
+
+ outParams.push_back(*q);
+ }
+ else
+ {
+ paramsInvoke.push_back(typeString);
+ paramsDeclInvoke.push_back(typeString + ' ' + paramName);
+
+ inParams.push_back(*q);
+ }
+ }
+
+ paramsInvoke.push_back("const ::Ice::Context*");
+ paramsDeclInvoke.push_back("const ::Ice::Context* __ctx");
+
+ if(cl->hasMetaData("ami") || p->hasMetaData("ami"))
+ {
+ H << sp << nl << "class " << _dllExport << classNameAMI << '_' << name <<" : public ::Ice::AMICallbackBase";
+ H << sb;
+ H.dec();
+ H << nl << "public:";
+ H.inc();
+ H << sp;
+ H << nl << "virtual void ice_response" << spar << params << epar << " = 0;";
+ H << sp;
+ H << nl << "void __response" << spar << paramsDecl << epar;
+ H << sb;
+ H << nl << "ice_response" << spar << args << epar << ';';
+ H << eb;
+ H << nl << "void __exception(const ::Ice::Exception& ex)";
+ H << sb;
+ H << nl << "ice_exception(ex);";
+ H << eb;
+ H << nl << "void __sent(bool sentSynchronously)";
+ H << sb;
+ H.zeroIndent();
+ H << nl << "#if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug"; // COMPILERFIX
+ H.restoreIndent();
+ H << nl << "AMICallbackBase::__sent(sentSynchronously);";
+ H.zeroIndent();
+ H << nl << "#else";
+ H.restoreIndent();
+ H << nl << "::Ice::AMICallbackBase::__sent(sentSynchronously);";
+ H.zeroIndent();
+ H << nl << "#endif";
+ H.restoreIndent();
+ H << eb;
+ H << eb << ';';
+ H << sp << nl << "typedef ::IceUtil::Handle< " << classScopedAMI << '_' << name << "> " << classNameAMI
+ << '_' << name << "Ptr;";
+ }
+
+ if(cl->hasMetaData("amd") || p->hasMetaData("amd"))
+ {
+ H << sp << nl << "class " << _dllExport << classNameAMD << '_' << name
+ << " : virtual public ::Ice::AMDCallback";
+ H << sb;
+ H.dec();
+ H << nl << "public:";
+ H.inc();
+ H << sp;
+ H << nl << "virtual void ice_response" << spar << paramsAMD << epar << " = 0;";
+ H << eb << ';';
+ H << sp << nl << "typedef ::IceUtil::Handle< " << classScopedAMD << '_' << name << "> "
+ << classNameAMD << '_' << name << "Ptr;";
+ }
+}
+
+Slice::Gen::AsyncImplVisitor::AsyncImplVisitor(Output& h, Output& c, const string& dllExport) :
+ H(h), C(c), _dllExport(dllExport), _useWstring(false)
+{
+}
+
+bool
+Slice::Gen::AsyncImplVisitor::visitUnitStart(const UnitPtr& p)
+{
+ if(!p->hasNonLocalClassDecls() || !p->hasContentsWithMetaData("amd"))
+ {
+ return false;
+ }
+
+ H << sp << nl << "namespace IceAsync" << nl << '{';
+
+ return true;
+}
+
+void
+Slice::Gen::AsyncImplVisitor::visitUnitEnd(const UnitPtr& p)
+{
+ H << sp << nl << '}';
+}
+
+bool
+Slice::Gen::AsyncImplVisitor::visitModuleStart(const ModulePtr& p)
+{
+ if(!p->hasNonLocalClassDecls() || !p->hasContentsWithMetaData("amd"))
+ {
+ return false;
+ }
+
+ _useWstring = setUseWstring(p, _useWstringHist, _useWstring);
+
+ string name = fixKwd(p->name());
+
+ H << sp << nl << "namespace " << name << nl << '{';
+
+ return true;
+}
+
+void
+Slice::Gen::AsyncImplVisitor::visitModuleEnd(const ModulePtr& p)
+{
+ H << sp << nl << '}';
+
+ _useWstring = resetUseWstring(_useWstringHist);
+}
+
+bool
+Slice::Gen::AsyncImplVisitor::visitClassDefStart(const ClassDefPtr& p)
+{
+ _useWstring = setUseWstring(p, _useWstringHist, _useWstring);
+ return true;
+}
+
+void
+Slice::Gen::AsyncImplVisitor::visitClassDefEnd(const ClassDefPtr&)
+{
+ _useWstring = resetUseWstring(_useWstringHist);
+}
+
+void
+Slice::Gen::AsyncImplVisitor::visitOperation(const OperationPtr& p)
+{
+ ContainerPtr container = p->container();
+ ClassDefPtr cl = ClassDefPtr::dynamicCast(container);
+
+ if(cl->isLocal() || (!cl->hasMetaData("amd") && !p->hasMetaData("amd")))
+ {
+ return;
+ }
+
+ string name = p->name();
+
+ string classNameAMD = "AMD_" + cl->name();
+ string classScope = fixKwd(cl->scope());
+ string classScopedAMD = classScope + classNameAMD;
+
+ string params;
+ string paramsDecl;
+ string args;
+
+ ExceptionList throws = p->throws();
+ throws.sort();
+ throws.unique();
+
+ //
+ // Arrange exceptions into most-derived to least-derived order. If we don't
+ // do this, a base exception handler can appear before a derived exception
+ // handler, causing compiler warnings and resulting in the base exception
+ // being marshaled instead of the derived exception.
+ //
+#if defined(__SUNPRO_CC)
+ throws.sort(derivedToBaseCompare);
+#else
+ throws.sort(Slice::DerivedToBaseCompare());
+#endif
+
+ TypePtr ret = p->returnType();
+ string retS = inputTypeToString(ret, p->getMetaData(), _useWstring);
+
+ if(ret)
+ {
+ params += retS;
+ paramsDecl += retS;
+ paramsDecl += ' ';
+ paramsDecl += "__ret";
+ args += "__ret";
+ }
+
+ ParamDeclList outParams;
+ ParamDeclList paramList = p->parameters();
+ for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q)
+ {
+ if((*q)->isOutParam())
+ {
+ string paramName = fixKwd((*q)->name());
+ TypePtr type = (*q)->type();
+ string typeString = inputTypeToString(type, (*q)->getMetaData(), _useWstring);
+
+ if(ret || !outParams.empty())
+ {
+ params += ", ";
+ paramsDecl += ", ";
+ args += ", ";
+ }
+
+ params += typeString;
+ paramsDecl += typeString;
+ paramsDecl += ' ';
+ paramsDecl += paramName;
+ args += paramName;
+
+ outParams.push_back(*q);
+ }
+ }
+
+ H << sp << nl << "class " << _dllExport << classNameAMD << '_' << name
+ << " : public " << classScopedAMD << '_' << name << ", public ::IceInternal::IncomingAsync";
+ H << sb;
+ H.dec();
+ H << nl << "public:";
+ H.inc();
+
+ H << sp;
+ H << nl << classNameAMD << '_' << name << "(::IceInternal::Incoming&);";
+
+ H << sp;
+ H << nl << "virtual void ice_response(" << params << ");";
+ if(!throws.empty())
+ {
+ H << nl << "virtual void ice_exception(const ::std::exception&);";
+
+ H.zeroIndent();
+ H << nl << "#if defined(__BCPLUSPLUS__)";
+ H.restoreIndent();
+ H << nl << "// COMPILERFIX: Avoid compiler warnings with C++Builder 2010";
+ H << nl << "virtual void ice_exception()";
+ H << sb;
+ H << nl << "::IceInternal::IncomingAsync::ice_exception();";
+ H << eb;
+ H.zeroIndent();
+ H << nl << "#endif";
+ H.restoreIndent();
+ }
+ H << eb << ';';
+
+ C << sp << nl << "IceAsync" << classScopedAMD << '_' << name << "::" << classNameAMD << '_' << name
+ << "(::IceInternal::Incoming& in) :";
+ C.inc();
+ C << nl << "::IceInternal::IncomingAsync(in)";
+ C.dec();
+ C << sb;
+ C << eb;
+
+ C << sp << nl << "void" << nl << "IceAsync" << classScopedAMD << '_' << name << "::ice_response("
+ << paramsDecl << ')';
+ C << sb;
+ C << nl << "if(__validateResponse(true))";
+ C << sb;
+ if(ret || !outParams.empty())
+ {
+ C << nl << "try";
+ C << sb;
+ C << nl << "::IceInternal::BasicStream* __os = this->__os();";
+ writeMarshalCode(C, outParams, 0, StringList(), true);
+ if(ret)
+ {
+ writeMarshalUnmarshalCode(C, ret, "__ret", true, "", true, p->getMetaData(), true);
+ }
+ if(p->returnsClasses())
+ {
+ C << nl << "__os->writePendingObjects();";
+ }
+ C << eb;
+ C << nl << "catch(const ::Ice::Exception& __ex)";
+ C << sb;
+ C << nl << "__exception(__ex);";
+ C << nl << "return;";
+ C << eb;
+ }
+ C << nl << "__response(true);";
+ C << eb;
+ C << eb;
+
+ if(!throws.empty())
+ {
+ C << sp << nl << "void" << nl << "IceAsync" << classScopedAMD << '_' << name
+ << "::ice_exception(const ::std::exception& ex)";
+ C << sb;
+ ExceptionList::const_iterator r;
+ for(r = throws.begin(); r != throws.end(); ++r)
+ {
+ C << nl;
+ if(r != throws.begin())
+ {
+ C << "else ";
+ }
+ C << "if(const " << fixKwd((*r)->scoped()) << "* __ex = dynamic_cast<const " << fixKwd((*r)->scoped())
+ << "*>(&ex))";
+ C << sb;
+ C << nl <<"if(__validateResponse(false))";
+ C << sb;
+ C << nl << "__os()->write(*__ex);";
+ C << nl << "__response(false);";
+ C << eb;
+ C << eb;
+ }
+ C << nl << "else";
+ C << sb;
+ C.zeroIndent();
+ C << nl << "#if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug"; // COMPILERFIX
+ C.restoreIndent();
+ C << nl << "IncomingAsync::ice_exception(ex);";
+ C.zeroIndent();
+ C << nl << "#else";
+ C.restoreIndent();
+ C << nl << "::IceInternal::IncomingAsync::ice_exception(ex);";
+ C.zeroIndent();
+ C << nl << "#endif";
+ C.restoreIndent();
+ C << eb;
+ C << eb;
+ }
+}
+
+Slice::Gen::StreamVisitor::StreamVisitor(Output& h, Output& c) :
+ H(h), C(c)
+{
+
+}
+
+bool
+Slice::Gen::StreamVisitor::visitModuleStart(const ModulePtr& m)
+{
+ if(!m->hasNonLocalContained(Contained::ContainedTypeStruct) &&
+ !m->hasNonLocalContained(Contained::ContainedTypeEnum) &&
+ !m->hasNonLocalContained(Contained::ContainedTypeException))
+ {
+ return false;
+ }
+
+ if(UnitPtr::dynamicCast(m->container()))
+ {
+ //
+ // Only emit this for the top-level module.
+ //
+ H << sp;
+ H.zeroIndent();
+ H << nl << "#if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug"; // COMPILERFIX
+ H << nl << "#else";
+ H.restoreIndent();
+ H << nl << "namespace Ice" << nl << '{';
+ }
+
+ return true;
+}
+
+void
+Slice::Gen::StreamVisitor::visitModuleEnd(const ModulePtr& m)
+{
+ if(UnitPtr::dynamicCast(m->container()))
+ {
+ //
+ // Only emit this for the top-level module.
+ //
+ H << nl << '}';
+ H.zeroIndent();
+ H << nl << "#endif";
+ H.restoreIndent();
+ }
+}
+
+bool
+Slice::Gen::StreamVisitor::visitExceptionStart(const ExceptionPtr& p)
+{
+ if(!p->isLocal())
+ {
+ string scoped = p->scoped();
+ H << nl << "template<>";
+ H << nl << "struct StreamTrait< " << fixKwd(scoped) << ">";
+ H << sb;
+ H << nl << "static const ::Ice::StreamTraitType type = ::Ice::StreamTraitTypeUserException;";
+ H << eb << ";" << nl;
+ }
+ return false;
+}
+
+bool
+Slice::Gen::StreamVisitor::visitStructStart(const StructPtr& p)
+{
+ if(!p->isLocal())
+ {
+ bool classMetaData = findMetaData(p->getMetaData(), false) == "class";
+ string scoped = p->scoped();
+ H << nl << "template<>";
+ if(classMetaData)
+ {
+ H << nl << "struct StreamTrait< " << fixKwd(scoped + "Ptr") << ">";
+ }
+ else
+ {
+ H << nl << "struct StreamTrait< " << fixKwd(scoped) << ">";
+ }
+ H << sb;
+ if(classMetaData)
+ {
+ H << nl << "static const ::Ice::StreamTraitType type = ::Ice::StreamTraitTypeStructClass;";
+ }
+ else
+ {
+ H << nl << "static const ::Ice::StreamTraitType type = ::Ice::StreamTraitTypeStruct;";
+ }
+ H << nl << "static const int minWireSize = " << p->minWireSize() << ";";
+ H << eb << ";" << nl;
+ }
+ return false;
+}
+
+void
+Slice::Gen::StreamVisitor::visitEnum(const EnumPtr& p)
+{
+ string scoped = fixKwd(p->scoped());
+ H << nl << "template<>";
+ H << nl << "struct StreamTrait< " << scoped << ">";
+ H << sb;
+ H << nl << "static const ::Ice::StreamTraitType type = ";
+ size_t sz = p->getEnumerators().size();
+ if(sz <= 127)
+ {
+ H << "::Ice::StreamTraitTypeByteEnum;";
+ }
+ else if(sz <= 32767)
+ {
+ H << "::Ice::StreamTraitTypeShortEnum;";
+ }
+ else
+ {
+ H << "::Ice::StreamTraitTypeIntEnum;";
+ }
+ H << nl << "static const int enumLimit = " << sz << ";";
+ H << nl << "static const int minWireSize = " << p->minWireSize() << ";";
+ H << eb << ";" << nl;
+}
+
+void
+Slice::Gen::validateMetaData(const UnitPtr& u)
+{
+ MetaDataVisitor visitor;
+ u->visit(&visitor, false);
+}
+
+bool
+Slice::Gen::MetaDataVisitor::visitUnitStart(const UnitPtr& p)
+{
+ static const string prefix = "cpp:";
+
+ //
+ // Validate global metadata in the top-level file and all included files.
+ //
+ StringList files = p->allFiles();
+
+ for(StringList::iterator q = files.begin(); q != files.end(); ++q)
+ {
+ string file = *q;
+ DefinitionContextPtr dc = p->findDefinitionContext(file);
+ assert(dc);
+ StringList globalMetaData = dc->getMetaData();
+ int headerExtension = 0;
+ for(StringList::const_iterator r = globalMetaData.begin(); r != globalMetaData.end(); ++r)
+ {
+ string s = *r;
+ if(_history.count(s) == 0)
+ {
+ if(s.find(prefix) == 0)
+ {
+ static const string cppIncludePrefix = "cpp:include:";
+ static const string cppHeaderExtPrefix = "cpp:header-ext:";
+ if(s.find(cppIncludePrefix) == 0 && s.size() > cppIncludePrefix.size())
+ {
+ continue;
+ }
+ else if(s.find(cppHeaderExtPrefix) == 0 && s.size() > cppHeaderExtPrefix.size())
+ {
+ headerExtension++;
+ if(headerExtension > 1)
+ {
+ ostringstream ostr;
+ ostr << "ignoring invalid global metadata `" << s
+ << "': directive can appear only once per file";
+ emitWarning(file, -1, ostr.str());
+ _history.insert(s);
+ }
+ continue;
+ }
+ ostringstream ostr;
+ ostr << "ignoring invalid global metadata `" << s << "'";
+ emitWarning(file, -1, ostr.str());
+ }
+ _history.insert(s);
+ }
+ }
+ }
+
+ return true;
+}
+
+bool
+Slice::Gen::MetaDataVisitor::visitModuleStart(const ModulePtr& p)
+{
+ validate(p, p->getMetaData(), p->file(), p->line());
+ return true;
+}
+
+void
+Slice::Gen::MetaDataVisitor::visitModuleEnd(const ModulePtr&)
+{
+}
+
+void
+Slice::Gen::MetaDataVisitor::visitClassDecl(const ClassDeclPtr& p)
+{
+ validate(p, p->getMetaData(), p->file(), p->line());
+}
+
+bool
+Slice::Gen::MetaDataVisitor::visitClassDefStart(const ClassDefPtr& p)
+{
+ validate(p, p->getMetaData(), p->file(), p->line());
+ return true;
+}
+
+void
+Slice::Gen::MetaDataVisitor::visitClassDefEnd(const ClassDefPtr&)
+{
+}
+
+bool
+Slice::Gen::MetaDataVisitor::visitExceptionStart(const ExceptionPtr& p)
+{
+ validate(p, p->getMetaData(), p->file(), p->line());
+ return true;
+}
+
+void
+Slice::Gen::MetaDataVisitor::visitExceptionEnd(const ExceptionPtr&)
+{
+}
+
+bool
+Slice::Gen::MetaDataVisitor::visitStructStart(const StructPtr& p)
+{
+ validate(p, p->getMetaData(), p->file(), p->line());
+ return true;
+}
+
+void
+Slice::Gen::MetaDataVisitor::visitStructEnd(const StructPtr&)
+{
+}
+
+void
+Slice::Gen::MetaDataVisitor::visitOperation(const OperationPtr& p)
+{
+
+ bool ami = false;
+ ClassDefPtr cl = ClassDefPtr::dynamicCast(p->container());
+ if(cl->hasMetaData("ami") || p->hasMetaData("ami") || cl->hasMetaData("amd") || p->hasMetaData("amd"))
+ {
+ ami = true;
+ }
+
+ if(p->hasMetaData("UserException"))
+ {
+ if(!cl->isLocal())
+ {
+ ostringstream ostr;
+ ostr << "ignoring invalid metadata `UserException': directive applies only to local operations "
+ << "but enclosing " << (cl->isInterface() ? "interface" : "class") << "`" << cl->name()
+ << "' is not local";
+ emitWarning(p->file(), p->line(), ostr.str());
+ }
+ }
+
+ StringList metaData = p->getMetaData();
+ metaData.remove("cpp:const");
+
+ TypePtr returnType = p->returnType();
+ if(!metaData.empty())
+ {
+ if(!returnType)
+ {
+ for(StringList::const_iterator q = metaData.begin(); q != metaData.end(); ++q)
+ {
+ if(q->find("cpp:type:", 0) == 0 || q->find("cpp:array", 0) == 0 || q->find("cpp:range", 0) == 0)
+ {
+ emitWarning(p->file(), p->line(), "ignoring invalid metadata `" + *q +
+ "' for operation with void return type");
+ break;
+ }
+ }
+ }
+ else
+ {
+ validate(returnType, metaData, p->file(), p->line(), ami);
+ }
+ }
+
+ ParamDeclList params = p->parameters();
+ for(ParamDeclList::iterator q = params.begin(); q != params.end(); ++q)
+ {
+ validate((*q)->type(), (*q)->getMetaData(), p->file(), (*q)->line(), ami || !(*q)->isOutParam());
+ }
+}
+
+void
+Slice::Gen::MetaDataVisitor::visitDataMember(const DataMemberPtr& p)
+{
+ validate(p->type(), p->getMetaData(), p->file(), p->line());
+}
+
+void
+Slice::Gen::MetaDataVisitor::visitSequence(const SequencePtr& p)
+{
+ StringList metaData = p->getMetaData();
+ const string file = p->file();
+ const string line = p->line();
+ static const string prefix = "cpp:protobuf";
+ for(StringList::const_iterator q = metaData.begin(); q != metaData.end(); )
+ {
+ string s = *q++;
+ if(_history.count(s) == 0)
+ {
+ if(s.find(prefix) == 0)
+ {
+ //
+ // Remove from list so validate does not try to handle as well.
+ //
+ metaData.remove(s);
+
+ BuiltinPtr builtin = BuiltinPtr::dynamicCast(p->type());
+ if(!builtin || builtin->kind() != Builtin::KindByte)
+ {
+ _history.insert(s);
+ emitWarning(file, line, "ignoring invalid metadata `" + s + "':\n"+
+ "`protobuf' encoding must be a byte sequence.");
+ }
+ }
+ }
+ }
+
+ validate(p, metaData, file, line);
+}
+
+void
+Slice::Gen::MetaDataVisitor::visitDictionary(const DictionaryPtr& p)
+{
+ validate(p, p->getMetaData(), p->file(), p->line());
+}
+
+void
+Slice::Gen::MetaDataVisitor::visitEnum(const EnumPtr& p)
+{
+ validate(p, p->getMetaData(), p->file(), p->line());
+}
+
+void
+Slice::Gen::MetaDataVisitor::visitConst(const ConstPtr& p)
+{
+ validate(p, p->getMetaData(), p->file(), p->line());
+}
+
+void
+Slice::Gen::MetaDataVisitor::validate(const SyntaxTreeBasePtr& cont, const StringList& metaData,
+ const string& file, const string& line, bool inParam)
+{
+ static const string prefix = "cpp:";
+ for(StringList::const_iterator p = metaData.begin(); p != metaData.end(); ++p)
+ {
+ string s = *p;
+ if(_history.count(s) == 0)
+ {
+ if(s.find(prefix) == 0)
+ {
+ string ss = s.substr(prefix.size());
+ if(ss.find("type:wstring") == 0 || ss.find("type:string") == 0)
+ {
+ BuiltinPtr builtin = BuiltinPtr::dynamicCast(cont);
+ ModulePtr module = ModulePtr::dynamicCast(cont);
+ ClassDefPtr clss = ClassDefPtr::dynamicCast(cont);
+ StructPtr strct = StructPtr::dynamicCast(cont);
+ ExceptionPtr exception = ExceptionPtr::dynamicCast(cont);
+ if((builtin && builtin->kind() == Builtin::KindString) || module || clss || strct || exception)
+ {
+ continue;
+ }
+ }
+ if(SequencePtr::dynamicCast(cont))
+ {
+ if(ss.find("type:") == 0 || ss == "array" || ss.find("range") == 0)
+ {
+ continue;
+ }
+ }
+ if(StructPtr::dynamicCast(cont) && ss.find("class") == 0)
+ {
+ continue;
+ }
+ if(ClassDefPtr::dynamicCast(cont) && ss.find("virtual") == 0)
+ {
+ continue;
+ }
+ emitWarning(file, line, "ignoring invalid metadata `" + s + "'");
+ }
+ _history.insert(s);
+ }
+ }
+}
+
+int
+Slice::Gen::setUseWstring(ContainedPtr p, list<int>& hist, int use)
+{
+ hist.push_back(use);
+ StringList metaData = p->getMetaData();
+ if(find(metaData.begin(), metaData.end(), "cpp:type:wstring") != metaData.end())
+ {
+ use = TypeContextUseWstring;
+ }
+ else if(find(metaData.begin(), metaData.end(), "cpp:type:string") != metaData.end())
+ {
+ use = 0;
+ }
+ return use;
+}
+
+int
+Slice::Gen::resetUseWstring(list<int>& hist)
+{
+ int use = hist.back();
+ hist.pop_back();
+ return use;
+}
+
+string
+Slice::Gen::getHeaderExt(const string& file, const UnitPtr& unit)
+{
+ string ext;
+ static const string headerExtPrefix = "cpp:header-ext:";
+ DefinitionContextPtr dc = unit->findDefinitionContext(file);
+ assert(dc);
+ string meta = dc->findMetaData(headerExtPrefix);
+ if(meta.size() > headerExtPrefix.size())
+ {
+ ext = meta.substr(headerExtPrefix.size());
+ }
+ return ext;
+}
diff --git a/cpp/src/slice2cpp/Gen.h b/cpp/src/slice2cpp/Gen.h
new file mode 100644
index 00000000000..c9fda07af43
--- /dev/null
+++ b/cpp/src/slice2cpp/Gen.h
@@ -0,0 +1,493 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+#ifndef GEN_H
+#define GEN_H
+
+#include <Slice/Parser.h>
+#include <IceUtil/OutputUtil.h>
+
+namespace Slice
+{
+
+class Gen : private ::IceUtil::noncopyable
+{
+public:
+
+ Gen(const std::string&,
+ const std::string&,
+ const std::string&,
+ const std::vector<std::string>&,
+ const std::string&,
+ const std::vector<std::string>&,
+ const std::string&,
+ const std::string&,
+ bool,
+ bool,
+ bool,
+ bool);
+ ~Gen();
+
+ void generate(const UnitPtr&);
+ void closeOutput();
+
+ static int setUseWstring(ContainedPtr, std::list<int>&, int);
+ static int resetUseWstring(std::list<int>&);
+
+private:
+
+ void writeExtraHeaders(::IceUtilInternal::Output&);
+
+
+ //
+ // Returns the header extension defined in the global metadata for a given file,
+ // or an empty string if no global metadata was found.
+ //
+ std::string getHeaderExt(const std::string& file, const UnitPtr& unit);
+
+ ::IceUtilInternal::Output H;
+ ::IceUtilInternal::Output C;
+
+ ::IceUtilInternal::Output implH;
+ ::IceUtilInternal::Output implC;
+
+ std::string _base;
+ std::string _headerExtension;
+ std::string _implHeaderExtension;
+ std::string _sourceExtension;
+ std::vector<std::string> _extraHeaders;
+ std::string _include;
+ std::vector<std::string> _includePaths;
+ std::string _dllExport;
+ std::string _dir;
+ bool _impl;
+ bool _checksum;
+ bool _stream;
+ bool _ice;
+
+ class TypesVisitor : private ::IceUtil::noncopyable, public ParserVisitor
+ {
+ public:
+
+ TypesVisitor(::IceUtilInternal::Output&, ::IceUtilInternal::Output&, const std::string&, bool);
+
+ virtual bool visitModuleStart(const ModulePtr&);
+ virtual void visitModuleEnd(const ModulePtr&);
+ virtual bool visitClassDefStart(const ClassDefPtr&);
+ virtual bool visitExceptionStart(const ExceptionPtr&);
+ virtual void visitExceptionEnd(const ExceptionPtr&);
+ virtual bool visitStructStart(const StructPtr&);
+ virtual void visitStructEnd(const StructPtr&);
+ virtual void visitSequence(const SequencePtr&);
+ virtual void visitDictionary(const DictionaryPtr&);
+ virtual void visitEnum(const EnumPtr&);
+ virtual void visitConst(const ConstPtr&);
+ virtual void visitDataMember(const DataMemberPtr&);
+
+ private:
+
+ void emitUpcall(const ExceptionPtr&, const std::string&, bool = false);
+
+ ::IceUtilInternal::Output& H;
+ ::IceUtilInternal::Output& C;
+
+ std::string _dllExport;
+ bool _stream;
+ bool _doneStaticSymbol;
+ int _useWstring;
+ std::list<int> _useWstringHist;
+ };
+
+ class ProxyDeclVisitor : private ::IceUtil::noncopyable, public ParserVisitor
+ {
+ public:
+
+ ProxyDeclVisitor(::IceUtilInternal::Output&, ::IceUtilInternal::Output&, const std::string&);
+
+ virtual bool visitUnitStart(const UnitPtr&);
+ virtual void visitUnitEnd(const UnitPtr&);
+ virtual bool visitModuleStart(const ModulePtr&);
+ virtual void visitModuleEnd(const ModulePtr&);
+ virtual void visitClassDecl(const ClassDeclPtr&);
+
+ private:
+
+ ::IceUtilInternal::Output& H;
+ ::IceUtilInternal::Output& C;
+
+ std::string _dllExport;
+ };
+
+ class ProxyVisitor : private ::IceUtil::noncopyable, public ParserVisitor
+ {
+ public:
+
+ ProxyVisitor(::IceUtilInternal::Output&, ::IceUtilInternal::Output&, const std::string&);
+
+ virtual bool visitUnitStart(const UnitPtr&);
+ virtual void visitUnitEnd(const UnitPtr&);
+ virtual bool visitModuleStart(const ModulePtr&);
+ virtual void visitModuleEnd(const ModulePtr&);
+ virtual bool visitClassDefStart(const ClassDefPtr&);
+ virtual void visitClassDefEnd(const ClassDefPtr&);
+ virtual void visitOperation(const OperationPtr&);
+
+ private:
+
+ ::IceUtilInternal::Output& H;
+ ::IceUtilInternal::Output& C;
+
+ std::string _dllExport;
+ int _useWstring;
+ std::list<int> _useWstringHist;
+ };
+
+ class DelegateVisitor : private ::IceUtil::noncopyable, public ParserVisitor
+ {
+ public:
+
+ DelegateVisitor(::IceUtilInternal::Output&, ::IceUtilInternal::Output&, const std::string&);
+
+ virtual bool visitUnitStart(const UnitPtr&);
+ virtual void visitUnitEnd(const UnitPtr&);
+ virtual bool visitModuleStart(const ModulePtr&);
+ virtual void visitModuleEnd(const ModulePtr&);
+ virtual bool visitClassDefStart(const ClassDefPtr&);
+ virtual void visitClassDefEnd(const ClassDefPtr&);
+ virtual void visitOperation(const OperationPtr&);
+
+ private:
+
+ ::IceUtilInternal::Output& H;
+ ::IceUtilInternal::Output& C;
+
+ std::string _dllExport;
+ int _useWstring;
+ std::list<int> _useWstringHist;
+ };
+
+ class DelegateMVisitor : private ::IceUtil::noncopyable, public ParserVisitor
+ {
+ public:
+
+ DelegateMVisitor(::IceUtilInternal::Output&, ::IceUtilInternal::Output&, const std::string&);
+
+ virtual bool visitUnitStart(const UnitPtr&);
+ virtual void visitUnitEnd(const UnitPtr&);
+ virtual bool visitModuleStart(const ModulePtr&);
+ virtual void visitModuleEnd(const ModulePtr&);
+ virtual bool visitClassDefStart(const ClassDefPtr&);
+ virtual void visitClassDefEnd(const ClassDefPtr&);
+ virtual void visitOperation(const OperationPtr&);
+
+ private:
+
+ ::IceUtilInternal::Output& H;
+ ::IceUtilInternal::Output& C;
+
+ std::string _dllExport;
+ int _useWstring;
+ std::list<int> _useWstringHist;
+ };
+
+ class DelegateDVisitor : private ::IceUtil::noncopyable, public ParserVisitor
+ {
+ public:
+
+ DelegateDVisitor(::IceUtilInternal::Output&, ::IceUtilInternal::Output&, const std::string&);
+
+ virtual bool visitUnitStart(const UnitPtr&);
+ virtual void visitUnitEnd(const UnitPtr&);
+ virtual bool visitModuleStart(const ModulePtr&);
+ virtual void visitModuleEnd(const ModulePtr&);
+ virtual bool visitClassDefStart(const ClassDefPtr&);
+ virtual void visitClassDefEnd(const ClassDefPtr&);
+ virtual void visitOperation(const OperationPtr&);
+
+ private:
+
+ ::IceUtilInternal::Output& H;
+ ::IceUtilInternal::Output& C;
+
+ std::string _dllExport;
+ int _useWstring;
+ std::list<int> _useWstringHist;
+ };
+
+ class ObjectDeclVisitor : private ::IceUtil::noncopyable, public ParserVisitor
+ {
+ public:
+
+ ObjectDeclVisitor(::IceUtilInternal::Output&, ::IceUtilInternal::Output&, const std::string&);
+
+ virtual bool visitModuleStart(const ModulePtr&);
+ virtual void visitModuleEnd(const ModulePtr&);
+ virtual void visitClassDecl(const ClassDeclPtr&);
+ virtual void visitOperation(const OperationPtr&);
+
+ private:
+
+ ::IceUtilInternal::Output& H;
+ ::IceUtilInternal::Output& C;
+
+ std::string _dllExport;
+ };
+
+ class ObjectVisitor : private ::IceUtil::noncopyable, public ParserVisitor
+ {
+ public:
+
+ ObjectVisitor(::IceUtilInternal::Output&, ::IceUtilInternal::Output&, const std::string&, bool);
+
+ virtual bool visitModuleStart(const ModulePtr&);
+ virtual void visitModuleEnd(const ModulePtr&);
+ virtual bool visitClassDefStart(const ClassDefPtr&);
+ virtual void visitClassDefEnd(const ClassDefPtr&);
+ virtual bool visitExceptionStart(const ExceptionPtr&);
+ virtual bool visitStructStart(const StructPtr&);
+ virtual void visitOperation(const OperationPtr&);
+
+ private:
+
+ void emitGCFunctions(const ClassDefPtr&);
+ void emitGCInsertCode(const TypePtr&, const std::string&, const std::string&, int);
+ void emitGCClearCode(const TypePtr&, const std::string&, const std::string&, int);
+ bool emitVirtualBaseInitializers(const ClassDefPtr&, bool virtualInheritance);
+ void emitOneShotConstructor(const ClassDefPtr&);
+ void emitUpcall(const ClassDefPtr&, const std::string&);
+
+ ::IceUtilInternal::Output& H;
+ ::IceUtilInternal::Output& C;
+
+ std::string _dllExport;
+ bool _stream;
+ bool _doneStaticSymbol;
+ int _useWstring;
+ std::list<int> _useWstringHist;
+ };
+
+ class AsyncCallbackVisitor : private ::IceUtil::noncopyable, public ParserVisitor
+ {
+ public:
+
+ AsyncCallbackVisitor(::IceUtilInternal::Output&, ::IceUtilInternal::Output&, const std::string&);
+
+ virtual bool visitModuleStart(const ModulePtr&);
+ virtual void visitModuleEnd(const ModulePtr&);
+ virtual bool visitClassDefStart(const ClassDefPtr&);
+ virtual void visitClassDefEnd(const ClassDefPtr&);
+ virtual void visitOperation(const OperationPtr&);
+
+ private:
+
+ ::IceUtilInternal::Output& H;
+ ::IceUtilInternal::Output& C;
+
+ std::string _dllExport;
+ int _useWstring;
+ std::list<int> _useWstringHist;
+ };
+
+ class AsyncCallbackTemplateVisitor : private ::IceUtil::noncopyable, public ParserVisitor
+ {
+ public:
+
+ AsyncCallbackTemplateVisitor(::IceUtilInternal::Output&, ::IceUtilInternal::Output&, const std::string&);
+
+ virtual bool visitUnitStart(const UnitPtr&);
+ virtual void visitUnitEnd(const UnitPtr&);
+ virtual bool visitModuleStart(const ModulePtr&);
+ virtual void visitModuleEnd(const ModulePtr&);
+ virtual bool visitClassDefStart(const ClassDefPtr&);
+ virtual void visitClassDefEnd(const ClassDefPtr&);
+ virtual void visitOperation(const OperationPtr&);
+
+ private:
+
+ void generateOperation(const OperationPtr&, bool);
+
+ ::IceUtilInternal::Output& H;
+ ::IceUtilInternal::Output& C;
+
+ std::string _dllExport;
+ int _useWstring;
+ std::list<int> _useWstringHist;
+ };
+
+ class IceInternalVisitor : private ::IceUtil::noncopyable, public ParserVisitor
+ {
+ public:
+
+ IceInternalVisitor(::IceUtilInternal::Output&, ::IceUtilInternal::Output&, const std::string&);
+
+ virtual bool visitUnitStart(const UnitPtr&);
+ virtual void visitUnitEnd(const UnitPtr&);
+ virtual void visitClassDecl(const ClassDeclPtr&);
+ virtual bool visitClassDefStart(const ClassDefPtr&);
+
+ private:
+
+ ::IceUtilInternal::Output& H;
+ ::IceUtilInternal::Output& C;
+
+ std::string _dllExport;
+ };
+
+ class HandleVisitor : private ::IceUtil::noncopyable, public ParserVisitor
+ {
+ public:
+
+ HandleVisitor(::IceUtilInternal::Output&, ::IceUtilInternal::Output&, const std::string&, bool);
+
+ virtual bool visitModuleStart(const ModulePtr&);
+ virtual void visitModuleEnd(const ModulePtr&);
+ virtual void visitClassDecl(const ClassDeclPtr&);
+ virtual bool visitClassDefStart(const ClassDefPtr&);
+
+ private:
+
+ ::IceUtilInternal::Output& H;
+ ::IceUtilInternal::Output& C;
+
+ std::string _dllExport;
+ bool _stream;
+ };
+
+ class ImplVisitor : private ::IceUtil::noncopyable, public ParserVisitor
+ {
+ public:
+
+ ImplVisitor(::IceUtilInternal::Output&, ::IceUtilInternal::Output&, const std::string&);
+
+ virtual bool visitModuleStart(const ModulePtr&);
+ virtual void visitModuleEnd(const ModulePtr&);
+ virtual bool visitClassDefStart(const ClassDefPtr&);
+
+ private:
+
+ ::IceUtilInternal::Output& H;
+ ::IceUtilInternal::Output& C;
+
+ std::string _dllExport;
+ int _useWstring;
+ std::list<int> _useWstringHist;
+
+ //
+ // Generate code to emit a local variable declaration and initialize it
+ // if necessary.
+ //
+ void writeDecl(::IceUtilInternal::Output&, const std::string&, const TypePtr&, const StringList&);
+
+ //
+ // Generate code to return a dummy value
+ //
+ void writeReturn(::IceUtilInternal::Output&, const TypePtr&, const StringList&);
+ };
+
+ class AsyncVisitor : private ::IceUtil::noncopyable, public ParserVisitor
+ {
+ public:
+
+ AsyncVisitor(::IceUtilInternal::Output&, ::IceUtilInternal::Output&, const std::string&);
+
+ virtual bool visitModuleStart(const ModulePtr&);
+ virtual void visitModuleEnd(const ModulePtr&);
+ virtual bool visitClassDefStart(const ClassDefPtr&);
+ virtual void visitClassDefEnd(const ClassDefPtr&);
+ virtual void visitOperation(const OperationPtr&);
+
+ private:
+
+ ::IceUtilInternal::Output& H;
+ ::IceUtilInternal::Output& C;
+
+ std::string _dllExport;
+ int _useWstring;
+ std::list<int> _useWstringHist;
+ };
+
+ class AsyncImplVisitor : private ::IceUtil::noncopyable, public ParserVisitor
+ {
+ public:
+
+ AsyncImplVisitor(::IceUtilInternal::Output&, ::IceUtilInternal::Output&, const std::string&);
+
+ virtual bool visitUnitStart(const UnitPtr&);
+ virtual void visitUnitEnd(const UnitPtr&);
+ virtual bool visitModuleStart(const ModulePtr&);
+ virtual void visitModuleEnd(const ModulePtr&);
+ virtual bool visitClassDefStart(const ClassDefPtr&);
+ virtual void visitClassDefEnd(const ClassDefPtr&);
+ virtual void visitOperation(const OperationPtr&);
+
+ private:
+
+ ::IceUtilInternal::Output& H;
+ ::IceUtilInternal::Output& C;
+
+ std::string _dllExport;
+ int _useWstring;
+ std::list<int> _useWstringHist;
+ };
+
+ class StreamVisitor : private ::IceUtil::noncopyable, public ParserVisitor
+ {
+ public:
+
+ StreamVisitor(::IceUtilInternal::Output&, ::IceUtilInternal::Output&);
+
+ virtual bool visitModuleStart(const ModulePtr&);
+ virtual void visitModuleEnd(const ModulePtr&);
+ virtual bool visitStructStart(const StructPtr&);
+ virtual bool visitExceptionStart(const ExceptionPtr&);
+ virtual void visitEnum(const EnumPtr&);
+
+ private:
+
+ ::IceUtilInternal::Output& H;
+ ::IceUtilInternal::Output& C;
+ };
+
+private:
+
+ class MetaDataVisitor : public ParserVisitor
+ {
+ public:
+
+ virtual bool visitUnitStart(const UnitPtr&);
+ virtual bool visitModuleStart(const ModulePtr&);
+ virtual void visitModuleEnd(const ModulePtr&);
+ virtual void visitClassDecl(const ClassDeclPtr&);
+ virtual bool visitClassDefStart(const ClassDefPtr&);
+ virtual void visitClassDefEnd(const ClassDefPtr&);
+ virtual bool visitExceptionStart(const ExceptionPtr&);
+ virtual void visitExceptionEnd(const ExceptionPtr&);
+ virtual bool visitStructStart(const StructPtr&);
+ virtual void visitStructEnd(const StructPtr&);
+ virtual void visitOperation(const OperationPtr&);
+ virtual void visitDataMember(const DataMemberPtr&);
+ virtual void visitSequence(const SequencePtr&);
+ virtual void visitDictionary(const DictionaryPtr&);
+ virtual void visitEnum(const EnumPtr&);
+ virtual void visitConst(const ConstPtr&);
+
+ private:
+
+ void validate(const SyntaxTreeBasePtr&, const StringList&, const std::string&, const std::string&,
+ bool = false);
+
+ StringSet _history;
+ };
+
+ static void validateMetaData(const UnitPtr&);
+};
+
+}
+
+#endif
diff --git a/cpp/src/slice2cpp/Main.cpp b/cpp/src/slice2cpp/Main.cpp
new file mode 100644
index 00000000000..a55b72b873b
--- /dev/null
+++ b/cpp/src/slice2cpp/Main.cpp
@@ -0,0 +1,337 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+#include <IceUtil/Options.h>
+#include <IceUtil/CtrlCHandler.h>
+#include <IceUtil/Mutex.h>
+#include <IceUtil/MutexPtrLock.h>
+#include <Slice/Preprocessor.h>
+#include <Slice/FileTracker.h>
+#include <Slice/Util.h>
+#include <Gen.h>
+
+using namespace std;
+using namespace Slice;
+
+namespace
+{
+
+IceUtil::Mutex* mutex = 0;
+bool interrupted = false;
+
+class Init
+{
+public:
+
+ Init()
+ {
+ mutex = new IceUtil::Mutex;
+ }
+
+ ~Init()
+ {
+ delete mutex;
+ mutex = 0;
+ }
+};
+
+Init init;
+
+}
+
+void
+interruptedCallback(int signal)
+{
+ IceUtilInternal::MutexPtrLock<IceUtil::Mutex> sync(mutex);
+
+ interrupted = true;
+}
+
+void
+usage(const char* n)
+{
+ getErrorStream() << "Usage: " << n << " [options] slice-files...\n";
+ getErrorStream() <<
+ "Options:\n"
+ "-h, --help Show this message.\n"
+ "-v, --version Display the Ice version.\n"
+ "--header-ext EXT Use EXT instead of the default `h' extension.\n"
+ "--source-ext EXT Use EXT instead of the default `cpp' extension.\n"
+ "--add-header HDR[,GUARD] Add #include for HDR (with guard GUARD) to generated source file.\n"
+ "-DNAME Define NAME as 1.\n"
+ "-DNAME=DEF Define NAME as DEF.\n"
+ "-UNAME Remove any definition for NAME.\n"
+ "-IDIR Put DIR in the include file search path.\n"
+ "-E Print preprocessor output on stdout.\n"
+ "--include-dir DIR Use DIR as the header include directory in source files.\n"
+ "--output-dir DIR Create files in the directory DIR.\n"
+ "--dll-export SYMBOL Use SYMBOL for DLL exports.\n"
+ "--impl Generate sample implementations.\n"
+ "--depend Generate Makefile dependencies.\n"
+ "-d, --debug Print debug messages.\n"
+ "--ice Permit `Ice' prefix (for building Ice source code only).\n"
+ "--underscore Permit underscores in Slice identifiers.\n"
+ "--checksum Generate checksums for Slice definitions.\n"
+ "--stream Generate marshaling support for public stream API.\n"
+ ;
+}
+
+int
+compile(int argc, char* argv[])
+{
+ IceUtilInternal::Options opts;
+ opts.addOpt("h", "help");
+ opts.addOpt("v", "version");
+ opts.addOpt("", "header-ext", IceUtilInternal::Options::NeedArg, "h");
+ opts.addOpt("", "source-ext", IceUtilInternal::Options::NeedArg, "cpp");
+ opts.addOpt("", "add-header", IceUtilInternal::Options::NeedArg, "", IceUtilInternal::Options::Repeat);
+ opts.addOpt("D", "", IceUtilInternal::Options::NeedArg, "", IceUtilInternal::Options::Repeat);
+ opts.addOpt("U", "", IceUtilInternal::Options::NeedArg, "", IceUtilInternal::Options::Repeat);
+ opts.addOpt("I", "", IceUtilInternal::Options::NeedArg, "", IceUtilInternal::Options::Repeat);
+ opts.addOpt("E");
+ opts.addOpt("", "include-dir", IceUtilInternal::Options::NeedArg);
+ opts.addOpt("", "output-dir", IceUtilInternal::Options::NeedArg);
+ opts.addOpt("", "dll-export", IceUtilInternal::Options::NeedArg);
+ opts.addOpt("", "impl");
+ opts.addOpt("", "depend");
+ opts.addOpt("d", "debug");
+ opts.addOpt("", "ice");
+ opts.addOpt("", "underscore");
+ opts.addOpt("", "checksum");
+ opts.addOpt("", "stream");
+
+ vector<string> args;
+ try
+ {
+ args = opts.parse(argc, (const char**)argv);
+ }
+ catch(const IceUtilInternal::BadOptException& e)
+ {
+ getErrorStream() << argv[0] << ": " << e.reason << endl;
+ usage(argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ if(opts.isSet("help"))
+ {
+ usage(argv[0]);
+ return EXIT_SUCCESS;
+ }
+
+ if(opts.isSet("version"))
+ {
+ getErrorStream() << ICE_STRING_VERSION << endl;
+ return EXIT_SUCCESS;
+ }
+
+ string headerExtension = opts.optArg("header-ext");
+ string sourceExtension = opts.optArg("source-ext");
+
+ vector<string> extraHeaders = opts.argVec("add-header");
+
+ vector<string> cppArgs;
+ vector<string> optargs = opts.argVec("D");
+ vector<string>::const_iterator i;
+ for(i = optargs.begin(); i != optargs.end(); ++i)
+ {
+ cppArgs.push_back("-D" + *i);
+ }
+
+ optargs = opts.argVec("U");
+ for(i = optargs.begin(); i != optargs.end(); ++i)
+ {
+ cppArgs.push_back("-U" + *i);
+ }
+
+ vector<string> includePaths;
+ includePaths = opts.argVec("I");
+ for(i = includePaths.begin(); i != includePaths.end(); ++i)
+ {
+ cppArgs.push_back("-I" + Preprocessor::normalizeIncludePath(*i));
+ }
+
+ bool preprocess = opts.isSet("E");
+
+ string include = opts.optArg("include-dir");
+
+ string output = opts.optArg("output-dir");
+
+ string dllExport = opts.optArg("dll-export");
+
+ bool impl = opts.isSet("impl");
+
+ bool depend = opts.isSet("depend");
+
+ bool debug = opts.isSet("debug");
+
+ bool ice = opts.isSet("ice");
+
+ bool underscore = opts.isSet("underscore");
+
+ bool checksum = opts.isSet("checksum");
+
+ bool stream = opts.isSet("stream");
+
+ if(args.empty())
+ {
+ getErrorStream() << argv[0] << ": error: no input file" << endl;
+ usage(argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ int status = EXIT_SUCCESS;
+
+ IceUtil::CtrlCHandler ctrlCHandler;
+ ctrlCHandler.setCallback(interruptedCallback);
+
+ for(i = args.begin(); i != args.end(); ++i)
+ {
+ //
+ // Ignore duplicates.
+ //
+ vector<string>::iterator p = find(args.begin(), args.end(), *i);
+ if(p != i)
+ {
+ continue;
+ }
+
+ if(depend)
+ {
+ PreprocessorPtr icecpp = Preprocessor::create(argv[0], *i, cppArgs);
+ FILE* cppHandle = icecpp->preprocess(false);
+
+ if(cppHandle == 0)
+ {
+ return EXIT_FAILURE;
+ }
+
+ UnitPtr u = Unit::createUnit(false, false, ice, underscore);
+ int parseStatus = u->parse(*i, cppHandle, debug);
+ u->destroy();
+
+ if(parseStatus == EXIT_FAILURE)
+ {
+ return EXIT_FAILURE;
+ }
+
+ if(!icecpp->printMakefileDependencies(Preprocessor::CPlusPlus, includePaths, sourceExtension))
+ {
+ return EXIT_FAILURE;
+ }
+
+ if(!icecpp->close())
+ {
+ return EXIT_FAILURE;
+ }
+ }
+ else
+ {
+ PreprocessorPtr icecpp = Preprocessor::create(argv[0], *i, cppArgs);
+ FILE* cppHandle = icecpp->preprocess(false);
+
+ if(cppHandle == 0)
+ {
+ return EXIT_FAILURE;
+ }
+
+ if(preprocess)
+ {
+ char buf[4096];
+ while(fgets(buf, static_cast<int>(sizeof(buf)), cppHandle) != NULL)
+ {
+ if(fputs(buf, stdout) == EOF)
+ {
+ return EXIT_FAILURE;
+ }
+ }
+ if(!icecpp->close())
+ {
+ return EXIT_FAILURE;
+ }
+ }
+ else
+ {
+ UnitPtr u = Unit::createUnit(false, false, ice, underscore);
+ int parseStatus = u->parse(*i, cppHandle, debug);
+
+ if(!icecpp->close())
+ {
+ u->destroy();
+ return EXIT_FAILURE;
+ }
+
+ if(parseStatus == EXIT_FAILURE)
+ {
+ status = EXIT_FAILURE;
+ }
+ else
+ {
+ try
+ {
+ Gen gen(icecpp->getBaseName(), headerExtension, sourceExtension, extraHeaders, include,
+ includePaths, dllExport, output, impl, checksum, stream, ice);
+ gen.generate(u);
+ }
+ catch(const Slice::FileException& ex)
+ {
+ // If a file could not be created, then
+ // cleanup any created files.
+ FileTracker::instance()->cleanup();
+ u->destroy();
+ getErrorStream() << argv[0] << ": error: " << ex.reason() << endl;
+ return EXIT_FAILURE;
+ }
+ }
+
+ u->destroy();
+ }
+ }
+
+ {
+ IceUtilInternal::MutexPtrLock<IceUtil::Mutex> sync(mutex);
+
+ if(interrupted)
+ {
+ FileTracker::instance()->cleanup();
+ return EXIT_FAILURE;
+ }
+ }
+ }
+
+ return status;
+}
+
+int
+main(int argc, char* argv[])
+{
+ try
+ {
+ return compile(argc, argv);
+ }
+ catch(const std::exception& ex)
+ {
+ getErrorStream() << argv[0] << ": error:" << ex.what() << endl;
+ return EXIT_FAILURE;
+ }
+ catch(const std::string& msg)
+ {
+ getErrorStream() << argv[0] << ": error:" << msg << endl;
+ return EXIT_FAILURE;
+ }
+ catch(const char* msg)
+ {
+ getErrorStream() << argv[0] << ": error:" << msg << endl;
+ return EXIT_FAILURE;
+ }
+ catch(...)
+ {
+ getErrorStream() << argv[0] << ": error:" << "unknown exception" << endl;
+ return EXIT_FAILURE;
+ }
+}
diff --git a/cpp/src/slice2cpp/Makefile b/cpp/src/slice2cpp/Makefile
new file mode 100644
index 00000000000..e06b359bb9e
--- /dev/null
+++ b/cpp/src/slice2cpp/Makefile
@@ -0,0 +1,32 @@
+# **********************************************************************
+#
+# Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.
+#
+# This copy of Ice is licensed to you under the terms described in the
+# ICE_LICENSE file included in this distribution.
+#
+# **********************************************************************
+
+top_srcdir = ../..
+
+NAME = $(top_srcdir)/bin/slice2cpp
+
+TARGETS = $(NAME)
+
+OBJS = Gen.o \
+ Main.o
+
+SRCS = $(OBJS:.o=.cpp)
+
+include $(top_srcdir)/config/Make.rules
+
+CPPFLAGS := -I. $(CPPFLAGS)
+
+$(NAME): $(OBJS)
+ rm -f $@
+ $(CXX) $(LDFLAGS) -o $@ $(OBJS) -lSlice $(BASELIBS) $(MCPP_RPATH_LINK)
+
+install:: all
+ $(call installprogram,$(NAME),$(install_bindir))
+
+include .depend
diff --git a/cpp/src/slice2cpp/Makefile.mak b/cpp/src/slice2cpp/Makefile.mak
new file mode 100644
index 00000000000..e57e5ae802c
--- /dev/null
+++ b/cpp/src/slice2cpp/Makefile.mak
@@ -0,0 +1,61 @@
+# **********************************************************************
+#
+# Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.
+#
+# This copy of Ice is licensed to you under the terms described in the
+# ICE_LICENSE file included in this distribution.
+#
+# **********************************************************************
+
+top_srcdir = ..\..
+
+NAME = $(top_srcdir)\bin\slice2cpp.exe
+
+TARGETS = $(NAME)
+
+OBJS = Gen.obj \
+ Main.obj
+
+SRCS = $(OBJS:.obj=.cpp)
+
+!include $(top_srcdir)/config/Make.rules.mak
+
+CPPFLAGS = -I. $(CPPFLAGS) -DWIN32_LEAN_AND_MEAN
+
+!if "$(GENERATE_PDB)" == "yes"
+PDBFLAGS = /pdb:$(NAME:.exe=.pdb)
+!endif
+
+!if "$(BCPLUSPLUS)" == "yes"
+RES_FILE = ,, Slice2Cpp.res
+!else
+RES_FILE = Slice2Cpp.res
+!endif
+
+$(NAME): $(OBJS) Slice2Cpp.res
+ $(LINK) $(LD_EXEFLAGS) $(PDBFLAGS) $(OBJS) $(SETARGV) $(PREOUT)$@ $(PRELIBS)slice$(LIBSUFFIX).lib \
+ $(BASELIBS) $(RES_FILE)
+ @if exist $@.manifest echo ^ ^ ^ Embedding manifest using $(MT) && \
+ $(MT) -nologo -manifest $@.manifest -outputresource:$@;#1 && del /q $@.manifest
+
+clean::
+ del /q $(NAME:.exe=.*)
+ del /q Slice2Cpp.res
+
+install:: all
+ copy $(NAME) "$(install_bindir)"
+
+
+!if "$(BCPLUSPLUS)" == "yes" && "$(OPTIMIZE)" != "yes"
+
+install:: all
+ copy $(NAME:.exe=.tds) "$(install_bindir)"
+
+!elseif "$(GENERATE_PDB)" == "yes"
+
+install:: all
+ copy $(NAME:.exe=.pdb) "$(install_bindir)"
+
+!endif
+
+!include .depend.mak
diff --git a/cpp/src/slice2cpp/Slice2Cpp.rc b/cpp/src/slice2cpp/Slice2Cpp.rc
new file mode 100644
index 00000000000..d580b34024c
--- /dev/null
+++ b/cpp/src/slice2cpp/Slice2Cpp.rc
@@ -0,0 +1,34 @@
+#include "winver.h"
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 3,4,2,0
+ PRODUCTVERSION 3,4,2,0
+ FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
+#ifdef _DEBUG
+ FILEFLAGS VS_FF_DEBUG
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE VFT_APP
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904e4"
+ BEGIN
+ VALUE "CompanyName", "ZeroC, Inc.\0"
+ VALUE "FileDescription", "Slice To C++ Translator\0"
+ VALUE "FileVersion", "3.4.2\0"
+ VALUE "InternalName", "slice2cpp\0"
+ VALUE "LegalCopyright", "Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.\0"
+ VALUE "OriginalFilename", "slice2cpp.exe\0"
+ VALUE "ProductName", "Ice\0"
+ VALUE "ProductVersion", "3.4.2\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1252
+ END
+END