summaryrefslogtreecommitdiff
path: root/cpp/src
diff options
context:
space:
mode:
Diffstat (limited to 'cpp/src')
-rw-r--r--cpp/src/Makefile1
-rw-r--r--cpp/src/Slice/.depend1
-rw-r--r--cpp/src/Slice/Makefile3
-rw-r--r--cpp/src/Slice/PythonUtil.cpp1219
-rw-r--r--cpp/src/slice2py/.depend1
-rw-r--r--cpp/src/slice2py/Main.cpp479
-rw-r--r--cpp/src/slice2py/Makefile31
7 files changed, 1734 insertions, 1 deletions
diff --git a/cpp/src/Makefile b/cpp/src/Makefile
index 10faab8f212..e2000fecf7f 100644
--- a/cpp/src/Makefile
+++ b/cpp/src/Makefile
@@ -20,6 +20,7 @@ SUBDIRS = IceUtil \
slice2freezej \
slice2docbook \
slice2java \
+ slice2py \
Ice \
IceXML \
IceSSL \
diff --git a/cpp/src/Slice/.depend b/cpp/src/Slice/.depend
index 74c75cda5e4..b363db342c2 100644
--- a/cpp/src/Slice/.depend
+++ b/cpp/src/Slice/.depend
@@ -6,3 +6,4 @@ CsUtil.o: CsUtil.cpp ../../include/Slice/CsUtil.h ../../include/Slice/Parser.h .
JavaUtil.o: JavaUtil.cpp ../../include/Slice/JavaUtil.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/IceUtil/Functional.h
Preprocessor.o: Preprocessor.cpp ../../include/Slice/Preprocessor.h ../../include/IceUtil/Config.h
Checksum.o: Checksum.cpp ../../include/Slice/Checksum.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/MD5.h
+PythonUtil.o: PythonUtil.cpp ../../include/Slice/PythonUtil.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/IceUtil/Functional.h
diff --git a/cpp/src/Slice/Makefile b/cpp/src/Slice/Makefile
index 68b24389851..aa5fabce299 100644
--- a/cpp/src/Slice/Makefile
+++ b/cpp/src/Slice/Makefile
@@ -22,7 +22,8 @@ OBJS = Scanner.o \
CsUtil.o \
JavaUtil.o \
Preprocessor.o \
- Checksum.o
+ Checksum.o \
+ PythonUtil.o
SRCS = $(OBJS:.o=.cpp)
diff --git a/cpp/src/Slice/PythonUtil.cpp b/cpp/src/Slice/PythonUtil.cpp
new file mode 100644
index 00000000000..b121cd6d928
--- /dev/null
+++ b/cpp/src/Slice/PythonUtil.cpp
@@ -0,0 +1,1219 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2004 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 <Slice/PythonUtil.h>
+#include <IceUtil/Functional.h>
+
+using namespace std;
+using namespace Slice;
+using namespace IceUtil;
+
+namespace Slice
+{
+namespace Python
+{
+
+//
+// ModuleVisitor finds all of the Slice modules whose include level is greater
+// than 0 and emits a statement of the following form:
+//
+// _M_Foo = Ice.openModule('Foo')
+//
+// This statement allows the code generated for this translation unit to refer
+// to types residing in those included modules.
+//
+class ModuleVisitor : public ParserVisitor
+{
+public:
+
+ ModuleVisitor(Output&);
+
+ virtual bool visitModuleStart(const ModulePtr&);
+
+private:
+
+ Output& _out;
+};
+
+//
+// CodeVisitor generates the Python mapping for a translation unit.
+//
+class CodeVisitor : public ParserVisitor
+{
+public:
+
+ CodeVisitor(IceUtil::Output&);
+
+ virtual bool visitModuleStart(const ModulePtr&);
+ virtual void visitModuleEnd(const ModulePtr&);
+ virtual void visitClassDecl(const ClassDeclPtr&);
+ virtual bool visitClassDefStart(const ClassDefPtr&);
+ virtual bool visitExceptionStart(const ExceptionPtr&);
+ virtual bool visitStructStart(const StructPtr&);
+ virtual void visitSequence(const SequencePtr&);
+ virtual void visitDictionary(const DictionaryPtr&);
+ virtual void visitEnum(const EnumPtr&);
+ virtual void visitConst(const ConstPtr&);
+
+protected:
+
+ //
+ // Return a Python symbol for the given parser element.
+ //
+ string getSymbol(const ContainedPtr&);
+
+ //
+ // Emit Python code to assign the given symbol in the current module.
+ //
+ void registerName(const string&);
+
+ //
+ // Emit the tuple for a Slice type.
+ //
+ void writeType(const TypePtr&);
+
+ Output& _out;
+ list<string> _moduleStack;
+};
+
+}
+}
+
+static string
+lookupKwd(const string& name)
+{
+ //
+ // Keyword list. *Must* be kept in alphabetical order.
+ //
+ static const string keywordList[] =
+ {
+ "and", "assert", "break", "class", "continue", "def", "del", "elif", "else", "except", "exec",
+ "finally", "for", "from", "global", "if", "import", "in", "is", "lambda", "not", "or", "pass",
+ "print", "raise", "return", "try", "while", "yield"
+ };
+ bool found = binary_search(&keywordList[0],
+ &keywordList[sizeof(keywordList) / sizeof(*keywordList)],
+ name);
+ return found ? "_" + name : name;
+}
+
+//
+// Split a scoped name into its components and return the components as a list of (unscoped) identifiers.
+//
+static vector<string>
+splitScopedName(const string& scoped)
+{
+ assert(scoped[0] == ':');
+ vector<string> ids;
+ string::size_type next = 0;
+ string::size_type pos;
+ while((pos = scoped.find("::", next)) != string::npos)
+ {
+ pos += 2;
+ if(pos != scoped.size())
+ {
+ string::size_type endpos = scoped.find("::", pos);
+ if(endpos != string::npos)
+ {
+ ids.push_back(scoped.substr(pos, endpos - pos));
+ }
+ }
+ next = pos;
+ }
+ if(next != scoped.size())
+ {
+ ids.push_back(scoped.substr(next));
+ }
+ else
+ {
+ ids.push_back("");
+ }
+
+ return ids;
+}
+
+//
+// ModuleVisitor implementation.
+//
+Slice::Python::ModuleVisitor::ModuleVisitor(Output& out) :
+ _out(out)
+{
+}
+
+bool
+Slice::Python::ModuleVisitor::visitModuleStart(const ModulePtr& p)
+{
+ if(p->includeLevel() > 0)
+ {
+ string name = scopedToName(p->scoped());
+ _out << sp << nl << "# Included module " << name;
+ _out << nl << "_M_" << name << " = Ice.openModule('" << name << "')";
+ }
+
+ return true;
+}
+
+//
+// CodeVisitor implementation.
+//
+Slice::Python::CodeVisitor::CodeVisitor(Output& out) :
+ _out(out)
+{
+}
+
+bool
+Slice::Python::CodeVisitor::visitModuleStart(const ModulePtr& p)
+{
+ //
+ // As each module is opened, we emit the statement
+ //
+ // __name__ = 'Foo'
+ //
+ // This renames the current module to 'Foo' so that subsequent
+ // type definitions have the proper fully-qualified name.
+ //
+ // We also emit the statement
+ //
+ // _M_Foo = Ice.openModule('Foo')
+ //
+ // This allows us to create types in the module Foo.
+ //
+ string name = scopedToName(p->scoped());
+ _out << sp << nl << "# Start of module " << name;
+ _out << nl << "__name__ = '" << name << "'";
+ _out << nl << "_M_" << name << " = Ice.openModule('" << name << "')";
+ _moduleStack.push_front(name);
+ return true;
+}
+
+void
+Slice::Python::CodeVisitor::visitModuleEnd(const ModulePtr& p)
+{
+ assert(!_moduleStack.empty());
+ _out << sp << nl << "# End of module " << _moduleStack.front();
+ _moduleStack.pop_front();
+
+ if(!_moduleStack.empty())
+ {
+ _out << sp << nl << "__name__ = '" << _moduleStack.front() << "'";
+ }
+}
+
+void
+Slice::Python::CodeVisitor::visitClassDecl(const ClassDeclPtr& p)
+{
+ if(!p->isLocal())
+ {
+ //
+ // Emit forward declarations.
+ //
+ string scoped = p->scoped();
+ _out << sp << nl << "IceImpl.addClass('" << scoped << "')";
+ _out << nl << "IceImpl.addProxy('" << scoped << "')";
+ }
+}
+
+bool
+Slice::Python::CodeVisitor::visitClassDefStart(const ClassDefPtr& p)
+{
+ string scoped = p->scoped();
+ string fixedScoped = scopedToName(scoped);
+ string fixedName = fixIdent(p->name());
+ ClassList bases = p->bases();
+ OperationList ops = p->operations();
+ OperationList::iterator oli;
+
+ if(!p->isLocal())
+ {
+ //
+ // Define the proxy class.
+ //
+ _out << sp << nl << "_M_" << fixedScoped << "Prx = Ice.createTempClass()";
+ _out << nl << "class " << fixedName << "Prx(";
+ if(bases.empty())
+ {
+ _out << "IceImpl.ObjectPrx";
+ }
+ else
+ {
+ ClassList::const_iterator q = bases.begin();
+ while(q != bases.end())
+ {
+ _out << getSymbol(*q) << "Prx";
+ if(++q != bases.end())
+ {
+ _out << ", ";
+ }
+ }
+ }
+ _out << "):";
+ _out.inc();
+
+ for(oli = ops.begin(); oli != ops.end(); ++oli)
+ {
+ string fixedOpName = fixIdent((*oli)->name());
+ TypePtr ret = (*oli)->returnType();
+ ParamDeclList paramList = (*oli)->parameters();
+ string inParams;
+
+ for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q)
+ {
+ if(!(*q)->isOutParam())
+ {
+ if(!inParams.empty())
+ {
+ inParams.append(", ");
+ }
+ inParams.append(fixIdent((*q)->name()));
+ }
+ }
+
+ _out << sp << nl << "def " << fixedOpName << "(self";
+ if(!inParams.empty())
+ {
+ _out << ", " << inParams;
+ }
+ _out << ", ctx=None):";
+ _out.inc();
+ _out << nl << "return self.ice_operation('" << (*oli)->name() << "', '" << scoped << "', (" << inParams;
+ if(!inParams.empty())
+ {
+ _out << ", ";
+ }
+ _out << "ctx";
+ if(inParams.empty())
+ {
+ _out << ',';
+ }
+ _out << "))";
+ _out.dec();
+ }
+
+ _out << sp << nl << "def checkedCast(proxy, facet=''):";
+ _out.inc();
+ _out << nl << "return _M_" << fixedScoped << "Prx.ice_checkedCast(proxy, '" << scoped << "', facet)";
+ _out.dec();
+ _out << nl << "checkedCast = staticmethod(checkedCast)";
+
+ _out << sp << nl << "def uncheckedCast(proxy, facet=''):";
+ _out.inc();
+ _out << nl << "return _M_" << fixedScoped << "Prx.ice_uncheckedCast(proxy, facet)";
+ _out.dec();
+ _out << nl << "uncheckedCast = staticmethod(uncheckedCast)";
+
+ _out.dec();
+
+ _out << sp << nl << "IceImpl.defineProxy('" << scoped << "', " << fixedName << "Prx)";
+
+ registerName(fixedName + "Prx");
+ }
+
+ //
+ // Define the class.
+ //
+ _out << sp << nl << "_M_" << fixedScoped << " = Ice.createTempClass()";
+ _out << nl << "class " << fixedName << '(';
+ string baseScoped;
+ if(bases.empty())
+ {
+ if(p->isLocal())
+ {
+ _out << "Ice.LocalObject";
+ }
+ else
+ {
+ _out << "Ice.Object";
+ }
+ }
+ else
+ {
+ for(ClassList::const_iterator q = bases.begin(); q != bases.end(); ++q)
+ {
+ if(q != bases.begin())
+ {
+ _out << ", ";
+ }
+ _out << getSymbol(*q);
+ }
+ if(!bases.front()->isInterface())
+ {
+ baseScoped = bases.front()->scoped();
+ }
+ }
+ _out << "):";
+
+ _out.inc();
+ if(!p->isLocal())
+ {
+ //
+ // ice_ids
+ //
+ 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(scoped);
+ other.push_back("::Ice::Object");
+ other.sort();
+ ids.merge(other);
+ ids.unique();
+ _out << sp << nl << "def ice_ids(self, current=None):";
+ _out.inc();
+ _out << nl << "return (";
+ for(StringList::iterator q = ids.begin(); q != ids.end(); ++q)
+ {
+ if(q != ids.begin())
+ {
+ _out << ", ";
+ }
+ _out << "'" << *q << "'";
+ }
+ _out << ')';
+ _out.dec();
+
+ //
+ // ice_id
+ //
+ _out << sp << nl << "def ice_id(self, current=None):";
+ _out.inc();
+ _out << nl << "return '" << scoped << "'";
+ _out.dec();
+ }
+
+ if(p->isLocal() && ops.empty())
+ {
+ _out << nl << "pass";
+ }
+ else
+ {
+ //
+ // Emit a placeholder for each operation.
+ //
+ for(oli = ops.begin(); oli != ops.end(); ++oli)
+ {
+ string fixedOpName = fixIdent((*oli)->name());
+ _out << sp << nl << "def " << fixedOpName << "(self";
+
+ ParamDeclList params = (*oli)->parameters();
+
+ for(ParamDeclList::iterator pli = params.begin(); pli != params.end(); ++pli)
+ {
+ if(!(*pli)->isOutParam())
+ {
+ _out << ", " << fixIdent((*pli)->name());
+ }
+ }
+ if(!p->isLocal())
+ {
+ _out << ", current=None";
+ }
+ _out << "):";
+ _out.inc();
+ _out << nl << "raise RuntimeError(\"operation `" << fixedOpName << "' not implemented\")";
+ _out.dec();
+ }
+ }
+ _out.dec();
+
+ //
+ // Emit the type information for a non-local class.
+ //
+ if(!p->isLocal())
+ {
+ DataMemberList members = p->dataMembers();
+ _out << sp << nl << "IceImpl.defineClass('" << scoped << "', " << fixedName << ", ";
+ _out << (p->isInterface() ? "True" : "False") << ", '" << baseScoped << "', (";
+ //
+ // InterfaceIds
+ //
+ int interfaceCount = 0;
+ for(ClassList::const_iterator q = bases.begin(); q != bases.end(); ++q)
+ {
+ if((*q)->isInterface())
+ {
+ if(interfaceCount > 0)
+ {
+ _out << ", ";
+ }
+ _out << "'" << (*q)->scoped() << "'";
+ ++interfaceCount;
+ }
+ }
+ if(interfaceCount == 1)
+ {
+ _out << ',';
+ }
+ //
+ // Members
+ //
+ // Data members are represented as a tuple:
+ //
+ // ('MemberName', MemberType)
+ //
+ // where MemberType is either a primitive type constant (T_INT, etc.) or the id of a constructed type.
+ //
+ _out << "), (";
+ if(members.size() > 1)
+ {
+ _out.inc();
+ _out << nl;
+ }
+ for(DataMemberList::iterator r = members.begin(); r != members.end(); ++r)
+ {
+ if(r != members.begin())
+ {
+ _out << ',' << nl;
+ }
+ _out << "('" << fixIdent((*r)->name()) << "', ";
+ writeType((*r)->type());
+ _out << ')';
+ }
+ if(members.size() == 1)
+ {
+ _out << ',';
+ }
+ else if(members.size() > 1)
+ {
+ _out.dec();
+ _out << nl;
+ }
+ _out << "), {";
+ //
+ // OperationDict
+ //
+ // Each operation in OperationDict is described as follows:
+ //
+ // 'opName': (Mode, (InParams), (OutParams), ReturnType, (Exceptions))
+ //
+ // where InParams and OutParams are tuples of type descriptions, and Exceptions
+ // is a tuple of Python exception types.
+ //
+ _out.inc();
+ for(OperationList::iterator s = ops.begin(); s != ops.end(); ++s)
+ {
+ ParamDeclList params = (*s)->parameters();
+ ParamDeclList::iterator t;
+ int count;
+
+ if(s != ops.begin())
+ {
+ _out << ',';
+ }
+
+ _out << nl << "'" << (*s)->name() << "': (";
+ switch((*s)->mode())
+ {
+ case Operation::Normal:
+ _out << "IceImpl.OP_NORMAL";
+ break;
+ case Operation::Nonmutating:
+ _out << "IceImpl.OP_NONMUTATING";
+ break;
+ case Operation::Idempotent:
+ _out << "IceImpl.OP_IDEMPOTENT";
+ break;
+ }
+ _out << ", (";
+ for(t = params.begin(), count = 0; t != params.end(); ++t)
+ {
+ if(!(*t)->isOutParam())
+ {
+ if(count > 0)
+ {
+ _out << ", ";
+ }
+ writeType((*t)->type());
+ ++count;
+ }
+ }
+ if(count == 1)
+ {
+ _out << ',';
+ }
+ _out << "), (";
+ for(t = params.begin(), count = 0; t != params.end(); ++t)
+ {
+ if((*t)->isOutParam())
+ {
+ if(count > 0)
+ {
+ _out << ", ";
+ }
+ writeType((*t)->type());
+ ++count;
+ }
+ }
+ if(count == 1)
+ {
+ _out << ',';
+ }
+ _out << "), ";
+ TypePtr returnType = (*s)->returnType();
+ if(returnType)
+ {
+ writeType(returnType);
+ }
+ else
+ {
+ _out << "None";
+ }
+ _out << ", (";
+ ExceptionList exceptions = (*s)->throws();
+ for(ExceptionList::iterator u = exceptions.begin(); u != exceptions.end(); ++u)
+ {
+ if(u != exceptions.begin())
+ {
+ _out << ", ";
+ }
+ _out << "'" << (*u)->scoped() << "'";
+ }
+ if(exceptions.size() == 1)
+ {
+ _out << ',';
+ }
+ _out << "))";
+ }
+ _out.dec();
+ if(!ops.empty())
+ {
+ _out << nl;
+ }
+ _out << "})";
+ }
+
+ registerName(fixedName);
+
+ return false;
+}
+
+bool
+Slice::Python::CodeVisitor::visitExceptionStart(const ExceptionPtr& p)
+{
+ string scoped = p->scoped();
+ string fixedScoped = scopedToName(scoped);
+ string fixedName = fixIdent(p->name());
+ _out << sp << nl << "_M_" << fixedScoped << " = Ice.createTempClass()";
+ _out << nl << "class " << fixedName << '(';
+ ExceptionPtr base = p->base();
+ string baseScoped;
+ if(base)
+ {
+ baseScoped = base->scoped();
+ _out << getSymbol(base);
+ }
+ else if(p->isLocal())
+ {
+ _out << "Ice.LocalException";
+ }
+ else
+ {
+ _out << "Ice.UserException";
+ }
+ _out << "):";
+ _out.inc();
+ _out << nl << "def ice_id(self):";
+ _out.inc();
+ _out << nl << "return '" << scoped << "'";
+ _out.dec();
+ _out.dec();
+
+ //
+ // Emit the type information for a non-local exception.
+ //
+ if(!p->isLocal())
+ {
+ _out << sp << nl << "IceImpl.addException('" << scoped << "', " << fixedName << ", '" << baseScoped << "', (";
+ DataMemberList members = p->dataMembers();
+ if(members.size() > 1)
+ {
+ _out.inc();
+ _out << nl;
+ }
+ //
+ // Data members are represented as a tuple:
+ //
+ // ('MemberName', MemberType)
+ //
+ // where MemberType is either a primitive type constant (T_INT, etc.) or the id of a constructed type.
+ //
+ for(DataMemberList::iterator q = members.begin(); q != members.end(); ++q)
+ {
+ if(q != members.begin())
+ {
+ _out << ',' << nl;
+ }
+ _out << "(\"" << fixIdent((*q)->name()) << "\", ";
+ writeType((*q)->type());
+ _out << ')';
+ }
+ if(members.size() == 1)
+ {
+ _out << ',';
+ }
+ else if(members.size() > 1)
+ {
+ _out.dec();
+ _out << nl;
+ }
+ _out << "), " << (p->usesClasses() ? "True" : "False") << ")";
+ }
+
+ registerName(fixedName);
+
+ return false;
+}
+
+bool
+Slice::Python::CodeVisitor::visitStructStart(const StructPtr& p)
+{
+ string scoped = p->scoped();
+ string fixedScoped = scopedToName(scoped);
+ string fixedName = fixIdent(p->name());
+ _out << sp << nl << "_M_" << fixedScoped << " = Ice.createTempClass()";
+ _out << nl << "class " << fixedName << "(object):";
+ _out.inc();
+ _out << nl << "pass";
+ _out.dec();
+
+ //
+ // Emit the type information for a non-local struct.
+ //
+ if(!p->isLocal())
+ {
+ _out << sp << nl << "IceImpl.addStruct('" << scoped << "', " << fixedName << ", (";
+ //
+ // Data members are represented as a tuple:
+ //
+ // ('MemberName', MemberType)
+ //
+ // where MemberType is either a primitive type constant (T_INT, etc.) or the id of a constructed type.
+ //
+ DataMemberList members = p->dataMembers();
+ if(members.size() > 1)
+ {
+ _out.inc();
+ _out << nl;
+ }
+ for(DataMemberList::iterator q = members.begin(); q != members.end(); ++q)
+ {
+ if(q != members.begin())
+ {
+ _out << ',' << nl;
+ }
+ _out << "(\"" << fixIdent((*q)->name()) << "\", ";
+ writeType((*q)->type());
+ _out << ')';
+ }
+ if(members.size() == 1)
+ {
+ _out << ',';
+ }
+ else if(members.size() > 1)
+ {
+ _out.dec();
+ _out << nl;
+ }
+ _out << "))";
+ }
+
+ registerName(fixedName);
+
+ return false;
+}
+
+void
+Slice::Python::CodeVisitor::visitSequence(const SequencePtr& p)
+{
+ //
+ // Emit the type information for a non-local sequence.
+ //
+ if(!p->isLocal())
+ {
+ _out << sp << nl << "IceImpl.addSequence('" << p->scoped() << "', ";
+ writeType(p->type());
+ _out << ")";
+ }
+}
+
+void
+Slice::Python::CodeVisitor::visitDictionary(const DictionaryPtr& p)
+{
+ //
+ // Emit the type information for a non-local dictionary.
+ //
+ if(!p->isLocal())
+ {
+ _out << sp << nl << "IceImpl.addDictionary('" << p->scoped() << "', ";
+ writeType(p->keyType());
+ _out << ", ";
+ writeType(p->valueType());
+ _out << ")";
+ }
+}
+
+void
+Slice::Python::CodeVisitor::visitEnum(const EnumPtr& p)
+{
+ string scoped = p->scoped();
+ string fixedScoped = scopedToName(scoped);
+ string fixedName = fixIdent(p->name());
+ EnumeratorList enums = p->getEnumerators();
+ EnumeratorList::iterator q;
+ int i;
+
+ _out << sp << nl << "_M_" << fixedScoped << " = Ice.createTempClass()";
+ _out << nl << "class " << fixedName << "(object):";
+ _out.inc();
+ _out << sp << nl << "def __init__(self, val):";
+ _out.inc();
+ _out << nl << "self.value = val";
+ _out.dec();
+ _out << sp << nl << "def __str__(self):";
+ _out.inc();
+ for(q = enums.begin(), i = 0; q != enums.end(); ++q, ++i)
+ {
+ _out << nl;
+ if(q == enums.begin())
+ {
+ _out << "if";
+ }
+ else
+ {
+ _out << "elif";
+ }
+ ostringstream idx;
+ idx << i;
+ _out << " self.value == " << idx.str() << ':';
+ _out.inc();
+ _out << nl << "return '" << (*q)->name() << "'";
+ _out.dec();
+ }
+ _out << nl << "return None";
+ _out.dec();
+ _out << sp << nl << "__repr__ = __str__";
+ _out << sp << nl << "def __hash__(self):";
+ _out.inc();
+ _out << nl << "return self.value";
+ _out.dec();
+ _out << sp << nl << "def __cmp__(self, other):";
+ _out.inc();
+ _out << nl << "return cmp(self.value, other.value)";
+ _out.dec();
+ _out.dec();
+
+ _out << sp;
+ for(q = enums.begin(), i = 0; q != enums.end(); ++q, ++i)
+ {
+ string fixedEnum = fixIdent((*q)->name());
+ ostringstream idx;
+ idx << i;
+ _out << nl << fixedName << '.' << fixedEnum << " = " << fixedName << '(' << idx.str() << ')';
+ }
+
+ //
+ // Emit the type information for a non-local enum.
+ //
+ if(!p->isLocal())
+ {
+ _out << sp << nl << "IceImpl.addEnum('" << scoped << "', " << fixedName << ", (";
+ for(EnumeratorList::iterator q = enums.begin(); q != enums.end(); ++q)
+ {
+ if(q != enums.begin())
+ {
+ _out << ", ";
+ }
+ string fixedEnum = fixIdent((*q)->name());
+ _out << fixedName << '.' << fixedEnum;
+ }
+ if(enums.size() == 1)
+ {
+ _out << ',';
+ }
+ _out << "))";
+ }
+
+ registerName(fixedName);
+}
+
+void
+Slice::Python::CodeVisitor::visitConst(const ConstPtr& p)
+{
+ Slice::TypePtr type = p->type();
+ string value = p->value();
+ string name = fixIdent(p->name());
+
+ _out << sp << nl << "_M_" << scopedToName(p->scoped()) << " = ";
+
+ Slice::BuiltinPtr b = Slice::BuiltinPtr::dynamicCast(type);
+ Slice::EnumPtr en = Slice::EnumPtr::dynamicCast(type);
+ if(b)
+ {
+ switch(b->kind())
+ {
+ case Slice::Builtin::KindBool:
+ {
+ _out << (value == "true" ? "True" : "False");
+ break;
+ }
+ case Slice::Builtin::KindByte:
+ case Slice::Builtin::KindShort:
+ case Slice::Builtin::KindInt:
+ case Slice::Builtin::KindFloat:
+ case Slice::Builtin::KindDouble:
+ {
+ _out << value;
+ break;
+ }
+ case Slice::Builtin::KindLong:
+ {
+ IceUtil::Int64 l;
+ string::size_type pos;
+ IceUtil::stringToInt64(value, l, pos);
+ //
+ // The platform's 'long' type may not be 64 bits, so we store 64-bit
+ // values as a string.
+ //
+ if(sizeof(IceUtil::Int64) > sizeof(long) && (l < LONG_MIN || l > LONG_MAX))
+ {
+ _out << "'" << value << "'";
+ }
+ else
+ {
+ _out << value;
+ }
+ break;
+ }
+
+ case Slice::Builtin::KindString:
+ {
+ //
+ // Expand strings into the basic source character set. We can't use isalpha() and the like
+ // here because they are sensitive to the current locale.
+ //
+ static const string basicSourceChars = "abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789"
+ "_{}[]#()<>%:;,?*+=/^&|~!=, '";
+ static const set<char> charSet(basicSourceChars.begin(), basicSourceChars.end());
+
+ _out << "\""; // Opening "
+
+ ios_base::fmtflags originalFlags = _out.flags(); // Save stream state
+ streamsize originalWidth = _out.width();
+ ostream::char_type originalFill = _out.fill();
+
+ for(string::const_iterator c = value.begin(); c != value.end(); ++c)
+ {
+ switch(*c)
+ {
+ case '"':
+ {
+ _out << "\\\"";
+ break;
+ }
+ case '\\':
+ {
+ _out << "\\\\";
+ break;
+ }
+ case '\r':
+ {
+ _out << "\\r";
+ break;
+ }
+ case '\n':
+ {
+ _out << "\\n";
+ break;
+ }
+ case '\t':
+ {
+ _out << "\\t";
+ break;
+ }
+ case '\b':
+ {
+ _out << "\\b";
+ break;
+ }
+ case '\f':
+ {
+ _out << "\\f";
+ break;
+ }
+ default:
+ {
+ if(charSet.find(*c) == charSet.end())
+ {
+ unsigned char uc = *c; // Char may be signed, so make it positive.
+ _out << "\\"; // Print as octal if not in basic source character set.
+ _out.flags(ios_base::oct);
+ _out.width(3);
+ _out.fill('0');
+ _out << static_cast<unsigned>(uc);
+ }
+ else
+ {
+ _out << *c; // Print normally if in basic source character set.
+ }
+ break;
+ }
+ }
+ }
+
+ _out.fill(originalFill); // Restore stream state
+ _out.width(originalWidth);
+ _out.flags(originalFlags);
+
+ _out << "\""; // Closing "
+ break;
+ }
+
+ case Slice::Builtin::KindObject:
+ case Slice::Builtin::KindObjectProxy:
+ case Slice::Builtin::KindLocalObject:
+ assert(false);
+ }
+ }
+ else if(en)
+ {
+ string enumName = getSymbol(en);
+ string::size_type colon = value.rfind(':');
+ string enumerator;
+ if(colon != string::npos)
+ {
+ enumerator = fixIdent(value.substr(colon + 1));
+ }
+ else
+ {
+ enumerator = fixIdent(value);
+ }
+ _out << enumName << '.' << enumerator;
+ }
+ else
+ {
+ assert(false); // Unknown const type.
+ }
+}
+
+string
+Slice::Python::CodeVisitor::getSymbol(const ContainedPtr& p)
+{
+ //
+ // An explicit reference to another type must always be prefixed with "_M_".
+ //
+ return "_M_" + scopedToName(p->scoped());
+}
+
+void
+Slice::Python::CodeVisitor::registerName(const string& name)
+{
+ assert(!_moduleStack.empty());
+ _out << sp << nl << "_M_" << _moduleStack.front() << '.' << name << " = " << name;
+ _out << nl << "del " << name;
+}
+
+void
+Slice::Python::CodeVisitor::writeType(const TypePtr& p)
+{
+ BuiltinPtr builtin = BuiltinPtr::dynamicCast(p);
+ if(builtin)
+ {
+ switch(builtin->kind())
+ {
+ case Builtin::KindBool:
+ {
+ _out << "IceImpl.T_BOOL";
+ break;
+ }
+ case Builtin::KindByte:
+ {
+ _out << "IceImpl.T_BYTE";
+ break;
+ }
+ case Builtin::KindShort:
+ {
+ _out << "IceImpl.T_SHORT";
+ break;
+ }
+ case Builtin::KindInt:
+ {
+ _out << "IceImpl.T_INT";
+ break;
+ }
+ case Builtin::KindLong:
+ {
+ _out << "IceImpl.T_LONG";
+ break;
+ }
+ case Builtin::KindFloat:
+ {
+ _out << "IceImpl.T_FLOAT";
+ break;
+ }
+ case Builtin::KindDouble:
+ {
+ _out << "IceImpl.T_DOUBLE";
+ break;
+ }
+ case Builtin::KindString:
+ {
+ _out << "IceImpl.T_STRING";
+ break;
+ }
+ case Builtin::KindObject:
+ {
+ _out << "IceImpl.T_OBJECT";
+ break;
+ }
+ case Builtin::KindObjectProxy:
+ {
+ _out << "IceImpl.T_OBJECT_PROXY";
+ break;
+ }
+ case Builtin::KindLocalObject:
+ {
+ assert(false);
+ break;
+ }
+ }
+ return;
+ }
+
+ ProxyPtr prx = ProxyPtr::dynamicCast(p);
+ if(prx)
+ {
+ _out << "'" << prx->_class()->scoped() << "Prx'";
+ return;
+ }
+
+ ContainedPtr cont = ContainedPtr::dynamicCast(p);
+ assert(cont);
+ _out << "'" << cont->scoped() << "'";
+}
+
+void
+Slice::Python::generate(const UnitPtr& unit, Output& out)
+{
+ out << nl << "import Ice, IceImpl";
+
+ ModuleVisitor moduleVisitor(out);
+ unit->visit(&moduleVisitor, true);
+
+ CodeVisitor codeVisitor(out);
+ unit->visit(&codeVisitor, false);
+
+ out << nl; // Trailing newline.
+}
+
+bool
+Slice::Python::splitString(const string& str, vector<string>& args)
+{
+ string delim = " \t\n\r";
+ string::size_type beg;
+ string::size_type end = 0;
+ while(true)
+ {
+ beg = str.find_first_not_of(delim, end);
+ if(beg == string::npos)
+ {
+ break;
+ }
+
+ //
+ // Check for quoted argument.
+ //
+ char ch = str[beg];
+ if(ch == '"' || ch == '\'')
+ {
+ beg++;
+ end = str.find(ch, beg);
+ if(end == string::npos)
+ {
+ return false;
+ }
+ args.push_back(str.substr(beg, end - beg));
+ end++; // Skip end quote.
+ }
+ else
+ {
+ end = str.find_first_of(delim + "'\"", beg);
+ if(end == string::npos)
+ {
+ end = str.length();
+ }
+ args.push_back(str.substr(beg, end - beg));
+ }
+ }
+
+ return true;
+}
+
+string
+Slice::Python::scopedToName(const string& scoped)
+{
+ string result = fixIdent(scoped);
+ if(result.find("::") == 0)
+ {
+ result.erase(0, 2);
+ }
+
+ string::size_type pos;
+ while((pos = result.find("::")) != string::npos)
+ {
+ result.replace(pos, 2, ".");
+ }
+
+ return result;
+}
+
+string
+Slice::Python::fixIdent(const string& ident)
+{
+ if(ident[0] != ':')
+ {
+ return lookupKwd(ident);
+ }
+ vector<string> ids = splitScopedName(ident);
+ transform(ids.begin(), ids.end(), ids.begin(), ptr_fun(lookupKwd));
+ stringstream result;
+ for(vector<string>::const_iterator i = ids.begin(); i != ids.end(); ++i)
+ {
+ result << "::" + *i;
+ }
+ return result.str();
+}
+
+void
+Slice::Python::printHeader(IceUtil::Output& out)
+{
+ static const char* header =
+"# **********************************************************************\n"
+"#\n"
+"# Copyright (c) 2003-2004 ZeroC, Inc. All rights reserved.\n"
+"#\n"
+"# This copy of Ice is licensed to you under the terms described in the\n"
+"# ICE_LICENSE file included in this distribution.\n"
+"#\n"
+"# **********************************************************************\n"
+ ;
+
+ out << header;
+ out << "\n# Ice version " << ICE_STRING_VERSION;
+}
diff --git a/cpp/src/slice2py/.depend b/cpp/src/slice2py/.depend
new file mode 100644
index 00000000000..990139ff904
--- /dev/null
+++ b/cpp/src/slice2py/.depend
@@ -0,0 +1 @@
+Main.o: Main.cpp ../../include/Slice/Preprocessor.h ../../include/IceUtil/Config.h ../../include/Slice/PythonUtil.h ../../include/Slice/Parser.h ../../include/IceUtil/Shared.h ../../include/IceUtil/Handle.h ../../include/IceUtil/Exception.h ../../include/IceUtil/InputUtil.h ../../include/IceUtil/OutputUtil.h
diff --git a/cpp/src/slice2py/Main.cpp b/cpp/src/slice2py/Main.cpp
new file mode 100644
index 00000000000..028f67b5e0f
--- /dev/null
+++ b/cpp/src/slice2py/Main.cpp
@@ -0,0 +1,479 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2004 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 <Slice/Preprocessor.h>
+#include <Slice/PythonUtil.h>
+
+#include <fstream>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifdef _WIN32
+#include <direct.h>
+#endif
+
+#ifndef _WIN32
+#include <unistd.h>
+#endif
+
+using namespace std;
+using namespace Slice;
+using namespace Slice::Python;
+
+//
+// For each Slice file Foo.ice we generate Foo_ice.py containing the Python
+// mappings. Furthermore, for each Slice module M in Foo.ice, we create a
+// Python package of the same name. This package is simply a subdirectory
+// containing the special file "__init__.py" that is executed when a Python
+// script executes the statement "import M".
+//
+// Inside __init__.py we add an import statement for Foo_ice, causing
+// Foo_ice to be imported implicitly when M is imported.
+//
+// Of course, another Slice file Bar.ice may contain definitions for the
+// same Slice module M, in which case the __init__.py file for M is modified
+// to contain an additional import statement for Bar_ice. Therefore a
+// Python script executing "import M" implicitly imports the definitions
+// from both Foo_ice and Bar_ice.
+//
+// The __init__.py file also contains import statements for submodules,
+// so that importing the top-level module automatically imports all of
+// its submodules.
+//
+// The PackageVisitor class creates the directory hierarchy to mirror the
+// Slice module hierarchy, and updates the __init__.py files as necessary.
+//
+class PackageVisitor : public ParserVisitor
+{
+public:
+
+ PackageVisitor(const string&, const string&, const string&);
+
+ virtual bool visitModuleStart(const ModulePtr&);
+ virtual void visitModuleEnd(const ModulePtr&);
+
+private:
+
+ enum ReadState { PreModules, InModules, InSubmodules };
+
+ static const char* _moduleTag;
+ static const char* _submoduleTag;
+
+ bool readInit(const string&, StringList&, StringList&);
+ bool writeInit(const string&, const StringList&, const StringList&);
+
+ string _name;
+ string _module;
+ StringList _pathStack;
+};
+
+const char* PackageVisitor::_moduleTag = "# Modules:";
+const char* PackageVisitor::_submoduleTag = "# Submodules:";
+
+PackageVisitor::PackageVisitor(const string& name, const string& module, const string& dir) :
+ _name(name), _module(module)
+{
+ if(dir.empty())
+ {
+ _pathStack.push_front(".");
+ }
+ else
+ {
+ _pathStack.push_front(dir);
+ }
+}
+
+bool
+PackageVisitor::visitModuleStart(const ModulePtr& p)
+{
+ assert(!_pathStack.empty());
+ string name = fixIdent(p->name());
+ string path = _pathStack.front() + "/" + name;
+ string parentPath = _pathStack.front();
+ _pathStack.push_front(path);
+
+ struct stat st;
+ int result;
+ result = stat(path.c_str(), &st);
+ if(result != 0)
+ {
+#ifdef _WIN32
+ result = _mkdir(path.c_str());
+#else
+ result = mkdir(path.c_str(), S_IRWXU | S_IRWXG | S_IRWXO);
+#endif
+
+ if(result != 0)
+ {
+ cerr << _name << ": unable to create `" << path << "': " << strerror(errno) << endl;
+ return false;
+ }
+ }
+
+ //
+ // If necessary, add this file to the set of imported modules in __init__.py.
+ //
+ StringList modules, submodules;
+ if(readInit(path, modules, submodules))
+ {
+ StringList::iterator p;
+ p = find(modules.begin(), modules.end(), _module);
+ if(p == modules.end())
+ {
+ modules.push_back(_module);
+ writeInit(path, modules, submodules);
+ }
+ }
+
+ //
+ // If this is a submodule, then modify the parent's __init__.py to import us.
+ //
+ ModulePtr mod = ModulePtr::dynamicCast(p->container());
+ if(mod)
+ {
+ modules.clear();
+ submodules.clear();
+ if(readInit(parentPath, modules, submodules))
+ {
+ StringList::iterator p;
+ p = find(submodules.begin(), submodules.end(), name);
+ if(p == submodules.end())
+ {
+ submodules.push_back(name);
+ writeInit(parentPath, modules, submodules);
+ }
+ }
+ }
+
+ return true;
+}
+
+void
+PackageVisitor::visitModuleEnd(const ModulePtr& p)
+{
+ assert(!_pathStack.empty());
+ _pathStack.pop_front();
+}
+
+bool
+PackageVisitor::readInit(const string& dir, StringList& modules, StringList& submodules)
+{
+ string initPath = dir + "/__init__.py";
+
+ struct stat st;
+ if(stat(initPath.c_str(), &st) == 0)
+ {
+ ifstream in(initPath.c_str());
+ if(!in)
+ {
+ cerr << _name << ": unable to open `" << initPath << "': " << strerror(errno) << endl;
+ return false;
+ }
+
+ ReadState state = PreModules;
+ char line[1024];
+ while(in.getline(line, 1024))
+ {
+ string s = line;
+ if(s.find(_moduleTag) == 0)
+ {
+ if(state != PreModules)
+ {
+ break;
+ }
+ state = InModules;
+ }
+ else if(s.find(_submoduleTag) == 0)
+ {
+ if(state != InModules)
+ {
+ break;
+ }
+ state = InSubmodules;
+ }
+ else if(s.find("import") == 0)
+ {
+ if(state == PreModules)
+ {
+ break;
+ }
+
+ if(s.size() < 8)
+ {
+ cerr << _name << ": invalid line `" << s << "' in `" << initPath << "'" << endl;
+ return false;
+ }
+
+ string name = s.substr(7);
+ if(state == InModules)
+ {
+ modules.push_back(name);
+ }
+ else
+ {
+ submodules.push_back(name);
+ }
+ }
+ }
+
+ if(state != InSubmodules)
+ {
+ cerr << _name << ": invalid format in `" << initPath << "'" << endl;
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool
+PackageVisitor::writeInit(const string& dir, const StringList& modules, const StringList& submodules)
+{
+ string initPath = dir + "/__init__.py";
+
+ ofstream os(initPath.c_str());
+ if(!os)
+ {
+ return false;
+ }
+
+ StringList::const_iterator p;
+
+ os << "# Generated by slice2py - DO NOT EDIT!" << endl
+ << "#" << endl
+ << _moduleTag << endl;
+ for(p = modules.begin(); p != modules.end(); ++p)
+ {
+ os << "import " << *p << endl;
+ }
+
+ os << endl;
+ os << _submoduleTag << endl;
+ for(p = submodules.begin(); p != submodules.end(); ++p)
+ {
+ os << "import " << *p << endl;
+ }
+
+ return true;
+}
+
+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"
+ "--output-dir DIR Create files in the directory DIR.\n"
+ "-d, --debug Print debug messages.\n"
+ "--ice Permit `Ice' prefix (for building Ice source code only)\n"
+ "--all Generate code for Slice definitions in included files.\n"
+ ;
+ // Note: --case-sensitive is intentionally not shown here!
+}
+
+int
+main(int argc, char* argv[])
+{
+ string cppArgs;
+ string output;
+ bool debug = false;
+ bool ice = false;
+ bool caseSensitive = false;
+ bool all = false;
+
+ int idx = 1;
+ while(idx < argc)
+ {
+ if(strncmp(argv[idx], "-I", 2) == 0)
+ {
+ cppArgs += ' ';
+ cppArgs += argv[idx];
+
+ for(int i = idx ; i + 1 < argc ; ++i)
+ {
+ argv[i] = argv[i + 1];
+ }
+ --argc;
+ }
+ else if(strncmp(argv[idx], "-D", 2) == 0 || strncmp(argv[idx], "-U", 2) == 0)
+ {
+ cppArgs += ' ';
+ cppArgs += argv[idx];
+
+ for(int i = idx ; i + 1 < argc ; ++i)
+ {
+ argv[i] = argv[i + 1];
+ }
+ --argc;
+ }
+ else if(strcmp(argv[idx], "-h") == 0 || strcmp(argv[idx], "--help") == 0)
+ {
+ usage(argv[0]);
+ return EXIT_SUCCESS;
+ }
+ else if(strcmp(argv[idx], "-v") == 0 || strcmp(argv[idx], "--version") == 0)
+ {
+ cout << ICE_STRING_VERSION << endl;
+ return EXIT_SUCCESS;
+ }
+ else if(strcmp(argv[idx], "-d") == 0 || strcmp(argv[idx], "--debug") == 0)
+ {
+ debug = true;
+ for(int i = idx ; i + 1 < argc ; ++i)
+ {
+ argv[i] = argv[i + 1];
+ }
+ --argc;
+ }
+ else if(strcmp(argv[idx], "--ice") == 0)
+ {
+ ice = true;
+ for(int i = idx ; i + 1 < argc ; ++i)
+ {
+ argv[i] = argv[i + 1];
+ }
+ --argc;
+ }
+ else if(strcmp(argv[idx], "--case-sensitive") == 0)
+ {
+ caseSensitive = true;
+ for(int i = idx ; i + 1 < argc ; ++i)
+ {
+ argv[i] = argv[i + 1];
+ }
+ --argc;
+ }
+ else if(strcmp(argv[idx], "--all") == 0)
+ {
+ all = true;
+ for(int i = idx ; i + 1 < argc ; ++i)
+ {
+ argv[i] = argv[i + 1];
+ }
+ --argc;
+ }
+ else if(strcmp(argv[idx], "--output-dir") == 0)
+ {
+ if(idx + 1 >= argc)
+ {
+ cerr << argv[0] << ": argument expected for`" << argv[idx] << "'" << endl;
+ usage(argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ output = argv[idx + 1];
+ for(int i = idx ; i + 2 < argc ; ++i)
+ {
+ argv[i] = argv[i + 2];
+ }
+ argc -= 2;
+ }
+ else if(argv[idx][0] == '-')
+ {
+ cerr << argv[0] << ": unknown option `" << argv[idx] << "'" << endl;
+ usage(argv[0]);
+ return EXIT_FAILURE;
+ }
+ else
+ {
+ ++idx;
+ }
+ }
+
+ if(argc < 2)
+ {
+ cerr << argv[0] << ": no input file" << endl;
+ usage(argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ int status = EXIT_SUCCESS;
+
+ for(idx = 1 ; idx < argc ; ++idx)
+ {
+ Preprocessor icecpp(argv[0], argv[idx], cppArgs);
+ FILE* cppHandle = icecpp.preprocess(false);
+
+ if(cppHandle == 0)
+ {
+ return EXIT_FAILURE;
+ }
+
+ UnitPtr u = Unit::createUnit(false, all, ice, caseSensitive);
+ int parseStatus = u->parse(cppHandle, debug);
+
+ if(!icecpp.close())
+ {
+ u->destroy();
+ return EXIT_FAILURE;
+ }
+
+ if(parseStatus == EXIT_FAILURE)
+ {
+ status = EXIT_FAILURE;
+ }
+ else
+ {
+ string base = icecpp.getBaseName();
+ string::size_type pos = base.rfind('/');
+ if(pos != string::npos)
+ {
+ base.erase(0, pos + 1);
+ }
+
+ //
+ // Append the suffix "_ice" to the filename in order to avoid any conflicts
+ // with Slice module names. For example, if the file Test.ice defines a
+ // Slice module named "Test", then we couldn't create a Python package named
+ // "Test" and also call the generated file "Test.py".
+ //
+ string file = base + "_ice.py";
+ if(!output.empty())
+ {
+ file = output + '/' + file;
+ }
+
+ IceUtil::Output out;
+ out.open(file.c_str());
+ if(!out)
+ {
+ cerr << argv[0] << ": can't open `" << file << "' for writing" << endl;
+ u->destroy();
+ return EXIT_FAILURE;
+ }
+
+ printHeader(out);
+ out << "\n# Generated from file `" << base << ".ice'\n";
+
+ //
+ // Generate the Python mapping.
+ //
+ generate(u, out);
+
+ //
+ // Create or update the Python package hierarchy.
+ //
+ PackageVisitor visitor(argv[0], base + "_ice", output);
+ u->visit(&visitor, false);
+ }
+
+ u->destroy();
+ }
+
+ return status;
+}
diff --git a/cpp/src/slice2py/Makefile b/cpp/src/slice2py/Makefile
new file mode 100644
index 00000000000..c7a1b0e06a3
--- /dev/null
+++ b/cpp/src/slice2py/Makefile
@@ -0,0 +1,31 @@
+# **********************************************************************
+#
+# Copyright (c) 2003-2004 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/slice2py
+
+TARGETS = $(NAME)
+
+OBJS = 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