diff options
author | Dwayne Boone <dwayne@zeroc.com> | 2005-03-18 17:24:43 +0000 |
---|---|---|
committer | Dwayne Boone <dwayne@zeroc.com> | 2005-03-18 17:24:43 +0000 |
commit | 18dd6970efb0bd518fb84dc3d7bb27a94298d785 (patch) | |
tree | 931de6d02b2c743cfd87274d7190a5745ffc57c0 /cpp/src | |
parent | Added support for perf with CosEvent (diff) | |
download | ice-18dd6970efb0bd518fb84dc3d7bb27a94298d785.tar.bz2 ice-18dd6970efb0bd518fb84dc3d7bb27a94298d785.tar.xz ice-18dd6970efb0bd518fb84dc3d7bb27a94298d785.zip |
Adde embedded ice compilers
Diffstat (limited to 'cpp/src')
-rw-r--r-- | cpp/src/Makefile | 2 | ||||
-rw-r--r-- | cpp/src/slice2cppe/.depend | 2 | ||||
-rw-r--r-- | cpp/src/slice2cppe/Gen.cpp | 4362 | ||||
-rw-r--r-- | cpp/src/slice2cppe/Gen.h | 383 | ||||
-rw-r--r-- | cpp/src/slice2cppe/Main.cpp | 205 | ||||
-rw-r--r-- | cpp/src/slice2cppe/Makefile | 32 | ||||
-rw-r--r-- | cpp/src/slice2cppe/slice2cppe.dsp | 126 | ||||
-rw-r--r-- | cpp/src/slice2javae/.depend | 2 | ||||
-rw-r--r-- | cpp/src/slice2javae/Gen.cpp | 5008 | ||||
-rw-r--r-- | cpp/src/slice2javae/Gen.h | 281 | ||||
-rw-r--r-- | cpp/src/slice2javae/Main.cpp | 226 | ||||
-rw-r--r-- | cpp/src/slice2javae/Makefile | 32 | ||||
-rw-r--r-- | cpp/src/slice2javae/slice2javae.dsp | 126 |
13 files changed, 10787 insertions, 0 deletions
diff --git a/cpp/src/Makefile b/cpp/src/Makefile index 161db603988..c8e4a7854b3 100644 --- a/cpp/src/Makefile +++ b/cpp/src/Makefile @@ -22,6 +22,8 @@ SUBDIRS = IceUtil \ slice2docbook \ slice2java \ slice2py \ + slice2cppe \ + slice2javae \ Ice \ IceXML \ IceSSL \ diff --git a/cpp/src/slice2cppe/.depend b/cpp/src/slice2cppe/.depend new file mode 100644 index 00000000000..73b2db66ce7 --- /dev/null +++ b/cpp/src/slice2cppe/.depend @@ -0,0 +1,2 @@ +Gen.o: Gen.cpp Gen.h ../../include/Slice/Parser.h ../../include/IceUtil/Shared.h ../../include/IceUtil/Config.h ../../include/IceUtil/Handle.h ../../include/IceUtil/Exception.h ../../include/IceUtil/InputUtil.h ../../include/IceUtil/OutputUtil.h ../../include/Slice/CPlusPlusUtil.h ../../include/IceUtil/Functional.h ../../include/IceUtil/Iterator.h ../../include/Slice/Checksum.h +Main.o: Main.cpp ../../include/IceUtil/Options.h ../../include/IceUtil/Config.h ../../include/IceUtil/RecMutex.h ../../include/IceUtil/Lock.h ../../include/IceUtil/ThreadException.h ../../include/IceUtil/Exception.h ../../include/Slice/Preprocessor.h Gen.h ../../include/Slice/Parser.h ../../include/IceUtil/Shared.h ../../include/IceUtil/Handle.h ../../include/IceUtil/InputUtil.h ../../include/IceUtil/OutputUtil.h diff --git a/cpp/src/slice2cppe/Gen.cpp b/cpp/src/slice2cppe/Gen.cpp new file mode 100644 index 00000000000..ef49c9f0eb5 --- /dev/null +++ b/cpp/src/slice2cppe/Gen.cpp @@ -0,0 +1,4362 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2005 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 <Gen.h> +#include <Slice/CPlusPlusUtil.h> +#include <IceUtil/Functional.h> +#include <IceUtil/Iterator.h> +#include <Slice/Checksum.h> + +#include <limits> +#include <sys/stat.h> + +using namespace std; +using namespace Slice; +using namespace IceUtil; + +Slice::Gen::Gen(const string& name, const string& base, const string& headerExtension, + const string& sourceExtension, const string& include, const vector<string>& includePaths, + const string& dllExport, const string& dir, bool imp, bool checksum, bool stream) : + _base(base), + _headerExtension(headerExtension), + _sourceExtension(sourceExtension), + _include(include), + _includePaths(includePaths), + _dllExport(dllExport), + _impl(imp), + _checksum(checksum), + _stream(stream) +{ + for(vector<string>::iterator p = _includePaths.begin(); p != _includePaths.end(); ++p) + { + if(p->length() && (*p)[p->length() - 1] != '/') + { + *p += '/'; + } + } + + string::size_type pos = _base.rfind('/'); + if(pos == string::npos) + { + pos = _base.rfind('\\'); + } + if(pos != string::npos) + { + _base.erase(0, pos + 1); + } + + if(_impl) + { + string fileImplH = _base + "I." + _headerExtension; + string fileImplC = _base + "I." + _sourceExtension; + if(!dir.empty()) + { + fileImplH = dir + '/' + fileImplH; + fileImplC = dir + '/' + fileImplC; + } + + struct stat st; + if(stat(fileImplH.c_str(), &st) == 0) + { + cerr << name << ": `" << fileImplH << "' already exists - will not overwrite" << endl; + return; + } + if(stat(fileImplC.c_str(), &st) == 0) + { + cerr << name << ": `" << fileImplC << "' already exists - will not overwrite" << endl; + return; + } + + implH.open(fileImplH.c_str()); + if(!implH) + { + cerr << name << ": can't open `" << fileImplH << "' for writing" << endl; + return; + } + + implC.open(fileImplC.c_str()); + if(!implC) + { + cerr << name << ": can't open `" << fileImplC << "' for writing" << endl; + return; + } + + 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) + { + cerr << name << ": can't open `" << fileH << "' for writing" << endl; + return; + } + + C.open(fileC.c_str()); + if(!C) + { + cerr << name << ": can't open `" << fileC << "' for writing" << endl; + return; + } + + printHeader(H); + printHeader(C); + H << "\n// Generated from file `" << changeInclude(_base, _includePaths) << ".ice'\n"; + C << "\n// Generated from file `" << changeInclude(_base, _includePaths) << ".ice'\n"; + + 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'; +} + +Slice::Gen::~Gen() +{ + H << "\n\n#endif\n"; + C << '\n'; + + if(_impl) + { + implH << "\n\n#endif\n"; + implC << '\n'; + } +} + +bool +Slice::Gen::operator!() const +{ + if(!H || !C) + { + return true; + } + if(_impl && (!implH || !implC)) + { + return true; + } + return false; +} + +void +Slice::Gen::generate(const UnitPtr& p) +{ + validateMetaData(p); + + 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>"; + if(p->hasContentsWithMetaData("ami")) + { + 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>"; + } + + if(p->hasNonLocalExceptions()) + { + H << "\n#include <Ice/UserExceptionFactory.h>"; + } + + if(p->hasDataOnlyClasses() || p->hasNonLocalExceptions()) + { + H << "\n#include <Ice/FactoryTable.h>"; + } + + if(p->usesNonLocals()) + { + C << "\n#include <Ice/BasicStream.h>"; + C << "\n#include <Ice/Object.h>"; + } + + if(_stream || p->hasNonLocalClassDefs() || p->hasNonLocalExceptions()) + { + H << "\n#include <Ice/StreamF.h>"; + + if(!p->hasNonLocalClassDefs()) + { + C << "\n#include <Ice/LocalException.h>"; + } + + if(_stream) + { + C << "\n#include <Ice/Stream.h>"; + } + } + + if(_checksum) + { + C << "\n#include <Ice/SliceChecksums.h>"; + } + + StringList includes = p->includeFiles(); + + for(StringList::const_iterator q = includes.begin(); q != includes.end(); ++q) + { + H << "\n#include <" << changeInclude(*q, _includePaths) << "." << _headerExtension << ">"; + } + + 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); + + 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(_impl) + { + implH << "\n#include <"; + if(_include.size()) + { + implH << _include << '/'; + } + implH << _base << ".h>"; + + implC << "#include <"; + if(_include.size()) + { + implC << _include << '/'; + } + implC << _base << "I.h>"; + + 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 p = map.begin(); p != map.end(); ++p) + { + C << nl << "\"" << p->first << "\", \""; + ostringstream str; + str.flags(ios_base::hex); + str.fill('0'); + for(vector<unsigned char>::const_iterator q = p->second.begin(); q != p->second.end(); ++q) + { + str << (int)(*q); + } + C << str.str() << "\","; + } + C << nl << "0"; + C << eb << ';'; + C << nl << "static IceInternal::SliceChecksumInit __sliceChecksumInit(__sliceChecksums);"; + } + } +} + +Slice::Gen::TypesVisitor::TypesVisitor(Output& h, Output& c, const string& dllExport, bool stream) : + H(h), C(c), _dllExport(dllExport), _stream(stream) +{ +} + +bool +Slice::Gen::TypesVisitor::visitModuleStart(const ModulePtr& p) +{ + string name = fixKwd(p->name()); + + H << sp << nl << "namespace " << name << nl << '{'; + + return true; +} + +void +Slice::Gen::TypesVisitor::visitModuleEnd(const ModulePtr& p) +{ + H << sp << nl << '}'; +} + +bool +Slice::Gen::TypesVisitor::visitClassDefStart(const ClassDefPtr&) +{ + return false; +} + +bool +Slice::Gen::TypesVisitor::visitExceptionStart(const ExceptionPtr& p) +{ + string name = fixKwd(p->name()); + string scoped = fixKwd(p->scoped()); + ExceptionPtr base = p->base(); + + H << sp << nl << "class " << _dllExport << name << " : "; + H.useCurrentPosAsIndent(); + if(!base) + { + if(p->isLocal()) + { + H << "public ::Ice::LocalException"; + } + else + { + H << "public ::Ice::UserException"; + } + } + else + { + H << "public " << fixKwd(base->scoped()); + } + H.restoreIndent(); + H << sb; + + H.dec(); + H << nl << "public:"; + H.inc(); + + H << sp; + if(p->isLocal()) + { + H << nl << name << "(const char*, int);"; + C << sp << nl << scoped.substr(2) << "::" << name << "(const char* file, int line) : "; + C.inc(); + if(!base) + { + C << nl << "::Ice::LocalException(file, line)"; + } + else + { + C << nl << fixKwd(base->scoped()) << "(file, line)"; + } + C.dec(); + C << sb; + C << eb; + } + + H << nl << "virtual const ::std::string& ice_name() const;"; + + string flatName = p->flattenedScope() + p->name() + "_name"; + + C << sp << nl << "static const ::std::string " << flatName << " = \"" << p->scoped().substr(2) << "\";"; + C << sp << nl << "const ::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();"; + } + 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 << sp << nl << "virtual void __write(const ::Ice::OutputStreamPtr&) const;"; + H << nl << "virtual void __read(const ::Ice::InputStreamPtr&, bool);"; + + TypeStringList memberList; + for(q = dataMembers.begin(); q != dataMembers.end(); ++q) + { + memberList.push_back(make_pair((*q)->type(), (*q)->name())); + } + C << sp << nl << "void" << nl << scoped.substr(2) << "::__write(::IceInternal::BasicStream* __os) const"; + C << sb; + C << nl << "__os->write(::std::string(\"" << p->scoped() << "\"));"; + C << nl << "__os->startWriteSlice();"; + writeMarshalCode(C, memberList, 0); + C << nl << "__os->endWriteSlice();"; + if(base) + { + C.zeroIndent(); + C << nl << "#if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug"; // COMPILERBUG + C.restoreIndent(); + C << nl << fixKwd(base->name()) << "::__write(__os);"; + C.zeroIndent(); + C << nl << "#else"; + C.restoreIndent(); + C << nl << fixKwd(base->scoped()) << "::__write(__os);"; + C.zeroIndent(); + C << nl << "#endif"; + C.restoreIndent(); + } + 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);"; + C << eb; + C << nl << "__is->startReadSlice();"; + writeUnmarshalCode(C, memberList, 0); + C << nl << "__is->endReadSlice();"; + if(base) + { + C.zeroIndent(); + C << nl << "#if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug"; // COMPILERBUG + C.restoreIndent(); + C << nl << fixKwd(base->name()) << "::__read(__is, true);"; + C.zeroIndent(); + C << nl << "#else"; + C.restoreIndent(); + C << nl << fixKwd(base->scoped()) << "::__read(__is, true);"; + C.zeroIndent(); + C << nl << "#endif"; + C.restoreIndent(); + } + C << eb; + + if(_stream) + { + C << sp << nl << "void" << nl << scoped.substr(2) << "::__write(const ::Ice::OutputStreamPtr& __out) const"; + C << sb; + C << nl << "__out->writeString(::std::string(\"" << p->scoped() << "\"));"; + C << nl << "__out->startSlice();"; + writeStreamMarshalCode(C, memberList, 0); + C << nl << "__out->endSlice();"; + if(base) + { + C.zeroIndent(); + C << nl << "#if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug"; // COMPILERBUG + C.restoreIndent(); + C << nl << fixKwd(base->name()) << "::__write(__out);"; + C.zeroIndent(); + C << nl << "#else"; + C.restoreIndent(); + C << nl << fixKwd(base->scoped()) << "::__write(__out);"; + C.zeroIndent(); + C << nl << "#endif"; + C.restoreIndent(); + } + C << eb; + + C << sp << nl << "void" << nl << scoped.substr(2) + << "::__read(const ::Ice::InputStreamPtr& __in, bool __rid)"; + C << sb; + C << nl << "if(__rid)"; + C << sb; + C << nl << "__in->readString();"; + C << eb; + C << nl << "__in->startSlice();"; + writeStreamUnmarshalCode(C, memberList, 0); + C << nl << "__in->endSlice();"; + if(base) + { + C.zeroIndent(); + C << nl << "#if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug"; // COMPILERBUG + C.restoreIndent(); + C << nl << fixKwd(base->name()) << "::__read(__in, true);"; + C.zeroIndent(); + C << nl << "#else"; + C.restoreIndent(); + C << nl << fixKwd(base->scoped()) << "::__read(__in, true);"; + C.zeroIndent(); + C << nl << "#endif"; + C.restoreIndent(); + } + C << eb; + } + else + { + // + // Emit placeholder functions to catch errors. + // + C << sp << 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; + } + + 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 << "::Ice::factoryTable->addExceptionFactory(\"" << p->scoped() << "\", " << scoped + << "::ice_factory());"; + C << eb; + C << sp << nl << "~" << factoryName << "__Init()"; + C << sb; + C << nl << "::Ice::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()) + { + H << sp << nl << "static " << name << " __" << p->name() << "_init;"; + } +} + +bool +Slice::Gen::TypesVisitor::visitStructStart(const StructPtr& p) +{ + string name = fixKwd(p->name()); + + H << sp << nl << "struct " << name; + H << sb; + + 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()); + + H << sp; + H << nl << _dllExport << "bool operator==(const " << name << "&) const;"; + H << nl << _dllExport << "bool operator!=(const " << name << "&) const;"; + H << nl << _dllExport << "bool operator<(const " << name << "&) const;"; + + DataMemberList dataMembers = p->dataMembers(); + DataMemberList::const_iterator q; + C << sp << nl << "bool" << nl << scoped.substr(2) << "::operator==(const " << name << "& __rhs) const"; + C << sb; + C << nl << "return !operator!=(__rhs);"; + C << eb; + C << sp << nl << "bool" << nl << scoped.substr(2) << "::operator!=(const " << name << "& __rhs) const"; + C << sb; + C << nl << "if(this == &__rhs)"; + C << sb; + C << nl << "return false;"; + C << eb; + for(q = dataMembers.begin(); q != dataMembers.end(); ++q) + { + C << nl << "if(" << fixKwd((*q)->name()) << " != __rhs." << fixKwd((*q)->name()) << ')'; + C << sb; + C << nl << "return true;"; + C << eb; + } + C << nl << "return false;"; + C << eb; + C << sp << nl << "bool" << nl << scoped.substr(2) << "::operator<(const " << name << "& __rhs) const"; + C << sb; + C << nl << "if(this == &__rhs)"; + C << sb; + C << nl << "return false;"; + C << eb; + for(q = dataMembers.begin(); q != dataMembers.end(); ++q) + { + C << nl << "if(" << fixKwd((*q)->name()) << " < __rhs." << fixKwd((*q)->name()) << ')'; + C << sb; + C << nl << "return true;"; + C << eb; + C << nl << "else if(__rhs." << fixKwd((*q)->name()) << " < " << fixKwd((*q)->name()) << ')'; + C << sb; + C << nl << "return false;"; + C << eb; + } + C << nl << "return false;"; + C << 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 << sp << nl << _dllExport << "void __write(const ::Ice::OutputStreamPtr&) const;"; + H << nl << _dllExport << "void __read(const ::Ice::InputStreamPtr&);"; + } + + TypeStringList memberList; + for(q = dataMembers.begin(); q != dataMembers.end(); ++q) + { + memberList.push_back(make_pair((*q)->type(), (*q)->name())); + } + C << sp << nl << "void" << nl << scoped.substr(2) << "::__write(::IceInternal::BasicStream* __os) const"; + C << sb; + writeMarshalCode(C, memberList, 0); + C << eb; + + C << sp << nl << "void" << nl << scoped.substr(2) << "::__read(::IceInternal::BasicStream* __is)"; + C << sb; + writeUnmarshalCode(C, memberList, 0); + C << eb; + + if(_stream) + { + C << sp << nl << "void" << nl << scoped.substr(2) << "::__write(const ::Ice::OutputStreamPtr& __out) const"; + C << sb; + writeStreamMarshalCode(C, memberList, 0); + C << eb; + + C << sp << nl << "void" << nl << scoped.substr(2) << "::__read(const ::Ice::InputStreamPtr& __in)"; + C << sb; + writeStreamUnmarshalCode(C, memberList, 0); + C << eb; + } + } + + H << eb << ';'; + + if(!p->isLocal() && _stream) + { + H << sp << nl << _dllExport << "void ice_write" << p->name() << "(const ::Ice::OutputStreamPtr&, const " + << name << "&);"; + H << nl << _dllExport << "void ice_read" << p->name() << "(const ::Ice::InputStreamPtr&, " << name << "&);"; + + C << sp << nl << "void" << nl << scope.substr(2) << "ice_write" << p->name() + << "(const ::Ice::OutputStreamPtr& __out, const " << scoped << "& __v)"; + C << sb; + C << nl << "__v.__write(__out);"; + C << eb; + + C << sp << nl << "void" << nl << scope.substr(2) << "ice_read" << p->name() + << "(const ::Ice::InputStreamPtr& __in, " << scoped << "& __v)"; + C << sb; + C << nl << "__v.__read(__in);"; + C << eb; + } +} + +void +Slice::Gen::TypesVisitor::visitDataMember(const DataMemberPtr& p) +{ + string name = fixKwd(p->name()); + string s = typeToString(p->type()); + H << sp << nl << s << ' ' << name << ';'; +} + +void +Slice::Gen::TypesVisitor::visitSequence(const SequencePtr& p) +{ + string name = fixKwd(p->name()); + TypePtr type = p->type(); + string s = typeToString(type); + if(s[0] == ':') + { + s.insert(0, " "); + } + H << sp << nl << "typedef ::std::vector<" << s << "> " << name << ';'; + + BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); + if(!p->isLocal() && + (!builtin || builtin->kind() == Builtin::KindObject || builtin->kind() == Builtin::KindObjectProxy)) + { + string scoped = fixKwd(p->scoped()); + string scope = fixKwd(p->scope()); + + H << sp << nl << "class __U__" << name << " { };"; + H << nl << _dllExport << "void __write(::IceInternal::BasicStream*, const " << name << "&, __U__" << name + << ");"; + H << nl << _dllExport << "void __read(::IceInternal::BasicStream*, " << name << "&, __U__" << name << ");"; + + if(_stream) + { + 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 << "&);"; + } + + C << sp << nl << "void" << nl << scope.substr(2) << "__write(::IceInternal::BasicStream* __os, const " + << scoped << "& v, " << scope << "__U__" << name << ")"; + 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, type, "(*p)", true); + C << eb; + C << eb; + + C << sp << nl << "void" << nl << scope.substr(2) << "__read(::IceInternal::BasicStream* __is, " << scoped + << "& v, " << scope << "__U__" << name << ')'; + C << sb; + C << nl << "::Ice::Int sz;"; + C << nl << "__is->readSize(sz);"; + if(type->isVariableLength()) + { + C << nl << "__is->startSeq(sz, " << type->minWireSize() << ");"; // Protect against bogus sequence sizes. + } + else + { + C << nl << "__is->checkFixedSeq(sz, " << type->minWireSize() << ");"; + } + C << nl << "v.resize(sz);"; + C << nl << "for(int i = 0; i < sz; ++i)"; + C << sb; + writeMarshalUnmarshalCode(C, type, "v[i]", false); + + // + // After unmarshaling each element, check that there are still enough bytes left in the stream + // to unmarshal the remainder of the sequence, and decrement the count of elements + // yet to be unmarshaled for sequences with variable-length element type (that is, for sequences + // of classes, structs, dictionaries, sequences, strings, or proxies). This allows us to + // abort unmarshaling for bogus sequence sizes at the earliest possible moment. + // (For fixed-length sequences, we don't need to do this because the prediction of how many + // bytes will be taken up by the sequence is accurate.) + // + if(type->isVariableLength()) + { + if(!SequencePtr::dynamicCast(type)) + { + // + // No need to check for directly nested sequences because, at the start of each + // sequence, we check anyway. + // + C << nl << "__is->checkSeq();"; + } + C << nl << "__is->endElement();"; + } + C << eb; + if(type->isVariableLength()) + { + C << nl << "__is->endSeq(sz);"; + } + C << eb; + + if(_stream) + { + C << sp << nl << "void" << nl << scope.substr(2) << "ice_write" << p->name() + << "(const ::Ice::OutputStreamPtr& __out, const " << scoped << "& v)"; + C << sb; + C << nl << "__out->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); + C << eb; + C << eb; + + C << sp << nl << "void" << nl << scope.substr(2) << "ice_read" << p->name() + << "(const ::Ice::InputStreamPtr& __in, " << scoped << "& v)"; + C << sb; + C << nl << "::Ice::Int sz = __in->readSize();"; + C << nl << "v.resize(sz);"; + C << nl << "for(int i = 0; i < sz; ++i)"; + C << sb; + writeStreamMarshalUnmarshalCode(C, type, "v[i]", false); + C << eb; + C << eb; + } + } +} + +void +Slice::Gen::TypesVisitor::visitDictionary(const DictionaryPtr& p) +{ + string name = fixKwd(p->name()); + TypePtr keyType = p->keyType(); + TypePtr valueType = p->valueType(); + string ks = typeToString(keyType); + if(ks[0] == ':') + { + ks.insert(0, " "); + } + string vs = typeToString(valueType); + H << sp << nl << "typedef ::std::map<" << ks << ", " << vs << "> " << name << ';'; + + if(!p->isLocal()) + { + string scoped = fixKwd(p->scoped()); + string scope = fixKwd(p->scope()); + + H << sp << nl << "class __U__" << name << " { };"; + H << nl << _dllExport << "void __write(::IceInternal::BasicStream*, const " << name + << "&, __U__" << name << ");"; + H << nl << _dllExport << "void __read(::IceInternal::BasicStream*, " << name + << "&, __U__" << name << ");"; + + if(_stream) + { + 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 << "&);"; + } + + C << sp << nl << "void" << nl << scope.substr(2) << "__write(::IceInternal::BasicStream* __os, const " + << scoped << "& v, " << scope << "__U__" << name << ")"; + 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(::IceInternal::BasicStream* __is, " << scoped + << "& v, " << scope << "__U__" << name << ')'; + 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;"; + 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 << nl << "void" << nl << scope.substr(2) << "ice_write" << p->name() + << "(const ::Ice::OutputStreamPtr& __out, const " << scoped << "& v)"; + C << sb; + C << nl << "__out->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); + writeStreamMarshalUnmarshalCode(C, valueType, "p->second", true); + C << eb; + C << eb; + + C << sp << nl << "void" << nl << scope.substr(2) << "ice_read" << p->name() + << "(const ::Ice::InputStreamPtr& __in, " << scoped << "& v)"; + C << sb; + C << nl << "::Ice::Int sz = __in->readSize();"; + C << nl << "while(sz--)"; + C << sb; + C << nl << "::std::pair<const " << ks << ", " << vs << "> pair;"; + string pf = string("const_cast<") + ks + "&>(pair.first)"; + writeStreamMarshalUnmarshalCode(C, keyType, pf, false); + C << nl << scoped << "::iterator __i = v.insert(v.end(), pair);"; + writeStreamMarshalUnmarshalCode(C, valueType, "__i->second", false); + C << eb; + C << eb; + } + } +} + +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 << sp << nl << _dllExport << "void ice_write" << p->name() + << "(const ::Ice::OutputStreamPtr&, " << name << ");"; + H << nl << _dllExport << "void ice_read" << p->name() << "(const ::Ice::InputStreamPtr&, " << name << "&);"; + } + + 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));"; + } + else if(sz <= 0x7fff) + { + C << nl << "__os->write(static_cast< ::Ice::Short>(v));"; + } + else + { + C << nl << "__os->write(static_cast< ::Ice::Int>(v));"; + } + 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;"; + C << nl << "__is->read(val);"; + C << nl << "v = static_cast< " << scoped << ">(val);"; + } + else if(sz <= 0x7fff) + { + C << nl << "::Ice::Short val;"; + C << nl << "__is->read(val);"; + C << nl << "v = static_cast< " << scoped << ">(val);"; + } + else + { + C << nl << "::Ice::Int val;"; + C << nl << "__is->read(val);"; + C << nl << "v = static_cast< " << scoped << ">(val);"; + } + C << eb; + + if(_stream) + { + C << sp << nl << "void" << nl << scope.substr(2) << "ice_write" << p->name() + << "(const ::Ice::OutputStreamPtr& __out, " << scoped << " v)"; + C << sb; + if(sz <= 0x7f) + { + C << nl << "__out->writeByte(static_cast< ::Ice::Byte>(v));"; + } + else if(sz <= 0x7fff) + { + C << nl << "__out->writeShort(static_cast< ::Ice::Short>(v));"; + } + else + { + C << nl << "__out->writeInt(static_cast< ::Ice::Int>(v));"; + } + C << eb; + + C << sp << nl << "void" << nl << scope.substr(2) << "ice_read" << p->name() + << "(const ::Ice::InputStreamPtr& __in, " << scoped << "& v)"; + C << sb; + if(sz <= 0x7f) + { + C << nl << "::Ice::Byte val = __in->readByte();"; + C << nl << "v = static_cast< " << scoped << ">(val);"; + } + else if(sz <= 0x7fff) + { + C << nl << "::Ice::Short val = __in->readShort();"; + C << nl << "v = static_cast< " << scoped << ">(val);"; + } + else + { + C << nl << "::Ice::Int val = __in->readInt();"; + C << nl << "v = static_cast< " << scoped << ">(val);"; + } + C << eb; + } + } +} + +void +Slice::Gen::TypesVisitor::visitConst(const ConstPtr& p) +{ + H << sp; + H << nl << "const " << typeToString(p->type()) << " " << fixKwd(p->name()) << " = "; + + BuiltinPtr bp = BuiltinPtr::dynamicCast(p->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" + "_{}[]#()<>%:;,?*+=/^&|~!=,\\\"' \t"; + static const set<char> charSet(basicSourceChars.begin(), basicSourceChars.end()); + + H << "\""; // Opening " + + ios_base::fmtflags originalFlags = H.flags(); // Save stream state + streamsize originalWidth = H.width(); + ostream::char_type originalFill = H.fill(); + + const string val = p->value(); + for(string::const_iterator c = val.begin(); c != val.end(); ++c) + { + if(charSet.find(*c) == charSet.end()) + { + unsigned char uc = *c; // char may be signed, so make it positive + H << "\\"; // Print as octal if not in basic source character set + H.flags(ios_base::oct); + H.width(3); + H.fill('0'); + H << static_cast<unsigned>(uc); + } + else + { + H << *c; // Print normally if in basic source character set + } + } + + H.fill(originalFill); // Restore stream state + H.width(originalWidth); + H.flags(originalFlags); + + H << "\""; // Closing " + } + else if(bp && bp->kind() == Builtin::KindLong) + { + H << "ICE_INT64(" << p->value() << ")"; + } + else + { + EnumPtr ep = EnumPtr::dynamicCast(p->type()); + if(ep) + { + H << fixKwd(p->value()); + } + else + { + H << p->value(); + } + } + + H << ';'; +} + +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 << ';'; + H << nl << _dllExport << "bool operator==(const " << name << "&, const " << name << "&);"; + H << nl << _dllExport << "bool operator!=(const " << name << "&, const " << name << "&);"; + H << nl << _dllExport << "bool operator<(const " << name << "&, const " << name << "&);"; +} + +Slice::Gen::ProxyVisitor::ProxyVisitor(Output& h, Output& c, const string& dllExport) : + H(h), C(c), _dllExport(dllExport) +{ +} + +bool +Slice::Gen::ProxyVisitor::visitUnitStart(const UnitPtr& p) +{ + if(!p->hasNonLocalClassDecls()) + { + 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->hasNonLocalClassDecls()) + { + return false; + } + + string name = fixKwd(p->name()); + + H << sp << nl << "namespace " << name << nl << '{'; + + return true; +} + +void +Slice::Gen::ProxyVisitor::visitModuleEnd(const ModulePtr& p) +{ + H << sp << nl << '}'; +} + +bool +Slice::Gen::ProxyVisitor::visitClassDefStart(const ClassDefPtr& p) +{ + if(p->isLocal()) + { + return false; + } + + string name = fixKwd(p->name()); + string scoped = fixKwd(p->scoped()); + ClassList bases = p->bases(); + + H << sp << nl << "class " << _dllExport << 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(); + + return true; +} + +void +Slice::Gen::ProxyVisitor::visitClassDefEnd(const ClassDefPtr& p) +{ + string scoped = fixKwd(p->scoped()); + string scope = fixKwd(p->scope()); + + H << nl << nl << "static const ::std::string& ice_staticId();"; + + H.dec(); + H << sp << nl << "private: "; + H.inc(); + H << sp << nl << "virtual ::IceInternal::Handle< ::IceDelegateM::Ice::Object> __createDelegateM();"; + H << nl << "virtual ::IceInternal::Handle< ::IceDelegateD::Ice::Object> __createDelegateD();"; + 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; + C << nl << "bool" << nl << "IceProxy" << scope << "operator==(const ::IceProxy" << scoped + << "& l, const ::IceProxy" << scoped << "& r)"; + C << sb; + C << nl << "return static_cast<const ::IceProxy::Ice::Object&>(l) == " + << "static_cast<const ::IceProxy::Ice::Object&>(r);"; + C << eb; + C << sp; + C << nl << "bool" << nl << "IceProxy" << scope << "operator!=(const ::IceProxy" << scoped + << "& l, const ::IceProxy" << scoped << "& r)"; + C << sb; + C << nl << "return static_cast<const ::IceProxy::Ice::Object&>(l) != " + << "static_cast<const ::IceProxy::Ice::Object&>(r);"; + C << eb; + C << sp; + C << nl << "bool" << nl << "IceProxy" << scope << "operator<(const ::IceProxy" << scoped + << "& l, const ::IceProxy" << scoped << "& r)"; + C << sb; + C << nl << "return static_cast<const ::IceProxy::Ice::Object&>(l) < " + << "static_cast<const ::IceProxy::Ice::Object&>(r);"; + C << eb; +} + +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); + + vector<string> params; + vector<string> paramsDecl; + vector<string> args; + + vector<string> paramsAMI; + vector<string> paramsDeclAMI; + vector<string> argsAMI; + + ParamDeclList paramList = p->parameters(); + for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q) + { + string paramName = fixKwd((*q)->name()); + +#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()); + } + else + { + typeString = inputTypeToString((*q)->type()); + } +#else + string typeString = (*q)->isOutParam() ? outputTypeToString((*q)->type()) : inputTypeToString((*q)->type()); +#endif + + params.push_back(typeString); + paramsDecl.push_back(typeString + ' ' + paramName); + args.push_back(paramName); + + if(!(*q)->isOutParam()) + { + string inputTypeString = inputTypeToString((*q)->type()); + + paramsAMI.push_back(inputTypeString); + paramsDeclAMI.push_back(inputTypeString + ' ' + paramName); + argsAMI.push_back(paramName); + } + } + + string thisPointer = fixKwd(scope.substr(0, scope.size() - 2)) + "*"; + + H << sp; + H << nl << retS << ' ' << fixKwd(name) << spar << params << epar << ';'; + H << nl << retS << ' ' << fixKwd(name) << spar << params << "const ::Ice::Context&" << epar << ';'; + + C << sp << nl << retS << nl << "IceProxy" << scoped << spar << paramsDecl << epar; + C << sb; + C << nl; + if(ret) + { + C << "return "; + } + C << fixKwd(name) << spar << args << "__defaultContext()" << epar << ';'; + C << eb; + + 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 << "try"; + C << sb; + if(p->returnsData()) + { + C << nl << "__checkTwowayOnly(\"" << name << "\");"; + } + C << nl << "::IceInternal::Handle< ::IceDelegate::Ice::Object> __delBase = __getDelegate();"; + 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::NonRepeatable& __ex)"; + C << sb; + if(p->mode() == Operation::Idempotent || p->mode() == Operation::Nonmutating) + { + C << nl << "__handleException(*__ex.get(), __cnt);"; + } + else + { + C << nl << "__rethrowException(*__ex.get());"; + } + C << eb; + C << nl << "catch(const ::Ice::LocalException& __ex)"; + C << sb; + C << nl << "__handleException(__ex, __cnt);"; + C << eb; + C << eb; + C << eb; + + ContainerPtr container = p->container(); + ClassDefPtr cl = ClassDefPtr::dynamicCast(container); + if(cl->hasMetaData("ami") || p->hasMetaData("ami")) + { + string classNameAMI = "AMI_" + cl->name(); + string classScope = fixKwd(cl->scope()); + string classScopedAMI = classScope + classNameAMI; + + H << nl << "void " << name << "_async" << spar << ("const" + classScopedAMI + '_' + name + "Ptr&") + << paramsAMI << epar << ';'; + H << nl << "void " << name << "_async" << spar << ("const" + classScopedAMI + '_' + name + "Ptr&") + << paramsAMI << "const ::Ice::Context&" << epar << ';'; + + C << sp << nl << "void" << nl << "IceProxy" << scope << name << "_async" << spar + << ("const " + classScopedAMI + '_' + name + "Ptr& __cb") << paramsDeclAMI << epar; + C << sb; + C << nl << name << "_async" << spar << "__cb" << argsAMI << "__defaultContext()" << epar << ';'; + C << eb; + + C << sp << nl << "void" << nl << "IceProxy" << scope << name << "_async" << spar + << ("const " + classScopedAMI + '_' + name + "Ptr& __cb") << paramsDeclAMI << "const ::Ice::Context& __ctx" + << epar; + C << sb; + // Async requests may only be sent twoway. + C << nl << "__checkTwowayOnly(\"" << name << "\");"; + C << nl << "__cb->__invoke" << spar << "this" << argsAMI << "__ctx" << epar << ';'; + C << eb; + } +} + +Slice::Gen::DelegateVisitor::DelegateVisitor(Output& h, Output& c, const string& dllExport) : + H(h), C(c), _dllExport(dllExport) +{ +} + +bool +Slice::Gen::DelegateVisitor::visitUnitStart(const UnitPtr& p) +{ + if(!p->hasNonLocalClassDecls()) + { + 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->hasNonLocalClassDecls()) + { + return false; + } + + string name = fixKwd(p->name()); + + H << sp << nl << "namespace " << name << nl << '{'; + + return true; +} + +void +Slice::Gen::DelegateVisitor::visitModuleEnd(const ModulePtr& p) +{ + H << sp << nl << '}'; +} + +bool +Slice::Gen::DelegateVisitor::visitClassDefStart(const ClassDefPtr& p) +{ + if(p->isLocal()) + { + return false; + } + + 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 << ';'; +} + +void +Slice::Gen::DelegateVisitor::visitOperation(const OperationPtr& p) +{ + string name = fixKwd(p->name()); + + TypePtr ret = p->returnType(); + string retS = returnTypeToString(ret); + + vector<string> params; + + ParamDeclList paramList = p->parameters(); + for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q) + { +#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()); + } + else + { + typeString = inputTypeToString((*q)->type()); + } +#else + string typeString = (*q)->isOutParam() ? outputTypeToString((*q)->type()) : inputTypeToString((*q)->type()); +#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) +{ +} + +bool +Slice::Gen::DelegateMVisitor::visitUnitStart(const UnitPtr& p) +{ + if(!p->hasNonLocalClassDecls()) + { + 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->hasNonLocalClassDecls()) + { + return false; + } + + string name = fixKwd(p->name()); + + H << sp << nl << "namespace " << name << nl << '{'; + + return true; +} + +void +Slice::Gen::DelegateMVisitor::visitModuleEnd(const ModulePtr& p) +{ + H << sp << nl << '}'; +} + +bool +Slice::Gen::DelegateMVisitor::visitClassDefStart(const ClassDefPtr& p) +{ + if(p->isLocal()) + { + return false; + } + + 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 << ';'; +} + +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); + + vector<string> params; + vector<string> paramsDecl; + + TypeStringList inParams; + TypeStringList 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(make_pair(type, paramName)); + typeString = outputTypeToString(type); + } + else + { + inParams.push_back(make_pair(type, paramName)); + typeString = inputTypeToString(type); + } + + params.push_back(typeString); + paramsDecl.push_back(typeString + ' ' + paramName); + } + + params.push_back("const ::Ice::Context&"); + paramsDecl.push_back("const ::Ice::Context& __context"); + + H << sp << nl << "virtual " << retS << ' ' << name << spar << params << epar << ';'; + C << sp << nl << retS << nl << "IceDelegateM" << scoped << spar << paramsDecl << epar; + C << sb; + C << nl << "static const ::std::string __operation(\"" << p->name() << "\");"; + C << nl << "::IceInternal::Outgoing __out(__connection.get(), __reference.get(), __operation, " + << "static_cast< ::Ice::OperationMode>(" << p->mode() << "), __context, __compress);"; + if(!inParams.empty()) + { + C << nl << "try"; + C << sb; + C << nl << "::IceInternal::BasicStream* __os = __out.os();"; + writeMarshalCode(C, inParams, 0); + if(p->sendsClasses()) + { + C << nl << "__os->writePendingObjects();"; + } + C << eb; + C << nl << "catch(const ::Ice::LocalException& __ex)"; + C << sb; + C << nl << "__out.abort(__ex);"; + C << eb; + } + C << nl << "bool __ok = __out.invoke();"; + C << nl << "try"; + C << sb; + C << nl << "::IceInternal::BasicStream* __is = __out.is();"; + C << nl << "if(!__ok)"; + C << sb; + C << nl << "__is->throwException();"; + C << eb; + writeAllocateCode(C, TypeStringList(), ret); + writeUnmarshalCode(C, outParams, ret); + if(p->returnsClasses()) + { + C << nl << "__is->readPendingObjects();"; + } + if(ret) + { + C << nl << "return __ret;"; + } + 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) + { + string scoped = (*i)->scoped(); + C << nl << "catch(const " << fixKwd((*i)->scoped()) << "&)"; + C << sb; + C << nl << "throw;"; + C << eb; + } + C << nl << "catch(const ::Ice::UserException&)"; + C << sb; + C << nl << "throw ::Ice::UnknownUserException(__FILE__, __LINE__);"; + C << eb; + C << nl << "catch(const ::Ice::LocalException& __ex)"; + C << sb; + C << nl << "throw ::IceInternal::NonRepeatable(__ex);"; + C << eb; + C << eb; +} + +Slice::Gen::DelegateDVisitor::DelegateDVisitor(Output& h, Output& c, const string& dllExport) : + H(h), C(c), _dllExport(dllExport) +{ +} + +bool +Slice::Gen::DelegateDVisitor::visitUnitStart(const UnitPtr& p) +{ + if(!p->hasNonLocalClassDecls()) + { + 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->hasNonLocalClassDecls()) + { + return false; + } + + string name = fixKwd(p->name()); + + H << sp << nl << "namespace " << name << nl << '{'; + + return true; +} + +void +Slice::Gen::DelegateDVisitor::visitModuleEnd(const ModulePtr& p) +{ + H << sp << nl << '}'; +} + +bool +Slice::Gen::DelegateDVisitor::visitClassDefStart(const ClassDefPtr& p) +{ + if(p->isLocal()) + { + return false; + } + + 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 << ';'; +} + +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); + + vector<string> params; + vector<string> paramsDecl; + vector<string> args; + + ParamDeclList paramList = p->parameters(); + for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q) + { + string paramName = fixKwd((*q)->name()); + +#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()); + } + else + { + typeString = inputTypeToString((*q)->type()); + } +#else + string typeString = (*q)->isOutParam() ? outputTypeToString((*q)->type()) : inputTypeToString((*q)->type()); +#endif + + params.push_back(typeString); + paramsDecl.push_back(typeString + ' ' + paramName); + args.push_back(paramName); + } + + params.push_back("const ::Ice::Context&"); + paramsDecl.push_back("const ::Ice::Context& __context"); + args.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__);"; + C << eb; + } + else + { + C << sp << nl << retS << nl << "IceDelegateD" << scoped << spar << paramsDecl << epar; + C << sb; + C << nl << "::Ice::Current __current;"; + C << nl << "__initCurrent(__current, \"" << p->name() + << "\", static_cast< ::Ice::OperationMode>(" << p->mode() << "), __context);"; + C << nl << "while(true)"; + C << sb; + C << nl << "::IceInternal::Direct __direct(__current);"; + C << nl << thisPointer << " __servant = dynamic_cast< " << thisPointer << ">(__direct.servant().get());"; + C << nl << "if(!__servant)"; + C << sb; + C << nl << "::Ice::OperationNotExistException __opEx(__FILE__, __LINE__);"; + C << nl << "__opEx.id = __current.id;"; + C << nl << "__opEx.facet = __current.facet;"; + C << nl << "__opEx.operation = __current.operation;"; + C << nl << "throw __opEx;"; + C << eb; + C << nl << "try"; + C << sb; + C << nl; + if(ret) + { + C << "return "; + } + C << "__servant->" << name << spar << args << epar << ';'; + if(!ret) + { + C << nl << "return;"; + } + C << eb; + C << nl << "catch(const ::Ice::LocalException& __ex)"; + C << sb; + C << nl << "throw ::IceInternal::NonRepeatable(__ex);"; + C << eb; + C << eb; + 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 << _dllExport << "bool operator==(const " << name << "&, const " << name << "&);"; + H << nl << _dllExport << "bool operator!=(const " << name << "&, const " << name << "&);"; + H << nl << _dllExport << "bool operator<(const " << name << "&, const " << name << "&);"; +} + +Slice::Gen::ObjectVisitor::ObjectVisitor(Output& h, Output& c, const string& dllExport, bool stream) : + H(h), C(c), _dllExport(dllExport), _stream(stream) +{ +} + +bool +Slice::Gen::ObjectVisitor::visitModuleStart(const ModulePtr& p) +{ + if(!p->hasClassDefs()) + { + return false; + } + + 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 << '}'; +} + +bool +Slice::Gen::ObjectVisitor::visitClassDefStart(const ClassDefPtr& p) +{ + string name = fixKwd(p->name()); + ClassList bases = p->bases(); + + H << sp; + H << 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(); + while(q != bases.end()) + { + H << "virtual public " << fixKwd((*q)->scoped()); + if(++q != bases.end()) + { + H << ',' << nl; + } + } + } + H.restoreIndent(); + H << sb; + H.dec(); + H << nl << "public:"; + H.inc(); + + if(!p->isAbstract() && !p->isLocal()) + { + H << sp << nl << "void __copyMembers(" << fixKwd(p->scoped() + "Ptr") + ") const;"; + + C << sp; + C << nl << "void "; + C << nl << fixKwd(p->scoped()).substr(2) << "::__copyMembers(" << fixKwd(p->scoped() + "Ptr") << " __to) const"; + C << sb; + string winUpcall; + string unixUpcall; + if(!bases.empty() && !bases.front()->isInterface()) + { + winUpcall = fixKwd(bases.front()->name()) + "::__copyMembers(__to);"; + unixUpcall = fixKwd(bases.front()->scoped()) + "::__copyMembers(__to);"; + } + else + { + winUpcall = "Object::__copyMembers(__to);"; + unixUpcall = "::Ice::Object::__copyMembers(__to);"; + } + C.zeroIndent(); + C << nl << "#if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug"; // COMPILERBUG + C.restoreIndent(); + C << nl << winUpcall; + C.zeroIndent(); + C << nl << "#else"; + C.restoreIndent(); + C << nl << unixUpcall; + C.zeroIndent(); + C << nl << "#endif"; + C.restoreIndent(); + DataMemberList dataMembers = p->dataMembers(); + for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q) + { + C << nl << "__to->" << fixKwd((*q)->name()) << " = " << fixKwd((*q)->name()) << ';'; + } + C << eb; + + H << nl << "virtual ::Ice::ObjectPtr ice_clone() const;"; + + C << sp; + C << nl << "::Ice::ObjectPtr"; + C << nl << fixKwd(p->scoped()).substr(2) << "::ice_clone() const"; + C << sb; + C << nl << fixKwd(p->scope()) << p->name() << "Ptr __p = new " << fixKwd(p->scoped()) << ';'; + C.zeroIndent(); + C << nl << "#if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug"; // COMPILERBUG + C.restoreIndent(); + C << nl << fixKwd(name) + "::__copyMembers(__p);"; + C.zeroIndent(); + C << nl << "#else"; + C.restoreIndent(); + C << nl << fixKwd(p->scoped()) + "::__copyMembers(__p);"; + C.zeroIndent(); + C << nl << "#endif"; + C.restoreIndent(); + C << nl << "return __p;"; + C << eb; + } + + if(!p->isLocal()) + { + 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 = ice_distance(firstIter, scopedIter); + + StringList::const_iterator q; + + 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();"; + + string flatName = p->flattenedScope() + p->name() + "_ids"; + + C << sp; + C << nl << "static const ::std::string " << flatName << '[' << ids.size() << "] ="; + C << sb; + q = ids.begin(); + while(q != ids.end()) + { + C << nl << '"' << *q << '"'; + if(++q != ids.end()) + { + C << ','; + } + } + C << eb << ';'; + + C << sp; + C << nl << "bool" << nl << fixKwd(p->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 << fixKwd(p->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 << fixKwd(p->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 << fixKwd(p->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 ::IceInternal::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 << "::IceInternal::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 << "return ::IceInternal::DispatchOperationNotExist;"; + 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 << "return ::IceInternal::DispatchOperationNotExist;"; + C << eb; + } + + H << sp; + H << nl << "virtual void __write(::IceInternal::BasicStream*) const;"; + H << nl << "virtual void __read(::IceInternal::BasicStream*, bool);"; + H << nl << "virtual void __write(const ::Ice::OutputStreamPtr&) const;"; + H << nl << "virtual void __read(const ::Ice::InputStreamPtr&, bool);"; + + TypeStringList memberList; + DataMemberList dataMembers = p->dataMembers(); + for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q) + { + memberList.push_back(make_pair((*q)->type(), (*q)->name())); + } + 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();"; + writeMarshalCode(C, memberList, 0); + C << nl << "__os->endWriteSlice();"; + C.zeroIndent(); + C << nl << "#if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug"; // COMPILERBUG + C.restoreIndent(); + C << nl << (base ? fixKwd(base->name()) : "Object") << "::__write(__os);"; + C.zeroIndent(); + C << nl << "#else"; + C.restoreIndent(); + C << nl << (base ? fixKwd(base->scoped()) : "::Ice::Object") << "::__write(__os);"; + C.zeroIndent(); + C << nl << "#endif"; + C.restoreIndent(); + 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();"; + writeUnmarshalCode(C, memberList, 0); + C << nl << "__is->endReadSlice();"; + C.zeroIndent(); + C << nl << "#if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug"; // COMPILERBUG + C.restoreIndent(); + C << nl << (base ? fixKwd(base->name()) : "Object") << "::__read(__is, true);"; + C.zeroIndent(); + C << nl << "#else"; + C.restoreIndent(); + C << nl << (base ? fixKwd(base->scoped()) : "::Ice::Object") << "::__read(__is, true);"; + C.zeroIndent(); + C << nl << "#endif"; + C.restoreIndent(); + C << eb; + + if(_stream) + { + C << sp; + C << nl << "void" << nl << scoped.substr(2) << "::__write(const ::Ice::OutputStreamPtr& __out) const"; + C << sb; + C << nl << "__out->writeTypeId(ice_staticId());"; + C << nl << "__out->startSlice();"; + writeStreamMarshalCode(C, memberList, 0); + C << nl << "__out->endSlice();"; + C.zeroIndent(); + C << nl << "#if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug"; // COMPILERBUG + C.restoreIndent(); + C << nl << (base ? fixKwd(base->name()) : "Object") << "::__write(__out);"; + C.zeroIndent(); + C << nl << "#else"; + C.restoreIndent(); + C << nl << (base ? fixKwd(base->scoped()) : "::Ice::Object") << "::__write(__out);"; + C.zeroIndent(); + C << nl << "#endif"; + C.restoreIndent(); + C << eb; + C << sp; + C << nl << "void" << nl << scoped.substr(2) << "::__read(const ::Ice::InputStreamPtr& __in, bool __rid)"; + C << sb; + C << nl << "if(__rid)"; + C << sb; + C << nl << "__in->readTypeId();"; + C << eb; + C << nl << "__in->startSlice();"; + writeStreamUnmarshalCode(C, memberList, 0); + C << nl << "__in->endSlice();"; + C.zeroIndent(); + C << nl << "#if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug"; // COMPILERBUG + C.restoreIndent(); + C << nl << (base ? fixKwd(base->name()) : "Object") << "::__read(__in, true);"; + C.zeroIndent(); + C << nl << "#else"; + C.restoreIndent(); + C << nl << (base ? fixKwd(base->scoped()) : "::Ice::Object") << "::__read(__in, true);"; + C.zeroIndent(); + C << nl << "#endif"; + C.restoreIndent(); + C << eb; + } + else + { + // + // Emit placeholder functions to catch errors. + // + C << sp; + 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; + } + + 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 << "::Ice::factoryTable->addObjectFactory(" << scoped << "::ice_staticId(), " + << scoped << "::ice_factory());"; + C << eb; + C << sp << nl << "~" << factoryName << "__Init()"; + C << sb; + C << nl << "::Ice::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"; + } + } + + H << eb << ';'; + + if(!p->isAbstract() && !p->isLocal()) + { + H << sp << nl << "static " << scoped << " __" << p->name() << "_init;"; + } + + if(p->isLocal()) + { + C << sp; + C << nl << "bool" << nl << scope.substr(2) << "operator==(const " << scoped + << "& l, const " << scoped << "& r)"; + C << sb; + C << nl << "return static_cast<const ::Ice::LocalObject&>(l) == static_cast<const ::Ice::LocalObject&>(r);"; + C << eb; + C << sp; + C << nl << "bool" << nl << scope.substr(2) << "operator!=(const " << scoped + << "& l, const " << scoped << "& r)"; + C << sb; + C << nl << "return static_cast<const ::Ice::LocalObject&>(l) != static_cast<const ::Ice::LocalObject&>(r);"; + C << eb; + C << sp; + C << nl << "bool" << nl << scope.substr(2) << "operator<(const " << scoped + << "& l, const " << scoped << "& r)"; + C << sb; + C << nl << "return static_cast<const ::Ice::LocalObject&>(l) < static_cast<const ::Ice::LocalObject&>(r);"; + C << eb; + } + else + { + string name = p->name(); + + H << sp << nl << "void " << _dllExport << "__patch__" << name << "Ptr(void*, ::Ice::ObjectPtr&);"; + + C << sp << nl << "void " << _dllExport; + C << nl << scope.substr(2) << "__patch__" << name << "Ptr(void* __addr, ::Ice::ObjectPtr& v)"; + C << sb; + C << nl << scope << name << "Ptr* p = static_cast< " << scope << name << "Ptr*>(__addr);"; + C << nl << "assert(p);"; + C << nl << "*p = " << scope << name << "Ptr::dynamicCast(v);"; + C << nl << "if(v && !*p)"; + C << sb; + C << nl << "::Ice::NoObjectFactoryException e(__FILE__, __LINE__);"; + C << nl << "e.type = " << scope << fixKwd(name) << "::ice_staticId();"; + C << nl << "throw e;"; + C << eb; + C << eb; + + C << sp; + C << nl << "bool" << nl << scope.substr(2) << "operator==(const " << scoped + << "& l, const " << scoped << "& r)"; + C << sb; + C << nl << "return static_cast<const ::Ice::Object&>(l) == static_cast<const ::Ice::Object&>(r);"; + C << eb; + C << sp; + C << nl << "bool" << nl << scope.substr(2) << "operator!=(const " << scoped + << "& l, const " << scoped << "& r)"; + C << sb; + C << nl << "return static_cast<const ::Ice::Object&>(l) != static_cast<const ::Ice::Object&>(r);"; + C << eb; + C << sp; + C << nl << "bool" << nl << scope.substr(2) << "operator<(const " << scoped + << "& l, const " << scoped << "& r)"; + C << sb; + C << nl << "return static_cast<const ::Ice::Object&>(l) < static_cast<const ::Ice::Object&>(r);"; + C << eb; + } +} + +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); + + 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, "; + + TypeStringList inParams; + TypeStringList 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(make_pair(type, paramName)); + typeString = outputTypeToString(type); + } + else + { + inParams.push_back(make_pair(type, paramName)); + typeString = inputTypeToString((*q)->type()); + } + + 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 nonmutating = p->mode() == Operation::Nonmutating; + bool amd = !cl->isLocal() && (cl->hasMetaData("amd") || p->hasMetaData("amd")); + + H << sp; + if(!amd) + { + H << nl << "virtual " << retS << ' ' << fixKwd(name) << params + << (nonmutating ? " const" : "") << " = 0;"; + } + else + { + H << nl << "virtual void " << name << "_async" << paramsAMD + << (nonmutating ? " const" : "") << " = 0;"; + } + + if(!cl->isLocal()) + { + H << nl << "::IceInternal::DispatchStatus ___" << name + << "(::IceInternal::Incoming&, const ::Ice::Current&)" << (nonmutating ? " const" : "") << ';'; + + C << sp; + C << nl << "::IceInternal::DispatchStatus" << nl << scope.substr(2) << "___" << name + << "(::IceInternal::Incoming& __in, const ::Ice::Current& __current)" << (nonmutating ? " 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 + + if(!inParams.empty()) + { + C << nl << "::IceInternal::BasicStream* __is = __in.is();"; + } + if(ret || !outParams.empty() || !throws.empty()) + { + C << nl << "::IceInternal::BasicStream* __os = __in.os();"; + } + writeAllocateCode(C, inParams, 0); + writeUnmarshalCode(C, inParams, 0); + if(p->sendsClasses()) + { + C << nl << "__is->readPendingObjects();"; + } + writeAllocateCode(C, outParams, 0); + if(!throws.empty()) + { + C << nl << "try"; + C << sb; + } + C << nl; + if(ret) + { + C << retS << " __ret = "; + } + C << fixKwd(name) << args << ';'; + writeMarshalCode(C, outParams, ret); + 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 ::IceInternal::DispatchUserException;"; + C << eb; + } + } + C << nl << "return ::IceInternal::DispatchOK;"; + } + else + { + if(!inParams.empty()) + { + C << nl << "::IceInternal::BasicStream* __is = __in.is();"; + } + writeAllocateCode(C, inParams, 0); + writeUnmarshalCode(C, inParams, 0); + if(p->sendsClasses()) + { + C << nl << "__is->readPendingObjects();"; + } + C << nl << classScopedAMD << '_' << name << "Ptr __cb = new IceAsync" << classScopedAMD << '_' << name + << "(__in);"; + C << nl << "try"; + C << sb; + C << nl << name << "_async" << argsAMD << ';'; + C << eb; + C << nl << "catch(const ::Ice::Exception& __ex)"; + C << sb; + C << nl << "__cb->ice_exception(__ex);"; + 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 ::IceInternal::DispatchAsync;"; + } + C << eb; + } +} + +void +Slice::Gen::ObjectVisitor::visitDataMember(const DataMemberPtr& p) +{ + string name = fixKwd(p->name()); + string s = typeToString(p->type()); + H << sp; + H << nl << s << ' ' << name << ';'; +} + +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() and __decRef() and, hence, consider instances + // of the class as candidates for collection by the garbage collector. + // We override __incRef() and __decRef() 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 __incRef();"; + + C << sp << nl << "void" << nl << scoped.substr(2) << "::__incRef()"; + C << sb; + C << nl << "IceUtil::gcRecMutex._m->lock();"; + C << nl << "assert(_ref >= 0);"; + C << nl << "if(_ref == 0)"; + C << sb; + C.zeroIndent(); + C << nl << "#ifdef NDEBUG // To avoid annoying warnings about variables that are not used..."; + C.restoreIndent(); + C << nl << "IceUtil::gcObjects.insert(this);"; + C.zeroIndent(); + C << nl << "#else"; + C.restoreIndent(); + C << nl << "std::pair<IceUtil::GCObjectSet::iterator, bool> rc = IceUtil::gcObjects.insert(this);"; + C << nl << "assert(rc.second);"; + C.zeroIndent(); + C << nl << "#endif"; + C.restoreIndent(); + C << eb; + C << nl << "++_ref;"; + C << nl << "IceUtil::gcRecMutex._m->unlock();"; + C << eb; + + H << nl << "virtual void __decRef();"; + + C << sp << nl << "void" << nl << scoped.substr(2) << "::__decRef()"; + C << sb; + C << nl << "IceUtil::gcRecMutex._m->lock();"; + C << nl << "bool doDelete = false;"; + C << nl << "assert(_ref > 0);"; + C << nl << "if(--_ref == 0)"; + C << sb; + C << nl << "doDelete = !_noDelete;"; + C << nl << "_noDelete = true;"; + C.zeroIndent(); + C << nl << "#ifdef NDEBUG // To avoid annoying warnings about variables that are not used..."; + C.restoreIndent(); + C << nl << "IceUtil::gcObjects.erase(this);"; + C.zeroIndent(); + C << nl << "#else"; + C.restoreIndent(); + C << nl << "IceUtil::GCObjectSet::size_type num = IceUtil::gcObjects.erase(this);"; + C << nl << "assert(num == 1);"; + C.zeroIndent(); + C << nl << "#endif"; + C.restoreIndent(); + C << eb; + C << nl << "IceUtil::gcRecMutex._m->unlock();"; + C << nl << "if(doDelete)"; + C << sb; + C << nl << "delete this;"; + C << eb; + 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(::IceUtil::GCObjectMultiSet&) const;"; + + C << sp << nl << "void" << nl << scoped.substr(2) << "::__gcReachable(::IceUtil::GCObjectMultiSet& _c) const"; + C << sb; + + string vc6Prefix; + string otherPrefix; + + bool hasCyclicBase = hasBaseClass && bases.front()->canBeCyclic(); + if(hasCyclicBase) + { + vc6Prefix = bases.front()->name(); + otherPrefix = bases.front()->scoped(); + + // + // Up-call to the base's __gcReachable() member function. + // + C.zeroIndent(); + C << nl << "#if defined(_MSC_VER) && (MSC_VER < 1300) // VC++ 6 compiler bug"; + C.restoreIndent(); + C << nl << vc6Prefix << "::__gcReachable(_c);"; + C.zeroIndent(); + C << nl << "#else"; + C.restoreIndent(); + C << nl << otherPrefix << "::__gcReachable(_c);"; + C.zeroIndent(); + C << nl << "#endif"; + C.restoreIndent(); + } + 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) + { + // + // Up-call to the base's __gcClear() member function. + // + C.zeroIndent(); + C << nl << "#if defined(_MSC_VER) && (MSC_VER < 1300) // VC++ 6 compiler bug"; + C.restoreIndent(); + C << nl << vc6Prefix<< "::__gcClear();"; + C.zeroIndent(); + C << nl << "#else"; + C.restoreIndent(); + C << nl << otherPrefix << "::__gcClear();"; + C.zeroIndent(); + C << nl << "#endif"; + C.restoreIndent(); + } + 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 << "__addObject(_c, " << prefix << name << ".get());"; + } + else if(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 d = DictionaryPtr::dynamicCast(p)) + { + string scoped = fixKwd(d->scoped()); + stringstream 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 s = SequencePtr::dynamicCast(p)) + { + string scoped = fixKwd(s->scoped()); + stringstream 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; + C << nl << prefix << name << "->__decRefUnsafe();"; + C << nl << prefix << name << ".__clearHandleUnsafe();"; + C << eb; + } + else if(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 d = DictionaryPtr::dynamicCast(p)) + { + string scoped = fixKwd(d->scoped()); + stringstream 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 s = SequencePtr::dynamicCast(p)) + { + string scoped = fixKwd(s->scoped()); + stringstream 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;; + } +} + +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; + H << nl << _dllExport << "void incRef(" << scoped << "*);"; + H << nl << _dllExport << "void decRef(" << scoped << "*);"; + if(!p->isLocal()) + { + H << sp; + H << nl << _dllExport << "void incRef(::IceProxy" << scoped << "*);"; + H << nl << _dllExport << "void decRef(::IceProxy" << scoped << "*);"; + } +} + +bool +Slice::Gen::IceInternalVisitor::visitClassDefStart(const ClassDefPtr& p) +{ + string scoped = fixKwd(p->scoped()); + + C << sp; + C << nl << "void" << nl << "IceInternal::incRef(" << scoped << "* p)"; + C << sb; + C << nl << "p->__incRef();"; + C << eb; + + C << sp; + C << nl << "void" << nl << "IceInternal::decRef(" << scoped << "* p)"; + C << sb; + C << nl << "p->__decRef();"; + C << eb; + + if(!p->isLocal()) + { + C << sp; + C << nl << "void" << nl << "IceInternal::incRef(::IceProxy" << scoped << "* p)"; + C << sb; + C << nl << "p->__incRef();"; + C << eb; + + C << sp; + C << nl << "void" << nl << "IceInternal::decRef(::IceProxy" << scoped << "* p)"; + C << sb; + C << nl << "p->__decRef();"; + C << eb; + } + + 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 __write(::IceInternal::BasicStream*, const " << name << "Prx&);"; + H << nl << _dllExport << "void __read(::IceInternal::BasicStream*, " << name << "Prx&);"; + H << nl << _dllExport << "void __write(::IceInternal::BasicStream*, const " << name << "Ptr&);"; + H << nl << _dllExport << "void __patch__" << name << "Ptr(void*, ::Ice::ObjectPtr&);"; + if(_stream) + { + H << sp; + H << nl << _dllExport << "void ice_write" << name << "Prx(const ::Ice::OutputStreamPtr&, const " << name + << "Prx&);"; + H << nl << _dllExport << "void ice_read" << name << "Prx(const ::Ice::InputStreamPtr&, " << name + << "Prx&);"; + + H << nl << _dllExport << "void ice_write" << name << "(const ::Ice::OutputStreamPtr&, const " + << name << "Ptr&);"; + H << nl << _dllExport << "void ice_read" << name << "(const ::Ice::InputStreamPtr&, " << name << "Ptr&);"; + } + } +} + +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) << "__write(::IceInternal::BasicStream* __os, const " + << scope << name << "Prx& v)"; + C << sb; + C << nl << "__os->write(::Ice::ObjectPrx(v));"; + C << eb; + + 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; + + C << sp; + C << nl << "void" << nl << scope.substr(2) << "__write(::IceInternal::BasicStream* __os, const " + << scope << name << "Ptr& v)"; + C << sb; + C << nl << "__os->write(::Ice::ObjectPtr(v));"; + C << eb; + + if(_stream) + { + C << sp; + C << nl << "void" << nl << scope.substr(2) << "ice_write" << name + << "Prx(const ::Ice::OutputStreamPtr& __out, const " << scope << name << "Prx& v)"; + C << sb; + C << nl << "__out->writeProxy(v);"; + C << eb; + + C << sp; + C << nl << "void" << nl << scope.substr(2) << "ice_read" << name + << "Prx(const ::Ice::InputStreamPtr& __in, " << scope << name << "Prx& v)"; + C << sb; + C << nl << "::Ice::ObjectPrx proxy = __in->readProxy();"; + 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; + + C << sp; + C << nl << "void" << nl << scope.substr(2) << "ice_write" << name + << "(const ::Ice::OutputStreamPtr& __out, const " << scope << name << "Ptr& v)"; + C << sb; + C << nl << "__out->writeObject(v);"; + C << eb; + + C << sp; + C << nl << "void" << nl << scope.substr(2) << "ice_read" << name << "(const ::Ice::InputStreamPtr& __in, " + << scoped << "Ptr& __v)"; + C << sb; + C << nl << "::Ice::ReadObjectCallbackPtr __cb = new ::Ice::ReadObjectCallbackI(" << scope << "__patch__" + << name << "Ptr, &__v);"; + C << nl << "__in->readObject(__cb);"; + C << eb; + } + } + + return true; +} + +Slice::Gen::ImplVisitor::ImplVisitor(Output& h, Output& c, + const string& dllExport) : + H(h), C(c), _dllExport(dllExport) +{ +} + +void +Slice::Gen::ImplVisitor::writeDecl(Output& out, const string& name, const TypePtr& type) +{ + out << nl << typeToString(type) << ' ' << 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) +{ + 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 " << fixKwd(seq->scoped()) << "();"; + } + 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; + } + + 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 << '}'; +} + +bool +Slice::Gen::ImplVisitor::visitClassDefStart(const ClassDefPtr& p) +{ + if(!p->isAbstract()) + { + return false; + } + + 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(); + ClassDefPtr base; + if(!bases.empty() && !bases.front()->isInterface()) + { + base = bases.front(); + } + + 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); + + 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()); + } + } + H << ',' << nl << "const Ice::Current&"; + H.restoreIndent(); + + bool nonmutating = op->mode() == Operation::Nonmutating; + + H << ")" << (nonmutating ? " 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()) << ' ' << fixKwd((*q)->name()); + } + } + C << ',' << nl << "const Ice::Current& current"; + C.restoreIndent(); + C << ")" << (nonmutating ? " 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); + } + for(q = paramList.begin(); q != paramList.end(); ++q) + { + if((*q)->isOutParam()) + { + writeDecl(C, fixKwd((*q)->name()), (*q)->type()); + } + } + + 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; + } +#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()); + } + else + { + typeString = inputTypeToString((*q)->type()); + } +#else + string typeString = (*q)->isOutParam() ? + outputTypeToString((*q)->type()) : inputTypeToString((*q)->type()); +#endif + H << typeString; + } + if(!p->isLocal()) + { + if(!paramList.empty()) + { + H << ',' << nl; + } + H << "const Ice::Current&"; + } + H.restoreIndent(); + + bool nonmutating = op->mode() == Operation::Nonmutating; + + H << ")" << (nonmutating ? " 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; + } +#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()); + } + else + { + typeString = inputTypeToString((*q)->type()); + } +#else + string typeString = (*q)->isOutParam() ? + outputTypeToString((*q)->type()) : inputTypeToString((*q)->type()); +#endif + C << typeString << ' ' << fixKwd((*q)->name()); + } + if(!p->isLocal()) + { + if(!paramList.empty()) + { + C << ',' << nl; + } + C << "const Ice::Current& current"; + } + C.restoreIndent(); + C << ')'; + C << (nonmutating ? " const" : ""); + C << sb; + + if(ret) + { + writeReturn(C, ret); + } + + C << eb; + } + } + + H << eb << ';'; + + return true; +} + +Slice::Gen::AsyncVisitor::AsyncVisitor(Output& h, Output& c, const string& dllExport) : + H(h), C(c), _dllExport(dllExport) +{ +} + +bool +Slice::Gen::AsyncVisitor::visitModuleStart(const ModulePtr& p) +{ + if(!p->hasNonLocalClassDecls() || (!p->hasContentsWithMetaData("ami") && !p->hasContentsWithMetaData("amd"))) + { + return false; + } + + string name = fixKwd(p->name()); + + H << sp << nl << "namespace " << name << nl << '{'; + + return true; +} + +void +Slice::Gen::AsyncVisitor::visitModuleEnd(const ModulePtr& p) +{ + H << sp << nl << '}'; +} + +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> 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); + + if(ret) + { + params.push_back(retS); + paramsDecl.push_back(retS + " __ret"); + args.push_back("__ret"); + } + + TypeStringList inParams; + TypeStringList 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); + + if((*q)->isOutParam()) + { + params.push_back(typeString); + paramsDecl.push_back(typeString + ' ' + paramName); + args.push_back(paramName); + + outParams.push_back(make_pair(type, paramName)); + } + else + { + paramsInvoke.push_back(typeString); + paramsDeclInvoke.push_back(typeString + ' ' + paramName); + + inParams.push_back(make_pair(type, paramName)); + } + } + + 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 ::IceInternal::OutgoingAsync"; + H << sb; + H.dec(); + H << nl << "public:"; + H.inc(); + H << sp; + H << nl << "virtual void ice_response" << spar << params << epar << " = 0;"; + H << nl << "virtual void ice_exception(const ::Ice::Exception&) = 0;"; + H << sp; + H << nl << "void __invoke" << spar << paramsInvoke << epar << ';'; + H << sp; + H.dec(); + H << nl << "protected:"; + H.inc(); + H << sp; + H << nl << "virtual void __response(bool);"; + H << eb << ';'; + H << sp << nl << "typedef ::IceUtil::Handle< " << classScopedAMI << '_' << name << "> " << classNameAMI + << '_' << name << "Ptr;"; + + C << sp << nl << "void" << nl << classScopedAMI.substr(2) << '_' << name << "::__invoke" << spar + << paramsDeclInvoke << epar; + C << sb; + C << nl << "try"; + C << sb; + C << nl << "static const ::std::string __operation(\"" << name << "\");"; + C << nl << "__prepare(__prx, __operation, static_cast< ::Ice::OperationMode>(" << p->mode() << "), __ctx);"; + writeMarshalCode(C, inParams, 0); + if(p->sendsClasses()) + { + C << nl << "__os->writePendingObjects();"; + } + C << nl << "__os->endWriteEncaps();"; + C << eb; + C << nl << "catch(const ::Ice::LocalException& __ex)"; + C << sb; + C << nl << "__finished(__ex);"; + C << nl << "return;"; + C << eb; + C << nl << "__send();"; + C << eb; + + C << sp << nl << "void" << nl << classScopedAMI.substr(2) << '_' << name << "::__response(bool __ok)"; + C << sb; + writeAllocateCode(C, outParams, ret); + C << nl << "try"; + C << sb; + C << nl << "if(!__ok)"; + C << sb; + C << nl << "__is->throwException();"; + C << eb; + writeUnmarshalCode(C, outParams, ret); + if(p->returnsClasses()) + { + C << nl << "__is->readPendingObjects();"; + } + C << eb; + C << nl << "catch(const ::Ice::LocalException& __ex)"; + C << sb; + C << nl << "__finished(__ex);"; + C << nl << "return;"; + 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()) << "& __ex)"; + C << sb; + C << nl << "ice_exception(__ex);"; + C << nl << "return;"; + C << eb; + } + C << nl << "catch(const ::Ice::UserException&)"; + C << sb; + C << nl << "ice_exception(::Ice::UnknownUserException(__FILE__, __LINE__));"; + C << nl << "return;"; + C << eb; + C << nl << "ice_response" << spar << args << epar << ';'; + C << eb; + } + + if(cl->hasMetaData("amd") || p->hasMetaData("amd")) + { + H << sp << nl << "class " << _dllExport << classNameAMD << '_' << name + << " : virtual public ::IceUtil::Shared"; + H << sb; + H.dec(); + H << nl << "public:"; + H.inc(); + H << sp; + H << nl << "virtual void ice_response" << spar << params << epar << " = 0;"; + H << nl << "virtual void ice_exception(const ::Ice::Exception&) = 0;"; + H << nl << "virtual void ice_exception(const ::std::exception&) = 0;"; + H << nl << "virtual void ice_exception() = 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) +{ +} + +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; + } + + string name = fixKwd(p->name()); + + H << sp << nl << "namespace " << name << nl << '{'; + + return true; +} + +void +Slice::Gen::AsyncImplVisitor::visitModuleEnd(const ModulePtr& p) +{ + H << sp << nl << '}'; +} + +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); + + if(ret) + { + params += retS; + paramsDecl += retS; + paramsDecl += ' '; + paramsDecl += "__ret"; + args += "__ret"; + } + + TypeStringList 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); + + if(ret || !outParams.empty()) + { + params += ", "; + paramsDecl += ", "; + args += ", "; + } + + params += typeString; + paramsDecl += typeString; + paramsDecl += ' '; + paramsDecl += paramName; + args += paramName; + + outParams.push_back(make_pair(type, paramName)); + } + } + + 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 << ");"; + H << nl << "virtual void ice_exception(const ::Ice::Exception&);"; + H << nl << "virtual void ice_exception(const ::std::exception&);"; + H << nl << "virtual void ice_exception();"; + H << eb << ';'; + + C << sp << nl << "IceAsync" << classScopedAMD << '_' << name << "::" << classNameAMD << '_' << name + << "(::IceInternal::Incoming& in) :"; + C.inc(); + C << nl << "IncomingAsync(in)"; + C.dec(); + C << sb; + C << eb; + + C << sp << nl << "void" << nl << "IceAsync" << classScopedAMD << '_' << name << "::ice_response(" + << paramsDecl << ')'; + C << sb; + if(ret || !outParams.empty()) + { + C << nl << "try"; + C << sb; + C << nl << "::IceInternal::BasicStream* __os = this->__os();"; + writeMarshalCode(C, outParams, ret); + 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 << sp << nl << "void" << nl << "IceAsync" << classScopedAMD << '_' << name + << "::ice_exception(const ::Ice::Exception& ex)"; + C << sb; + if(throws.empty()) + { + C << nl << "__exception(ex);"; + } + else + { + C << nl << "try"; + C << sb; + C << nl << "ex.ice_throw();"; + 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);"; + if((*r)->usesClasses()) + { + C << nl << "__os()->writePendingObjects();"; + } + C << nl << "__response(false);"; + C << eb; + } + C << nl << "catch(const ::Ice::Exception& __ex)"; + C << sb; + C << nl << "__exception(__ex);"; + C << eb; + } + C << eb; + + C << sp << nl << "void" << nl << "IceAsync" << classScopedAMD << '_' << name + << "::ice_exception(const ::std::exception& ex)"; + C << sb; + C << nl << "__exception(ex);"; + C << eb; + + C << sp << nl << "void" << nl << "IceAsync" << classScopedAMD << '_' << name + << "::ice_exception()"; + C << sb; + C << nl << "__exception();"; + C << eb; +} + +void +Slice::Gen::validateMetaData(const UnitPtr& unit) +{ + MetaDataVisitor visitor; + unit->visit(&visitor, false); +} + +bool +Slice::Gen::MetaDataVisitor::visitModuleStart(const ModulePtr& p) +{ + validate(p); + return true; +} + +void +Slice::Gen::MetaDataVisitor::visitModuleEnd(const ModulePtr&) +{ +} + +void +Slice::Gen::MetaDataVisitor::visitClassDecl(const ClassDeclPtr& p) +{ + validate(p); +} + +bool +Slice::Gen::MetaDataVisitor::visitClassDefStart(const ClassDefPtr& p) +{ + validate(p); + return true; +} + +void +Slice::Gen::MetaDataVisitor::visitClassDefEnd(const ClassDefPtr&) +{ +} + +bool +Slice::Gen::MetaDataVisitor::visitExceptionStart(const ExceptionPtr& p) +{ + validate(p); + return true; +} + +void +Slice::Gen::MetaDataVisitor::visitExceptionEnd(const ExceptionPtr&) +{ +} + +bool +Slice::Gen::MetaDataVisitor::visitStructStart(const StructPtr& p) +{ + validate(p); + return true; +} + +void +Slice::Gen::MetaDataVisitor::visitStructEnd(const StructPtr&) +{ +} + +void +Slice::Gen::MetaDataVisitor::visitOperation(const OperationPtr& p) +{ + validate(p); +} + +void +Slice::Gen::MetaDataVisitor::visitParamDecl(const ParamDeclPtr& p) +{ + validate(p); +} + +void +Slice::Gen::MetaDataVisitor::visitDataMember(const DataMemberPtr& p) +{ + validate(p); +} + +void +Slice::Gen::MetaDataVisitor::visitSequence(const SequencePtr& p) +{ + validate(p); +} + +void +Slice::Gen::MetaDataVisitor::visitDictionary(const DictionaryPtr& p) +{ + validate(p); +} + +void +Slice::Gen::MetaDataVisitor::visitEnum(const EnumPtr& p) +{ + validate(p); +} + +void +Slice::Gen::MetaDataVisitor::visitConst(const ConstPtr& p) +{ + validate(p); +} + +void +Slice::Gen::MetaDataVisitor::validate(const ContainedPtr& cont) +{ + DefinitionContextPtr dc = cont->definitionContext(); + assert(dc); + StringList globalMetaData = dc->getMetaData(); + string file = dc->filename(); + + StringList localMetaData = cont->getMetaData(); + + StringList::const_iterator p; + static const string prefix = "cpp:"; + + for(p = globalMetaData.begin(); p != globalMetaData.end(); ++p) + { + string s = *p; + if(_history.count(s) == 0) + { + if(s.find(prefix) == 0) + { + cout << file << ": warning: ignoring invalid global metadata `" << s << "'" << endl; + } + _history.insert(s); + } + } + + for(p = localMetaData.begin(); p != localMetaData.end(); ++p) + { + string s = *p; + if(_history.count(s) == 0) + { + if(s.find(prefix) == 0) + { + if(SequencePtr::dynamicCast(cont)) + { + if(s.substr(prefix.size()) == "collection") + { + continue; + } + } + if(StructPtr::dynamicCast(cont)) + { + if(s.substr(prefix.size()) == "class") + { + continue; + } + } + cout << file << ": warning: ignoring invalid metadata `" << s << "'" << endl; + } + _history.insert(s); + } + } +} diff --git a/cpp/src/slice2cppe/Gen.h b/cpp/src/slice2cppe/Gen.h new file mode 100644 index 00000000000..f32715b3fb1 --- /dev/null +++ b/cpp/src/slice2cppe/Gen.h @@ -0,0 +1,383 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2005 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 : public ::IceUtil::noncopyable +{ +public: + + Gen(const std::string&, + const std::string&, + const std::string&, + const std::string&, + const std::string&, + const std::vector<std::string>&, + const std::string&, + const std::string&, + bool, + bool, + bool); + ~Gen(); + + bool operator!() const; // Returns true if there was a constructor error + + void generate(const UnitPtr&); + +private: + + ::IceUtil::Output H; + ::IceUtil::Output C; + + ::IceUtil::Output implH; + ::IceUtil::Output implC; + + std::string _base; + std::string _headerExtension; + std::string _sourceExtension; + std::string _include; + std::vector<std::string> _includePaths; + std::string _dllExport; + bool _impl; + bool _checksum; + bool _stream; + + class TypesVisitor : public ::IceUtil::noncopyable, public ParserVisitor + { + public: + + TypesVisitor(::IceUtil::Output&, ::IceUtil::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 emitExceptionBase(const ExceptionPtr&, const std::string&); + + ::IceUtil::Output& H; + ::IceUtil::Output& C; + + std::string _dllExport; + bool _stream; + }; + + class ProxyDeclVisitor : public ::IceUtil::noncopyable, public ParserVisitor + { + public: + + ProxyDeclVisitor(::IceUtil::Output&, ::IceUtil::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: + + ::IceUtil::Output& H; + ::IceUtil::Output& C; + + std::string _dllExport; + }; + + class ProxyVisitor : public ::IceUtil::noncopyable, public ParserVisitor + { + public: + + ProxyVisitor(::IceUtil::Output&, ::IceUtil::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: + + ::IceUtil::Output& H; + ::IceUtil::Output& C; + + std::string _dllExport; + }; + + class DelegateVisitor : public ::IceUtil::noncopyable, public ParserVisitor + { + public: + + DelegateVisitor(::IceUtil::Output&, ::IceUtil::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: + + ::IceUtil::Output& H; + ::IceUtil::Output& C; + + std::string _dllExport; + }; + + class DelegateMVisitor : public ::IceUtil::noncopyable, public ParserVisitor + { + public: + + DelegateMVisitor(::IceUtil::Output&, ::IceUtil::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: + + ::IceUtil::Output& H; + ::IceUtil::Output& C; + + std::string _dllExport; + }; + + class DelegateDVisitor : public ::IceUtil::noncopyable, public ParserVisitor + { + public: + + DelegateDVisitor(::IceUtil::Output&, ::IceUtil::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: + + ::IceUtil::Output& H; + ::IceUtil::Output& C; + + std::string _dllExport; + }; + + class ObjectDeclVisitor : public ::IceUtil::noncopyable, public ParserVisitor + { + public: + + ObjectDeclVisitor(::IceUtil::Output&, ::IceUtil::Output&, const std::string&); + + virtual bool visitModuleStart(const ModulePtr&); + virtual void visitModuleEnd(const ModulePtr&); + virtual void visitClassDecl(const ClassDeclPtr&); + + private: + + ::IceUtil::Output& H; + ::IceUtil::Output& C; + + std::string _dllExport; + }; + + class ObjectVisitor : public ::IceUtil::noncopyable, public ParserVisitor + { + public: + + ObjectVisitor(::IceUtil::Output&, ::IceUtil::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&); + virtual void visitDataMember(const DataMemberPtr&); + + 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); + + ::IceUtil::Output& H; + ::IceUtil::Output& C; + + std::string _dllExport; + bool _stream; + }; + + class IceInternalVisitor : public ::IceUtil::noncopyable, public ParserVisitor + { + public: + + IceInternalVisitor(::IceUtil::Output&, ::IceUtil::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: + + ::IceUtil::Output& H; + ::IceUtil::Output& C; + + std::string _dllExport; + }; + + class HandleVisitor : public ::IceUtil::noncopyable, public ParserVisitor + { + public: + + HandleVisitor(::IceUtil::Output&, ::IceUtil::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: + + ::IceUtil::Output& H; + ::IceUtil::Output& C; + + std::string _dllExport; + bool _stream; + }; + + class ImplVisitor : public ::IceUtil::noncopyable, public ParserVisitor + { + public: + + ImplVisitor(::IceUtil::Output&, ::IceUtil::Output&, const std::string&); + + virtual bool visitModuleStart(const ModulePtr&); + virtual void visitModuleEnd(const ModulePtr&); + virtual bool visitClassDefStart(const ClassDefPtr&); + + private: + + ::IceUtil::Output& H; + ::IceUtil::Output& C; + + std::string _dllExport; + + // + // Generate code to emit a local variable declaration and initialize it + // if necessary. + // + void writeDecl(::IceUtil::Output&, const std::string&, const TypePtr&); + + // + // Generate code to return a dummy value + // + void writeReturn(::IceUtil::Output&, const TypePtr&); + }; + + class AsyncVisitor : public ::IceUtil::noncopyable, public ParserVisitor + { + public: + + AsyncVisitor(::IceUtil::Output&, ::IceUtil::Output&, const std::string&); + + virtual bool visitModuleStart(const ModulePtr&); + virtual void visitModuleEnd(const ModulePtr&); + virtual void visitOperation(const OperationPtr&); + + private: + + ::IceUtil::Output& H; + ::IceUtil::Output& C; + + std::string _dllExport; + }; + + class AsyncImplVisitor : public ::IceUtil::noncopyable, public ParserVisitor + { + public: + + AsyncImplVisitor(::IceUtil::Output&, ::IceUtil::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 visitOperation(const OperationPtr&); + + private: + + ::IceUtil::Output& H; + ::IceUtil::Output& C; + + std::string _dllExport; + }; + +private: + + class MetaDataVisitor : public ParserVisitor + { + public: + + 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 visitParamDecl(const ParamDeclPtr&); + 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 ContainedPtr&); + + StringSet _history; + }; + + static void validateMetaData(const UnitPtr&); +}; + +} + +#endif diff --git a/cpp/src/slice2cppe/Main.cpp b/cpp/src/slice2cppe/Main.cpp new file mode 100644 index 00000000000..d60fc9032ef --- /dev/null +++ b/cpp/src/slice2cppe/Main.cpp @@ -0,0 +1,205 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2005 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 <Slice/Preprocessor.h> +#include <Gen.h> + +using namespace std; +using namespace Slice; + +void +usage(const char* n) +{ + cerr << "Usage: " << n << " [options] slice-files...\n"; + cerr << + "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" + "-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" + "--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" + "--checksum Generate checksums for Slice definitions.\n" + "--stream Generate marshaling support for public stream API.\n" + ; + // Note: --case-sensitive is intentionally not shown here! +} + +int +main(int argc, char* argv[]) +{ + string cppArgs; + vector<string> includePaths; + string include; + string output; + string dllExport; + bool impl; + bool depend; + bool debug; + bool ice; + bool checksum; + bool stream; + bool caseSensitive; + + IceUtil::Options opts; + opts.addOpt("h", "help"); + opts.addOpt("v", "version"); + opts.addOpt("", "header-ext", IceUtil::Options::NeedArg, "h"); + opts.addOpt("", "source-ext", IceUtil::Options::NeedArg, "cpp"); + opts.addOpt("D", "", IceUtil::Options::NeedArg, "", IceUtil::Options::Repeat); + opts.addOpt("U", "", IceUtil::Options::NeedArg, "", IceUtil::Options::Repeat); + opts.addOpt("I", "", IceUtil::Options::NeedArg, "", IceUtil::Options::Repeat); + opts.addOpt("", "include-dir", IceUtil::Options::NeedArg); + opts.addOpt("", "output-dir", IceUtil::Options::NeedArg); + opts.addOpt("", "dll-export", IceUtil::Options::NeedArg); + opts.addOpt("", "impl"); + opts.addOpt("", "depend"); + opts.addOpt("d", "debug"); + opts.addOpt("", "ice"); + opts.addOpt("", "checksum"); + opts.addOpt("", "stream"); + opts.addOpt("", "case-sensitive"); + + vector<string> args; + try + { + args = opts.parse(argc, argv); + } + catch(const IceUtil::Options::BadOpt& e) + { + cerr << argv[0] << ": " << e.reason << endl; + usage(argv[0]); + return EXIT_FAILURE; + } + + if(opts.isSet("h") || opts.isSet("help")) + { + usage(argv[0]); + return EXIT_SUCCESS; + } + if(opts.isSet("v") || opts.isSet("version")) + { + cout << ICE_STRING_VERSION << endl; + return EXIT_SUCCESS; + } + + string headerExtension = opts.optArg("header-ext"); + string sourceExtension = opts.optArg("source-ext"); + + if(opts.isSet("D")) + { + vector<string> optargs = opts.argVec("D"); + for(vector<string>::const_iterator i = optargs.begin(); i != optargs.end(); ++i) + { + cppArgs += " -D" + *i; + } + } + if(opts.isSet("U")) + { + vector<string> optargs = opts.argVec("U"); + for(vector<string>::const_iterator i = optargs.begin(); i != optargs.end(); ++i) + { + cppArgs += " -U" + *i; + } + } + if(opts.isSet("I")) + { + includePaths = opts.argVec("I"); + for(vector<string>::const_iterator i = includePaths.begin(); i != includePaths.end(); ++i) + { + cppArgs += " -I" + *i; + } + } + if(opts.isSet("include-dir")) + { + include = opts.optArg("include-dir"); + } + if(opts.isSet("output-dir")) + { + output = opts.optArg("output-dir"); + } + if(opts.isSet("dll-export")) + { + dllExport = opts.optArg("dll-export"); + } + impl = opts.isSet("impl"); + depend = opts.isSet("depend"); + debug = opts.isSet("d") || opts.isSet("debug"); + ice = opts.isSet("ice"); + checksum = opts.isSet("checksum"); + stream = opts.isSet("stream"); + caseSensitive = opts.isSet("case-sensitive"); + + if(args.empty()) + { + cerr << argv[0] << ": no input file" << endl; + usage(argv[0]); + return EXIT_FAILURE; + } + + int status = EXIT_SUCCESS; + + for(vector<string>::const_iterator i = args.begin(); i != args.end(); ++i) + { + if(depend) + { + Preprocessor icecpp(argv[0], *i, cppArgs); + icecpp.printMakefileDependencies(Preprocessor::CPlusPlus); + } + else + { + Preprocessor icecpp(argv[0], *i, cppArgs); + FILE* cppHandle = icecpp.preprocess(false); + + if(cppHandle == 0) + { + return EXIT_FAILURE; + } + + UnitPtr u = Unit::createUnit(false, false, ice, caseSensitive); + int parseStatus = u->parse(cppHandle, debug, false); + + if(!icecpp.close()) + { + u->destroy(); + return EXIT_FAILURE; + } + + if(parseStatus == EXIT_FAILURE) + { + status = EXIT_FAILURE; + } + else + { + Gen gen(argv[0], icecpp.getBaseName(), headerExtension, sourceExtension, include, + includePaths, dllExport, output, impl, checksum, stream); + if(!gen) + { + u->destroy(); + return EXIT_FAILURE; + } + gen.generate(u); + } + + u->destroy(); + } + } + + return status; +} diff --git a/cpp/src/slice2cppe/Makefile b/cpp/src/slice2cppe/Makefile new file mode 100644 index 00000000000..f21c48b538b --- /dev/null +++ b/cpp/src/slice2cppe/Makefile @@ -0,0 +1,32 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2005 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/slice2cppe + +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) + +install:: all + $(INSTALL_PROGRAM) $(NAME) $(install_bindir) + +include .depend diff --git a/cpp/src/slice2cppe/slice2cppe.dsp b/cpp/src/slice2cppe/slice2cppe.dsp new file mode 100644 index 00000000000..8e909c1b8b8 --- /dev/null +++ b/cpp/src/slice2cppe/slice2cppe.dsp @@ -0,0 +1,126 @@ +# Microsoft Developer Studio Project File - Name="slice2cppe" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=slice2cppe - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "slice2cppe.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "slice2cppe.mak" CFG="slice2cppe - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "slice2cppe - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "slice2cppe - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "slice2cppe - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /WX /GR /GX /O2 /I "." /I "../../include" /D "NDEBUG" /D "_CONSOLE" /FD /c
+# SUBTRACT CPP /Fr /YX
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 setargv.obj /nologo /subsystem:console /incremental:yes /machine:I386
+# SUBTRACT LINK32 /debug /nodefaultlib
+# Begin Special Build Tool
+OutDir=.\Release
+TargetName=slice2cppe
+SOURCE="$(InputPath)"
+PostBuild_Cmds=copy $(OutDir)\$(TargetName).exe ..\..\bin
+# End Special Build Tool
+
+!ELSEIF "$(CFG)" == "slice2cppe - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /WX /Gm /GR /GX /Zi /Od /I "." /I "../../include" /D "_DEBUG" /D "_CONSOLE" /FD /GZ /c
+# SUBTRACT CPP /Fr /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 setargv.obj /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# SUBTRACT LINK32 /incremental:no /nodefaultlib
+# Begin Special Build Tool
+OutDir=.\Debug
+TargetName=slice2cppe
+SOURCE="$(InputPath)"
+PostBuild_Cmds=copy $(OutDir)\$(TargetName).exe ..\..\bin
+# End Special Build Tool
+
+!ENDIF
+
+# Begin Target
+
+# Name "slice2cppe - Win32 Release"
+# Name "slice2cppe - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\Gen.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\Main.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\Gen.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/cpp/src/slice2javae/.depend b/cpp/src/slice2javae/.depend new file mode 100644 index 00000000000..f8bf3e4fd9f --- /dev/null +++ b/cpp/src/slice2javae/.depend @@ -0,0 +1,2 @@ +Gen.o: Gen.cpp Gen.h ../../include/Slice/Parser.h ../../include/IceUtil/Shared.h ../../include/IceUtil/Config.h ../../include/IceUtil/Handle.h ../../include/IceUtil/Exception.h ../../include/IceUtil/InputUtil.h ../../include/Slice/JavaUtil.h ../../include/IceUtil/OutputUtil.h ../../include/Slice/Checksum.h ../../include/IceUtil/Functional.h ../../include/IceUtil/Algorithm.h ../../include/IceUtil/Iterator.h +Main.o: Main.cpp ../../include/IceUtil/Options.h ../../include/IceUtil/Config.h ../../include/IceUtil/RecMutex.h ../../include/IceUtil/Lock.h ../../include/IceUtil/ThreadException.h ../../include/IceUtil/Exception.h ../../include/Slice/Preprocessor.h Gen.h ../../include/Slice/Parser.h ../../include/IceUtil/Shared.h ../../include/IceUtil/Handle.h ../../include/IceUtil/InputUtil.h ../../include/Slice/JavaUtil.h ../../include/IceUtil/OutputUtil.h ../../include/Slice/Checksum.h diff --git a/cpp/src/slice2javae/Gen.cpp b/cpp/src/slice2javae/Gen.cpp new file mode 100644 index 00000000000..e92cadc18cc --- /dev/null +++ b/cpp/src/slice2javae/Gen.cpp @@ -0,0 +1,5008 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2005 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 <Gen.h> +#include <Slice/Checksum.h> +#include <IceUtil/Functional.h> +#include <IceUtil/Algorithm.h> +#include <IceUtil/Iterator.h> + +#include <limits> + +using namespace std; +using namespace Slice; + +// +// Don't use "using namespace IceUtil", or stupid VC++ 6.0 complains +// about ambigious symbols for constructs like +// "IceUtil::constMemFun(&Slice::Exception::isLocal)". +// +using IceUtil::Output; +using IceUtil::nl; +using IceUtil::sp; +using IceUtil::sb; +using IceUtil::eb; +using IceUtil::spar; +using IceUtil::epar; + +static string +sliceModeToIceMode(const OperationPtr& op) +{ + string mode; + switch(op->mode()) + { + case Operation::Normal: + { + mode = "Ice.OperationMode.Normal"; + break; + } + case Operation::Nonmutating: + { + mode = "Ice.OperationMode.Nonmutating"; + break; + } + case Operation::Idempotent: + { + mode = "Ice.OperationMode.Idempotent"; + break; + } + default: + { + assert(false); + break; + } + } + return mode; +} + +Slice::JavaVisitor::JavaVisitor(const string& dir) : + JavaGenerator(dir) +{ +} + +Slice::JavaVisitor::~JavaVisitor() +{ +} + +vector<string> +Slice::JavaVisitor::getParams(const OperationPtr& op, const string& package) +{ + vector<string> params; + + ParamDeclList paramList = op->parameters(); + for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q) + { + StringList metaData = (*q)->getMetaData(); + string typeString = typeToString((*q)->type(), (*q)->isOutParam() ? TypeModeOut : TypeModeIn, package, + metaData); + params.push_back(typeString + ' ' + fixKwd((*q)->name())); + } + + return params; +} + +vector<string> +Slice::JavaVisitor::getParamsAsync(const OperationPtr& op, const string& package, bool amd) +{ + vector<string> params; + + string name = op->name(); + ContainerPtr container = op->container(); + ClassDefPtr cl = ClassDefPtr::dynamicCast(container); + string classNameAsync = getAbsolute(cl, package, amd ? "AMD_" : "AMI_", '_' + name); + params.push_back(classNameAsync + " __cb"); + + ParamDeclList paramList = op->parameters(); + for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q) + { + if(!(*q)->isOutParam()) + { + StringList metaData = (*q)->getMetaData(); + string typeString = typeToString((*q)->type(), TypeModeIn, package, metaData); + params.push_back(typeString + ' ' + fixKwd((*q)->name())); + } + } + + return params; +} + +vector<string> +Slice::JavaVisitor::getParamsAsyncCB(const OperationPtr& op, const string& package) +{ + vector<string> params; + + TypePtr ret = op->returnType(); + if(ret) + { + string retS = typeToString(ret, TypeModeIn, package, op->getMetaData()); + params.push_back(retS + " __ret"); + } + + ParamDeclList paramList = op->parameters(); + for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q) + { + if((*q)->isOutParam()) + { + string typeString = typeToString((*q)->type(), TypeModeIn, package, (*q)->getMetaData()); + params.push_back(typeString + ' ' + fixKwd((*q)->name())); + } + } + + return params; +} + +vector<string> +Slice::JavaVisitor::getArgs(const OperationPtr& op) +{ + vector<string> args; + + ParamDeclList paramList = op->parameters(); + for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q) + { + args.push_back(fixKwd((*q)->name())); + } + + return args; +} + +vector<string> +Slice::JavaVisitor::getArgsAsync(const OperationPtr& op) +{ + vector<string> args; + + args.push_back("__cb"); + + ParamDeclList paramList = op->parameters(); + for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q) + { + if(!(*q)->isOutParam()) + { + args.push_back(fixKwd((*q)->name())); + } + } + + return args; +} + +vector<string> +Slice::JavaVisitor::getArgsAsyncCB(const OperationPtr& op) +{ + vector<string> args; + + TypePtr ret = op->returnType(); + if(ret) + { + BuiltinPtr builtin = BuiltinPtr::dynamicCast(ret); + if((builtin && builtin->kind() == Builtin::KindObject) || ClassDeclPtr::dynamicCast(ret)) + { + args.push_back("__ret.value"); + } + else + { + args.push_back("__ret"); + } + } + + ParamDeclList paramList = op->parameters(); + for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q) + { + if((*q)->isOutParam()) + { + BuiltinPtr builtin = BuiltinPtr::dynamicCast((*q)->type()); + if((builtin && builtin->kind() == Builtin::KindObject) || ClassDeclPtr::dynamicCast((*q)->type())) + { + args.push_back(fixKwd((*q)->name()) + ".value"); + } + else + { + args.push_back(fixKwd((*q)->name())); + } + } + } + + return args; +} + +void +Slice::JavaVisitor::writeThrowsClause(const string& package, const ExceptionList& throws) +{ + Output& out = output(); + if(throws.size() > 0) + { + out.inc(); + out << nl << "throws "; + out.useCurrentPosAsIndent(); + ExceptionList::const_iterator r; + int count = 0; + for(r = throws.begin(); r != throws.end(); ++r) + { + if(count > 0) + { + out << "," << nl; + } + out << getAbsolute(*r, package); + count++; + } + out.restoreIndent(); + out.dec(); + } +} + +void +Slice::JavaVisitor::writeDelegateThrowsClause(const string& package, const ExceptionList& throws) +{ + Output& out = output(); + out.inc(); + out << nl << "throws "; + out.useCurrentPosAsIndent(); + out << "IceInternal.NonRepeatable"; + + ExceptionList::const_iterator r; + for(r = throws.begin(); r != throws.end(); ++r) + { + out << "," << nl; + out << getAbsolute(*r, package); + } + out.restoreIndent(); + out.dec(); +} + +void +Slice::JavaVisitor::writeHashCode(Output& out, const TypePtr& type, const string& name, int& iter, + const StringList& metaData) +{ + BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); + if(builtin) + { + switch(builtin->kind()) + { + case Builtin::KindByte: + case Builtin::KindShort: + case Builtin::KindLong: + { + out << nl << "__h = 5 * __h + (int)" << name << ';'; + break; + } + case Builtin::KindBool: + { + out << nl << "__h = 5 * __h + (" << name << " ? 1 : 0);"; + break; + } + case Builtin::KindInt: + { + out << nl << "__h = 5 * __h + " << name << ';'; + break; + } + case Builtin::KindFloat: + { + out << nl << "__h = 5 * __h + java.lang.Float.floatToIntBits(" << name << ");"; + break; + } + case Builtin::KindDouble: + { + out << nl << "__h = 5 * __h + (int)java.lang.Double.doubleToLongBits(" << name << ");"; + break; + } + case Builtin::KindString: + { + out << nl << "if(" << name << " != null)"; + out << sb; + out << nl << "__h = 5 * __h + " << name << ".hashCode();"; + out << eb; + break; + } + case Builtin::KindObject: + case Builtin::KindObjectProxy: + case Builtin::KindLocalObject: + { + out << nl << "if(" << name << " != null)"; + out << sb; + out << nl << "__h = 5 * __h + " << name << ".hashCode();"; + out << eb; + break; + } + } + return; + } + + ProxyPtr prx = ProxyPtr::dynamicCast(type); + ClassDeclPtr cl = ClassDeclPtr::dynamicCast(type); + DictionaryPtr dict = DictionaryPtr::dynamicCast(type); + if(prx || cl || dict) + { + out << nl << "if(" << name << " != null)"; + out << sb; + out << nl << "__h = 5 * __h + " << name << ".hashCode();"; + out << eb; + return; + } + + SequencePtr seq = SequencePtr::dynamicCast(type); + if(seq) + { + string listType = findMetaData(metaData); + if(listType.empty()) + { + StringList l = seq->getMetaData(); + listType = findMetaData(l); + } + + out << nl << "if(" << name << " != null)"; + out << sb; + if(!listType.empty()) + { + out << nl << "__h = 5 * __h + " << name << ".hashCode();"; + } + else + { + out << nl << "for(int __i" << iter << " = 0; __i" << iter << " < " << name << ".length; __i" << iter + << "++)"; + out << sb; + ostringstream elem; + elem << name << "[__i" << iter << ']'; + iter++; + writeHashCode(out, seq->type(), elem.str(), iter); + out << eb; + } + out << eb; + return; + } + + ConstructedPtr constructed = ConstructedPtr::dynamicCast(type); + assert(constructed); + out << nl << "__h = 5 * __h + " << name << ".hashCode();"; +} + +void +Slice::JavaVisitor::writeDispatch(Output& out, const ClassDefPtr& p) +{ + string name = fixKwd(p->name()); + string package = getPackage(p); + string scoped = p->scoped(); + ClassList bases = p->bases(); + + ClassList allBases = p->allBases(); + StringList ids; + transform(allBases.begin(), allBases.end(), back_inserter(ids), ::IceUtil::constMemFun(&Contained::scoped)); + StringList other; + other.push_back(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(), scoped); + assert(scopedIter != ids.end()); + StringList::difference_type scopedPos = ice_distance(firstIter, scopedIter); + + out << sp << nl << "public static final String[] __ids ="; + out << sb; + + { + StringList::const_iterator q = ids.begin(); + while(q != ids.end()) + { + out << nl << '"' << *q << '"'; + if(++q != ids.end()) + { + out << ','; + } + } + } + out << eb << ';'; + + out << sp << nl << "public boolean" << nl << "ice_isA(String s)"; + out << sb; + out << nl << "return java.util.Arrays.binarySearch(__ids, s) >= 0;"; + out << eb; + + out << sp << nl << "public boolean" << nl << "ice_isA(String s, Ice.Current __current)"; + out << sb; + out << nl << "return java.util.Arrays.binarySearch(__ids, s) >= 0;"; + out << eb; + + out << sp << nl << "public String[]" << nl << "ice_ids()"; + out << sb; + out << nl << "return __ids;"; + out << eb; + + out << sp << nl << "public String[]" << nl << "ice_ids(Ice.Current __current)"; + out << sb; + out << nl << "return __ids;"; + out << eb; + + out << sp << nl << "public String" << nl << "ice_id()"; + out << sb; + out << nl << "return __ids[" << scopedPos << "];"; + out << eb; + + out << sp << nl << "public String" << nl << "ice_id(Ice.Current __current)"; + out << sb; + out << nl << "return __ids[" << scopedPos << "];"; + out << eb; + + out << sp << nl << "public static String" << nl << "ice_staticId()"; + out << sb; + out << nl << "return __ids[" << scopedPos << "];"; + out << eb; + + OperationList ops = p->allOperations(); + OperationList::const_iterator r; + + // + // Write the "no Current" implementation of each operation. + // + for(r = ops.begin(); r != ops.end(); ++r) + { + OperationPtr op = *r; + string opName = op->name(); + + ContainerPtr container = op->container(); + ClassDefPtr cl = ClassDefPtr::dynamicCast(container); + assert(cl); + + bool amd = cl->hasMetaData("amd") || op->hasMetaData("amd"); + + vector<string> params; + vector<string> args; + TypePtr ret; + + if(amd) + { + opName += "_async"; + params = getParamsAsync(op, package, true); + args = getArgsAsync(op); + } + else + { + opName = fixKwd(opName); + ret = op->returnType(); + params = getParams(op, package); + args = getArgs(op); + } + + ExceptionList throws = op->throws(); + throws.sort(); + throws.unique(); + + // + // Only generate a "no current" version of the operation if it hasn't been done in a base + // class already, because the "no current" version is final. + // + bool generateOperation = cl == p; // Generate if the operation is defined in this class. + if(!generateOperation) + { + // + // The operation is not defined in this class. + // + ClassList bases = p->bases(); + if(!bases.empty()) + { + // + // Check if the operation is already implemented by a base class. + // + bool implementedByBase = false; + if(!bases.front()->isInterface()) + { + OperationList baseOps = bases.front()->allOperations(); + OperationList::const_iterator i; + for(i = baseOps.begin(); i != baseOps.end(); ++i) + { + if((*i)->name() == op->name()) + { + implementedByBase = true; + break; + } + } + if(i == baseOps.end()) + { + generateOperation = true; + } + } + if(!generateOperation && !implementedByBase) + { + // + // No base class defines the operation. Check if one of the + // interfaces defines it, in which case this class must provide it. + // + if(bases.front()->isInterface() || bases.size() > 1) + { + generateOperation = true; + } + } + } + } + if(generateOperation) + { + out << sp << nl << "public final " << typeToString(ret, TypeModeReturn, package, op->getMetaData()) + << nl << opName << spar << params << epar; + writeThrowsClause(package, throws); + out << sb << nl; + if(ret) + { + out << nl << "return "; + } + out << opName << spar << args << "null" << epar << ';'; + out << eb; + } + } + + // + // Dispatch operations. We only generate methods for operations + // defined in this ClassDef, because we reuse existing methods + // for inherited operations. + // + ops = p->operations(); + for(r = ops.begin(); r != ops.end(); ++r) + { + OperationPtr op = *r; + StringList opMetaData = op->getMetaData(); + ContainerPtr container = op->container(); + ClassDefPtr cl = ClassDefPtr::dynamicCast(container); + assert(cl); + + string opName = op->name(); + out << sp << nl << "public static IceInternal.DispatchStatus" << nl << "___" << opName << '(' << name + << " __obj, IceInternal.Incoming __in, Ice.Current __current)"; + out << sb; + + bool amd = cl->hasMetaData("amd") || op->hasMetaData("amd"); + if(!amd) + { + TypePtr ret = op->returnType(); + + ParamDeclList inParams; + ParamDeclList outParams; + ParamDeclList paramList = op->parameters(); + ParamDeclList::const_iterator pli; + for(pli = paramList.begin(); pli != paramList.end(); ++pli) + { + if((*pli)->isOutParam()) + { + outParams.push_back(*pli); + } + else + { + inParams.push_back(*pli); + } + } + + ExceptionList throws = op->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(Slice::derivedToBaseCompare); +#else + throws.sort(Slice::DerivedToBaseCompare()); +#endif + + int iter; + + if(!inParams.empty()) + { + out << nl << "IceInternal.BasicStream __is = __in.is();"; + } + if(!outParams.empty() || ret || !throws.empty()) + { + out << nl << "IceInternal.BasicStream __os = __in.os();"; + } + + // + // Unmarshal 'in' parameters. + // + iter = 0; + for(pli = inParams.begin(); pli != inParams.end(); ++pli) + { + StringList metaData = (*pli)->getMetaData(); + TypePtr paramType = (*pli)->type(); + string paramName = fixKwd((*pli)->name()); + string typeS = typeToString(paramType, TypeModeIn, package, metaData); + BuiltinPtr builtin = BuiltinPtr::dynamicCast(paramType); + if((builtin && builtin->kind() == Builtin::KindObject) || ClassDeclPtr::dynamicCast(paramType)) + { + out << nl << typeS << "Holder " << paramName << " = new " << typeS << "Holder();"; + writeMarshalUnmarshalCode(out, package, paramType, paramName, false, iter, true, + metaData, string()); + } + else + { + out << nl << typeS << ' ' << paramName << ';'; + writeMarshalUnmarshalCode(out, package, paramType, paramName, false, iter, false, metaData); + } + } + if(op->sendsClasses()) + { + out << nl << "__is.readPendingObjects();"; + } + + // + // Create holders for 'out' parameters. + // + for(pli = outParams.begin(); pli != outParams.end(); ++pli) + { + string typeS = typeToString((*pli)->type(), TypeModeOut, package, (*pli)->getMetaData()); + out << nl << typeS << ' ' << fixKwd((*pli)->name()) << " = new " << typeS << "();"; + } + + // + // Call on the servant. + // + if(!throws.empty()) + { + out << nl << "try"; + out << sb; + } + out << nl; + if(ret) + { + string retS = typeToString(ret, TypeModeReturn, package, opMetaData); + out << retS << " __ret = "; + } + out << "__obj." << fixKwd(opName) << '('; + for(pli = inParams.begin(); pli != inParams.end(); ++pli) + { + TypePtr paramType = (*pli)->type(); + out << fixKwd((*pli)->name()); + BuiltinPtr builtin = BuiltinPtr::dynamicCast(paramType); + if((builtin && builtin->kind() == Builtin::KindObject) || ClassDeclPtr::dynamicCast(paramType)) + { + out << ".value"; + } + out << ", "; + } + for(pli = outParams.begin(); pli != outParams.end(); ++pli) + { + out << fixKwd((*pli)->name()) << ", "; + } + out << "__current);"; + + // + // Marshal 'out' parameters and return value. + // + for(pli = outParams.begin(); pli != outParams.end(); ++pli) + { + writeMarshalUnmarshalCode(out, package, (*pli)->type(), fixKwd((*pli)->name()), true, iter, true, + (*pli)->getMetaData()); + } + if(ret) + { + writeMarshalUnmarshalCode(out, package, ret, "__ret", true, iter, false, opMetaData); + } + if(op->returnsClasses()) + { + out << nl << "__os.writePendingObjects();"; + } + out << nl << "return IceInternal.DispatchStatus.DispatchOK;"; + + // + // Handle user exceptions. + // + if(!throws.empty()) + { + out << eb; + ExceptionList::const_iterator t; + for(t = throws.begin(); t != throws.end(); ++t) + { + string exS = getAbsolute(*t, package); + out << nl << "catch(" << exS << " ex)"; + out << sb; + out << nl << "__os.writeUserException(ex);"; + out << nl << "return IceInternal.DispatchStatus.DispatchUserException;"; + out << eb; + } + } + + out << eb; + } + else + { + ParamDeclList inParams; + ParamDeclList paramList = op->parameters(); + ParamDeclList::const_iterator pli; + for(pli = paramList.begin(); pli != paramList.end(); ++pli) + { + if(!(*pli)->isOutParam()) + { + inParams.push_back(*pli); + } + } + + int iter; + + if(!inParams.empty()) + { + out << nl << "IceInternal.BasicStream __is = __in.is();"; + } + + // + // Unmarshal 'in' parameters. + // + iter = 0; + for(pli = inParams.begin(); pli != inParams.end(); ++pli) + { + StringList metaData = (*pli)->getMetaData(); + TypePtr paramType = (*pli)->type(); + string paramName = fixKwd((*pli)->name()); + string typeS = typeToString(paramType, TypeModeIn, package, metaData); + BuiltinPtr builtin = BuiltinPtr::dynamicCast(paramType); + if((builtin && builtin->kind() == Builtin::KindObject) || ClassDeclPtr::dynamicCast(paramType)) + { + out << nl << typeS << "Holder " << paramName << " = new " << typeS << "Holder();"; + writeMarshalUnmarshalCode(out, package, paramType, paramName, false, iter, true, metaData, + string()); + } + else + { + out << nl << typeS << ' ' << paramName << ';'; + writeMarshalUnmarshalCode(out, package, paramType, paramName, false, iter, false, metaData); + } + } + if(op->sendsClasses()) + { + out << nl << "__is.readPendingObjects();"; + } + + // + // Call on the servant. + // + string classNameAMD = "AMD_" + p->name(); + out << nl << classNameAMD << '_' << opName << " __cb = new _" << classNameAMD << '_' << opName + << "(__in);"; + out << nl << "try"; + out << sb; + out << nl << "__obj." << (amd ? opName + "_async" : fixKwd(opName)) << (amd ? "(__cb, " : "("); + for(pli = inParams.begin(); pli != inParams.end(); ++pli) + { + TypePtr paramType = (*pli)->type(); + out << fixKwd((*pli)->name()); + BuiltinPtr builtin = BuiltinPtr::dynamicCast(paramType); + if((builtin && builtin->kind() == Builtin::KindObject) || ClassDeclPtr::dynamicCast(paramType)) + { + out << ".value"; + } + out << ", "; + } + out << "__current);"; + out << eb; + out << nl << "catch(java.lang.Exception ex)"; + out << sb; + out << nl << "__cb.ice_exception(ex);"; + out << eb; + out << nl << "return IceInternal.DispatchStatus.DispatchAsync;"; + + out << eb; + } + } + + OperationList allOps = p->allOperations(); + if(!allOps.empty()) + { + StringList allOpNames; + transform(allOps.begin(), allOps.end(), back_inserter(allOpNames), ::IceUtil::constMemFun(&Contained::name)); + 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; + + out << sp << nl << "private final static String[] __all ="; + out << sb; + q = allOpNames.begin(); + while(q != allOpNames.end()) + { + out << nl << '"' << *q << '"'; + if(++q != allOpNames.end()) + { + out << ','; + } + } + out << eb << ';'; + + out << sp << nl << "public IceInternal.DispatchStatus" << nl + << "__dispatch(IceInternal.Incoming in, Ice.Current __current)"; + out << sb; + out << nl << "int pos = java.util.Arrays.binarySearch(__all, __current.operation);"; + out << nl << "if(pos < 0)"; + out << sb; + out << nl << "return IceInternal.DispatchStatus.DispatchOperationNotExist;"; + out << eb; + out << sp << nl << "switch(pos)"; + out << sb; + int i = 0; + for(q = allOpNames.begin(); q != allOpNames.end(); ++q) + { + string opName = *q; + + out << nl << "case " << i++ << ':'; + out << sb; + if(opName == "ice_id") + { + out << nl << "return ___ice_id(this, in, __current);"; + } + else if(opName == "ice_ids") + { + out << nl << "return ___ice_ids(this, in, __current);"; + } + else if(opName == "ice_isA") + { + out << nl << "return ___ice_isA(this, in, __current);"; + } + else if(opName == "ice_ping") + { + out << nl << "return ___ice_ping(this, in, __current);"; + } + else + { + // + // There's probably a better way to do this. + // + for(OperationList::const_iterator t = allOps.begin(); t != allOps.end(); ++t) + { + if((*t)->name() == (*q)) + { + ContainerPtr container = (*t)->container(); + ClassDefPtr cl = ClassDefPtr::dynamicCast(container); + assert(cl); + if(cl->scoped() == p->scoped()) + { + out << nl << "return ___" << opName << "(this, in, __current);"; + } + else + { + string base; + if(cl->isInterface()) + { + base = getAbsolute(cl, package, "_", "Disp"); + } + else + { + base = getAbsolute(cl, package); + } + out << nl << "return " << base << ".___" << opName << "(this, in, __current);"; + } + break; + } + } + } + out << eb; + } + out << eb; + out << sp << nl << "assert(false);"; + out << nl << "return IceInternal.DispatchStatus.DispatchOperationNotExist;"; + out << eb; + } +} + +Slice::Gen::Gen(const string& name, const string& base, const vector<string>& includePaths, const string& dir) : + _base(base), + _includePaths(includePaths), + _dir(dir) +{ +} + +Slice::Gen::~Gen() +{ +} + +bool +Slice::Gen::operator!() const +{ + return false; +} + +void +Slice::Gen::generate(const UnitPtr& p, bool stream) +{ + JavaGenerator::validateMetaData(p); + + OpsVisitor opsVisitor(_dir); + p->visit(&opsVisitor, false); + + PackageVisitor packageVisitor(_dir); + p->visit(&packageVisitor, false); + + TypesVisitor typesVisitor(_dir, stream); + p->visit(&typesVisitor, false); + + HolderVisitor holderVisitor(_dir, stream); + p->visit(&holderVisitor, false); + + HelperVisitor helperVisitor(_dir, stream); + p->visit(&helperVisitor, false); + + ProxyVisitor proxyVisitor(_dir); + p->visit(&proxyVisitor, false); + + DelegateVisitor delegateVisitor(_dir); + p->visit(&delegateVisitor, false); + + DelegateMVisitor delegateMVisitor(_dir); + p->visit(&delegateMVisitor, false); + + DelegateDVisitor delegateDVisitor(_dir); + p->visit(&delegateDVisitor, false); + + DispatcherVisitor dispatcherVisitor(_dir); + p->visit(&dispatcherVisitor, false); + + AsyncVisitor asyncVisitor(_dir); + p->visit(&asyncVisitor, false); +} + +void +Slice::Gen::generateTie(const UnitPtr& p) +{ + TieVisitor tieVisitor(_dir); + p->visit(&tieVisitor, false); +} + +void +Slice::Gen::generateImpl(const UnitPtr& p) +{ + ImplVisitor implVisitor(_dir); + p->visit(&implVisitor, false); +} + +void +Slice::Gen::generateImplTie(const UnitPtr& p) +{ + ImplTieVisitor implTieVisitor(_dir); + p->visit(&implTieVisitor, false); +} + +void +Slice::Gen::writeChecksumClass(const string& checksumClass, const string& dir, const ChecksumMap& m) +{ + // + // Attempt to open the source file for the checksum class. + // + JavaOutput out; + if(!out.openClass(checksumClass, dir)) + { + cerr << "can't open class `" << checksumClass << "' for writing: " << strerror(errno) << endl; + return; + } + + // + // Get the class name. + // + string className; + string::size_type pos = checksumClass.rfind('.'); + if(pos == string::npos) + { + className = checksumClass; + } + else + { + className = checksumClass.substr(pos + 1); + } + + // + // Emit the class. + // + out << sp << nl << "public class " << className; + out << sb; + + // + // Use a static initializer to populate the checksum map. + // + out << sp << nl << "public static java.util.Map checksums;"; + out << sp << nl << "static"; + out << sb; + out << nl << "java.util.Map map = new java.util.HashMap();"; + for(ChecksumMap::const_iterator p = m.begin(); p != m.end(); ++p) + { + out << nl << "map.put(\"" << p->first << "\", \""; + ostringstream str; + str.flags(ios_base::hex); + str.fill('0'); + for(vector<unsigned char>::const_iterator q = p->second.begin(); q != p->second.end(); ++q) + { + str << (int)(*q); + } + out << str.str() << "\");"; + } + out << nl << "checksums = java.util.Collections.unmodifiableMap(map);"; + + out << eb; + out << eb; + out << nl; +} + +Slice::Gen::OpsVisitor::OpsVisitor(const string& dir) : + JavaVisitor(dir) +{ +} + +bool +Slice::Gen::OpsVisitor::visitClassDefStart(const ClassDefPtr& p) +{ + // + // Don't generate an Operations interface for non-abstract classes + // + if(!p->isAbstract()) + { + return false; + } + + if(!p->isLocal()) + { + writeOperations(p, false); + } + writeOperations(p, true); + + return false; +} + +void +Slice::Gen::OpsVisitor::writeOperations(const ClassDefPtr& p, bool noCurrent) +{ + string name = p->name(); + ClassList bases = p->bases(); + string package = getPackage(p); + string opIntfName = "Operations"; + if(noCurrent || p->isLocal()) + { + opIntfName += "NC"; + } + string absolute = getAbsolute(p, "", "_", opIntfName); + + if(!open(absolute)) + { + return; + } + + Output& out = output(); + + // + // Generate the operations interface + // + out << sp << nl << "public interface " << '_' << name << opIntfName; + if((bases.size() == 1 && bases.front()->isAbstract()) || bases.size() > 1) + { + out << " extends "; + out.useCurrentPosAsIndent(); + ClassList::const_iterator q = bases.begin(); + bool first = true; + while(q != bases.end()) + { + if((*q)->isAbstract()) + { + if(!first) + { + out << ',' << nl; + } + else + { + first = false; + } + out << getAbsolute(*q, package, "_", opIntfName); + } + ++q; + } + out.restoreIndent(); + } + out << sb; + + OperationList ops = p->operations(); + OperationList::const_iterator r; + for(r = ops.begin(); r != ops.end(); ++r) + { + OperationPtr op = *r; + ContainerPtr container = op->container(); + ClassDefPtr cl = ClassDefPtr::dynamicCast(container); + string name = op->name(); + + TypePtr ret; + vector<string> params; + + bool amd = !p->isLocal() && (cl->hasMetaData("amd") || op->hasMetaData("amd")); + + if(amd) + { + params = getParamsAsync(op, package, true); + } + else + { + params = getParams(op, package); + ret = op->returnType(); + } + + string retS = typeToString(ret, TypeModeReturn, package, op->getMetaData()); + + ExceptionList throws = op->throws(); + throws.sort(); + throws.unique(); + out << sp << nl << retS << ' ' << (amd ? name + "_async" : fixKwd(name)) << spar << params; + if(!noCurrent && !p->isLocal()) + { + out << "Ice.Current __current"; + } + out << epar; + writeThrowsClause(package, throws); + out << ';'; + } + + out << eb; + + close(); +} + +Slice::Gen::TieVisitor::TieVisitor(const string& dir) : + JavaVisitor(dir) +{ +} + +bool +Slice::Gen::TieVisitor::visitClassDefStart(const ClassDefPtr& p) +{ + string name = p->name(); + ClassList bases = p->bases(); + string package = getPackage(p); + string absolute = getAbsolute(p, "", "_", "Tie"); + string opIntfName = "Operations"; + if(p->isLocal()) + { + opIntfName += "NC"; + } + + // + // Don't generate a TIE class for a non-abstract class + // + if(!p->isAbstract()) + { + return false; + } + + if(!open(absolute)) + { + return false; + } + + Output& out = output(); + + // + // Generate the TIE class + // + out << sp << nl << "public class " << '_' << name << "Tie"; + if(p->isInterface()) + { + if(p->isLocal()) + { + out << " implements " << fixKwd(name) << ", Ice.TieBase"; + } + else + { + out << " extends " << '_' << name << "Disp implements Ice.TieBase"; + } + } + else + { + out << " extends " << fixKwd(name) << " implements Ice.TieBase"; + } + + out << sb; + + out << sp << nl << "public" << nl << '_' << name << "Tie()"; + out << sb; + out << eb; + + out << sp << nl << "public" << nl << '_' << name << "Tie(" << '_' << name << opIntfName + << " delegate)"; + out << sb; + out << nl << "_ice_delegate = delegate;"; + out << eb; + + out << sp << nl << "public java.lang.Object" << nl << "ice_delegate()"; + out << sb; + out << nl << "return _ice_delegate;"; + out << eb; + + out << sp << nl << "public void" << nl << "ice_delegate(java.lang.Object delegate)"; + out << sb; + out << nl << "_ice_delegate = (_" << name << opIntfName << ")delegate;"; + out << eb; + + out << sp << nl << "public boolean" << nl << "equals(java.lang.Object rhs)"; + out << sb; + out << nl << "if(this == rhs)"; + out << sb; + out << nl << "return true;"; + out << eb; + out << nl << "if(!(rhs instanceof " << '_' << name << "Tie))"; + out << sb; + out << nl << "return false;"; + out << eb; + out << sp << nl << "return _ice_delegate.equals(((" << '_' << name << "Tie)rhs)._ice_delegate);"; + out << eb; + + out << sp << nl << "public int" << nl << "hashCode()"; + out << sb; + out << nl << "return _ice_delegate.hashCode();"; + out << eb; + + if(p->isLocal()) + { + out << sp << nl << "public int" << nl << "ice_hash()"; + out << sb; + out << nl << "return hashCode();"; + out << eb; + + out << sp << nl << "public java.lang.Object" << nl << "clone()"; + out.inc(); + out << nl << "throws java.lang.CloneNotSupportedException"; + out.dec(); + out << sb; + out << nl << "return super.clone();"; + out << eb; + } + + OperationList ops = p->allOperations(); + OperationList::const_iterator r; + for(r = ops.begin(); r != ops.end(); ++r) + { + ContainerPtr container = (*r)->container(); + ClassDefPtr cl = ClassDefPtr::dynamicCast(container); + bool hasAMD = cl->hasMetaData("amd") || (*r)->hasMetaData("amd"); +#if defined(__SUNPRO_CC) && (__SUNPRO_CC==0x550) + // + // Work around for Sun CC 5.5 bug #4853566 + // + string opName; + if(hasAMD) + { + opName = (*r)->name() + "_async"; + } + else + { + opName = fixKwd((*r)->name()); + } +#else + string opName = hasAMD ? (*r)->name() + "_async" : fixKwd((*r)->name()); +#endif + TypePtr ret = (*r)->returnType(); + string retS = typeToString(ret, TypeModeReturn, package, (*r)->getMetaData()); + + vector<string> params; + vector<string> args; + if(hasAMD) + { + params = getParamsAsync((*r), package, true); + args = getArgsAsync(*r); + } + else + { + params = getParams((*r), package); + args = getArgs(*r); + } + + out << sp; + out << nl << "public " << (hasAMD ? "void" : retS) << nl << opName << spar << params; + if(!p->isLocal()) + { + out << "Ice.Current __current"; + } + out << epar; + + ExceptionList throws = (*r)->throws(); + throws.sort(); + throws.unique(); + writeThrowsClause(package, throws); + out << sb; + out << nl; + if(ret && !hasAMD) + { + out << "return "; + } + out << "_ice_delegate." << opName << spar << args; + if(!p->isLocal()) + { + out << "__current"; + } + out << epar << ';'; + out << eb; + } + + out << sp << nl << "private " << '_' << name << opIntfName << " _ice_delegate;"; + out << eb; + close(); + + return false; +} + +Slice::Gen::PackageVisitor::PackageVisitor(const string& dir) : + JavaVisitor(dir) +{ +} + +bool +Slice::Gen::PackageVisitor::visitModuleStart(const ModulePtr& p) +{ + DefinitionContextPtr dc = p->definitionContext(); + assert(dc); + StringList globalMetaData = dc->getMetaData(); + + static const string packagePrefix = "java:package:"; + + for(StringList::const_iterator q = globalMetaData.begin(); q != globalMetaData.end(); ++q) + { + string s = *q; + if(s.find(packagePrefix) == 0) + { + string markerClass = s.substr(packagePrefix.size()) + "." + fixKwd(p->name()) + "._Marker"; + + if(!open(markerClass)) + { + cerr << "can't open class `" << markerClass << "' for writing: " << strerror(errno) << endl; + return false; + } + + Output& out = output(); + out << sp << nl << "interface _Marker"; + out << sb; + out << eb; + + close(); + } + } + + return false; +} + +Slice::Gen::TypesVisitor::TypesVisitor(const string& dir, bool stream) : + JavaVisitor(dir), _stream(stream) +{ +} + +bool +Slice::Gen::TypesVisitor::visitClassDefStart(const ClassDefPtr& p) +{ + string name = p->name(); + ClassList bases = p->bases(); + string package = getPackage(p); + string absolute = getAbsolute(p); + + if(!open(absolute)) + { + return false; + } + + Output& out = output(); + + // + // Slice interfaces map to Java interfaces. + // + if(p->isInterface()) + { + out << sp << nl << "public interface " << fixKwd(name) << " extends "; + out.useCurrentPosAsIndent(); + if(p->isLocal()) + { + out << "Ice.LocalObject"; + } + else + { + out << "Ice.Object"; + } + out << "," << nl << '_' << name; + if(!p->isLocal()) + { + out << "Operations, _" << name << "OperationsNC"; + } + else + { + out << "OperationsNC"; + } + if(!bases.empty()) + { + ClassList::const_iterator q = bases.begin(); + while(q != bases.end()) + { + out << ',' << nl << getAbsolute(*q, package); + q++; + } + } + out.restoreIndent(); + } + else + { + out << sp << nl << "public "; + if(p->isAbstract()) + { + out << "abstract "; + } + out << "class " << fixKwd(name); + out.useCurrentPosAsIndent(); + if(bases.empty() || bases.front()->isInterface()) + { + if(p->isLocal()) + { + out << " extends Ice.LocalObjectImpl"; + } + else + { + out << " extends Ice.ObjectImpl"; + } + } + else + { + out << " extends "; + ClassDefPtr base = bases.front(); + out << getAbsolute(base, package); + bases.pop_front(); + } + + // + // Implement interfaces + // + StringList implements; + if(p->isAbstract()) + { + if(!p->isLocal()) + { + implements.push_back("_" + name + "Operations"); + } + implements.push_back("_" + name + "OperationsNC"); + } + if(!bases.empty()) + { + ClassList::const_iterator q = bases.begin(); + while(q != bases.end()) + { + implements.push_back(getAbsolute(*q, package)); + q++; + } + } + + if(!implements.empty()) + { + out << nl << " implements "; + out.useCurrentPosAsIndent(); + + StringList::const_iterator q = implements.begin(); + while(q != implements.end()) + { + if(q != implements.begin()) + { + out << ',' << nl; + } + out << *q; + q++; + } + + out.restoreIndent(); + } + + out.restoreIndent(); + } + + out << sb; + + // + // Default factory for non-abstract classes. + // + if(!p->isAbstract() && !p->isLocal()) + { + out << sp; + out << nl << "private static class __F extends Ice.LocalObjectImpl implements Ice.ObjectFactory"; + out << sb; + out << nl << "public Ice.Object" << nl << "create(String type)"; + out << sb; + out << nl << "assert(type.equals(ice_staticId()));"; + out << nl << "return new " << fixKwd(name) << "();"; + out << eb; + out << sp << nl << "public void" << nl << "destroy()"; + out << sb; + out << eb; + out << eb; + out << nl << "private static Ice.ObjectFactory _factory = new __F();"; + out << sp; + out << nl << "public static Ice.ObjectFactory" << nl << "ice_factory()"; + out << sb; + out << nl << "return _factory;"; + out << eb; + } + + // + // Marshalling & dispatch support. + // + if(!p->isInterface() && !p->isLocal()) + { + writeDispatch(out, p); + + DataMemberList members = p->dataMembers(); + DataMemberList::const_iterator d; + int iter; + + out << sp << nl << "public void" << nl << "__write(IceInternal.BasicStream __os)"; + out << sb; + out << nl << "__os.writeTypeId(ice_staticId());"; + out << nl << "__os.startWriteSlice();"; + iter = 0; + for(d = members.begin(); d != members.end(); ++d) + { + StringList metaData = (*d)->getMetaData(); + writeMarshalUnmarshalCode(out, package, (*d)->type(), fixKwd((*d)->name()), true, iter, false, metaData); + } + out << nl << "__os.endWriteSlice();"; + out << nl << "super.__write(__os);"; + out << eb; + + DataMemberList allClassMembers = p->allClassDataMembers(); + if(allClassMembers.size() != 0) + { + out << sp << nl << "private class Patcher implements IceInternal.Patcher"; + if(_stream) + { + out << ", Ice.ReadObjectCallback"; + } + out << sb; + if(allClassMembers.size() > 1) + { + out << sp << nl << "Patcher(int member)"; + out << sb; + out << nl << "__member = member;"; + out << eb; + } + + out << sp << nl << "public void" << nl << "patch(Ice.Object v)"; + out << sb; + if(allClassMembers.size() > 1) + { + out << nl << "switch(__member)"; + out << sb; + } + int memberCount = 0; + for(d = allClassMembers.begin(); d != allClassMembers.end(); ++d) + { + if(allClassMembers.size() > 1) + { + out.dec(); + out << nl << "case " << memberCount << ":"; + out.inc(); + } + if(allClassMembers.size() > 1) + { + out << nl << "__typeId = \"" << (*d)->type()->typeId() << "\";"; + } + string memberName = fixKwd((*d)->name()); + string memberType = typeToString((*d)->type(), TypeModeMember, package); + out << nl << memberName << " = (" << memberType << ")v;"; + if(allClassMembers.size() > 1) + { + out << nl << "break;"; + } + memberCount++; + } + if(allClassMembers.size() > 1) + { + out << eb; + } + out << eb; + + out << sp << nl << "public String" << nl << "type()"; + out << sb; + if(allClassMembers.size() > 1) + { + out << nl << "return __typeId;"; + } + else + { + out << nl << "return \"" << (*allClassMembers.begin())->type()->typeId() << "\";"; + } + out << eb; + + if(_stream) + { + out << sp << nl << "public void" << nl << "invoke(Ice.Object v)"; + out << sb; + out << nl << "patch(v);"; + out << eb; + } + + if(allClassMembers.size() > 1) + { + out << sp << nl << "private int __member;"; + out << nl << "private String __typeId;"; + } + out << eb; + } + + out << sp << nl << "public void" << nl << "__read(IceInternal.BasicStream __is, boolean __rid)"; + out << sb; + out << nl << "if(__rid)"; + out << sb; + out << nl << "String myId = __is.readTypeId();"; + out << eb; + out << nl << "__is.startReadSlice();"; + iter = 0; + DataMemberList classMembers = p->classDataMembers(); + long classMemberCount = allClassMembers.size() - classMembers.size(); + for(d = members.begin(); d != members.end(); ++d) + { + StringList metaData = (*d)->getMetaData(); + ostringstream patchParams; + BuiltinPtr builtin = BuiltinPtr::dynamicCast((*d)->type()); + if((builtin && builtin->kind() == Builtin::KindObject) || ClassDeclPtr::dynamicCast((*d)->type())) + { + if(classMembers.size() > 1 || allClassMembers.size() > 1) + { + patchParams << "new Patcher(" << classMemberCount++ << ')'; + } + } + writeMarshalUnmarshalCode(out, package, (*d)->type(), fixKwd((*d)->name()), false, iter, false, metaData, + patchParams.str()); + } + out << nl << "__is.endReadSlice();"; + out << nl << "super.__read(__is, true);"; + out << eb; + + if(_stream) + { + out << sp << nl << "public void" << nl << "__write(Ice.OutputStream __out)"; + out << sb; + out << nl << "__out.writeTypeId(ice_staticId());"; + out << nl << "__out.startSlice();"; + iter = 0; + for(d = members.begin(); d != members.end(); ++d) + { + StringList metaData = (*d)->getMetaData(); + writeStreamMarshalUnmarshalCode(out, package, (*d)->type(), fixKwd((*d)->name()), true, iter, false, + metaData); + } + out << nl << "__out.endSlice();"; + out << nl << "super.__write(__out);"; + out << eb; + + out << sp << nl << "public void" << nl << "__read(Ice.InputStream __in, boolean __rid)"; + out << sb; + out << nl << "if(__rid)"; + out << sb; + out << nl << "String myId = __in.readTypeId();"; + out << eb; + out << nl << "__in.startSlice();"; + iter = 0; + for(d = members.begin(); d != members.end(); ++d) + { + StringList metaData = (*d)->getMetaData(); + ostringstream patchParams; + BuiltinPtr builtin = BuiltinPtr::dynamicCast((*d)->type()); + if((builtin && builtin->kind() == Builtin::KindObject) || ClassDeclPtr::dynamicCast((*d)->type())) + { + if(classMembers.size() > 1 || allClassMembers.size() > 1) + { + patchParams << "new Patcher(" << classMemberCount++ << ')'; + } + } + writeStreamMarshalUnmarshalCode(out, package, (*d)->type(), fixKwd((*d)->name()), false, iter, false, + metaData, patchParams.str()); + } + out << nl << "__in.endSlice();"; + out << nl << "super.__read(__in, true);"; + out << eb; + } + else + { + // + // Emit placeholder functions to catch errors. + // + string scoped = p->scoped(); + out << sp << nl << "public void" << nl << "__write(Ice.OutputStream __out)"; + out << sb; + out << nl << "Ice.MarshalException ex = new Ice.MarshalException();"; + out << nl << "ex.reason = \"type " << scoped.substr(2) << " was not generated with stream support\";"; + out << nl << "throw ex;"; + out << eb; + + out << sp << nl << "public void" << nl << "__read(Ice.InputStream __in, boolean __rid)"; + out << sb; + out << nl << "Ice.MarshalException ex = new Ice.MarshalException();"; + out << nl << "ex.reason = \"type " << scoped.substr(2) << " was not generated with stream support\";"; + out << nl << "throw ex;"; + out << eb; + } + } + + return true; +} + +void +Slice::Gen::TypesVisitor::visitClassDefEnd(const ClassDefPtr& p) +{ + Output& out = output(); + out << eb; + close(); +} + +bool +Slice::Gen::TypesVisitor::visitExceptionStart(const ExceptionPtr& p) +{ + string name = fixKwd(p->name()); + string scoped = p->scoped(); + ExceptionPtr base = p->base(); + string package = getPackage(p); + string absolute = getAbsolute(p); + + if(!open(absolute)) + { + return false; + } + + Output& out = output(); + + out << sp << nl << "public class " << name << " extends "; + + if(!base) + { + if(p->isLocal()) + { + out << "Ice.LocalException"; + } + else + { + out << "Ice.UserException"; + } + } + else + { + out << getAbsolute(base, package); + } + out << sb; + + out << sp << nl << "public String" << nl << "ice_name()"; + out << sb; + out << nl << "return \"" << scoped.substr(2) << "\";"; + out << eb; + + return true; +} + +void +Slice::Gen::TypesVisitor::visitExceptionEnd(const ExceptionPtr& p) +{ + Output& out = output(); + + if(!p->isLocal()) + { + string name = fixKwd(p->name()); + string scoped = p->scoped(); + string package = getPackage(p); + ExceptionPtr base = p->base(); + + DataMemberList members = p->dataMembers(); + DataMemberList::const_iterator d; + int iter; + + out << sp << nl << "public void" << nl << "__write(IceInternal.BasicStream __os)"; + out << sb; + out << nl << "__os.writeString(\"" << scoped << "\");"; + out << nl << "__os.startWriteSlice();"; + iter = 0; + for(d = members.begin(); d != members.end(); ++d) + { + StringList metaData = (*d)->getMetaData(); + writeMarshalUnmarshalCode(out, package, (*d)->type(), fixKwd((*d)->name()), true, iter, false, metaData); + } + out << nl << "__os.endWriteSlice();"; + if(base) + { + out << nl << "super.__write(__os);"; + } + out << eb; + + DataMemberList allClassMembers = p->allClassDataMembers(); + if(allClassMembers.size() != 0) + { + out << sp << nl << "private class Patcher implements IceInternal.Patcher"; + if(_stream) + { + out << ", Ice.ReadObjectCallback"; + } + out << sb; + if(allClassMembers.size() > 1) + { + out << sp << nl << "Patcher(int member)"; + out << sb; + out << nl << "__member = member;"; + out << eb; + } + + out << sp << nl << "public void" << nl << "patch(Ice.Object v)"; + out << sb; + if(allClassMembers.size() > 1) + { + out << nl << "switch(__member)"; + out << sb; + } + int memberCount = 0; + for(d = allClassMembers.begin(); d != allClassMembers.end(); ++d) + { + if(allClassMembers.size() > 1) + { + out.dec(); + out << nl << "case " << memberCount << ":"; + out.inc(); + } + if(allClassMembers.size() > 1) + { + out << nl << "__typeId = \"" << (*d)->type()->typeId() << "\";"; + } + string memberName = fixKwd((*d)->name()); + string memberType = typeToString((*d)->type(), TypeModeMember, package); + out << nl << memberName << " = (" << memberType << ")v;"; + if(allClassMembers.size() > 1) + { + out << nl << "break;"; + } + memberCount++; + } + if(allClassMembers.size() > 1) + { + out << eb; + } + out << eb; + + out << sp << nl << "public String" << nl << "type()"; + out << sb; + if(allClassMembers.size() > 1) + { + out << nl << "return __typeId;"; + } + else + { + out << nl << "return \"" << (*allClassMembers.begin())->type()->typeId() << "\";"; + } + out << eb; + + if(_stream) + { + out << sp << nl << "public void" << nl << "invoke(Ice.Object v)"; + out << sb; + out << nl << "patch(v);"; + out << eb; + } + + if(allClassMembers.size() > 1) + { + out << sp << nl << "private int __member;"; + out << nl << "private String __typeId;"; + } + out << eb; + } + out << sp << nl << "public void" << nl << "__read(IceInternal.BasicStream __is, boolean __rid)"; + out << sb; + out << nl << "if(__rid)"; + out << sb; + out << nl << "String myId = __is.readString();"; + out << eb; + out << nl << "__is.startReadSlice();"; + iter = 0; + DataMemberList classMembers = p->classDataMembers(); + long classMemberCount = allClassMembers.size() - classMembers.size(); + for(d = members.begin(); d != members.end(); ++d) + { + ostringstream patchParams; + BuiltinPtr builtin = BuiltinPtr::dynamicCast((*d)->type()); + if((builtin && builtin->kind() == Builtin::KindObject) || ClassDeclPtr::dynamicCast((*d)->type())) + { + if(classMembers.size() > 1 || allClassMembers.size() > 1) + { + patchParams << "new Patcher(" << classMemberCount++ << ')'; + } + } + StringList metaData = (*d)->getMetaData(); + writeMarshalUnmarshalCode(out, package, (*d)->type(), fixKwd((*d)->name()), false, iter, false, metaData, + patchParams.str()); + } + out << nl << "__is.endReadSlice();"; + if(base) + { + out << nl << "super.__read(__is, true);"; + } + out << eb; + + if(_stream) + { + out << sp << nl << "public void" << nl << "__write(Ice.OutputStream __out)"; + out << sb; + out << nl << "__out.writeString(\"" << scoped << "\");"; + out << nl << "__out.startSlice();"; + iter = 0; + for(d = members.begin(); d != members.end(); ++d) + { + StringList metaData = (*d)->getMetaData(); + writeStreamMarshalUnmarshalCode(out, package, (*d)->type(), fixKwd((*d)->name()), true, iter, false, + metaData); + } + out << nl << "__out.endSlice();"; + if(base) + { + out << nl << "super.__write(__out);"; + } + out << eb; + + out << sp << nl << "public void" << nl << "__read(Ice.InputStream __in, boolean __rid)"; + out << sb; + out << nl << "if(__rid)"; + out << sb; + out << nl << "String myId = __in.readString();"; + out << eb; + out << nl << "__in.startSlice();"; + iter = 0; + for(d = members.begin(); d != members.end(); ++d) + { + ostringstream patchParams; + BuiltinPtr builtin = BuiltinPtr::dynamicCast((*d)->type()); + if((builtin && builtin->kind() == Builtin::KindObject) || ClassDeclPtr::dynamicCast((*d)->type())) + { + if(classMembers.size() > 1 || allClassMembers.size() > 1) + { + patchParams << "new Patcher(" << classMemberCount++ << ')'; + } + } + StringList metaData = (*d)->getMetaData(); + writeStreamMarshalUnmarshalCode(out, package, (*d)->type(), fixKwd((*d)->name()), false, iter, false, + metaData, patchParams.str()); + } + out << nl << "__in.endSlice();"; + if(base) + { + out << nl << "super.__read(__in, true);"; + } + out << eb; + } + else + { + // + // Emit placeholder functions to catch errors. + // + string scoped = p->scoped(); + out << sp << nl << "public void" << nl << "__write(Ice.OutputStream __out)"; + out << sb; + out << nl << "Ice.MarshalException ex = new Ice.MarshalException();"; + out << nl << "ex.reason = \"exception " << scoped.substr(2) << " was not generated with stream support\";"; + out << nl << "throw ex;"; + out << eb; + + out << sp << nl << "public void" << nl << "__read(Ice.InputStream __in, boolean __rid)"; + out << sb; + out << nl << "Ice.MarshalException ex = new Ice.MarshalException();"; + out << nl << "ex.reason = \"exception " << scoped.substr(2) << " was not generated with stream support\";"; + out << nl << "throw ex;"; + out << eb; + } + + if(p->usesClasses()) + { + if(!base || base && !base->usesClasses()) + { + out << sp << nl << "public boolean" << nl << "__usesClasses()"; + out << sb; + out << nl << "return true;"; + out << eb; + } + } + } + + out << eb; + close(); +} + +bool +Slice::Gen::TypesVisitor::visitStructStart(const StructPtr& p) +{ + string name = fixKwd(p->name()); + string absolute = getAbsolute(p); + + if(!open(absolute)) + { + return false; + } + + Output& out = output(); + + out << sp << nl << "public final class " << name << " implements java.lang.Cloneable"; + out << sb; + + return true; +} + +void +Slice::Gen::TypesVisitor::visitStructEnd(const StructPtr& p) +{ + string package = getPackage(p); + + Output& out = output(); + + DataMemberList members = p->dataMembers(); + DataMemberList::const_iterator d; + int iter; + + string typeS = typeToString(p, TypeModeIn, package); + + out << sp << nl << "public boolean" << nl << "equals(java.lang.Object rhs)"; + out << sb; + out << nl << typeS << " _r = null;"; + out << nl << "try"; + out << sb; + out << nl << "_r = (" << typeS << ")rhs;"; + out << eb; + out << nl << "catch(ClassCastException ex)"; + out << sb; + out << eb; + out << sp << nl << "if(_r != null)"; + out << sb; + for(d = members.begin(); d != members.end(); ++d) + { + string memberName = fixKwd((*d)->name()); + BuiltinPtr b = BuiltinPtr::dynamicCast((*d)->type()); + if(b) + { + switch(b->kind()) + { + case Builtin::KindByte: + case Builtin::KindBool: + case Builtin::KindShort: + case Builtin::KindInt: + case Builtin::KindLong: + case Builtin::KindFloat: + case Builtin::KindDouble: + { + out << nl << "if(" << memberName << " != _r." << memberName << ')'; + out << sb; + out << nl << "return false;"; + out << eb; + break; + } + + case Builtin::KindString: + case Builtin::KindObject: + case Builtin::KindObjectProxy: + case Builtin::KindLocalObject: + { + out << nl << "if(" << memberName << " != _r." << memberName << " && " << memberName + << " != null && !" << memberName << ".equals(_r." << memberName << "))"; + out << sb; + out << nl << "return false;"; + out << eb; + break; + } + } + } + else + { + // + // We treat sequences differently because the native equals() method for + // a Java array does not perform a deep comparison. If the mapped type + // is not overridden via metadata, we use the helper method + // java.util.Arrays.equals() to compare native arrays. + // + // For all other types, we can use the native equals() method. + // + SequencePtr seq = SequencePtr::dynamicCast((*d)->type()); + if(seq) + { + StringList metaData = (*d)->getMetaData(); + string listType = findMetaData(metaData); + if(listType.empty()) + { + StringList l = seq->getMetaData(); + listType = findMetaData(l); + } + if(!listType.empty()) + { + out << nl << "if(" << memberName << " != _r." << memberName << " && " << memberName + << " != null && !" << memberName << ".equals(_r." << memberName << "))"; + out << sb; + out << nl << "return false;"; + out << eb; + } + else + { + out << nl << "if(!java.util.Arrays.equals(" << memberName << ", _r." << memberName << "))"; + out << sb; + out << nl << "return false;"; + out << eb; + } + } + else + { + out << nl << "if(" << memberName << " != _r." << memberName << " && " << memberName + << " != null && !" << memberName << ".equals(_r." << memberName << "))"; + out << sb; + out << nl << "return false;"; + out << eb; + } + } + } + out << sp << nl << "return true;"; + out << eb; + out << sp << nl << "return false;"; + out << eb; + + out << sp << nl << "public int" << nl << "hashCode()"; + out << sb; + out << nl << "int __h = 0;"; + iter = 0; + for(d = members.begin(); d != members.end(); ++d) + { + string memberName = fixKwd((*d)->name()); + StringList metaData = (*d)->getMetaData(); + writeHashCode(out, (*d)->type(), memberName, iter, metaData); + } + out << nl << "return __h;"; + out << eb; + + out << sp << nl << "public java.lang.Object" << nl << "clone()"; + out.inc(); + out << nl << "throws java.lang.CloneNotSupportedException"; + out.dec(); + out << sb; + out << nl << "return super.clone();"; + out << eb; + + if(!p->isLocal()) + { + out << sp << nl << "public void" << nl << "__write(IceInternal.BasicStream __os)"; + out << sb; + iter = 0; + for(d = members.begin(); d != members.end(); ++d) + { + StringList metaData = (*d)->getMetaData(); + writeMarshalUnmarshalCode(out, package, (*d)->type(), fixKwd((*d)->name()), true, iter, false, metaData); + } + out << eb; + + DataMemberList classMembers = p->classDataMembers(); + + if(classMembers.size() != 0) + { + out << sp << nl << "private class Patcher implements IceInternal.Patcher"; + if(_stream) + { + out << ", Ice.ReadObjectCallback"; + } + out << sb; + if(classMembers.size() > 1) + { + out << sp << nl << "Patcher(int member)"; + out << sb; + out << nl << "__member = member;"; + out << eb; + } + + out << sp << nl << "public void" << nl << "patch(Ice.Object v)"; + out << sb; + if(classMembers.size() > 1) + { + out << nl << "switch(__member)"; + out << sb; + } + int memberCount = 0; + for(d = classMembers.begin(); d != classMembers.end(); ++d) + { + if(classMembers.size() > 1) + { + out.dec(); + out << nl << "case " << memberCount << ":"; + out.inc(); + } + if(classMembers.size() > 1) + { + out << nl << "__typeId = \"" << (*d)->type()->typeId() << "\";"; + } + string memberName = fixKwd((*d)->name()); + string memberType = typeToString((*d)->type(), TypeModeMember, package); + out << nl << memberName << " = (" << memberType << ")v;"; + if(classMembers.size() > 1) + { + out << nl << "break;"; + } + memberCount++; + } + if(classMembers.size() > 1) + { + out << eb; + } + out << eb; + + out << sp << nl << "public String" << nl << "type()"; + out << sb; + if(classMembers.size() > 1) + { + out << nl << "return __typeId;"; + } + else + { + out << nl << "return \"" << (*classMembers.begin())->type()->typeId() << "\";"; + } + out << eb; + + if(_stream) + { + out << sp << nl << "public void" << nl << "invoke(Ice.Object v)"; + out << sb; + out << nl << "patch(v);"; + out << eb; + } + + if(classMembers.size() > 1) + { + out << sp << nl << "private int __member;"; + out << nl << "private String __typeId;"; + } + out << eb; + } + + out << sp << nl << "public void" << nl << "__read(IceInternal.BasicStream __is)"; + out << sb; + iter = 0; + int classMemberCount = 0; + for(d = members.begin(); d != members.end(); ++d) + { + ostringstream patchParams; + BuiltinPtr builtin = BuiltinPtr::dynamicCast((*d)->type()); + if((builtin && builtin->kind() == Builtin::KindObject) || ClassDeclPtr::dynamicCast((*d)->type())) + { + if(classMembers.size() > 1) + { + patchParams << "new Patcher(" << classMemberCount++ << ')'; + } + } + StringList metaData = (*d)->getMetaData(); + writeMarshalUnmarshalCode(out, package, (*d)->type(), fixKwd((*d)->name()), false, iter, false, metaData, + patchParams.str()); + } + out << eb; + + if(_stream) + { + out << sp << nl << "public void" << nl << "__write(Ice.OutputStream __out)"; + out << sb; + iter = 0; + for(d = members.begin(); d != members.end(); ++d) + { + StringList metaData = (*d)->getMetaData(); + writeStreamMarshalUnmarshalCode(out, package, (*d)->type(), fixKwd((*d)->name()), true, iter, false, + metaData); + } + out << eb; + + out << sp << nl << "public void" << nl << "__read(Ice.InputStream __in)"; + out << sb; + iter = 0; + classMemberCount = 0; + for(d = members.begin(); d != members.end(); ++d) + { + ostringstream patchParams; + BuiltinPtr builtin = BuiltinPtr::dynamicCast((*d)->type()); + if((builtin && builtin->kind() == Builtin::KindObject) || ClassDeclPtr::dynamicCast((*d)->type())) + { + if(classMembers.size() > 1) + { + patchParams << "new Patcher(" << classMemberCount++ << ')'; + } + } + StringList metaData = (*d)->getMetaData(); + writeStreamMarshalUnmarshalCode(out, package, (*d)->type(), fixKwd((*d)->name()), false, iter, false, + metaData, patchParams.str()); + } + out << eb; + } + } + + out << eb; + close(); +} + +void +Slice::Gen::TypesVisitor::visitDataMember(const DataMemberPtr& p) +{ + string name = fixKwd(p->name()); + ContainerPtr container = p->container(); + ContainedPtr contained = ContainedPtr::dynamicCast(container); + StringList metaData = p->getMetaData(); + string s = typeToString(p->type(), TypeModeMember, getPackage(contained), metaData); + Output& out = output(); + out << sp << nl << "public " << s << ' ' << name << ';'; +} + +void +Slice::Gen::TypesVisitor::visitEnum(const EnumPtr& p) +{ + string name = fixKwd(p->name()); + string absolute = getAbsolute(p); + EnumeratorList enumerators = p->getEnumerators(); + EnumeratorList::const_iterator en; + size_t sz = enumerators.size(); + + if(!open(absolute)) + { + return; + } + + Output& out = output(); + + out << sp << nl << "public final class " << name; + out << sb; + out << nl << "private static " << name << "[] __values = new " << name << "[" << sz << "];"; + out << nl << "private int __value;"; + out << sp; + int n; + for(en = enumerators.begin(), n = 0; en != enumerators.end(); ++en, ++n) + { + string member = fixKwd((*en)->name()); + out << nl << "public static final int _" << member << " = " << n << ';'; + out << nl << "public static final " << name << ' ' << fixKwd(member) + << " = new " << name << "(_" << member << ");"; + } + + out << sp << nl << "public static " << name << nl << "convert(int val)"; + out << sb; + out << nl << "assert val < " << sz << ';'; + out << nl << "return __values[val];"; + out << eb; + + out << sp << nl << "public int" << nl << "value()"; + out << sb; + out << nl << "return __value;"; + out << eb; + + out << sp << nl << "public String" << nl << "toString()"; + out << sb; + out << nl << "return __T[__value];"; + out << eb; + + out << sp << nl << "private" << nl << name << "(int val)"; + out << sb; + out << nl << "__value = val;"; + out << nl << "__values[val] = this;"; + out << eb; + + if(!p->isLocal()) + { + out << sp << nl << "public void" << nl << "__write(IceInternal.BasicStream __os)"; + out << sb; + if(sz <= 0x7f) + { + out << nl << "__os.writeByte((byte)__value);"; + } + else if(sz <= 0x7fff) + { + out << nl << "__os.writeShort((short)__value);"; + } + else + { + out << nl << "__os.writeInt(__value);"; + } + out << eb; + + out << sp << nl << "public static " << name << nl << "__read(IceInternal.BasicStream __is)"; + out << sb; + if(sz <= 0x7f) + { + out << nl << "int __v = __is.readByte();"; + } + else if(sz <= 0x7fff) + { + out << nl << "int __v = __is.readShort();"; + } + else + { + out << nl << "int __v = __is.readInt();"; + } + out << nl << "if(__v < 0 || __v >= " << sz << ')'; + out << sb; + out << nl << "throw new Ice.MarshalException();"; + out << eb; + out << nl << "return " << name << ".convert(__v);"; + out << eb; + + if(_stream) + { + out << sp << nl << "public void" << nl << "__write(Ice.OutputStream __out)"; + out << sb; + if(sz <= 0x7f) + { + out << nl << "__out.writeByte((byte)__value);"; + } + else if(sz <= 0x7fff) + { + out << nl << "__out.writeShort((short)__value);"; + } + else + { + out << nl << "__out.writeInt(__value);"; + } + out << eb; + + out << sp << nl << "public static " << name << nl << "__read(Ice.InputStream __in)"; + out << sb; + if(sz <= 0x7f) + { + out << nl << "int __v = __in.readByte();"; + } + else if(sz <= 0x7fff) + { + out << nl << "int __v = __in.readShort();"; + } + else + { + out << nl << "int __v = __in.readInt();"; + } + out << nl << "if(__v < 0 || __v >= " << sz << ')'; + out << sb; + out << nl << "throw new Ice.MarshalException();"; + out << eb; + out << nl << "return " << name << ".convert(__v);"; + out << eb; + } + } + + out << sp << nl << "final static private String[] __T ="; + out << sb; + en = enumerators.begin(); + while(en != enumerators.end()) + { + out << nl << "\"" << (*en)->name() << "\""; + if(++en != enumerators.end()) + { + out << ','; + } + } + out << eb << ';'; + + out << eb; + close(); +} + +void +Slice::Gen::TypesVisitor::visitConst(const ConstPtr& p) +{ + string name = fixKwd(p->name()); + string package = getPackage(p); + string absolute = getAbsolute(p); + TypePtr type = p->type(); + + if(!open(absolute)) + { + return; + } + Output& out = output(); + out << sp << nl << "public interface " << name; + out << sb; + out << nl << typeToString(type, TypeModeIn, package) << " value = "; + + BuiltinPtr bp; + EnumPtr ep; + if(bp = BuiltinPtr::dynamicCast(type)) + { + switch(bp->kind()) + { + case Builtin::KindString: + { + out << "\""; + + ios_base::fmtflags originalFlags = out.flags(); + streamsize originalWidth = out.width(); + ostream::char_type originalFill = out.fill(); + + const string val = p->value(); + for(string::const_iterator c = val.begin(); c != val.end(); ++c) + { + if(isascii(*c) && isprint(*c)) + { + switch(*c) + { + case '\\': + case '"': + { + out << "\\"; + break; + } + } + out << *c; + } + else + { + switch(*c) + { + case '\r': + { + out << "\\r"; + break; + } + case '\n': + { + out << "\\n"; + break; + } + default: + { + unsigned char uc = *c; + out << "\\u"; + out.flags(ios_base::hex); + out.width(4); + out.fill('0'); + out << static_cast<unsigned>(uc); + break; + } + } + } + } + + out.fill(originalFill); + out.width(originalWidth); + out.flags(originalFlags); + + out << "\""; + break; + } + case Builtin::KindByte: + { + int i = atoi(p->value().c_str()); + if(i > 127) + { + i -= 256; + } + out << i; // Slice byte runs from 0-255, Java byte runs from -128 - 127. + break; + } + case Builtin::KindLong: + { + out << p->value() << "L"; // Need to append "L" modifier for long constants. + break; + } + case Builtin::KindBool: + case Builtin::KindShort: + case Builtin::KindInt: + case Builtin::KindFloat: + case Builtin::KindDouble: + case Builtin::KindObject: + case Builtin::KindObjectProxy: + case Builtin::KindLocalObject: + { + out << p->value(); + break; + } + } + + } + else if(ep = EnumPtr::dynamicCast(type)) + { + string val = p->value(); + string::size_type pos = val.rfind(':'); + if(pos != string::npos) + { + val.erase(0, pos + 1); + } + out << getAbsolute(ep, package) << '.' << fixKwd(val); + } + else + { + out << p->value(); + } + out << ';' << eb; + close(); +} + +Slice::Gen::HolderVisitor::HolderVisitor(const string& dir, bool stream) : + JavaVisitor(dir), _stream(stream) +{ +} + +bool +Slice::Gen::HolderVisitor::visitClassDefStart(const ClassDefPtr& p) +{ + ClassDeclPtr decl = p->declaration(); + writeHolder(decl); + + if(!p->isLocal()) + { + string name = p->name(); + string absolute = getAbsolute(p, "", "", "PrxHolder"); + + if(open(absolute)) + { + Output& out = output(); + out << sp << nl << "public final class " << name << "PrxHolder"; + out << sb; + out << sp << nl << "public" << nl << name << "PrxHolder()"; + out << sb; + out << eb; + out << sp << nl << "public" << nl << name << "PrxHolder(" << name << "Prx value)"; + out << sb; + out << nl << "this.value = value;"; + out << eb; + out << sp << nl << "public " << name << "Prx value;"; + out << eb; + close(); + } + } + + return false; +} + +bool +Slice::Gen::HolderVisitor::visitStructStart(const StructPtr& p) +{ + writeHolder(p); + return false; +} + +void +Slice::Gen::HolderVisitor::visitSequence(const SequencePtr& p) +{ + writeHolder(p); +} + +void +Slice::Gen::HolderVisitor::visitDictionary(const DictionaryPtr& p) +{ + writeHolder(p); +} + +void +Slice::Gen::HolderVisitor::visitEnum(const EnumPtr& p) +{ + writeHolder(p); +} + +void +Slice::Gen::HolderVisitor::writeHolder(const TypePtr& p) +{ + ContainedPtr contained = ContainedPtr::dynamicCast(p); + assert(contained); + string name = contained->name(); + string absolute = getAbsolute(contained, "", "", "Holder"); + + if(open(absolute)) + { + Output& out = output(); + string typeS = typeToString(p, TypeModeIn, getPackage(contained)); + out << sp << nl << "public final class " << name << "Holder"; + out << sb; + out << sp << nl << "public" << nl << name << "Holder()"; + out << sb; + out << eb; + out << sp << nl << "public" << nl << name << "Holder(" << typeS << " value)"; + out << sb; + out << nl << "this.value = value;"; + out << eb; + if(!p->isLocal()) + { + BuiltinPtr builtin = BuiltinPtr::dynamicCast(p); + if((builtin && builtin->kind() == Builtin::KindObject) || ClassDeclPtr::dynamicCast(p)) + { + out << sp << nl << "public class Patcher implements IceInternal.Patcher"; + if(_stream) + { + out << ", Ice.ReadObjectCallback"; + } + out << sb; + out << nl << "public void"; + out << nl << "patch(Ice.Object v)"; + out << sb; + out << nl << "value = (" << typeS << ")v;"; + out << eb; + + out << sp << nl << "public String" << nl << "type()"; + out << sb; + out << nl << "return \"" << p->typeId() << "\";"; + out << eb; + + if(_stream) + { + out << sp << nl << "public void" << nl << "invoke(Ice.Object v)"; + out << sb; + out << nl << "patch(v);"; + out << eb; + } + out << eb; + + out << sp << nl << "public Patcher"; + out << nl << "getPatcher()"; + out << sb; + out << nl << "return new Patcher();"; + out << eb; + } + } + out << sp << nl << "public " << typeS << " value;"; + out << eb; + close(); + } +} + +Slice::Gen::HelperVisitor::HelperVisitor(const string& dir, bool stream) : + JavaVisitor(dir), _stream(stream) +{ +} + +bool +Slice::Gen::HelperVisitor::visitClassDefStart(const ClassDefPtr& p) +{ + if(p->isLocal()) + { + return false; + } + + // + // Proxy helper + // + string name = p->name(); + string scoped = p->scoped(); + ClassList bases = p->bases(); + string package = getPackage(p); + string absolute = getAbsolute(p); + + if(!open(getAbsolute(p, "", "", "PrxHelper"))) + { + return false; + } + + Output& out = output(); + + // + // A proxy helper class serves two purposes: it implements the + // proxy interface, and provides static helper methods for use + // by applications (e.g., checkedCast, etc.) + // + out << sp << nl << "public final class " << name << "PrxHelper extends Ice.ObjectPrxHelperBase implements " << name + << "Prx"; + + out << sb; + + OperationList ops = p->allOperations(); + + OperationList::const_iterator r; + for(r = ops.begin(); r != ops.end(); ++r) + { + OperationPtr op = *r; + ContainerPtr container = op->container(); + ClassDefPtr cl = ClassDefPtr::dynamicCast(container); + string opName = fixKwd(op->name()); + TypePtr ret = op->returnType(); + string retS = typeToString(ret, TypeModeReturn, package, op->getMetaData()); + + vector<string> params = getParams(op, package); + vector<string> args = getArgs(op); + + ExceptionList throws = op->throws(); + throws.sort(); + throws.unique(); + + // + // Write two versions of the operation - with and without a + // context parameter + // + out << sp; + out << nl << "public " << retS << nl << opName << spar << params << epar; + writeThrowsClause(package, throws); + out << sb; + out << nl; + if(ret) + { + out << "return "; + } + out << opName << spar << args << "__defaultContext()" << epar << ';'; + out << eb; + + out << sp; + out << nl << "public " << retS << nl << opName << spar << params << "java.util.Map __ctx" << epar; + writeThrowsClause(package, throws); + out << sb; + out << nl << "int __cnt = 0;"; + out << nl << "while(true)"; + out << sb; + out << nl << "try"; + out << sb; + if(op->returnsData()) + { + out << nl << "__checkTwowayOnly(\"" << opName << "\");"; + } + out << nl << "Ice._ObjectDel __delBase = __getDelegate();"; + out << nl << '_' << name << "Del __del = (_" << name << "Del)__delBase;"; + out << nl; + if(ret) + { + out << "return "; + } + out << "__del." << opName << spar << args << "__ctx" << epar << ';'; + if(!ret) + { + out << nl << "return;"; + } + out << eb; + out << nl << "catch(IceInternal.NonRepeatable __ex)"; + out << sb; + if(op->mode() == Operation::Idempotent || op->mode() == Operation::Nonmutating) + { + out << nl << "__cnt = __handleException(__ex.get(), __cnt);"; + } + else + { + out << nl << "__rethrowException(__ex.get());"; + } + out << eb; + out << nl << "catch(Ice.LocalException __ex)"; + out << sb; + out << nl << "__cnt = __handleException(__ex, __cnt);"; + out << eb; + out << eb; + out << eb; + + if(cl->hasMetaData("ami") || op->hasMetaData("ami")) + { + vector<string> paramsAMI = getParamsAsync(op, package, false); + vector<string> argsAMI = getArgsAsync(op); + + // + // Write two versions of the operation - with and without a + // context parameter + // + out << sp; + out << nl << "public void" << nl << op->name() << "_async" << spar << paramsAMI << epar; + out << sb; + out << nl << op->name() << "_async" << spar << argsAMI << "__defaultContext()" << epar << ';'; + out << eb; + + out << sp; + out << nl << "public void" << nl << op->name() << "_async" << spar << paramsAMI << "java.util.Map __ctx" + << epar; + out << sb; + // Async requests may only be sent twoway. + out << nl << "__checkTwowayOnly(\"" << p->name() << "\");"; + out << nl << "__cb.__invoke" << spar << "this" << argsAMI << "__ctx" << epar << ';'; + out << eb; + } + } + + out << sp << nl << "public static " << name << "Prx" << nl << "checkedCast(Ice.ObjectPrx b)"; + out << sb; + out << nl << name << "Prx d = null;"; + out << nl << "if(b != null)"; + out << sb; + out << nl << "try"; + out << sb; + out << nl << "d = (" << name << "Prx)b;"; + out << eb; + out << nl << "catch(ClassCastException ex)"; + out << sb; + out << nl << "if(b.ice_isA(\"" << scoped << "\"))"; + out << sb; + out << nl << name << "PrxHelper h = new " << name << "PrxHelper();"; + out << nl << "h.__copyFrom(b);"; + out << nl << "d = h;"; + out << eb; + out << eb; + out << eb; + out << nl << "return d;"; + out << eb; + + out << sp << nl << "public static " << name << "Prx" << nl << "checkedCast(Ice.ObjectPrx b, java.util.Map ctx)"; + out << sb; + out << nl << name << "Prx d = null;"; + out << nl << "if(b != null)"; + out << sb; + out << nl << "try"; + out << sb; + out << nl << "d = (" << name << "Prx)b;"; + out << eb; + out << nl << "catch(ClassCastException ex)"; + out << sb; + out << nl << "if(b.ice_isA(\"" << scoped << "\", ctx))"; + out << sb; + out << nl << name << "PrxHelper h = new " << name << "PrxHelper();"; + out << nl << "h.__copyFrom(b);"; + out << nl << "d = h;"; + out << eb; + out << eb; + out << eb; + out << nl << "return d;"; + out << eb; + + out << sp << nl << "public static " << name << "Prx" << nl << "checkedCast(Ice.ObjectPrx b, String f)"; + out << sb; + out << nl << name << "Prx d = null;"; + out << nl << "if(b != null)"; + out << sb; + out << nl << "Ice.ObjectPrx bb = b.ice_newFacet(f);"; + out << nl << "try"; + out << sb; + out << nl << "if(bb.ice_isA(\"" << scoped << "\"))"; + out << sb; + out << nl << name << "PrxHelper h = new " << name << "PrxHelper();"; + out << nl << "h.__copyFrom(bb);"; + out << nl << "d = h;"; + out << eb; + out << eb; + out << nl << "catch(Ice.FacetNotExistException ex)"; + out << sb; + out << eb; + out << eb; + out << nl << "return d;"; + out << eb; + + out << sp << nl << "public static " << name << "Prx" + << nl << "checkedCast(Ice.ObjectPrx b, String f, java.util.Map ctx)"; + out << sb; + out << nl << name << "Prx d = null;"; + out << nl << "if(b != null)"; + out << sb; + out << nl << "Ice.ObjectPrx bb = b.ice_newFacet(f);"; + out << nl << "try"; + out << sb; + out << nl << "if(bb.ice_isA(\"" << scoped << "\", ctx))"; + out << sb; + out << nl << name << "PrxHelper h = new " << name << "PrxHelper();"; + out << nl << "h.__copyFrom(bb);"; + out << nl << "d = h;"; + out << eb; + out << eb; + out << nl << "catch(Ice.FacetNotExistException ex)"; + out << sb; + out << eb; + out << eb; + out << nl << "return d;"; + out << eb; + + out << sp << nl << "public static " << name << "Prx" << nl << "uncheckedCast(Ice.ObjectPrx b)"; + out << sb; + out << nl << name << "Prx d = null;"; + out << nl << "if(b != null)"; + out << sb; + out << nl << name << "PrxHelper h = new " << name << "PrxHelper();"; + out << nl << "h.__copyFrom(b);"; + out << nl << "d = h;"; + out << eb; + out << nl << "return d;"; + out << eb; + + out << sp << nl << "public static " << name << "Prx" << nl << "uncheckedCast(Ice.ObjectPrx b, String f)"; + out << sb; + out << nl << name << "Prx d = null;"; + out << nl << "if(b != null)"; + out << sb; + out << nl << "Ice.ObjectPrx bb = b.ice_newFacet(f);"; + out << nl << name << "PrxHelper h = new " << name << "PrxHelper();"; + out << nl << "h.__copyFrom(bb);"; + out << nl << "d = h;"; + out << eb; + out << nl << "return d;"; + out << eb; + + out << sp << nl << "protected Ice._ObjectDelM" << nl << "__createDelegateM()"; + out << sb; + out << nl << "return new _" << name << "DelM();"; + out << eb; + + out << sp << nl << "protected Ice._ObjectDelD" << nl << "__createDelegateD()"; + out << sb; + out << nl << "return new _" << name << "DelD();"; + out << eb; + + out << sp << nl << "public static void" << nl << "__write(IceInternal.BasicStream __os, " << name << "Prx v)"; + out << sb; + out << nl << "__os.writeProxy(v);"; + out << eb; + + out << sp << nl << "public static " << name << "Prx" << nl << "__read(IceInternal.BasicStream __is)"; + out << sb; + out << nl << "Ice.ObjectPrx proxy = __is.readProxy();"; + out << nl << "if(proxy != null)"; + out << sb; + out << nl << name << "PrxHelper result = new " << name << "PrxHelper();"; + out << nl << "result.__copyFrom(proxy);"; + out << nl << "return result;"; + out << eb; + out << nl << "return null;"; + out << eb; + + if(_stream) + { + out << sp << nl << "public static void" << nl << "write(Ice.OutputStream __out, " << name << "Prx v)"; + out << sb; + out << nl << "__out.writeProxy(v);"; + out << eb; + + out << sp << nl << "public static " << name << "Prx" << nl << "read(Ice.InputStream __in)"; + out << sb; + out << nl << "Ice.ObjectPrx proxy = __in.readProxy();"; + out << nl << "if(proxy != null)"; + out << sb; + out << nl << name << "PrxHelper result = new " << name << "PrxHelper();"; + out << nl << "result.__copyFrom(proxy);"; + out << nl << "return result;"; + out << eb; + out << nl << "return null;"; + out << eb; + } + + out << eb; + close(); + + if(_stream) + { + // + // Class helper. + // + if(!open(getAbsolute(p, "", "", "Helper"))) + { + return false; + } + + Output& out2 = output(); + + out2 << sp << nl << "public final class " << name << "Helper"; + out2 << sb; + + out2 << sp << nl << "public static void" << nl << "write(Ice.OutputStream __out, " << fixKwd(name) << " __v)"; + out2 << sb; + out2 << nl << "__out.writeObject(__v);"; + out2 << eb; + + out2 << sp << nl << "public static void" << nl << "read(Ice.InputStream __in, " << name << "Holder __h)"; + out2 << sb; + out2 << nl << "__in.readObject(__h.getPatcher());"; + out2 << eb; + + out2 << eb; + close(); + } + + return false; +} + +bool +Slice::Gen::HelperVisitor::visitStructStart(const StructPtr& p) +{ + if(!p->isLocal() && _stream) + { + string name = p->name(); + string fixedName = fixKwd(name); + + if(!open(getAbsolute(p, "", "", "Helper"))) + { + return false; + } + + Output& out = output(); + + out << sp << nl << "public final class " << name << "Helper"; + out << sb; + + out << sp << nl << "public static void" << nl << "write(Ice.OutputStream __out, " << fixedName << " __v)"; + out << sb; + out << nl << "__v.__write(__out);"; + out << eb; + + out << sp << nl << "public static " << fixedName << nl << "read(Ice.InputStream __in)"; + out << sb; + out << nl << fixedName << " __v = new " << fixedName << "();"; + out << nl << "__v.__read(__in);"; + out << nl << "return __v;"; + out << eb; + + out << eb; + close(); + } + + return false; +} + +void +Slice::Gen::HelperVisitor::visitSequence(const SequencePtr& p) +{ + // + // Don't generate helper for a sequence of a local type. + // + if(p->isLocal()) + { + return; + } + + string name = p->name(); + string absolute = getAbsolute(p); + string helper = getAbsolute(p, "", "", "Helper"); + string package = getPackage(p); + string typeS = typeToString(p, TypeModeIn, package); + + if(open(helper)) + { + Output& out = output(); + int iter; + + out << sp << nl << "public final class " << name << "Helper"; + out << sb; + + out << nl << "public static void" << nl << "write(IceInternal.BasicStream __os, " << typeS << " __v)"; + out << sb; + iter = 0; + writeSequenceMarshalUnmarshalCode(out, package, p, "__v", true, iter, false); + out << eb; + + out << sp << nl << "public static " << typeS << nl << "read(IceInternal.BasicStream __is)"; + out << sb; + out << nl << typeS << " __v;"; + iter = 0; + writeSequenceMarshalUnmarshalCode(out, package, p, "__v", false, iter, false); + out << nl << "return __v;"; + out << eb; + + if(_stream) + { + out << sp << nl << "public static void" << nl << "write(Ice.OutputStream __out, " << typeS << " __v)"; + out << sb; + iter = 0; + writeStreamSequenceMarshalUnmarshalCode(out, package, p, "__v", true, iter, false); + out << eb; + + out << sp << nl << "public static " << typeS << nl << "read(Ice.InputStream __in)"; + out << sb; + out << nl << typeS << " __v;"; + iter = 0; + writeStreamSequenceMarshalUnmarshalCode(out, package, p, "__v", false, iter, false); + out << nl << "return __v;"; + out << eb; + } + + out << eb; + close(); + } +} + +void +Slice::Gen::HelperVisitor::visitDictionary(const DictionaryPtr& p) +{ + // + // Don't generate helper for a dictionary containing a local type + // + if(p->isLocal()) + { + return; + } + + TypePtr key = p->keyType(); + TypePtr value = p->valueType(); + + string absolute = getAbsolute(p); + string helper = getAbsolute(p, "", "", "Helper"); + + if(open(helper)) + { + Output& out = output(); + string name = p->name(); + string package = getPackage(p); + string keyS = typeToString(key, TypeModeIn, package); + string valueS = typeToString(value, TypeModeIn, package); + StringList metaData = p->getMetaData(); + string dictType = findMetaData(metaData); + int iter; + int i; + + out << sp << nl << "public final class " << name << "Helper"; + out << sb; + + out << nl << "public static void" << nl << "write(IceInternal.BasicStream __os, " << "java.util.Map __v)"; + out << sb; + out << nl << "if(__v == null)"; + out << sb; + out << nl << "__os.writeSize(0);"; + out << eb; + out << nl << "else"; + out << sb; + out << nl << "__os.writeSize(__v.size());"; + out << nl << "java.util.Iterator __i = __v.entrySet().iterator();"; + out << nl << "while(__i.hasNext())"; + out << sb; + out << nl << "java.util.Map.Entry __e = (java.util.Map.Entry)" << "__i.next();"; + iter = 0; + for(i = 0; i < 2; i++) + { + string val; + string arg; + TypePtr type; + if(i == 0) + { + arg = "__e.getKey()"; + type = key; + } + else + { + arg = "__e.getValue()"; + type = value; + } + + BuiltinPtr b = BuiltinPtr::dynamicCast(type); + if(b) + { + switch(b->kind()) + { + case Builtin::KindByte: + { + val = "((java.lang.Byte)" + arg + ").byteValue()"; + break; + } + case Builtin::KindBool: + { + val = "((java.lang.Boolean)" + arg + ").booleanValue()"; + break; + } + case Builtin::KindShort: + { + val = "((java.lang.Short)" + arg + ").shortValue()"; + break; + } + case Builtin::KindInt: + { + val = "((java.lang.Integer)" + arg + ").intValue()"; + break; + } + case Builtin::KindLong: + { + val = "((java.lang.Long)" + arg + ").longValue()"; + break; + } + case Builtin::KindFloat: + { + val = "((java.lang.Float)" + arg + ").floatValue()"; + break; + } + case Builtin::KindDouble: + { + val = "((java.lang.Double)" + arg + ").doubleValue()"; + break; + } + case Builtin::KindString: + case Builtin::KindObject: + case Builtin::KindObjectProxy: + { + break; + } + case Builtin::KindLocalObject: + { + assert(false); + break; + } + } + } + + if(val.empty()) + { + val = "((" + typeToString(type, TypeModeIn, package) + ')' + arg + ')'; + } + writeMarshalUnmarshalCode(out, package, type, val, true, iter, false); + } + out << eb; + out << eb; + out << eb; + + BuiltinPtr builtin = BuiltinPtr::dynamicCast(value); + if((builtin && builtin->kind() == Builtin::KindObject) || ClassDeclPtr::dynamicCast(value)) + { + // + // The dictionary uses class values. + // + out << sp << nl << "private static class Patcher implements IceInternal.Patcher"; + if(_stream) + { + out << ", Ice.ReadObjectCallback"; + } + out << sb; + string keyTypeS = keyS; + BuiltinPtr b = BuiltinPtr::dynamicCast(key); + if(b) + { + switch(b->kind()) + { + case Builtin::KindByte: + { + keyTypeS = "java.lang.Byte"; + break; + } + case Builtin::KindBool: + { + keyTypeS = "java.lang.Boolean"; + break; + } + case Builtin::KindShort: + { + keyTypeS = "java.lang.Short"; + break; + } + case Builtin::KindInt: + { + keyTypeS = "java.lang.Integer"; + break; + } + case Builtin::KindLong: + { + keyTypeS = "java.lang.Long"; + break; + } + case Builtin::KindFloat: + { + keyTypeS = "java.lang.Float"; + break; + } + case Builtin::KindDouble: + { + keyTypeS = "java.lang.Double"; + break; + } + default: + { + break; // Do nothing + } + } + } + out << sp << nl << "Patcher(java.util.Map m, " << keyTypeS << " key)"; + out << sb; + out << nl << "__m = m;"; + out << nl << "__key = key;"; + out << eb; + + out << sp << nl << "public void" << nl << "patch(Ice.Object v)"; + out << sb; + out << nl << valueS << " _v = (" << valueS << ")v;"; + out << nl << "__m.put(__key, v);"; + out << eb; + + out << sp << nl << "public String" << nl << "type()"; + out << sb; + out << nl << "return \"" << value->typeId() << "\";"; + out << eb; + + if(_stream) + { + out << sp << nl << "public void" << nl << "invoke(Ice.Object v)"; + out << sb; + out << nl << "patch(v);"; + out << eb; + } + + out << sp << nl << "private java.util.Map __m;"; + out << nl << "private " << keyTypeS << " __key;"; + out << eb; + } + + out << sp << nl << "public static " << (dictType.empty() ? "java.util.Map" : dictType); + out << nl << "read(IceInternal.BasicStream __is)"; + out << sb; + out << nl << "int __sz = __is.readSize();"; + out << nl << (dictType.empty() ? "java.util.Map" : dictType) << " __r = new " + << (dictType.empty() ? "java.util.HashMap(__sz)" : dictType + "()") << ';'; + out << nl << "for(int __i = 0; __i < __sz; __i++)"; + out << sb; + iter = 0; + for(i = 0; i < 2; i++) + { + string arg; + TypePtr type; + if(i == 0) + { + arg = "__key"; + type = key; + } + else + { + arg = "__value"; + type = value; + } + + BuiltinPtr b = BuiltinPtr::dynamicCast(type); + if(b) + { + switch(b->kind()) + { + case Builtin::KindByte: + { + out << nl << "java.lang.Byte " << arg << " = new java.lang.Byte(__is.readByte());"; + break; + } + case Builtin::KindBool: + { + out << nl << "java.lang.Boolean " << arg << " = new java.lang.Boolean(__is.readBool());"; + break; + } + case Builtin::KindShort: + { + out << nl << "java.lang.Short " << arg << " = new java.lang.Short(__is.readShort());"; + break; + } + case Builtin::KindInt: + { + out << nl << "java.lang.Integer " << arg << " = new java.lang.Integer(__is.readInt());"; + break; + } + case Builtin::KindLong: + { + out << nl << "java.lang.Long " << arg << " = new java.lang.Long(__is.readLong());"; + break; + } + case Builtin::KindFloat: + { + out << nl << "java.lang.Float " << arg << " = new java.lang.Float(__is.readFloat());"; + break; + } + case Builtin::KindDouble: + { + out << nl << "java.lang.Double " << arg << " = new java.lang.Double(__is.readDouble());"; + break; + } + case Builtin::KindString: + { + out << nl << "java.lang.String " << arg << " = __is.readString();"; + break; + } + case Builtin::KindObject: + { + out << nl << "__is.readObject(new Patcher(__r, __key));"; + break; + } + case Builtin::KindObjectProxy: + { + out << nl << "Ice.ObjectPrx " << arg << " = __is.readProxy();"; + break; + } + case Builtin::KindLocalObject: + { + assert(false); + break; + } + } + } + else + { + string s = typeToString(type, TypeModeIn, package); + BuiltinPtr builtin2 = BuiltinPtr::dynamicCast(type); + if((builtin2 && builtin2->kind() == Builtin::KindObject) || ClassDeclPtr::dynamicCast(type)) + { + writeMarshalUnmarshalCode(out, package, type, arg, false, iter, false, StringList(), + "new Patcher(__r, __key)"); + } + else + { + out << nl << s << ' ' << arg << ';'; + writeMarshalUnmarshalCode(out, package, type, arg, false, iter, false); + } + } + } + if(!(builtin && builtin->kind() == Builtin::KindObject) && !ClassDeclPtr::dynamicCast(value)) + { + out << nl << "__r.put(__key, __value);"; + } + out << eb; + out << nl << "return __r;"; + out << eb; + + if(_stream) + { + out << sp << nl << "public static void" << nl << "write(Ice.OutputStream __out, " << "java.util.Map __v)"; + out << sb; + out << nl << "if(__v == null)"; + out << sb; + out << nl << "__out.writeSize(0);"; + out << eb; + out << nl << "else"; + out << sb; + out << nl << "__out.writeSize(__v.size());"; + out << nl << "java.util.Iterator __i = __v.entrySet().iterator();"; + out << nl << "while(__i.hasNext())"; + out << sb; + out << nl << "java.util.Map.Entry __e = (java.util.Map.Entry)" << "__i.next();"; + iter = 0; + for(i = 0; i < 2; i++) + { + string val; + string arg; + TypePtr type; + if(i == 0) + { + arg = "__e.getKey()"; + type = key; + } + else + { + arg = "__e.getValue()"; + type = value; + } + + BuiltinPtr b = BuiltinPtr::dynamicCast(type); + if(b) + { + switch(b->kind()) + { + case Builtin::KindByte: + { + val = "((java.lang.Byte)" + arg + ").byteValue()"; + break; + } + case Builtin::KindBool: + { + val = "((java.lang.Boolean)" + arg + ").booleanValue()"; + break; + } + case Builtin::KindShort: + { + val = "((java.lang.Short)" + arg + ").shortValue()"; + break; + } + case Builtin::KindInt: + { + val = "((java.lang.Integer)" + arg + ").intValue()"; + break; + } + case Builtin::KindLong: + { + val = "((java.lang.Long)" + arg + ").longValue()"; + break; + } + case Builtin::KindFloat: + { + val = "((java.lang.Float)" + arg + ").floatValue()"; + break; + } + case Builtin::KindDouble: + { + val = "((java.lang.Double)" + arg + ").doubleValue()"; + break; + } + case Builtin::KindString: + case Builtin::KindObject: + case Builtin::KindObjectProxy: + { + break; + } + case Builtin::KindLocalObject: + { + assert(false); + break; + } + } + } + + if(val.empty()) + { + val = "((" + typeToString(type, TypeModeIn, package) + ')' + arg + ')'; + } + writeStreamMarshalUnmarshalCode(out, package, type, val, true, iter, false); + } + out << eb; + out << eb; + out << eb; + + out << sp << nl << "public static " << (dictType.empty() ? "java.util.Map" : dictType) + << nl << "read(Ice.InputStream __in)"; + out << sb; + out << nl << "int __sz = __in.readSize();"; + out << nl << (dictType.empty() ? "java.util.Map" : dictType) << " __r = new " + << (dictType.empty() ? "java.util.HashMap(__sz)" : dictType + "()") << ';'; + out << nl << "for(int __i = 0; __i < __sz; __i++)"; + out << sb; + iter = 0; + for(i = 0; i < 2; i++) + { + string arg; + TypePtr type; + if(i == 0) + { + arg = "__key"; + type = key; + } + else + { + arg = "__value"; + type = value; + } + + BuiltinPtr b = BuiltinPtr::dynamicCast(type); + if(b) + { + switch(b->kind()) + { + case Builtin::KindByte: + { + out << nl << "java.lang.Byte " << arg << " = new java.lang.Byte(__in.readByte());"; + break; + } + case Builtin::KindBool: + { + out << nl << "java.lang.Boolean " << arg << " = new java.lang.Boolean(__in.readBool());"; + break; + } + case Builtin::KindShort: + { + out << nl << "java.lang.Short " << arg << " = new java.lang.Short(__in.readShort());"; + break; + } + case Builtin::KindInt: + { + out << nl << "java.lang.Integer " << arg << " = new java.lang.Integer(__in.readInt());"; + break; + } + case Builtin::KindLong: + { + out << nl << "java.lang.Long " << arg << " = new java.lang.Long(__in.readLong());"; + break; + } + case Builtin::KindFloat: + { + out << nl << "java.lang.Float " << arg << " = new java.lang.Float(__in.readFloat());"; + break; + } + case Builtin::KindDouble: + { + out << nl << "java.lang.Double " << arg << " = new java.lang.Double(__in.readDouble());"; + break; + } + case Builtin::KindString: + { + out << nl << "java.lang.String " << arg << " = __in.readString();"; + break; + } + case Builtin::KindObject: + { + out << nl << "__in.readObject(new Patcher(__r, __key));"; + break; + } + case Builtin::KindObjectProxy: + { + out << nl << "Ice.ObjectPrx " << arg << " = __in.readProxy();"; + break; + } + case Builtin::KindLocalObject: + { + assert(false); + break; + } + } + } + else + { + string s = typeToString(type, TypeModeIn, package); + BuiltinPtr builtin2 = BuiltinPtr::dynamicCast(type); + if((builtin2 && builtin2->kind() == Builtin::KindObject) || ClassDeclPtr::dynamicCast(type)) + { + writeStreamMarshalUnmarshalCode(out, package, type, arg, false, iter, false, StringList(), + "new Patcher(__r, __key)"); + } + else + { + out << nl << s << ' ' << arg << ';'; + writeStreamMarshalUnmarshalCode(out, package, type, arg, false, iter, false); + } + } + } + if(!(builtin && builtin->kind() == Builtin::KindObject) && !ClassDeclPtr::dynamicCast(value)) + { + out << nl << "__r.put(__key, __value);"; + } + out << eb; + out << nl << "return __r;"; + out << eb; + } + + out << eb; + close(); + } +} + +void +Slice::Gen::HelperVisitor::visitEnum(const EnumPtr& p) +{ + if(!p->isLocal() && _stream) + { + string name = p->name(); + string fixedName = fixKwd(name); + + if(!open(getAbsolute(p, "", "", "Helper"))) + { + return; + } + + Output& out = output(); + + out << sp << nl << "public final class " << name << "Helper"; + out << sb; + + out << sp << nl << "public static void" << nl << "write(Ice.OutputStream __out, " << fixedName << " __v)"; + out << sb; + out << nl << "__v.__write(__out);"; + out << eb; + + out << sp << nl << "public static " << fixedName << nl << "read(Ice.InputStream __in)"; + out << sb; + out << nl << "return " << fixedName << ".__read(__in);"; + out << eb; + + out << eb; + close(); + } +} + +Slice::Gen::ProxyVisitor::ProxyVisitor(const string& dir) : + JavaVisitor(dir) +{ +} + +bool +Slice::Gen::ProxyVisitor::visitClassDefStart(const ClassDefPtr& p) +{ + if(p->isLocal()) + { + return false; + } + + string name = p->name(); + ClassList bases = p->bases(); + string package = getPackage(p); + string absolute = getAbsolute(p, "", "", "Prx"); + + if(!open(absolute)) + { + return false; + } + + Output& out = output(); + + // + // Generate a Java interface as the user-visible type + // + out << sp << nl << "public interface " << name << "Prx extends "; + if(bases.empty()) + { + out << "Ice.ObjectPrx"; + } + else + { + out.useCurrentPosAsIndent(); + ClassList::const_iterator q = bases.begin(); + while(q != bases.end()) + { + out << getAbsolute(*q, package, "", "Prx"); + if(++q != bases.end()) + { + out << ',' << nl; + } + } + out.restoreIndent(); + } + + out << sb; + + return true; +} + +void +Slice::Gen::ProxyVisitor::visitClassDefEnd(const ClassDefPtr& p) +{ + Output& out = output(); + out << eb; + close(); +} + +void +Slice::Gen::ProxyVisitor::visitOperation(const OperationPtr& p) +{ + string name = fixKwd(p->name()); + ContainerPtr container = p->container(); + ClassDefPtr cl = ClassDefPtr::dynamicCast(container); + string package = getPackage(cl); + + Output& out = output(); + + TypePtr ret = p->returnType(); + string retS = typeToString(ret, TypeModeReturn, package, p->getMetaData()); + vector<string> params = getParams(p, package); + ExceptionList throws = p->throws(); + throws.sort(); + throws.unique(); + + // + // Write two versions of the operation - with and without a + // context parameter. + // + out << sp; + out << nl << "public " << retS << ' ' << name << spar << params << epar; + writeThrowsClause(package, throws); + out << ';'; + out << nl << "public " << retS << ' ' << name << spar << params << "java.util.Map __ctx" << epar; + writeThrowsClause(package, throws); + out << ';'; + + if(cl->hasMetaData("ami") || p->hasMetaData("ami")) + { + vector<string> paramsAMI = getParamsAsync(p, package, false); + + // + // Write two versions of the operation - with and without a + // context parameter. + // + out << sp; + out << nl << "public void " << p->name() << "_async" << spar << paramsAMI << epar << ';'; + out << nl << "public void " << p->name() << "_async" << spar << paramsAMI << "java.util.Map __ctx" + << epar << ';'; + } +} + +Slice::Gen::DelegateVisitor::DelegateVisitor(const string& dir) : + JavaVisitor(dir) +{ +} + +bool +Slice::Gen::DelegateVisitor::visitClassDefStart(const ClassDefPtr& p) +{ + if(p->isLocal()) + { + return false; + } + + string name = p->name(); + ClassList bases = p->bases(); + string package = getPackage(p); + string absolute = getAbsolute(p, "", "_", "Del"); + + if(!open(absolute)) + { + return false; + } + + Output& out = output(); + + out << sp << nl << "public interface _" << name << "Del extends "; + if(bases.empty()) + { + out << "Ice._ObjectDel"; + } + else + { + out.useCurrentPosAsIndent(); + ClassList::const_iterator q = bases.begin(); + while(q != bases.end()) + { + out << getAbsolute(*q, package, "_", "Del"); + if(++q != bases.end()) + { + out << ',' << nl; + } + } + out.restoreIndent(); + } + + out << sb; + + OperationList ops = p->operations(); + + OperationList::const_iterator r; + for(r = ops.begin(); r != ops.end(); ++r) + { + OperationPtr op = *r; + string opName = fixKwd(op->name()); + TypePtr ret = op->returnType(); + string retS = typeToString(ret, TypeModeReturn, package, op->getMetaData()); + + vector<string> params = getParams(op, package); + + ExceptionList throws = op->throws(); + throws.sort(); + throws.unique(); + + out << sp; + out << nl << retS << ' ' << opName << spar << params << "java.util.Map __ctx" << epar; + writeDelegateThrowsClause(package, throws); + out << ';'; + } + + out << eb; + close(); + + return false; +} + +Slice::Gen::DelegateMVisitor::DelegateMVisitor(const string& dir) : + JavaVisitor(dir) +{ +} + +bool +Slice::Gen::DelegateMVisitor::visitClassDefStart(const ClassDefPtr& p) +{ + if(p->isLocal()) + { + return false; + } + + string name = p->name(); + ClassList bases = p->bases(); + string package = getPackage(p); + string absolute = getAbsolute(p, "", "_", "DelM"); + + if(!open(absolute)) + { + return false; + } + + Output& out = output(); + + out << sp << nl << "public final class _" << name << "DelM extends Ice._ObjectDelM implements _" << name << "Del"; + out << sb; + + OperationList ops = p->allOperations(); + + OperationList::const_iterator r; + for(r = ops.begin(); r != ops.end(); ++r) + { + OperationPtr op = *r; + StringList opMetaData = op->getMetaData(); + string opName = fixKwd(op->name()); + TypePtr ret = op->returnType(); + string retS = typeToString(ret, TypeModeReturn, package, opMetaData); + int iter; + + ParamDeclList inParams; + ParamDeclList outParams; + ParamDeclList paramList = op->parameters(); + ParamDeclList::const_iterator pli; + for(pli = paramList.begin(); pli != paramList.end(); ++pli) + { + if((*pli)->isOutParam()) + { + outParams.push_back(*pli); + } + else + { + inParams.push_back(*pli); + } + } + + ExceptionList throws = op->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(Slice::derivedToBaseCompare); +#else + throws.sort(Slice::DerivedToBaseCompare()); +#endif + + vector<string> params = getParams(op, package); + + out << sp; + out << nl << "public " << retS << nl << opName << spar << params << "java.util.Map __ctx" << epar; + writeDelegateThrowsClause(package, throws); + out << sb; + + out << nl << "IceInternal.Outgoing __out = getOutgoing(\"" << op->name() << "\", " << sliceModeToIceMode(op) + << ", __ctx);"; + out << nl << "try"; + out << sb; + if(!inParams.empty()) + { + out << nl << "try"; + out << sb; + out << nl << "IceInternal.BasicStream __os = __out.os();"; + iter = 0; + for(pli = inParams.begin(); pli != inParams.end(); ++pli) + { + writeMarshalUnmarshalCode(out, package, (*pli)->type(), fixKwd((*pli)->name()), true, iter, false, + (*pli)->getMetaData()); + } + if(op->sendsClasses()) + { + out << nl << "__os.writePendingObjects();"; + } + out << eb; + out << nl << "catch(Ice.LocalException __ex)"; + out << sb; + out << nl << "__out.abort(__ex);"; + out << eb; + } + out << nl << "boolean __ok = __out.invoke();"; + out << nl << "try"; + out << sb; + out << nl << "IceInternal.BasicStream __is = __out.is();"; + out << nl << "if(!__ok)"; + out << sb; + out << nl << "try"; + out << sb; + out << nl << "__is.throwException();"; + out << eb; + for(ExceptionList::const_iterator t = throws.begin(); t != throws.end(); ++t) + { + out << nl << "catch(" << getAbsolute(*t, package) << " __ex)"; + out << sb; + out << nl << "throw __ex;"; + out << eb; + } + out << nl << "catch(Ice.UserException __ex)"; + out << sb; + out << nl << "throw new Ice.UnknownUserException();"; + out << eb; + out << eb; + for(pli = outParams.begin(); pli != outParams.end(); ++pli) + { + writeMarshalUnmarshalCode(out, package, (*pli)->type(), fixKwd((*pli)->name()), false, iter, true, + (*pli)->getMetaData()); + } + if(ret) + { + BuiltinPtr builtin = BuiltinPtr::dynamicCast(ret); + if((builtin && builtin->kind() == Builtin::KindObject) || ClassDeclPtr::dynamicCast(ret)) + { + out << nl << retS << "Holder __ret = new " << retS << "Holder();"; + out << nl << "__is.readObject(__ret.getPatcher());"; + } + else + { + out << nl << retS << " __ret;"; + writeMarshalUnmarshalCode(out, package, ret, "__ret", false, iter, false, opMetaData); + } + } + if(op->returnsClasses()) + { + out << nl << "__is.readPendingObjects();"; + } + if(ret) + { + BuiltinPtr builtin = BuiltinPtr::dynamicCast(ret); + if((builtin && builtin->kind() == Builtin::KindObject) || ClassDeclPtr::dynamicCast(ret)) + { + out << nl << "return __ret.value;"; + } + else + { + out << nl << "return __ret;"; + } + } + out << eb; + out << nl << "catch(Ice.LocalException __ex)"; + out << sb; + out << nl << "throw new IceInternal.NonRepeatable(__ex);"; + out << eb; + out << eb; + out << nl << "finally"; + out << sb; + out << nl << "reclaimOutgoing(__out);"; + out << eb; + out << eb; + } + + out << eb; + close(); + + return false; +} + +Slice::Gen::DelegateDVisitor::DelegateDVisitor(const string& dir) : + JavaVisitor(dir) +{ +} + +bool +Slice::Gen::DelegateDVisitor::visitClassDefStart(const ClassDefPtr& p) +{ + if(p->isLocal()) + { + return false; + } + + string name = p->name(); + ClassList bases = p->bases(); + string package = getPackage(p); + string absolute = getAbsolute(p, "", "_", "DelD"); + + if(!open(absolute)) + { + return false; + } + + Output& out = output(); + + out << sp << nl << "public final class _" << name << "DelD extends Ice._ObjectDelD implements _" << name << "Del"; + out << sb; + + OperationList ops = p->allOperations(); + + OperationList::const_iterator r; + for(r = ops.begin(); r != ops.end(); ++r) + { + OperationPtr op = *r; + ContainerPtr container = op->container(); + ClassDefPtr cl = ClassDefPtr::dynamicCast(container); + string opName = fixKwd(op->name()); + TypePtr ret = op->returnType(); + string retS = typeToString(ret, TypeModeReturn, package, op->getMetaData()); + + ExceptionList throws = op->throws(); + throws.sort(); + throws.unique(); + + vector<string> params = getParams(op, package); + vector<string> args = getArgs(op); + + out << sp; + out << nl << "public " << retS << nl << opName << spar << params << "java.util.Map __ctx" << epar; + writeDelegateThrowsClause(package, throws); + out << sb; + if(cl->hasMetaData("amd") || op->hasMetaData("amd")) + { + out << nl << "throw new Ice.CollocationOptimizationException();"; + } + else + { + StringList metaData = op->getMetaData(); + out << nl << "Ice.Current __current = new Ice.Current();"; + out << nl << "__initCurrent(__current, \"" << op->name() << "\", " << sliceModeToIceMode(op) + << ", __ctx);"; + out << nl << "while(true)"; + out << sb; + out << nl << "IceInternal.Direct __direct = new IceInternal.Direct(__current);"; + out << nl << "try"; + out << sb; + out << nl << fixKwd(name) << " __servant = null;"; + out << nl << "try"; + out << sb; + out << nl << "__servant = (" << fixKwd(name) << ")__direct.servant();"; + out << eb; + out << nl << "catch(ClassCastException __ex)"; + out << sb; + out << nl << "Ice.OperationNotExistException __opEx = new Ice.OperationNotExistException();"; + out << nl << "__opEx.id = __current.id;"; + out << nl << "__opEx.facet = __current.facet;"; + out << nl << "__opEx.operation = __current.operation;"; + out << nl << "throw __opEx;"; + out << eb; + out << nl << "try"; + out << sb; + out << nl; + if(ret) + { + out << "return "; + } + out << "__servant." << opName << spar << args << "__current" << epar << ';'; + if(!ret) + { + out << nl << "return;"; + } + out << eb; + out << nl << "catch(Ice.LocalException __ex)"; + out << sb; + out << nl << "throw new IceInternal.NonRepeatable(__ex);"; + out << eb; + out << eb; + out << nl << "finally"; + out << sb; + out << nl << "__direct.destroy();"; + out << eb; + out << eb; + } + out << eb; + } + + out << eb; + close(); + + return false; +} + +Slice::Gen::DispatcherVisitor::DispatcherVisitor(const string& dir) : + JavaVisitor(dir) +{ +} + +bool +Slice::Gen::DispatcherVisitor::visitClassDefStart(const ClassDefPtr& p) +{ + if(p->isLocal() || !p->isInterface()) + { + return false; + } + + string name = p->name(); + ClassList bases = p->bases(); + string absolute = getAbsolute(p, "", "_", "Disp"); + + if(!open(absolute)) + { + return false; + } + + Output& out = output(); + + out << sp << nl << "public abstract class _" << name << "Disp extends Ice.ObjectImpl implements " << fixKwd(name); + out << sb; + + out << sp << nl << "protected void" << nl << "ice_copyStateFrom(Ice.Object __obj)"; + out.inc(); + out << nl << "throws java.lang.CloneNotSupportedException"; + out.dec(); + out << sb; + out << nl << "throw new java.lang.CloneNotSupportedException();"; + out << eb; + + writeDispatch(out, p); + + out << eb; + close(); + + return false; +} + +Slice::Gen::BaseImplVisitor::BaseImplVisitor(const string& dir) : + JavaVisitor(dir) +{ +} + +void +Slice::Gen::BaseImplVisitor::writeDecl(Output& out, const string& package, const string& name, const TypePtr& type, + const StringList& metaData) +{ + out << nl << typeToString(type, TypeModeIn, package, metaData) << ' ' << name; + + BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); + if(builtin) + { + switch(builtin->kind()) + { + case Builtin::KindBool: + { + out << " = false"; + break; + } + case Builtin::KindByte: + { + out << " = (byte)0"; + break; + } + case Builtin::KindShort: + { + out << " = (short)0"; + break; + } + case Builtin::KindInt: + case Builtin::KindLong: + { + out << " = 0"; + break; + } + case Builtin::KindFloat: + { + out << " = (float)0.0"; + break; + } + case Builtin::KindDouble: + { + out << " = 0.0"; + break; + } + case Builtin::KindString: + { + out << " = \"\""; + break; + } + case Builtin::KindObject: + case Builtin::KindObjectProxy: + case Builtin::KindLocalObject: + { + out << " = null"; + break; + } + } + } + else + { + EnumPtr en = EnumPtr::dynamicCast(type); + if(en) + { + EnumeratorList enumerators = en->getEnumerators(); + out << " = " << getAbsolute(en, package) << '.' << fixKwd(enumerators.front()->name()); + } + else + { + out << " = null"; + } + } + + out << ';'; +} + +void +Slice::Gen::BaseImplVisitor::writeReturn(Output& out, const TypePtr& type) +{ + BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); + if(builtin) + { + switch(builtin->kind()) + { + case Builtin::KindBool: + { + out << nl << "return false;"; + break; + } + case Builtin::KindByte: + { + out << nl << "return (byte)0;"; + break; + } + case Builtin::KindShort: + { + out << nl << "return (short)0;"; + break; + } + case Builtin::KindInt: + case Builtin::KindLong: + { + out << nl << "return 0;"; + break; + } + case Builtin::KindFloat: + { + out << nl << "return (float)0.0;"; + break; + } + case Builtin::KindDouble: + { + out << nl << "return 0.0;"; + break; + } + case Builtin::KindString: + case Builtin::KindObject: + case Builtin::KindObjectProxy: + case Builtin::KindLocalObject: + { + out << nl << "return null;"; + break; + } + } + return; + } + + out << nl << "return null;"; +} + +void +Slice::Gen::BaseImplVisitor::writeOperation(Output& out, const string& package, const OperationPtr& op, bool local) +{ + string opName = op->name(); + + TypePtr ret = op->returnType(); + StringList opMetaData = op->getMetaData(); + string retS = typeToString(ret, TypeModeReturn, package, opMetaData); + vector<string> params = getParams(op, package); + + ContainerPtr container = op->container(); + ClassDefPtr cl = ClassDefPtr::dynamicCast(container); + + if(!local && (cl->hasMetaData("amd") || op->hasMetaData("amd"))) + { + vector<string> paramsAMD = getParamsAsync(op, package, true); + + out << sp << nl << "public void" << nl << opName << "_async" << spar << paramsAMD << "Ice.Current __current" + << epar; + + ExceptionList throws = op->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(Slice::derivedToBaseCompare); +#else + throws.sort(Slice::DerivedToBaseCompare()); +#endif + writeThrowsClause(package, throws); + + out << sb; + + string result = "__r"; + ParamDeclList paramList = op->parameters(); + ParamDeclList::const_iterator q; + for(q = paramList.begin(); q != paramList.end(); ++q) + { + if((*q)->name() == result) + { + result = "_" + result; + break; + } + } + if(ret) + { + writeDecl(out, package, result, ret, opMetaData); + } + for(q = paramList.begin(); q != paramList.end(); ++q) + { + if((*q)->isOutParam()) + { + writeDecl(out, package, fixKwd((*q)->name()), (*q)->type(), (*q)->getMetaData()); + } + } + + out << nl << "__cb.ice_response("; + if(ret) + { + out << result; + } + for(q = paramList.begin(); q != paramList.end(); ++q) + { + if((*q)->isOutParam()) + { + if(ret || q != paramList.begin()) + { + out << ", "; + } + out << fixKwd((*q)->name()); + } + } + out << ");"; + + out << eb; + } + else + { + out << sp << nl << "public " << retS << nl << fixKwd(opName) << spar << params; + if(!local) + { + out << "Ice.Current __current"; + } + out << epar; + + ExceptionList throws = op->throws(); + throws.sort(); + throws.unique(); + + writeThrowsClause(package, throws); + + out << sb; + + // + // Return value + // + if(ret) + { + writeReturn(out, ret); + } + + out << eb; + } +} + +Slice::Gen::ImplVisitor::ImplVisitor(const string& dir) : + BaseImplVisitor(dir) +{ +} + +bool +Slice::Gen::ImplVisitor::visitClassDefStart(const ClassDefPtr& p) +{ + if(!p->isAbstract()) + { + return false; + } + + string name = p->name(); + ClassList bases = p->bases(); + string package = getPackage(p); + string absolute = getAbsolute(p, "", "", "I"); + + if(!open(absolute)) + { + return false; + } + + Output& out = output(); + + out << sp << nl << "public final class " << name << 'I'; + if(p->isInterface()) + { + if(p->isLocal()) + { + out << " extends Ice.LocalObjectImpl implements " << fixKwd(name); + } + else + { + out << " extends _" << name << "Disp"; + } + } + else + { + out << " extends " << fixKwd(name); + } + out << sb; + + out << nl << "public" << nl << name << "I()"; + out << sb; + out << eb; + + OperationList ops = p->allOperations(); + + OperationList::const_iterator r; + for(r = ops.begin(); r != ops.end(); ++r) + { + writeOperation(out, package, *r, p->isLocal()); + } + + out << eb; + close(); + + return false; +} + +Slice::Gen::ImplTieVisitor::ImplTieVisitor(const string& dir) : + BaseImplVisitor(dir) +{ +} + +bool +Slice::Gen::ImplTieVisitor::visitClassDefStart(const ClassDefPtr& p) +{ + if(!p->isAbstract()) + { + return false; + } + + string name = p->name(); + ClassList bases = p->bases(); + string package = getPackage(p); + string absolute = getAbsolute(p, "", "", "I"); + + if(!open(absolute)) + { + return false; + } + + Output& out = output(); + + // + // Use implementation inheritance in the following situations: + // + // * if a class extends another class + // * if a class implements a single interface + // * if an interface extends only one interface + // + bool inheritImpl = (!p->isInterface() && !bases.empty() && !bases.front()->isInterface()) || (bases.size() == 1); + + out << sp << nl << "public class " << name << 'I'; + if(inheritImpl) + { + out << " extends "; + if(bases.front()->isAbstract()) + { + out << bases.front()->name() << 'I'; + } + else + { + out << fixKwd(bases.front()->name()); + } + } + out << " implements " << '_' << name << "Operations"; + if(p->isLocal()) + { + out << "NC"; + } + out << sb; + + out << nl << "public" << nl << name << "I()"; + out << sb; + out << eb; + + OperationList ops = p->allOperations(); + ops.sort(); + + OperationList baseOps; + if(inheritImpl) + { + baseOps = bases.front()->allOperations(); + baseOps.sort(); + } + + OperationList::const_iterator r; + for(r = ops.begin(); r != ops.end(); ++r) + { + if(inheritImpl && binary_search(baseOps.begin(), baseOps.end(), *r)) + { + out << sp; + out << nl << "/*"; + out << nl << " * Implemented by " << bases.front()->name() << 'I'; + out << nl << " *"; + writeOperation(out, package, *r, p->isLocal()); + out << sp; + out << nl << "*/"; + } + else + { + writeOperation(out, package, *r, p->isLocal()); + } + } + + out << eb; + close(); + + return false; +} + +Slice::Gen::AsyncVisitor::AsyncVisitor(const string& dir) : + JavaVisitor(dir) +{ +} + +void +Slice::Gen::AsyncVisitor::visitOperation(const OperationPtr& p) +{ + ContainerPtr container = p->container(); + ClassDefPtr cl = ClassDefPtr::dynamicCast(container); + + if(cl->isLocal()) + { + return; + } + + string name = p->name(); + string classPkg = getPackage(cl); + StringList opMetaData = p->getMetaData(); + + if(cl->hasMetaData("ami") || p->hasMetaData("ami")) + { + string classNameAMI = "AMI_" + cl->name(); + string absoluteAMI = getAbsolute(cl, "", "AMI_", "_" + name); + + if(!open(absoluteAMI)) + { + return; + } + + Output& out = output(); + + TypePtr ret = p->returnType(); + + ParamDeclList inParams; + ParamDeclList outParams; + ParamDeclList paramList = p->parameters(); + ParamDeclList::const_iterator pli; + for(pli = paramList.begin(); pli != paramList.end(); ++pli) + { + if((*pli)->isOutParam()) + { + outParams.push_back(*pli); + } + else + { + inParams.push_back(*pli); + } + } + + 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(Slice::derivedToBaseCompare); +#else + throws.sort(Slice::DerivedToBaseCompare()); +#endif + + int iter; + + vector<string> params = getParamsAsyncCB(p, classPkg); + vector<string> args = getArgsAsyncCB(p); + + vector<string> paramsInvoke = getParamsAsync(p, classPkg, false); + + out << sp << nl << "public abstract class " << classNameAMI << '_' << name + << " extends IceInternal.OutgoingAsync"; + out << sb; + out << sp; + out << nl << "public abstract void ice_response" << spar << params << epar << ';'; + out << nl << "public abstract void ice_exception(Ice.LocalException ex);"; + if(!throws.empty()) + { + out << nl << "public abstract void ice_exception(Ice.UserException ex);"; + } + + out << sp << nl << "public final void" << nl << "__invoke" << spar << "Ice.ObjectPrx __prx" + << paramsInvoke << "java.util.Map __ctx" << epar; + out << sb; + out << nl << "try"; + out << sb; + out << nl << "__prepare(__prx, \"" << p->name() << "\", " << sliceModeToIceMode(p) << ", __ctx);"; + iter = 0; + for(pli = inParams.begin(); pli != inParams.end(); ++pli) + { + StringList metaData = (*pli)->getMetaData(); + string typeS = typeToString((*pli)->type(), TypeModeIn, classPkg, metaData); + writeMarshalUnmarshalCode(out, classPkg, (*pli)->type(), fixKwd((*pli)->name()), true, iter, false, + metaData); + } + if(p->sendsClasses()) + { + out << nl << "__os.writePendingObjects();"; + } + out << nl << "__os.endWriteEncaps();"; + out << eb; + out << nl << "catch(Ice.LocalException __ex)"; + out << sb; + out << nl << "__finished(__ex);"; + out << nl << "return;"; + out << eb; + out << nl << "__send();"; + out << eb; + + out << sp << nl << "protected final void" << nl << "__response(boolean __ok)"; + out << sb; + for(pli = outParams.begin(); pli != outParams.end(); ++pli) + { + TypePtr paramType = (*pli)->type(); + string paramName = fixKwd((*pli)->name()); + string typeS = typeToString(paramType, TypeModeIn, classPkg, (*pli)->getMetaData()); + BuiltinPtr builtin = BuiltinPtr::dynamicCast(paramType); + if((builtin && builtin->kind() == Builtin::KindObject) || ClassDeclPtr::dynamicCast(paramType)) + { + out << nl << typeS << "Holder " << paramName << " = new " << typeS << "Holder();"; + } + else + { + out << nl << typeS << ' ' << paramName << ';'; + } + } + if(ret) + { + string retS = typeToString(ret, TypeModeIn, classPkg, opMetaData); + BuiltinPtr builtin = BuiltinPtr::dynamicCast(ret); + if((builtin && builtin->kind() == Builtin::KindObject) || ClassDeclPtr::dynamicCast(ret)) + { + out << nl << retS << "Holder __ret = new " << retS << "Holder();"; + } + else + { + out << nl << retS << " __ret;"; + } + } + out << nl << "try"; + out << sb; + out << nl << "if(!__ok)"; + out << sb; + out << nl << "try"; + out << sb; + out << nl << "__is.throwException();"; + out << eb; + for(ExceptionList::const_iterator r = throws.begin(); r != throws.end(); ++r) + { + out << nl << "catch(" << getAbsolute(*r, classPkg) << " __ex)"; + out << sb; + out << nl << "throw __ex;"; + out << eb; + } + out << nl << "catch(Ice.UserException __ex)"; + out << sb; + out << nl << "throw new Ice.UnknownUserException();"; + out << eb; + out << eb; + for(pli = outParams.begin(); pli != outParams.end(); ++pli) + { + TypePtr paramType = (*pli)->type(); + string paramName = fixKwd((*pli)->name()); + BuiltinPtr builtin = BuiltinPtr::dynamicCast(paramType); + if((builtin && builtin->kind() == Builtin::KindObject) || ClassDeclPtr::dynamicCast(paramType)) + { + out << nl << "__is.readObject(" << paramName << ".getPatcher());"; + } + else + { + writeMarshalUnmarshalCode(out, classPkg, paramType, paramName, false, iter, false, + (*pli)->getMetaData()); + } + } + if(ret) + { + BuiltinPtr builtin = BuiltinPtr::dynamicCast(ret); + if((builtin && builtin->kind() == Builtin::KindObject) || ClassDeclPtr::dynamicCast(ret)) + { + out << nl << "__is.readObject(__ret.getPatcher());"; + } + else + { + writeMarshalUnmarshalCode(out, classPkg, ret, "__ret", false, iter, false, opMetaData); + } + } + if(p->returnsClasses()) + { + out << nl << "__is.readPendingObjects();"; + } + out << eb; + out << nl << "catch(Ice.LocalException __ex)"; + out << sb; + out << nl << "__finished(__ex);"; + out << nl << "return;"; + out << eb; + if(!throws.empty()) + { + out << nl << "catch(Ice.UserException __ex)"; + out << sb; + out << nl << "ice_exception(__ex);"; + out << nl << "return;"; + out << eb; + } + out << nl << "ice_response" << spar << args << epar << ';'; + out << eb; + out << eb; + + close(); + } + + if(cl->hasMetaData("amd") || p->hasMetaData("amd")) + { + string classNameAMD = "AMD_" + cl->name(); + string absoluteAMD = getAbsolute(cl, "", "AMD_", "_" + name); + + string classNameAMDI = "_AMD_" + cl->name(); + string absoluteAMDI = getAbsolute(cl, "", "_AMD_", "_" + name); + + vector<string> paramsAMD = getParamsAsyncCB(p, classPkg); + + { + if(!open(absoluteAMD)) + { + return; + } + + Output& out = output(); + + out << sp << nl << "public interface " << classNameAMD << '_' << name; + out << sb; + out << sp << nl << "void ice_response" << spar << paramsAMD << epar << ';'; + out << sp << nl << "void ice_exception(java.lang.Exception ex);"; + out << eb; + + close(); + } + + { + if(!open(absoluteAMDI)) + { + return; + } + + Output& out = output(); + + TypePtr ret = p->returnType(); + + ParamDeclList outParams; + ParamDeclList paramList = p->parameters(); + ParamDeclList::const_iterator pli; + for(pli = paramList.begin(); pli != paramList.end(); ++pli) + { + if((*pli)->isOutParam()) + { + outParams.push_back(*pli); + } + } + + 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(Slice::derivedToBaseCompare); +#else + throws.sort(Slice::DerivedToBaseCompare()); +#endif + + int iter; + + out << sp << nl << "final class " << classNameAMDI << '_' << name + << " extends IceInternal.IncomingAsync implements " << classNameAMD << '_' << name; + out << sb; + + out << sp << nl << "public" << nl << classNameAMDI << '_' << name << "(IceInternal.Incoming in)"; + out << sb; + out << nl << "super(in);"; + out << eb; + + out << sp << nl << "public void" << nl << "ice_response" << spar << paramsAMD << epar; + out << sb; + iter = 0; + if(ret || !outParams.empty()) + { + out << nl << "try"; + out << sb; + out << nl << "IceInternal.BasicStream __os = this.__os();"; + for(pli = outParams.begin(); pli != outParams.end(); ++pli) + { + StringList metaData = (*pli)->getMetaData(); + string typeS = typeToString((*pli)->type(), TypeModeIn, classPkg, metaData); + writeMarshalUnmarshalCode(out, classPkg, (*pli)->type(), fixKwd((*pli)->name()), true, iter, + false, metaData); + } + if(ret) + { + string retS = typeToString(ret, TypeModeIn, classPkg, opMetaData); + writeMarshalUnmarshalCode(out, classPkg, ret, "__ret", true, iter, false, opMetaData); + } + if(p->returnsClasses()) + { + out << nl << "__os.writePendingObjects();"; + } + out << eb; + out << nl << "catch(Ice.LocalException __ex)"; + out << sb; + out << nl << "ice_exception(__ex);"; + out << eb; + } + out << nl << "__response(true);"; + out << eb; + + out << sp << nl << "public void" << nl << "ice_exception(java.lang.Exception ex)"; + out << sb; + if(throws.empty()) + { + out << nl << "__exception(ex);"; + } + else + { + out << nl << "try"; + out << sb; + out << nl << "throw ex;"; + out << eb; + ExceptionList::const_iterator r; + for(r = throws.begin(); r != throws.end(); ++r) + { + string exS = getAbsolute(*r, classPkg); + out << nl << "catch(" << exS << " __ex)"; + out << sb; + out << nl << "__os().writeUserException(__ex);"; + out << nl << "__response(false);"; + out << eb; + } + out << nl << "catch(java.lang.Exception __ex)"; + out << sb; + out << nl << "__exception(__ex);"; + out << eb; + } + out << eb; + + out << eb; + + close(); + } + } +} diff --git a/cpp/src/slice2javae/Gen.h b/cpp/src/slice2javae/Gen.h new file mode 100644 index 00000000000..ff555c28102 --- /dev/null +++ b/cpp/src/slice2javae/Gen.h @@ -0,0 +1,281 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2005 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 <Slice/JavaUtil.h> +#include <Slice/Checksum.h> + +namespace Slice +{ + +class JavaVisitor : public JavaGenerator, public ParserVisitor +{ +public: + + virtual ~JavaVisitor(); + +protected: + + JavaVisitor(const std::string&); + + // + // Compose the parameter lists for an operation. + // + std::vector<std::string> getParams(const OperationPtr&, const std::string&); + std::vector<std::string> getParamsAsync(const OperationPtr&, const std::string&, bool); + std::vector<std::string> getParamsAsyncCB(const OperationPtr&, const std::string&); + + // + // Compose the argument lists for an operation. + // + std::vector<std::string> getArgs(const OperationPtr&); + std::vector<std::string> getArgsAsync(const OperationPtr&); + std::vector<std::string> getArgsAsyncCB(const OperationPtr&); + + // + // Generate a throws clause containing only non-local exceptions. + // + void writeThrowsClause(const std::string&, const ExceptionList&); + + // + // Generate a throws clause for delegate operations containing only + // non-local exceptions. + // + void writeDelegateThrowsClause(const std::string&, const ExceptionList&); + + // + // Generate code to compute a hash code for a type. + // + void writeHashCode(::IceUtil::Output&, const TypePtr&, const std::string&, int&, + const std::list<std::string>& = std::list<std::string>()); + + // + // Generate dispatch methods for a class or interface. + // + void writeDispatch(::IceUtil::Output&, const ClassDefPtr&); +}; + +class Gen : public ::IceUtil::noncopyable +{ +public: + + Gen(const std::string&, + const std::string&, + const std::vector<std::string>&, + const std::string&); + ~Gen(); + + bool operator!() const; // Returns true if there was a constructor error + + void generate(const UnitPtr&, bool); + void generateTie(const UnitPtr&); + void generateImpl(const UnitPtr&); + void generateImplTie(const UnitPtr&); + + static void writeChecksumClass(const std::string&, const std::string&, const ChecksumMap&); + +private: + + std::string _base; + std::vector<std::string> _includePaths; + std::string _dir; + + class OpsVisitor : public JavaVisitor + { + public: + + OpsVisitor(const std::string&); + + virtual bool visitClassDefStart(const ClassDefPtr&); + + private: + void writeOperations(const ClassDefPtr&, bool); + }; + + class TieVisitor : public JavaVisitor + { + public: + + TieVisitor(const std::string&); + + virtual bool visitClassDefStart(const ClassDefPtr&); + }; + + class PackageVisitor : public JavaVisitor + { + public: + + PackageVisitor(const std::string&); + + virtual bool visitModuleStart(const ModulePtr&); + }; + + class TypesVisitor : public JavaVisitor + { + public: + + TypesVisitor(const std::string&, bool); + + 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 visitEnum(const EnumPtr&); + virtual void visitConst(const ConstPtr&); + virtual void visitDataMember(const DataMemberPtr&); + + private: + + bool _stream; + }; + + class HolderVisitor : public JavaVisitor + { + public: + + HolderVisitor(const std::string&, bool); + + virtual bool visitClassDefStart(const ClassDefPtr&); + virtual bool visitStructStart(const StructPtr&); + virtual void visitSequence(const SequencePtr&); + virtual void visitDictionary(const DictionaryPtr&); + virtual void visitEnum(const EnumPtr&); + + private: + + void writeHolder(const TypePtr&); + + bool _stream; + }; + + class HelperVisitor : public JavaVisitor + { + public: + + HelperVisitor(const std::string&, bool); + + virtual bool visitClassDefStart(const ClassDefPtr&); + virtual bool visitStructStart(const StructPtr&); + virtual void visitSequence(const SequencePtr&); + virtual void visitDictionary(const DictionaryPtr&); + virtual void visitEnum(const EnumPtr&); + + private: + + bool _stream; + }; + + class ProxyVisitor : public JavaVisitor + { + public: + + ProxyVisitor(const std::string&); + + virtual bool visitClassDefStart(const ClassDefPtr&); + virtual void visitClassDefEnd(const ClassDefPtr&); + virtual void visitOperation(const OperationPtr&); + }; + + class DelegateVisitor : public JavaVisitor + { + public: + + DelegateVisitor(const std::string&); + + virtual bool visitClassDefStart(const ClassDefPtr&); + }; + + class DelegateMVisitor : public JavaVisitor + { + public: + + DelegateMVisitor(const std::string&); + + virtual bool visitClassDefStart(const ClassDefPtr&); + }; + + class DelegateDVisitor : public JavaVisitor + { + public: + + DelegateDVisitor(const std::string&); + + virtual bool visitClassDefStart(const ClassDefPtr&); + }; + + class DispatcherVisitor : public JavaVisitor + { + public: + + DispatcherVisitor(const std::string&); + + virtual bool visitClassDefStart(const ClassDefPtr&); + }; + + class BaseImplVisitor : public JavaVisitor + { + public: + + BaseImplVisitor(const std::string&); + + protected: + + // + // Generate code to emit a local variable declaration and initialize it + // if necessary. + // + void writeDecl(::IceUtil::Output&, const std::string&, const std::string&, const TypePtr&, const StringList&); + + // + // Generate code to return a value. + // + void writeReturn(::IceUtil::Output&, const TypePtr&); + + // + // Generate an operation. + // + void writeOperation(::IceUtil::Output&, const std::string&, const OperationPtr&, bool); + }; + + class ImplVisitor : public BaseImplVisitor + { + public: + + ImplVisitor(const std::string&); + + virtual bool visitClassDefStart(const ClassDefPtr&); + }; + + class ImplTieVisitor : public BaseImplVisitor + { + public: + + ImplTieVisitor(const std::string&); + + virtual bool visitClassDefStart(const ClassDefPtr&); + }; + + class AsyncVisitor : public JavaVisitor + { + public: + + AsyncVisitor(const std::string&); + + virtual void visitOperation(const OperationPtr&); + }; +}; + +} + +#endif diff --git a/cpp/src/slice2javae/Main.cpp b/cpp/src/slice2javae/Main.cpp new file mode 100644 index 00000000000..cbbe476f91f --- /dev/null +++ b/cpp/src/slice2javae/Main.cpp @@ -0,0 +1,226 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2005 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 <Slice/Preprocessor.h> +#include <Gen.h> + +using namespace std; +using namespace Slice; + +void +usage(const char* n) +{ + cerr << "Usage: " << n << " [options] slice-files...\n"; + cerr << + "Options:\n" + "-h, --help Show this message.\n" + "-v, --version Display the Ice version.\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" + "--output-dir DIR Create files in the directory DIR.\n" + "--tie Generate TIE classes.\n" + "--impl Generate sample implementations.\n" + "--impl-tie Generate sample TIE implementations.\n" + "--depend Generate Makefile dependencies.\n" + "-d, --debug Print debug messages.\n" + "--ice Permit `Ice' prefix (for building Ice source code only)\n" + "--checksum CLASS Generate checksums for Slice definitions into CLASS.\n" + "--stream Generate marshaling support for public stream API.\n" + ; + // Note: --case-sensitive is intentionally not shown here! +} + +int +main(int argc, char* argv[]) +{ + string cppArgs; + vector<string> includePaths; + string output; + bool tie; + bool impl; + bool implTie; + bool depend; + bool debug; + bool ice; + string checksumClass; + bool stream; + bool caseSensitive; + + IceUtil::Options opts; + opts.addOpt("h", "help"); + opts.addOpt("v", "version"); + opts.addOpt("D", "", IceUtil::Options::NeedArg, "", IceUtil::Options::Repeat); + opts.addOpt("U", "", IceUtil::Options::NeedArg, "", IceUtil::Options::Repeat); + opts.addOpt("I", "", IceUtil::Options::NeedArg, "", IceUtil::Options::Repeat); + opts.addOpt("", "output-dir", IceUtil::Options::NeedArg); + opts.addOpt("", "tie"); + opts.addOpt("", "impl"); + opts.addOpt("", "impl-tie"); + opts.addOpt("", "depend"); + opts.addOpt("d", "debug"); + opts.addOpt("", "ice"); + opts.addOpt("", "checksum", IceUtil::Options::NeedArg); + opts.addOpt("", "stream"); + opts.addOpt("", "case-sensitive"); + + vector<string>args; + try + { + args = opts.parse(argc, argv); + } + catch(const IceUtil::Options::BadOpt& e) + { + cerr << argv[0] << ": " << e.reason << endl; + usage(argv[0]); + return EXIT_FAILURE; + } + + if(opts.isSet("h") || opts.isSet("help")) + { + usage(argv[0]); + return EXIT_SUCCESS; + } + if(opts.isSet("v") || opts.isSet("version")) + { + cout << ICE_STRING_VERSION << endl; + return EXIT_SUCCESS; + } + if(opts.isSet("D")) + { + vector<string> optargs = opts.argVec("D"); + for(vector<string>::const_iterator i = optargs.begin(); i != optargs.end(); ++i) + { + cppArgs += " -D" + *i; + } + } + if(opts.isSet("U")) + { + vector<string> optargs = opts.argVec("U"); + for(vector<string>::const_iterator i = optargs.begin(); i != optargs.end(); ++i) + { + cppArgs += " -U" + *i; + } + } + if(opts.isSet("I")) + { + includePaths = opts.argVec("I"); + for(vector<string>::const_iterator i = includePaths.begin(); i != includePaths.end(); ++i) + { + cppArgs += " -I" + *i; + } + } + if(opts.isSet("output-dir")) + { + output = opts.optArg("output-dir"); + } + tie = opts.isSet("tie"); + impl = opts.isSet("impl"); + implTie = opts.isSet("impl-tie"); + depend = opts.isSet("depend"); + debug = opts.isSet("d") || opts.isSet("debug"); + ice = opts.isSet("ice"); + if(opts.isSet("checksum")) + { + checksumClass = opts.optArg("checksum"); + } + stream = opts.isSet("stream"); + caseSensitive = opts.isSet("case-sensitive"); + + if(args.empty()) + { + cerr << argv[0] << ": no input file" << endl; + usage(argv[0]); + return EXIT_FAILURE; + } + + if(impl && implTie) + { + cerr << argv[0] << ": cannot specify both --impl and --impl-tie" << endl; + usage(argv[0]); + return EXIT_FAILURE; + } + + int status = EXIT_SUCCESS; + + ChecksumMap checksums; + + for(vector<string>::const_iterator i = args.begin(); i != args.end(); ++i) + { + if(depend) + { + Preprocessor icecpp(argv[0], *i, cppArgs); + icecpp.printMakefileDependencies(Preprocessor::Java); + } + else + { + Preprocessor icecpp(argv[0], *i, cppArgs); + FILE* cppHandle = icecpp.preprocess(false); + + if(cppHandle == 0) + { + return EXIT_FAILURE; + } + + UnitPtr p = Unit::createUnit(false, false, ice, caseSensitive); + int parseStatus = p->parse(cppHandle, debug, false); + + if(!icecpp.close()) + { + return EXIT_FAILURE; + } + + if(parseStatus == EXIT_FAILURE) + { + status = EXIT_FAILURE; + } + else + { + Gen gen(argv[0], icecpp.getBaseName(), includePaths, output); + if(!gen) + { + p->destroy(); + return EXIT_FAILURE; + } + gen.generate(p, stream); + if(tie) + { + gen.generateTie(p); + } + if(impl) + { + gen.generateImpl(p); + } + if(implTie) + { + gen.generateImplTie(p); + } + if(!checksumClass.empty()) + { + // + // Calculate checksums for the Slice definitions in the unit. + // + ChecksumMap m = createChecksums(p); + copy(m.begin(), m.end(), inserter(checksums, checksums.begin())); + } + } + + p->destroy(); + } + } + + if(!checksumClass.empty()) + { + Gen::writeChecksumClass(checksumClass, output, checksums); + } + + return status; +} diff --git a/cpp/src/slice2javae/Makefile b/cpp/src/slice2javae/Makefile new file mode 100644 index 00000000000..502d0a214a9 --- /dev/null +++ b/cpp/src/slice2javae/Makefile @@ -0,0 +1,32 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2005 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/slice2javae + +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) + +install:: all + $(INSTALL_PROGRAM) $(NAME) $(install_bindir) + +include .depend diff --git a/cpp/src/slice2javae/slice2javae.dsp b/cpp/src/slice2javae/slice2javae.dsp new file mode 100644 index 00000000000..2b64ade479a --- /dev/null +++ b/cpp/src/slice2javae/slice2javae.dsp @@ -0,0 +1,126 @@ +# Microsoft Developer Studio Project File - Name="slice2javae" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=slice2javae - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "slice2javae.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "slice2javae.mak" CFG="slice2javae - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "slice2javae - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "slice2javae - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "slice2javae - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /WX /GR /GX /O2 /I "." /I "../../include" /D "NDEBUG" /D "_CONSOLE" /FD /c
+# SUBTRACT CPP /Fr /YX
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 setargv.obj /nologo /subsystem:console /incremental:yes /machine:I386
+# SUBTRACT LINK32 /nodefaultlib
+# Begin Special Build Tool
+OutDir=.\Release
+TargetName=slice2javae
+SOURCE="$(InputPath)"
+PostBuild_Cmds=copy $(OutDir)\$(TargetName).exe ..\..\bin
+# End Special Build Tool
+
+!ELSEIF "$(CFG)" == "slice2javae - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /WX /Gm /GR /GX /Zi /Od /I "." /I "../../include" /D "_DEBUG" /D "_CONSOLE" /FD /GZ /c
+# SUBTRACT CPP /Fr /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 setargv.obj /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# SUBTRACT LINK32 /incremental:no /nodefaultlib
+# Begin Special Build Tool
+OutDir=.\Debug
+TargetName=slice2javae
+SOURCE="$(InputPath)"
+PostBuild_Cmds=copy $(OutDir)\$(TargetName).exe ..\..\bin
+# End Special Build Tool
+
+!ENDIF
+
+# Begin Target
+
+# Name "slice2javae - Win32 Release"
+# Name "slice2javae - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\Gen.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\Main.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\Gen.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
|