diff options
Diffstat (limited to 'cpp/src')
-rw-r--r-- | cpp/src/slice2cpp/Gen.cpp | 399 | ||||
-rw-r--r-- | cpp/src/slice2cpp/Gen.h | 30 | ||||
-rw-r--r-- | cpp/src/slice2cpp/Main.cpp | 14 |
3 files changed, 438 insertions, 5 deletions
diff --git a/cpp/src/slice2cpp/Gen.cpp b/cpp/src/slice2cpp/Gen.cpp index eb8a3c781bb..686c689e5b6 100644 --- a/cpp/src/slice2cpp/Gen.cpp +++ b/cpp/src/slice2cpp/Gen.cpp @@ -13,15 +13,18 @@ #include <Gen.h> #include <limits> +#include <sys/stat.h> + using namespace std; using namespace Slice; Slice::Gen::Gen(const string& name, const string& base, const string& include, const vector<string>& includePaths, - const string& dllExport, const string& dir) : + const string& dllExport, const string& dir, bool imp) : _base(base), _include(include), _includePaths(includePaths), - _dllExport(dllExport) + _dllExport(dllExport), + _impl(imp) { for (vector<string>::iterator p = _includePaths.begin(); p != _includePaths.end(); ++p) { @@ -37,6 +40,57 @@ Slice::Gen::Gen(const string& name, const string& base, const string& include, c _base.erase(0, pos + 1); } + if (_impl) + { + string fileImplH = _base + "I.h"; + string fileImplC = _base + "I.cpp"; + 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: " + << strerror(errno) << endl; + return; + } + + implC.open(fileImplC.c_str()); + if (!implC) + { + cerr << name << ": can't open `" << fileImplC << "' for writing: " + << strerror(errno) << 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 + ".h"; string fileC = _base + ".cpp"; if (!dir.empty()) @@ -79,12 +133,26 @@ Slice::Gen::~Gen() { H << "\n\n#endif\n"; C << '\n'; + + if (_impl) + { + implH << "\n\n#endif\n"; + implC << '\n'; + } } bool Slice::Gen::operator!() const { - return !H || !C; + if (!H || !C) + { + return true; + } + if (_impl && (!implH || !implC)) + { + return true; + } + return false; } void @@ -161,6 +229,26 @@ Slice::Gen::generate(const UnitPtr& unit) ObjectVisitor objectVisitor(H, C, _dllExport); unit->visit(&objectVisitor); + + 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); + unit->visit(&implVisitor); + } } Slice::Gen::TypesVisitor::TypesVisitor(Output& h, Output& c, const string& dllExport) : @@ -2004,6 +2092,311 @@ Slice::Gen::ObjectVisitor::visitDataMember(const DataMemberPtr& p) H << nl << s << ' ' << name << ';'; } +Slice::Gen::ImplVisitor::ImplVisitor(Output& h, Output& c, + const string& dllExport) : + H(h), C(c), _dllExport(dllExport) +{ +} + +void +Slice::Gen::ImplVisitor::writeAssign(Output& out, const TypePtr& type, + const string& name, int& iter) +{ + BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); + if (builtin) + { + switch (builtin->kind()) + { + case Builtin::KindByte: + { + out << nl << name << " = (Ice::Byte)0;"; + break; + } + case Builtin::KindBool: + { + out << nl << name << " = false;"; + break; + } + case Builtin::KindShort: + { + out << nl << name << " = (Ice::Short)0;"; + break; + } + case Builtin::KindInt: + { + out << nl << name << " = (Ice::Int)0;"; + break; + } + case Builtin::KindLong: + { + out << nl << name << " = (Ice::Long)0;"; + break; + } + case Builtin::KindFloat: + { + out << nl << name << " = (Ice::Float)0;"; + break; + } + case Builtin::KindDouble: + { + out << nl << name << " = (Ice::Double)0;"; + break; + } + case Builtin::KindString: + case Builtin::KindObject: + case Builtin::KindObjectProxy: + case Builtin::KindLocalObject: + { + // + // No initialization needed + // + break; + } + } + return; + } + + ProxyPtr prx = ProxyPtr::dynamicCast(type); + if (prx) + { + // + // No initialization needed + // + return; + } + + ClassDeclPtr cl = ClassDeclPtr::dynamicCast(type); + if (cl) + { + // + // No initialization needed + // + return; + } + + StructPtr st = StructPtr::dynamicCast(type); + if (st) + { + DataMemberList members = st->dataMembers(); + DataMemberList::const_iterator d; + for (d = members.begin(); d != members.end(); ++d) + { + string memberName = name + "." + (*d)->name(); + writeAssign(out, (*d)->type(), memberName, iter); + } + return; + } + + EnumPtr en = EnumPtr::dynamicCast(type); + if (en) + { + EnumeratorList enumerators = en->getEnumerators(); + out << nl << name << " = " << en->scope() + << enumerators.front()->name() << ';'; + return; + } + + SequencePtr seq = SequencePtr::dynamicCast(type); + if (seq) + { + out << nl << name << ".resize(5);"; + out << nl << "for (int __i" << iter << " = 0; __i" << iter << " < " + << name << ".size(); __i" << iter << "++)"; + out << sb; + ostringstream elem; + elem << name << "[__i" << iter << ']'; + iter++; + writeAssign(out, seq->type(), elem.str(), iter); + out << eb; + return; + } + + DictionaryPtr dict = DictionaryPtr::dynamicCast(type); + assert(dict); + // + // No initialization needed + // +} + +bool +Slice::Gen::ImplVisitor::visitModuleStart(const ModulePtr& p) +{ + if (!p->hasClassDefs()) + { + return false; + } + + string name = 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 = p->scope(); + string scoped = p->scoped(); + string cls = scope.substr(2) + name + "I"; + + ClassList bases = p->bases(); + ClassDefPtr base; + if (!bases.empty() && !bases.front()->isInterface()) + { + base = bases.front(); + } + + H << sp; + H << nl << "class " << name << "I : public " << name; + H << sb; + H.dec(); + H << nl << "public:"; + H.inc(); + + H << sp << nl << name << "I(const Ice::CommunicatorPtr&);"; + H << nl << "virtual ~" << name << "I();"; + + C << sp << nl << cls << "::" << name + << "I(const Ice::CommunicatorPtr& communicator)"; + C.inc(); + C << nl << "_communicator(communicator)"; + C.dec(); + C << sb; + C << eb; + + C << sp << nl << cls << "::~" << name << "I()"; + C << sb; + C << eb; + + OperationList ops = p->allOperations(); + OperationList::const_iterator r; + + // + // Operations + // + for (r = ops.begin(); r != ops.end(); ++r) + { + OperationPtr op = (*r); + string opName = op->name(); + + TypePtr ret = op->returnType(); + string retS = returnTypeToString(ret); + + TypeStringList inParams = op->inputParameters(); + TypeStringList outParams = op->outputParameters(); + TypeStringList::const_iterator q; + + H << sp << nl << "virtual " << retS << ' ' << opName << '('; + H.useCurrentPosAsIndent(); + for (q = inParams.begin(); q != inParams.end(); ++q) + { + if (q != inParams.begin()) + { + H << ',' << nl; + } + string typeString = inputTypeToString(q->first); + H << typeString; + } + for (q = outParams.begin(); q != outParams.end(); ++q) + { + if (!inParams.empty() || q != outParams.begin()) + { + H << ',' << nl; + } + string typeString = outputTypeToString(q->first); + H << typeString; + } + if (!p->isLocal()) + { + if (!inParams.empty() || !outParams.empty()) + { + H << ',' << nl; + } + H << "const Ice::Current&"; + } + H.restoreIndent(); + H << ");"; + + C << sp << nl << retS << nl << scoped.substr(2) << "I::" << opName + << '('; + C.useCurrentPosAsIndent(); + for (q = inParams.begin(); q != inParams.end(); ++q) + { + if (q != inParams.begin()) + { + C << ',' << nl; + } + string typeString = inputTypeToString(q->first); + C << typeString << ' ' << q->second; + } + for (q = outParams.begin(); q != outParams.end(); ++q) + { + if (!inParams.empty() || q != outParams.begin()) + { + C << ',' << nl; + } + string typeString = outputTypeToString(q->first); + C << typeString << ' ' << q->second; + } + if (!p->isLocal()) + { + if (!inParams.empty() || !outParams.empty()) + { + C << ',' << nl; + } + C << "const Ice::Current& current"; + } + C.restoreIndent(); + C << ")"; + C << sb; + + int iter = 0; + + // + // Assign values to 'out' params + // + for (q = outParams.begin(); q != outParams.end(); ++q) + { + writeAssign(C, q->first, q->second, iter); + } + + // + // Return value + // + if (ret) + { + C << sp << nl << retS << " __r;"; + writeAssign(C, ret, "__r", iter); + C << nl << "return __r;"; + } + + C << eb; + } + + H << sp; + H.dec(); + H << nl << "private:"; + H.inc(); + H << sp << nl << "Ice::CommunicatorPtr _communicator;"; + H << eb << ';'; + + return true; +} + Slice::Gen::IceInternalVisitor::IceInternalVisitor(Output& h, Output& c, const string& dllExport) : H(h), C(c), _dllExport(dllExport) { diff --git a/cpp/src/slice2cpp/Gen.h b/cpp/src/slice2cpp/Gen.h index 0a92b659fe1..347611a335e 100644 --- a/cpp/src/slice2cpp/Gen.h +++ b/cpp/src/slice2cpp/Gen.h @@ -26,7 +26,8 @@ public: const std::string&, const std::vector<std::string>&, const std::string&, - const std::string&); + const std::string&, + bool); ~Gen(); bool operator!() const; // Returns true if there was a constructor error @@ -38,10 +39,14 @@ private: Output H; Output C; + Output implH; + Output implC; + std::string _base; std::string _include; std::vector<std::string> _includePaths; std::string _dllExport; + bool _impl; class TypesVisitor : public ::IceUtil::noncopyable, public ParserVisitor { @@ -255,6 +260,29 @@ private: std::string _dllExport; }; + + class ImplVisitor : public ::IceUtil::noncopyable, public ParserVisitor + { + public: + + ImplVisitor(Output&, Output&, const std::string&); + + virtual bool visitModuleStart(const ModulePtr&); + virtual void visitModuleEnd(const ModulePtr&); + virtual bool visitClassDefStart(const ClassDefPtr&); + + private: + + Output& H; + Output& C; + + std::string _dllExport; + + // + // Generate code to assign a value + // + void writeAssign(Output&, const TypePtr&, const std::string&, int&); + }; }; } diff --git a/cpp/src/slice2cpp/Main.cpp b/cpp/src/slice2cpp/Main.cpp index 631cb029763..d8a9ea8d2a1 100644 --- a/cpp/src/slice2cpp/Main.cpp +++ b/cpp/src/slice2cpp/Main.cpp @@ -29,6 +29,7 @@ usage(const char* n) "--include-dir DIR Use DIR as the header include directory.\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" "-d, --debug Print debug messages.\n" ; } @@ -41,6 +42,7 @@ main(int argc, char* argv[]) string include; string output; string dllExport; + bool impl = false; bool debug = false; int idx = 1; @@ -141,6 +143,15 @@ main(int argc, char* argv[]) } argc -= 2; } + else if (strcmp(argv[idx], "--impl") == 0) + { + impl = true; + for (int i = idx ; i + 1 < argc ; ++i) + { + argv[i] = argv[i + 1]; + } + --argc; + } else if (argv[idx][0] == '-') { cerr << argv[0] << ": unknown option `" << argv[idx] << "'" << endl; @@ -214,7 +225,8 @@ main(int argc, char* argv[]) } else { - Gen gen(argv[0], base, include, includePaths, dllExport, output); + Gen gen(argv[0], base, include, includePaths, dllExport, output, + impl); if (!gen) { unit->destroy(); |