// ********************************************************************** // // Copyright (c) 2003-2014 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 #include #include #include #include #include #include #include #include #include #include #include using namespace std; using namespace IceUtil; using namespace IceUtilInternal; using namespace Slice; namespace { IceUtil::Mutex* globalMutex = 0; bool interrupted = false; class Init { public: Init() { globalMutex = new IceUtil::Mutex; } ~Init() { delete globalMutex; globalMutex = 0; } }; Init init; string ICE_ENCODING_COMPARE = "Freeze::IceEncodingCompare"; } void interruptedCallback(int /*signal*/) { IceUtilInternal::MutexPtrLock sync(globalMutex); interrupted = true; } class MetaDataVisitor : public ParserVisitor { public: MetaDataVisitor() : _useWstring(false) { } virtual bool visitModuleStart(const ModulePtr& p) { setUseWstring(p); return true; } virtual void visitModuleEnd(const ModulePtr&) { resetUseWstring(); } virtual bool visitClassDefStart(const ClassDefPtr& p) { setUseWstring(p); checkMetaData(p->dataMembers()); resetUseWstring(); return true; } virtual bool visitStructStart(const StructPtr& p) { setUseWstring(p); checkMetaData(p->dataMembers()); resetUseWstring(); return true; } private: void checkMetaData(const DataMemberList& dataMembers) { for(DataMemberList::const_iterator p = dataMembers.begin(); p != dataMembers.end(); ++p) { BuiltinPtr builtin = BuiltinPtr::dynamicCast((*p)->type()); if(builtin && builtin->kind() == Builtin::KindString) { StringList metaData = (*p)->getMetaData(); for(StringList::const_iterator q = metaData.begin(); q != metaData.end(); ++q) { if(*q == "cpp:type:string" || *q == "cpp:type:wstring") { continue; } } metaData.push_back(_useWstring ? "cpp:type:wstring" : "cpp:type:string"); (*p)->setMetaData(metaData); } } } void setUseWstring(ContainedPtr p) { _useWstringHist.push_back(_useWstring); StringList metaData = p->getMetaData(); if(find(metaData.begin(), metaData.end(), "cpp:type:wstring") != metaData.end()) { _useWstring = true; } else if(find(metaData.begin(), metaData.end(), "cpp:type:string") != metaData.end()) { _useWstring = false; } } void resetUseWstring() { _useWstring = _useWstringHist.back(); _useWstringHist.pop_back(); } bool _useWstring; std::list _useWstringHist; }; struct DictIndex { string member; bool caseSensitive; bool sort; string userCompare; bool operator==(const DictIndex& rhs) const { return member == rhs.member; } bool operator!=(const DictIndex& rhs) const { return member != rhs.member; } }; struct Dict { string name; string key; StringList keyMetaData; string value; StringList valueMetaData; bool sort; string userCompare; vector indices; }; struct Index { string name; string type; string member; bool caseSensitive; }; struct IndexType { TypePtr type; StringList metaData; }; void usage(const char* n) { getErrorStream() << "Usage: " << n << " [options] file-base [slice-files...]\n"; getErrorStream() << "Options:\n" "-h, --help Show this message.\n" "-v, --version Display the Ice version.\n" "--header-ext EXT Use EXT instead of the default `h' extension.\n" "--source-ext EXT Use EXT instead of the default `cpp' extension.\n" "--add-header HDR[,GUARD]\n" " Add #include for HDR (with guard GUARD) to generated source file.\n" "-DNAME Define NAME as 1.\n" "-DNAME=DEF Define NAME as DEF.\n" "-UNAME Remove any definition for NAME.\n" "-IDIR Put DIR in the include file search path.\n" "-E Print preprocessor output on stdout.\n" "--include-dir DIR Use DIR as the header include directory in source files.\n" "--dll-export SYMBOL Use SYMBOL for DLL exports.\n" "--dict NAME,KEY,VALUE[,sort[,COMPARE]]\n" " Create a Freeze dictionary with the name NAME,\n" " using KEY as key, and VALUE as value. This\n" " option may be specified multiple times for\n" " different names. NAME may be a scoped name.\n" " By default, keys are sorted using their binary\n" " Ice-encoding representation. Use 'sort' to sort\n" " with the COMPARE functor class. COMPARE's default\n" " value is std::less\n" "--index NAME,TYPE,MEMBER[,{case-sensitive|case-insensitive}]\n" " Create a Freeze evictor index with the name\n" " NAME for member MEMBER of class TYPE. This\n" " option may be specified multiple times for\n" " different names. NAME may be a scoped name.\n" " When member is a string, the case can be\n" " sensitive or insensitive (default is sensitive).\n" "--dict-index DICT[,MEMBER][,{case-sensitive|case-insensitive}]\n" " [,sort[,COMPARE]]\n" " Add an index to dictionary DICT. If MEMBER is \n" " specified, then DICT's VALUE must be a class or\n" " a struct, and MEMBER must designate a member of\n" " VALUE. Otherwise, the entire VALUE is used for \n" " indexing. When the secondary key is a string, \n" " the case can be sensitive or insensitive (default\n" " is sensitive).\n" " By default, keys are sorted using their binary\n" " Ice-encoding representation. Use 'sort' to sort\n" " with the COMPARE functor class. COMPARE's default\n" " value is std::less.\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" "--underscore Permit underscores in Slice identifiers.\n" ; } void checkIdentifier(string t, string s) { if(s.empty() || (!IceUtilInternal::isAlpha(s[0]) && s[0] != '_')) { ostringstream os; os << t << "' is not a valid type name"; throw os.str(); } for(unsigned int i = 1; i < s.size(); ++i) { if(!isalnum(static_cast(s[i])) && s[i] != '_') { ostringstream os; os << t << "' is not a valid type name"; throw os.str(); } } } void printFreezeTypes(Output& out, const vector& dicts, const vector& indices) { out << '\n'; out << "\n// Freeze types in this file:"; for(vector::const_iterator p = dicts.begin(); p != dicts.end(); ++p) { out << "\n// name=\"" << p->name << "\", key=\"" << p->key << "\", value=\"" << p->value << "\""; } for(vector::const_iterator q = indices.begin(); q != indices.end(); ++q) { out << "\n// name=\"" << q->name << "\", type=\"" << q->type << "\", member=\"" << q->member << "\""; if(q->caseSensitive == false) { out << " (case insensitive)"; } } out << '\n'; } template inline string getCompare(const T& t, const string& keyType) { if(t.sort) { if(t.userCompare == "") { return "std::less< " + keyType + ">"; } else { return t.userCompare; } } else { return ICE_ENCODING_COMPARE; } } void writeCodecH(const TypePtr& type, const StringList& metaData, const string& name, const string& freezeType, Output& H, const string& dllExport) { H << sp << nl << "class " << dllExport << name; H << sb; H.dec(); H << sp << nl << "public:"; H << sp; H.inc(); H << nl << "static void write(" << inputTypeToString(type, false, metaData) << ", Freeze::" << freezeType << "&, const ::Ice::CommunicatorPtr&, const Ice::EncodingVersion&);"; H << nl << "static void read(" << typeToString(type, metaData) << "&, const Freeze::" << freezeType << "&, " << "const ::Ice::CommunicatorPtr&, const Ice::EncodingVersion&);"; H << nl << "static const std::string& typeId();"; H << eb << ';'; } void writeCodecC(const TypePtr& type, const StringList& metaData, const string& name, const string& freezeType, bool encaps, Output& C) { string quotedFreezeType = "\"" + freezeType + "\""; C << sp << nl << "void" << nl << name << "::write(" << inputTypeToString(type, false, metaData) << " v, " << "Freeze::" << freezeType << "& bytes, const ::Ice::CommunicatorPtr& communicator, " << "const Ice::EncodingVersion& encoding)"; C << sb; C << nl << "IceInternal::InstancePtr instance = IceInternal::getInstance(communicator);"; C << nl << "IceInternal::BasicStream stream(instance.get(), encoding, true);"; if(encaps) { C << nl << "stream.startWriteEncaps();"; } writeMarshalUnmarshalCode(C, type, false, 0, "v", true, metaData, 0, "stream", false); if(type->usesClasses()) { C << nl << "stream.writePendingObjects();"; } if(encaps) { C << nl << "stream.endWriteEncaps();"; } C << nl << "::std::vector(stream.b.begin(), stream.b.end()).swap(bytes);"; C << eb; C << sp << nl << "void" << nl << name << "::read(" << typeToString(type, metaData) << "& v, " << "const Freeze::" << freezeType << "& bytes, const ::Ice::CommunicatorPtr& communicator, " << "const Ice::EncodingVersion& encoding)"; C << sb; C << nl << "IceInternal::InstancePtr instance = IceInternal::getInstance(communicator);"; C << nl << "IceInternal::BasicStream stream(instance.get(), encoding, &bytes[0], &bytes[0] + bytes.size());"; if(type->usesClasses()) { C << nl << "stream.sliceObjects(false);"; } if(encaps) { C << nl << "stream.startReadEncaps();"; } writeMarshalUnmarshalCode(C, type, false, 0, "v", false, metaData, 0, "stream", false); if(type->usesClasses()) { C << nl << "stream.readPendingObjects();"; } if(encaps) { C << nl << "stream.endReadEncaps();"; } C << eb; string staticName = "__"; for(string::const_iterator p = name.begin(); p != name.end(); ++p) { if((*p) == ':') { staticName += '_'; } else { staticName += *p; } } staticName += "_typeId"; string typeId = type->typeId(); BuiltinPtr builtInType = BuiltinPtr::dynamicCast(type); if(builtInType && builtInType->kind() == Builtin::KindString && metaData.size() != 0 && metaData.front() == "cpp:type:wstring") { typeId = "wstring"; } C << sp << nl << "namespace"; C << sb; C << sp << nl << "const ::std::string " << staticName << " = \"" << typeId << "\";"; C << eb; C << sp << nl << "const ::std::string&" << nl << name << "::typeId()"; C << sb; C << nl << "return " << staticName << ";"; C << eb; } void writeDictWithIndicesH(const string& name, const Dict& dict, const vector indexTypes, const TypePtr& keyType, const StringList& keyMetaData, const TypePtr& valueType, const StringList& valueMetaData, Output& H, const string& dllExport) { string compare = getCompare(dict, typeToString(keyType, keyMetaData)); string templateParams = string("< ") + typeToString(keyType, keyMetaData) + ", " + typeToString(valueType, valueMetaData) + ", " + name + "KeyCodec, " + name + "ValueCodec, " + compare + " >"; string keyCompareParams = string("< ") + typeToString(keyType, keyMetaData) + ", " + name + "KeyCodec, " + compare + " >"; vector capitalizedMembers; for(size_t i = 0; i < dict.indices.size(); ++i) { const string& member = dict.indices[i].member; if(!member.empty()) { string capitalizedMember = member; capitalizedMember[0] = toupper(static_cast(capitalizedMember[0])); capitalizedMembers.push_back(capitalizedMember); } else { capitalizedMembers.push_back("Value"); } } H << sp << nl << "class " << dllExport << name << " : public Freeze::Map" << templateParams; H << sb; H.dec(); H << sp << nl << "public:"; H << sp; H.inc(); // // Typedefs // /* H << nl << "typedef std::pair value_type;"; H << nl << "typedef Freeze::Iterator" << templateParams << " iterator;"; H << nl << "typedef Freeze::ConstIterator" << templateParams << " const_iterator;"; H << nl << "typedef size_t size_type;"; H << nl << "typedef ptrdiff_t difference_type;"; */ // // Nested index classes // for(size_t i = 0; i < capitalizedMembers.size(); ++i) { string className = capitalizedMembers[i] + "Index"; string indexCompare = getCompare(dict.indices[i], typeToString(indexTypes[i].type, indexTypes[i].metaData)); string indexCompareParams = string("< ") + typeToString(indexTypes[i].type, indexTypes[i].metaData) + ", " + className + ", " + indexCompare + " >"; H << sp << nl << "class " << dllExport << className << " : public Freeze::MapIndex" << indexCompareParams; H << sb; H.dec(); H << sp << nl << "public:"; H << sp; H.inc(); H << nl << capitalizedMembers[i] << "Index(const std::string&, const " << indexCompare << "& = " << indexCompare << "());"; H << sp; // // Codec // H << nl << "static void write(" << inputTypeToString(indexTypes[i].type, 0, indexTypes[i].metaData) << ", Freeze::Key&, const Ice::CommunicatorPtr&, const Ice::EncodingVersion&);"; H << nl << "static void read(" << typeToString(indexTypes[i].type, indexTypes[i].metaData) << "&, const Freeze::Key&, const ::Ice::CommunicatorPtr&, const Ice::EncodingVersion&);"; H.dec(); H << sp << nl << "protected:"; H << sp; H.inc(); H << nl << "virtual void marshalKey(const Freeze::Value&, Freeze::Key&) const;"; H << eb << ';'; } // // Constructors // H << sp; H << nl << name << "(const Freeze::ConnectionPtr&, const std::string&, " << "bool = true, const " << compare << "& = " << compare << "());"; H << sp; H << nl << "template " << nl << name << "(const Freeze::ConnectionPtr& __connection, " << "const std::string& __dbName, bool __createDb, " << "_InputIterator __first, _InputIterator __last, " << "const " << compare << "& __compare = " << compare << "())"; H.inc(); H << nl << ": Freeze::Map" << templateParams <<"(__connection->getCommunicator(), __connection->getEncoding())"; H.dec(); H << sb; H << nl << "Freeze::KeyCompareBasePtr __keyCompare = " << "new Freeze::KeyCompare" << keyCompareParams << "(__compare, this->_communicator, this->_encoding);"; H << nl << "std::vector __indices;"; for(size_t i = 0; i < capitalizedMembers.size(); ++i) { string indexName = dict.indices[i].member; if(indexName.empty()) { indexName = "index"; } indexName = string("\"") + indexName + "\""; H << nl << "__indices.push_back(new " << capitalizedMembers[i] << "Index(" << indexName << "));"; } H << nl << "this->_helper.reset(Freeze::MapHelper::create(__connection, __dbName, " << name + "KeyCodec::typeId(), " << name + "ValueCodec::typeId(), __keyCompare, __indices, __createDb));"; H << nl << "while(__first != __last)"; H << sb; H << nl << "put(*__first);"; H << nl << "++__first;"; H << eb; H << eb; // // Recreate // H << nl << "static void recreate(const Freeze::ConnectionPtr&, const std::string&, " << "const " << compare << "& = " << compare << "());"; H << sp; // // Find, begin, lowerBound, upperBound, equalRange and count functions // for(size_t i = 0; i < capitalizedMembers.size(); ++i) { H << sp; H << nl << "iterator findBy" << capitalizedMembers[i] << "(" << inputTypeToString(indexTypes[i].type, false, indexTypes[i].metaData) << ", bool = true);"; H << nl << "const_iterator findBy" << capitalizedMembers[i] << "(" << inputTypeToString(indexTypes[i].type, false, indexTypes[i].metaData) << ", bool = true) const;"; H << nl << "iterator beginFor" << capitalizedMembers[i] << "();"; H << nl << "const_iterator beginFor" << capitalizedMembers[i] << "() const;"; H << nl << "iterator endFor" << capitalizedMembers[i] << "();"; H << nl << "const_iterator endFor" << capitalizedMembers[i] << "() const;"; H << nl << "iterator lowerBoundFor" << capitalizedMembers[i] << "(" << inputTypeToString(indexTypes[i].type, false, indexTypes[i].metaData) << ");"; H << nl << "const_iterator lowerBoundFor" << capitalizedMembers[i] << "(" << inputTypeToString(indexTypes[i].type, false, indexTypes[i].metaData) << ") const;"; H << nl << "iterator upperBoundFor" << capitalizedMembers[i] << "(" << inputTypeToString(indexTypes[i].type, false, indexTypes[i].metaData) << ");"; H << nl << "const_iterator upperBoundFor" << capitalizedMembers[i] << "(" << inputTypeToString(indexTypes[i].type, false, indexTypes[i].metaData) << ") const;"; H << nl << "std::pair equalRangeFor" << capitalizedMembers[i] << "(" << inputTypeToString(indexTypes[i].type, false, indexTypes[i].metaData) << ");"; H << nl << "std::pair equalRangeFor" << capitalizedMembers[i] << "(" << inputTypeToString(indexTypes[i].type, false, indexTypes[i].metaData) << ") const;"; string countFunction = dict.indices[i].member.empty() ? string("valueCount") : dict.indices[i].member + "Count"; H << nl << "int " << countFunction << "(" << inputTypeToString(indexTypes[i].type, false, indexTypes[i].metaData) << ") const;"; } H << eb << ';'; } void writeDictWithIndicesC(const string& name, const string& absolute, const Dict& dict, const vector indexTypes, const TypePtr& keyType, const StringList& keyMetaData, const TypePtr& valueType, const StringList& valueMetaData, Output& C) { string compare = getCompare(dict, typeToString(keyType, keyMetaData)); string templateParams = string("< ") + typeToString(keyType, keyMetaData) + ", " + typeToString(valueType, valueMetaData) + ", " + name + "KeyCodec, " + name + "ValueCodec, " + compare + " >"; string keyCompareParams = string("< ") + typeToString(keyType, keyMetaData) + ", " + name + "KeyCodec, " + compare + " >"; vector capitalizedMembers; for(size_t i = 0; i < dict.indices.size(); ++i) { const string& member = dict.indices[i].member; if(!member.empty()) { string capitalizedMember = member; capitalizedMember[0] = toupper(static_cast(capitalizedMember[0])); capitalizedMembers.push_back(capitalizedMember); } else { capitalizedMembers.push_back("Value"); } } // // Nested index classes // for(size_t i = 0; i < capitalizedMembers.size(); ++i) { string className = capitalizedMembers[i] + "Index"; string indexCompare = getCompare(dict.indices[i], typeToString(indexTypes[i].type, indexTypes[i].metaData)); string indexCompareParams = string("< ") + typeToString(indexTypes[i].type, indexTypes[i].metaData) + ", " + className + ", " + indexCompare + " >"; C << sp << nl << absolute << "::" << className << "::" << className << "(const std::string& __name, " << "const " << indexCompare << "& __compare)"; C.inc(); C << nl << ": Freeze::MapIndex" << indexCompareParams << "(__name, __compare)"; C.dec(); C << sb; C << eb; C << sp << nl << "void" << nl << absolute << "::" << className << "::" << "marshalKey(const Freeze::Value& __v, Freeze::Key& __k) const"; C << sb; bool optimize = false; if(dict.indices[i].member.empty() && dict.indices[i].caseSensitive) { optimize = true; C << nl << "__k = __v;"; } else { // // Can't optimize // C << nl << typeToString(valueType, valueMetaData) << " __x;"; C << nl << absolute << "ValueCodec::read(__x, __v, _communicator, _encoding);"; string param = "__x"; if(!dict.indices[i].member.empty()) { if(ClassDeclPtr::dynamicCast(valueType) != 0) { param += "->" + dict.indices[i].member; } else { param += "." + dict.indices[i].member; } } C << nl << "write(" << param << ", __k, _communicator, _encoding);"; } C << eb; C << sp << nl << "void" << nl << absolute << "::" << className << "::" << "write(" << inputTypeToString(indexTypes[i].type, false, indexTypes[i].metaData) << " __index, Freeze::Key& __bytes, const Ice::CommunicatorPtr& __communicator, " << "const Ice::EncodingVersion& __encoding)"; C << sb; if(optimize) { C << nl << absolute << "ValueCodec::write(__index, __bytes, __communicator, __encoding);"; } else { assert(!indexTypes[i].type->usesClasses()); C << nl << "IceInternal::InstancePtr __instance = IceInternal::getInstance(__communicator);"; C << nl << "IceInternal::BasicStream __stream(__instance.get(), __encoding, true);"; string valueS; if(dict.indices[i].caseSensitive) { valueS = "__index"; } else { C << nl << typeToString(indexTypes[i].type, indexTypes[i].metaData) << " __lowerCaseIndex = IceUtilInternal::toLower(__index);"; valueS = "__lowerCaseIndex"; } writeMarshalUnmarshalCode(C, indexTypes[i].type, false, 0, valueS, true, indexTypes[i].metaData, 0, "__stream", false); C << nl << "::std::vector(__stream.b.begin(), __stream.b.end()).swap(__bytes);"; } C << eb; C << sp << nl << "void" << nl << absolute << "::" << className << "::" << "read(" << typeToString(indexTypes[i].type, indexTypes[i].metaData) << "& __index, const Freeze::Key& __bytes, const Ice::CommunicatorPtr& __communicator, " << "const Ice::EncodingVersion& __encoding)"; C << sb; if(optimize) { C << nl << absolute << "ValueCodec::read(__index, __bytes, __communicator, __encoding);"; } else { C << nl << "IceInternal::InstancePtr __instance = IceInternal::getInstance(__communicator);"; C << nl << "IceInternal::BasicStream __stream(__instance.get(), __encoding, "; C << "&__bytes[0], &__bytes[0] + __bytes.size());"; writeMarshalUnmarshalCode(C, indexTypes[i].type, false, 0, "__index", false, indexTypes[i].metaData, 0, "__stream", false); } C << eb; } // // Constructor // C << sp << nl << absolute << "::" << name << "(const Freeze::ConnectionPtr& __connection, const std::string& __dbName ," << "bool __createDb, const " << compare << "& __compare)"; C.inc(); C << nl << ": Freeze::Map" << templateParams <<"(__connection->getCommunicator(), __connection->getEncoding())"; C.dec(); C << sb; C << nl << "Freeze::KeyCompareBasePtr __keyCompare = " << "new Freeze::KeyCompare" << keyCompareParams << "(__compare, _communicator, _encoding);"; C << nl << "std::vector __indices;"; for(size_t i = 0; i < capitalizedMembers.size(); ++i) { string indexName = dict.indices[i].member; if(indexName.empty()) { indexName = "index"; } indexName = string("\"") + indexName + "\""; C << nl << "__indices.push_back(new " << capitalizedMembers[i] << "Index(" << indexName << "));"; } C << nl << "_helper.reset(Freeze::MapHelper::create(__connection, __dbName, " << absolute + "KeyCodec::typeId(), " << absolute + "ValueCodec::typeId(), __keyCompare, __indices, __createDb));"; C << eb; // // Recreate // C << sp << nl << "void" << nl << absolute << "::recreate(const Freeze::ConnectionPtr& __connection, const std::string& __dbName ," << " const " << compare << "& __compare)"; C << sb; C << nl << "Freeze::KeyCompareBasePtr __keyCompare = " << "new Freeze::KeyCompare" << keyCompareParams << "(__compare, __connection->getCommunicator()" <<", __connection->getEncoding());"; C << nl << "std::vector __indices;"; for(size_t i = 0; i < capitalizedMembers.size(); ++i) { string indexName = dict.indices[i].member; if(indexName.empty()) { indexName = "index"; } indexName = string("\"") + indexName + "\""; C << nl << "__indices.push_back(new " << capitalizedMembers[i] << "Index(" << indexName << "));"; } C << nl << "Freeze::MapHelper::recreate(__connection, __dbName, " << absolute + "KeyCodec::typeId(), " << absolute + "ValueCodec::typeId(), __keyCompare, __indices);"; C << eb; // // Find and count functions // for(size_t i = 0; i < capitalizedMembers.size(); ++i) { string indexClassName = capitalizedMembers[i] + "Index"; string indexName = dict.indices[i].member; if(indexName.empty()) { indexName = "index"; } indexName = string("\"") + indexName + "\""; C << sp << nl << absolute << "::iterator" << nl << absolute << "::" << "findBy" << capitalizedMembers[i] << "(" << inputTypeToString(indexTypes[i].type, false, indexTypes[i].metaData) << " __index, bool __onlyDups)"; C << sb; C << nl << "Freeze::Key __bytes;"; C << nl << indexClassName << "::" << "write(__index, __bytes, _communicator, _encoding);"; C << nl << "return iterator(_helper->index(" << indexName << ")->untypedFind(__bytes, false, __onlyDups), _communicator, _encoding);"; C << eb; C << sp << nl << absolute << "::const_iterator" << nl << absolute << "::" << "findBy" << capitalizedMembers[i] << "(" << inputTypeToString(indexTypes[i].type, false, indexTypes[i].metaData) << " __index, bool __onlyDups) const"; C << sb; C << nl << "Freeze::Key __bytes;"; C << nl << indexClassName << "::" << "write(__index, __bytes, _communicator, _encoding);"; C << nl << "return const_iterator(_helper->index(" << indexName << ")->untypedFind(__bytes, true, __onlyDups), _communicator, _encoding);"; C << eb; C << sp << nl << absolute << "::iterator" << nl << absolute << "::" << "beginFor" << capitalizedMembers[i] << "()"; C << sb; C << nl << "return iterator(_helper->index(" << indexName << ")->begin(false), _communicator, _encoding);"; C << eb; C << sp << nl << absolute << "::const_iterator" << nl << absolute << "::" << "beginFor" << capitalizedMembers[i] << "() const"; C << sb; C << nl << "return const_iterator(_helper->index(" << indexName << ")->begin(true), _communicator, _encoding);"; C << eb; C << sp << nl << absolute << "::iterator" << nl << absolute << "::" << "endFor" << capitalizedMembers[i] << "()"; C << sb; C << nl << "return iterator();"; C << eb; C << sp << nl << absolute << "::const_iterator" << nl << absolute << "::" << "endFor" << capitalizedMembers[i] << "() const"; C << sb; C << nl << "return const_iterator();"; C << eb; C << sp << nl << absolute << "::iterator" << nl << absolute << "::" << "lowerBoundFor" << capitalizedMembers[i] << "(" << inputTypeToString(indexTypes[i].type, false, indexTypes[i].metaData) << " __index)"; C << sb; C << nl << "Freeze::Key __bytes;"; C << nl << indexClassName << "::" << "write(__index, __bytes, _communicator, _encoding);"; C << nl << "return iterator(_helper->index(" << indexName << ")->untypedLowerBound(__bytes, false), _communicator, _encoding);"; C << eb; C << sp << nl << absolute << "::const_iterator" << nl << absolute << "::" << "lowerBoundFor" << capitalizedMembers[i] << "(" << inputTypeToString(indexTypes[i].type, false, indexTypes[i].metaData) << " __index) const"; C << sb; C << nl << "Freeze::Key __bytes;"; C << nl << indexClassName << "::" << "write(__index, __bytes, _communicator, _encoding);"; C << nl << "return const_iterator(_helper->index(" << indexName << ")->untypedLowerBound(__bytes, true), _communicator, _encoding);"; C << eb; C << sp << nl << absolute << "::iterator" << nl << absolute << "::" << "upperBoundFor" << capitalizedMembers[i] << "(" << inputTypeToString(indexTypes[i].type, false, indexTypes[i].metaData) << " __index)"; C << sb; C << nl << "Freeze::Key __bytes;"; C << nl << indexClassName << "::" << "write(__index, __bytes, _communicator, _encoding);"; C << nl << "return iterator(_helper->index(" << indexName << ")->untypedUpperBound(__bytes, false), _communicator, _encoding);"; C << eb; C << sp << nl << absolute << "::const_iterator" << nl << absolute << "::" << "upperBoundFor" << capitalizedMembers[i] << "(" << inputTypeToString(indexTypes[i].type, false, indexTypes[i].metaData) << " __index) const"; C << sb; C << nl << "Freeze::Key __bytes;"; C << nl << indexClassName << "::" << "write(__index, __bytes, _communicator, _encoding);"; C << nl << "return const_iterator(_helper->index(" << indexName << ")->untypedUpperBound(__bytes, true), _communicator, _encoding);"; C << eb; C << sp << nl << "std::pair<" << absolute << "::iterator, " << absolute << "::iterator>" << nl << absolute << "::" << "equalRangeFor" << capitalizedMembers[i] << "(" << inputTypeToString(indexTypes[i].type, false, indexTypes[i].metaData) << " __index)"; C << sb; C << nl << "return std::make_pair(lowerBoundFor" << capitalizedMembers[i] << "(__index), upperBoundFor" << capitalizedMembers[i] << "(__index));"; C << eb; C << sp << nl << "std::pair<" << absolute << "::const_iterator, " << absolute << "::const_iterator>" << nl << absolute << "::" << "equalRangeFor" << capitalizedMembers[i] << "(" << inputTypeToString(indexTypes[i].type, false, indexTypes[i].metaData) << " __index) const"; C << sb; C << nl << "return std::make_pair(lowerBoundFor" << capitalizedMembers[i] << "(__index), upperBoundFor" << capitalizedMembers[i] << "(__index));"; C << eb; string countFunction = dict.indices[i].member.empty() ? string("valueCount") : dict.indices[i].member + "Count"; C << sp << nl << "int" << nl << absolute << "::" << countFunction << "(" << inputTypeToString(indexTypes[i].type, false, indexTypes[i].metaData) << " __index) const"; C << sb; C << nl << "Freeze::Key __bytes;"; C << nl << indexClassName << "::" << "write(__index, __bytes, _communicator, _encoding);"; C << nl << "return _helper->index(" << indexName << ")->untypedCount(__bytes);"; C << eb; } } void writeDict(const string& n, const UnitPtr& u, const Dict& dict, Output& H, Output& C, const string& dllExport) { string absolute = dict.name; if(absolute.find("::") == 0) { absolute.erase(0, 2); } string name = absolute; vector scope; string::size_type pos; while((pos = name.find("::")) != string::npos) { string s = name.substr(0, pos); name.erase(0, pos + 2); checkIdentifier(absolute, s); scope.push_back(s); } checkIdentifier(absolute, name); TypeList keyTypes = u->lookupType(dict.key, false); if(keyTypes.empty()) { ostringstream os; os << "`" << dict.key << "' is not a valid type"; throw os.str(); } TypePtr keyType = keyTypes.front(); TypeList valueTypes = u->lookupType(dict.value, false); if(valueTypes.empty()) { ostringstream os; os << "`" << dict.value << "' is not a valid type"; throw os.str(); } TypePtr valueType = valueTypes.front(); for(vector::const_iterator q = scope.begin(); q != scope.end(); ++q) { H << sp; H << nl << "namespace " << *q << nl << '{'; } writeCodecH(keyType, dict.keyMetaData, name + "KeyCodec", "Key", H, dllExport); writeCodecH(valueType, dict.valueMetaData, name + "ValueCodec", "Value", H, dllExport); vector indexTypes; if(dict.indices.size() == 0) { string compare = getCompare(dict, typeToString(keyType, dict.keyMetaData)); H << sp << nl << "typedef Freeze::Map< " << typeToString(keyType, dict.keyMetaData) << ", " << typeToString(valueType, dict.valueMetaData) << ", " << name << "KeyCodec, " << name << "ValueCodec, " << compare << " > " << name << ";"; } else { for(vector::const_iterator p = dict.indices.begin(); p != dict.indices.end(); ++p) { const DictIndex& index = *p; if(index.member.empty()) { if(dict.indices.size() > 1) { ostringstream os; os << "bad index for dictionary `" << dict.name << "'"; throw os.str(); } bool containsSequence = false; if(!Dictionary::legalKeyType(valueType, containsSequence)) { ostringstream os; os << "`" << dict.value << "' is not a valid index type"; throw os.str(); } if(containsSequence) { getErrorStream() << n << ": warning: use of sequences in dictionary keys has been deprecated"; } if(index.caseSensitive == false) { // // Let's check value is a string // BuiltinPtr builtInType = BuiltinPtr::dynamicCast(valueType); if(builtInType == 0 || builtInType->kind() != Builtin::KindString) { ostringstream os; os << "VALUE is a `" << dict.value << "', not a string"; throw os.str(); } } IndexType iType; iType.type = valueType; iType.metaData = dict.valueMetaData; indexTypes.push_back(iType); } else { DataMemberPtr dataMember = 0; DataMemberList dataMembers; ClassDeclPtr classDecl = ClassDeclPtr::dynamicCast(valueType); if(classDecl != 0) { dataMembers = classDecl->definition()->allDataMembers(); } else { StructPtr structDecl = StructPtr::dynamicCast(valueType); if(structDecl == 0) { ostringstream os; os << "`" << dict.value << "' is neither a class nor a struct."; throw os.str(); } dataMembers = structDecl->dataMembers(); } DataMemberList::const_iterator d = dataMembers.begin(); while(d != dataMembers.end() && dataMember == 0) { if((*d)->name() == index.member) { dataMember = *d; } else { ++d; } } if(dataMember == 0) { ostringstream os; os << "The value of `" << dict.name << "' has no data member named `" << index.member << "'"; throw os.str(); } TypePtr dataMemberType = dataMember->type(); bool containsSequence = false; if(!Dictionary::legalKeyType(dataMemberType, containsSequence)) { ostringstream os; os << "`" << index.member << "' cannot be used as an index"; throw os.str(); } if(containsSequence) { getErrorStream() << n << ": warning: use of sequences in dictionary keys has been deprecated"; } if(index.caseSensitive == false) { // // Let's check member is a string // BuiltinPtr memberType = BuiltinPtr::dynamicCast(dataMemberType); if(memberType == 0 || memberType->kind() != Builtin::KindString) { ostringstream os; os << "`" << index.member << "' is not a string "; throw os.str(); } } IndexType iType; iType.type = dataMemberType; iType.metaData = dataMember->getMetaData(); indexTypes.push_back(iType); } } writeDictWithIndicesH(name, dict, indexTypes, keyType, dict.keyMetaData, valueType, dict.valueMetaData, H, dllExport); } for(vector::const_iterator q = scope.begin(); q != scope.end(); ++q) { H << sp; H << nl << '}'; } writeCodecC(keyType, dict.keyMetaData, absolute + "KeyCodec", "Key", false, C); writeCodecC(valueType, dict.valueMetaData, absolute + "ValueCodec", "Value", true, C); if(indexTypes.size() > 0) { writeDictWithIndicesC(name, absolute, dict, indexTypes, keyType, dict.keyMetaData, valueType, dict.valueMetaData, C); } } void writeIndexH(const string& memberTypeString, const string& name, Output& H, const string& dllExport) { H << sp << nl << "class " << dllExport << name << " : public Freeze::Index"; H << sb; H.dec(); H << sp << nl << "public:"; H << sp; H.inc(); H << nl << name << "(const std::string&, const std::string& = \"\");"; H << sp << nl << "std::vector"; H << nl << "findFirst(" << memberTypeString << ", Ice::Int) const;"; H << sp << nl << "std::vector"; H << nl << "find(" << memberTypeString << ") const;"; H << sp << nl << "Ice::Int"; H << nl << "count(" << memberTypeString << ") const;"; H.dec(); H << sp << nl << "private:"; H << sp; H.inc(); H << nl << "virtual bool"; H << nl << "marshalKey(const Ice::ObjectPtr&, Freeze::Key&) const;"; H << sp << nl << "void"; H << nl << "marshalKey(" << memberTypeString << ", Freeze::Key&) const;"; H << eb << ';'; H << sp; H << nl << "typedef IceUtil::Handle<" << name << "> " << name << "Ptr;"; } void writeIndexC(const TypePtr& type, const TypePtr& memberType, const string& memberName, bool caseSensitive, const string& fullName, const string& name, Output& C) { string inputType = inputTypeToString(memberType, false); C << sp << nl << fullName << "::" << name << "(const ::std::string& __name, const ::std::string& __facet)"; C.inc(); C << nl << ": Freeze::Index(__name, __facet)"; C.dec(); C << sb; C << eb; C << sp << nl << "std::vector"; C << nl << fullName << "::" << "findFirst(" << inputType << " __index, ::Ice::Int __firstN) const"; C << sb; C << nl << "Freeze::Key __bytes;"; C << nl << "marshalKey(__index, __bytes);"; C << nl << "return untypedFindFirst(__bytes, __firstN);"; C << eb; C << sp << nl << "std::vector"; C << nl << fullName << "::" << "find(" << inputType << " __index) const"; C << sb; C << nl << "Freeze::Key __bytes;"; C << nl << "marshalKey(__index, __bytes);"; C << nl << "return untypedFind(__bytes);"; C << eb; C << sp << nl << "Ice::Int"; C << nl << fullName << "::" << "count(" << inputType << " __index) const"; C << sb; C << nl << "Freeze::Key __bytes;"; C << nl << "marshalKey(__index, __bytes);"; C << nl << "return untypedCount(__bytes);"; C << eb; string typeString = typeToString(type); C << sp << nl << "bool"; C << nl << fullName << "::" << "marshalKey(const Ice::ObjectPtr& __servant, Freeze::Key& __bytes) const"; C << sb; C << nl << typeString << " __s = " << typeString << "::dynamicCast(__servant);"; C << nl << "if(__s != 0)"; C << sb; C << nl << "marshalKey(__s->" << memberName << ", __bytes);"; C << nl << "return true;"; C << eb; C << nl << "else"; C << sb; C << nl << "return false;"; C << eb; C << eb; C << sp << nl << "void"; C << nl << fullName << "::" << "marshalKey(" << inputType << " __index, Freeze::Key& __bytes) const"; C << sb; C << nl << "IceInternal::InstancePtr __instance = IceInternal::getInstance(_communicator);"; C << nl << "IceInternal::BasicStream __stream(__instance.get(), _encoding, true);"; string valueS; if(caseSensitive) { valueS = "__index"; } else { C << nl << typeToString(memberType) << " __lowerCaseIndex = IceUtilInternal::toLower(__index);"; valueS = "__lowerCaseIndex"; } writeMarshalUnmarshalCode(C, memberType, false, 0, valueS, true, StringList(), 0, "__stream", false); if(memberType->usesClasses()) { C << nl << "__stream.writePendingObjects();"; } C << nl << "::std::vector(__stream.b.begin(), __stream.b.end()).swap(__bytes);"; C << eb; } void writeIndex(const string& /*n*/, const UnitPtr& u, const Index& index, Output& H, Output& C, const string& dllExport) { string absolute = index.name; if(absolute.find("::") == 0) { absolute.erase(0, 2); } string name = absolute; vector scope; string::size_type pos; while((pos = name.find("::")) != string::npos) { string s = name.substr(0, pos); name.erase(0, pos + 2); checkIdentifier(absolute, s); scope.push_back(s); } checkIdentifier(absolute, name); TypeList types = u->lookupType(index.type, false); if(types.empty()) { ostringstream os; os << "`" << index.type << "' is not a valid type"; throw os.str(); } TypePtr type = types.front(); ClassDeclPtr classDecl = ClassDeclPtr::dynamicCast(type); if(classDecl == 0) { ostringstream os; os << "`" << index.type << "' is not a class"; throw os.str(); } DataMemberList dataMembers = classDecl->definition()->allDataMembers(); DataMemberPtr dataMember = 0; DataMemberList::const_iterator p = dataMembers.begin(); while(p != dataMembers.end() && dataMember == 0) { if((*p)->name() == index.member) { dataMember = *p; } else { ++p; } } if(dataMember == 0) { ostringstream os; os << "`" << index.type << "' has no data member named `" << index.member << "'"; throw os.str(); } if(index.caseSensitive == false) { // // Let's check member is a string // BuiltinPtr memberType = BuiltinPtr::dynamicCast(dataMember->type()); if(memberType == 0 || memberType->kind() != Builtin::KindString) { ostringstream os; os << "`" << index.member << "'is not a string"; throw os.str(); } } for(vector::const_iterator q = scope.begin(); q != scope.end(); ++q) { H << sp; H << nl << "namespace " << *q << nl << '{'; } writeIndexH(inputTypeToString(dataMember->type(), false), name, H, dllExport); for(vector::const_iterator q = scope.begin(); q != scope.end(); ++q) { H << sp; H << nl << '}'; } writeIndexC(type, dataMember->type(), index.member, index.caseSensitive, absolute, name, C); } void gen(const string& name, const UnitPtr& u, const vector& includePaths, const vector& extraHeaders, const vector& dicts, const vector& indices, const string& include, const string& headerExtension, const string& sourceExtension, string dllExport, const StringList& includes, const vector& args, const string& output) { string fileH = args[0]; fileH += "." + headerExtension; string includeH = fileH; string fileC = args[0]; fileC += "." + sourceExtension; if(!output.empty()) { fileH = output + '/' + fileH; fileC = output + '/' + fileC; } u->mergeModules(); u->sort(); IceUtilInternal::Output H; H.open(fileH.c_str()); if(!H) { ostringstream os; os << "cannot open `" << fileH << "': " << strerror(errno); throw FileException(__FILE__, __LINE__, os.str()); } FileTracker::instance()->addFile(fileH); printHeader(H); printGeneratedHeader(H, string(args[0]) + ".ice"); printFreezeTypes(H, dicts, indices); IceUtilInternal::Output CPP; CPP.open(fileC.c_str()); if(!CPP) { ostringstream os; os << "cannot open `" << fileC << "': " << strerror(errno); throw FileException(__FILE__, __LINE__, os.str()); } FileTracker::instance()->addFile(fileC); printHeader(CPP); printGeneratedHeader(CPP, string(args[0]) + ".ice"); printFreezeTypes(CPP, dicts, indices); for(vector::const_iterator i = extraHeaders.begin(); i != extraHeaders.end(); ++i) { string hdr = *i; string guard; string::size_type pos = hdr.rfind(','); if(pos != string::npos) { hdr = i->substr(0, pos); guard = i->substr(pos + 1); } if(!guard.empty()) { CPP << "\n#ifndef " << guard; CPP << "\n#define " << guard; } CPP << "\n#include <"; if(!include.empty()) { CPP << include << '/'; } CPP << hdr << '>'; if(!guard.empty()) { CPP << "\n#endif"; } } string s = fileH; transform(s.begin(), s.end(), s.begin(), ToIfdef()); H << "\n#ifndef __" << s << "__"; H << "\n#define __" << s << "__"; H << '\n'; if(dicts.size() > 0) { H << "\n#include "; } if(indices.size() > 0) { H << "\n#include "; } for(StringList::const_iterator p = includes.begin(); p != includes.end(); ++p) { H << "\n#include <" << changeInclude(*p, includePaths) << "." + headerExtension + ">"; } CPP << "\n#include "; CPP << "\n#include "; CPP << "\n#include <"; if(include.size()) { CPP << include << '/'; } CPP << includeH << '>'; printVersionCheck(H); printVersionCheck(CPP); printDllExportStuff(H, dllExport); if(dllExport.size()) { dllExport += " "; } for(vector::const_iterator p = dicts.begin(); p != dicts.end(); ++p) { writeDict(name, u, *p, H, CPP, dllExport); } for(vector::const_iterator q = indices.begin(); q != indices.end(); ++q) { writeIndex(name, u, *q, H, CPP, dllExport); } H << "\n\n#endif\n"; CPP << '\n'; H.close(); CPP.close(); } int compile(int argc, char* argv[]) { IceUtilInternal::Options opts; opts.addOpt("h", "help"); opts.addOpt("v", "version"); opts.addOpt("", "header-ext", IceUtilInternal::Options::NeedArg, "h"); opts.addOpt("", "source-ext", IceUtilInternal::Options::NeedArg, "cpp"); opts.addOpt("", "add-header", IceUtilInternal::Options::NeedArg, "", IceUtilInternal::Options::Repeat); opts.addOpt("D", "", IceUtilInternal::Options::NeedArg, "", IceUtilInternal::Options::Repeat); opts.addOpt("U", "", IceUtilInternal::Options::NeedArg, "", IceUtilInternal::Options::Repeat); opts.addOpt("I", "", IceUtilInternal::Options::NeedArg, "", IceUtilInternal::Options::Repeat); opts.addOpt("E"); opts.addOpt("", "include-dir", IceUtilInternal::Options::NeedArg); opts.addOpt("", "dll-export", IceUtilInternal::Options::NeedArg); opts.addOpt("", "dict", IceUtilInternal::Options::NeedArg, "", IceUtilInternal::Options::Repeat); opts.addOpt("", "index", IceUtilInternal::Options::NeedArg, "", IceUtilInternal::Options::Repeat); opts.addOpt("", "dict-index", IceUtilInternal::Options::NeedArg, "", IceUtilInternal::Options::Repeat); opts.addOpt("", "output-dir", IceUtilInternal::Options::NeedArg); opts.addOpt("d", "debug"); opts.addOpt("", "ice"); opts.addOpt("", "underscore"); vector args; try { args = opts.parse(argc, (const char**)argv); } catch(const IceUtilInternal::BadOptException& e) { getErrorStream() << argv[0] << ": error: " << e.reason << endl; usage(argv[0]); return EXIT_FAILURE; } if(opts.isSet("help")) { usage(argv[0]); return EXIT_SUCCESS; } if(opts.isSet("version")) { getErrorStream() << ICE_STRING_VERSION << endl; return EXIT_SUCCESS; } string headerExtension = opts.optArg("header-ext"); string sourceExtension = opts.optArg("source-ext"); vector cppArgs; vector extraHeaders = opts.argVec("add-header"); vector optargs = opts.argVec("D"); for(vector::const_iterator i = optargs.begin(); i != optargs.end(); ++i) { cppArgs.push_back("-D" + *i); } optargs = opts.argVec("U"); for(vector::const_iterator i = optargs.begin(); i != optargs.end(); ++i) { cppArgs.push_back("-U" + *i); } vector includePaths = opts.argVec("I"); for(vector::const_iterator i = includePaths.begin(); i != includePaths.end(); ++i) { cppArgs.push_back("-I" + Preprocessor::normalizeIncludePath(*i)); } // Convert include paths to full paths. for(vector::iterator p = includePaths.begin(); p != includePaths.end(); ++p) { *p = fullPath(*p); } bool preprocess= opts.isSet("E"); string include = opts.optArg("include-dir"); string dllExport = opts.optArg("dll-export"); vector dicts; optargs = opts.argVec("dict"); for(vector::const_iterator i = optargs.begin(); i != optargs.end(); ++i) { string s = IceUtilInternal::removeWhitespace(*i); Dict dict; string::size_type pos; pos = s.find(','); if(pos != string::npos) { dict.name = s.substr(0, pos); s.erase(0, pos + 1); } pos = s.find(','); if(pos != string::npos) { if(s.find("[\"") == 0) { string::size_type end = s.find("\"]"); if(end != string::npos && end < pos) { dict.key = s.substr(end + 2, pos - end - 2); dict.keyMetaData.push_back(s.substr(2, end - 2)); } else { dict.key = s.substr(0, pos); } } else { dict.key = s.substr(0, pos); } s.erase(0, pos + 1); } pos = s.find(','); if(pos == string::npos) { if(s.find("[\"") == 0) { string::size_type end = s.find("\"]"); if(end != string::npos) { dict.value = s.substr(end + 2); dict.valueMetaData.push_back(s.substr(2, end - 2)); } else { dict.value = s; } } else { dict.value = s; } dict.sort = false; } else { if(s.find("[\"") == 0) { string::size_type end = s.find("\"]"); if(end != string::npos && end < pos) { dict.value = s.substr(end + 2, pos - end - 2); dict.valueMetaData.push_back(s.substr(2, end - 2)); } else { dict.value = s.substr(0, pos); } } else { dict.value = s.substr(0, pos); } s.erase(0, pos + 1); pos = s.find(','); if(pos == string::npos) { if(s != "sort") { getErrorStream() << argv[0] << ": error: " << *i << ": nothing or ',sort' expected after value-type" << endl; usage(argv[0]); return EXIT_FAILURE; } dict.sort = true; } else { string sort = s.substr(0, pos); s.erase(0, pos + 1); if(sort != "sort") { getErrorStream() << argv[0] << ": error: " << *i << ": nothing or ',sort' expected after value-type" << endl; usage(argv[0]); return EXIT_FAILURE; } dict.sort = true; dict.userCompare = s; } } if(dict.name.empty()) { getErrorStream() << argv[0] << ": error: " << *i << ": no name specified" << endl; usage(argv[0]); return EXIT_FAILURE; } if(dict.key.empty()) { getErrorStream() << argv[0] << ": error: " << *i << ": no key specified" << endl; usage(argv[0]); return EXIT_FAILURE; } if(dict.value.empty()) { getErrorStream() << argv[0] << ": error: " << *i << ": no value specified" << endl; usage(argv[0]); return EXIT_FAILURE; } dicts.push_back(dict); } vector indices; optargs = opts.argVec("index"); for(vector::const_iterator i = optargs.begin(); i != optargs.end(); ++i) { string s = IceUtilInternal::removeWhitespace(*i); Index index; string::size_type pos; pos = s.find(','); if(pos != string::npos) { index.name = s.substr(0, pos); s.erase(0, pos + 1); } pos = s.find(','); if(pos != string::npos) { index.type = s.substr(0, pos); s.erase(0, pos + 1); } pos = s.find(','); string caseString; if(pos != string::npos) { index.member = s.substr(0, pos); s.erase(0, pos + 1); caseString = s; } else { index.member = s; caseString = "case-sensitive"; } if(index.name.empty()) { getErrorStream() << argv[0] << ": error: " << *i << ": no name specified" << endl; usage(argv[0]); return EXIT_FAILURE; } if(index.type.empty()) { getErrorStream() << argv[0] << ": error: " << *i << ": no type specified" << endl; usage(argv[0]); return EXIT_FAILURE; } if(index.member.empty()) { getErrorStream() << argv[0] << ": error: " << *i << ": no member specified" << endl; usage(argv[0]); return EXIT_FAILURE; } if(caseString != "case-sensitive" && caseString != "case-insensitive") { getErrorStream() << argv[0] << ": error: " << *i << ": the case can be `case-sensitive' or " << "`case-insensitive'" << endl; usage(argv[0]); return EXIT_FAILURE; } index.caseSensitive = (caseString == "case-sensitive"); indices.push_back(index); } optargs = opts.argVec("dict-index"); for(vector::const_iterator i = optargs.begin(); i != optargs.end(); ++i) { string s = IceUtilInternal::removeWhitespace(*i); string dictName; DictIndex index; index.sort = false; index.caseSensitive = true; string::size_type pos = s.find(','); if(pos == string::npos) { dictName = s; } else { dictName = s.substr(0, pos); s.erase(0, pos + 1); bool done = false; while(!done) { pos = s.find(','); if(pos == string::npos) { if(s == "sort") { index.sort = true; } else if(s == "case-sensitive") { index.caseSensitive = true; } else if(s == "case-insensitive") { index.caseSensitive = false; } else if(index.member.empty()) { if(s == "\\sort") { index.member = "sort"; } else { index.member = s; } } else { getErrorStream() << argv[0] << ": error: " << *i << ": syntax error" << endl; usage(argv[0]); return EXIT_FAILURE; } done = true; } else { string subs = s.substr(0, pos); s.erase(0, pos + 1); if(subs == "sort") { index.sort = true; index.userCompare = s; done = true; } else if(subs == "case-sensitive") { index.caseSensitive = true; } else if(subs == "case-insensitive") { index.caseSensitive = false; } else if(index.member.empty()) { if(subs == "\\sort") { index.member = "sort"; } else { index.member = subs; } } else { getErrorStream() << argv[0] << ": error: " << *i << ": syntax error" << endl; usage(argv[0]); return EXIT_FAILURE; } } } } if(dictName.empty()) { getErrorStream() << argv[0] << ": error: " << *i << ": no dictionary specified" << endl; usage(argv[0]); return EXIT_FAILURE; } bool found = false; for(vector::iterator p = dicts.begin(); p != dicts.end(); ++p) { if(p->name == dictName) { if(find(p->indices.begin(), p->indices.end(), index) != p->indices.end()) { getErrorStream() << argv[0] << ": error: --dict-index " << *i << ": this dict-index is defined twice" << endl; return EXIT_FAILURE; } p->indices.push_back(index); found = true; break; } } if(!found) { getErrorStream() << argv[0] << ": error: " << *i << ": unknown dictionary" << endl; usage(argv[0]); return EXIT_FAILURE; } } string output = opts.optArg("output-dir"); bool debug = opts.isSet("debug"); bool ice = opts.isSet("ice"); bool underscore = opts.isSet("underscore"); if(dicts.empty() && indices.empty()) { getErrorStream() << argv[0] << ": error: no Freeze types specified" << endl; usage(argv[0]); return EXIT_FAILURE; } if(args.empty()) { getErrorStream() << argv[0] << ": error: no file name base specified" << endl; usage(argv[0]); return EXIT_FAILURE; } UnitPtr u = Unit::createUnit(true, false, ice, underscore); StringList includes; int status = EXIT_SUCCESS; IceUtil::CtrlCHandler ctrlCHandler; ctrlCHandler.setCallback(interruptedCallback); for(vector::size_type idx = 1; idx < args.size(); ++idx) { PreprocessorPtr icecpp = Preprocessor::create(argv[0], args[idx], cppArgs); // // Add an include file for each Slice file. Note that the .h extension // is replaced with headerExtension later. // includes.push_back(icecpp->getBaseName() + ".h"); FILE* cppHandle = icecpp->preprocess(false, "-D__SLICE2FREEZE__"); if(cppHandle == 0) { u->destroy(); return EXIT_FAILURE; } if(preprocess) { char buf[4096]; while(fgets(buf, static_cast(sizeof(buf)), cppHandle) != NULL) { if(fputs(buf, stdout) == EOF) { u->destroy(); return EXIT_FAILURE; } } } else { status = u->parse(args[idx], cppHandle, debug); MetaDataVisitor visitor; u->visit(&visitor, false); } if(!icecpp->close()) { u->destroy(); return EXIT_FAILURE; } { IceUtilInternal::MutexPtrLock sync(globalMutex); if(interrupted) { return EXIT_FAILURE; } } } if(status == EXIT_SUCCESS && !preprocess) { try { gen(argv[0], u, includePaths, extraHeaders, dicts, indices, include, headerExtension, sourceExtension, dllExport, includes, args, output); } catch(const string& ex) { // If a file could not be created, then cleanup any // created files. FileTracker::instance()->cleanup(); u->destroy(); getErrorStream() << argv[0] << ": error: " << ex << endl; return EXIT_FAILURE; } catch(const Slice::FileException& ex) { // If a file could not be created, then cleanup any // created files. FileTracker::instance()->cleanup(); u->destroy(); getErrorStream() << argv[0] << ": error: " << ex.reason() << endl; return EXIT_FAILURE; } catch(...) { getErrorStream() << argv[0] << ": error: unknown exception" << endl; FileTracker::instance()->cleanup(); u->destroy(); return EXIT_FAILURE; } } u->destroy(); { IceUtilInternal::MutexPtrLock sync(globalMutex); if(interrupted) { FileTracker::instance()->cleanup(); return EXIT_FAILURE; } } return status; } int main(int argc, char* argv[]) { try { return compile(argc, argv); } catch(const std::exception& ex) { getErrorStream() << argv[0] << ": error:" << ex.what() << endl; return EXIT_FAILURE; } catch(const std::string& msg) { getErrorStream() << argv[0] << ": error:" << msg << endl; return EXIT_FAILURE; } catch(const char* msg) { getErrorStream() << argv[0] << ": error:" << msg << endl; return EXIT_FAILURE; } catch(...) { getErrorStream() << argv[0] << ": error:" << "unknown exception" << endl; return EXIT_FAILURE; } }