// ********************************************************************** // // Copyright (c) 2003-2016 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 using namespace std; using namespace Slice; using namespace IceUtil; using namespace IceUtilInternal; namespace { IceUtil::Mutex* globalMutex = 0; bool interrupted = false; class Init { public: Init() { globalMutex = new IceUtil::Mutex; } ~Init() { delete globalMutex; globalMutex = 0; } }; Init init; } void interruptedCallback(int /*signal*/) { IceUtilInternal::MutexPtrLock lock(globalMutex); interrupted = true; } struct DictIndex { string member; bool caseSensitive; 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; string value; vector indices; }; struct Index { string name; string type; string member; bool caseSensitive; }; class FreezeGenerator : public JavaGenerator { public: FreezeGenerator(const string&, const string&); virtual ~FreezeGenerator(); void generate(UnitPtr&, const Dict&); void generate(UnitPtr&, const Index&); #ifdef __SUNPRO_CC protected: using JavaGenerator::typeToObjectString; #endif private: string typeToObjectString(const TypePtr&); string varToObject(const TypePtr&, const string&); string objectToVar(const TypePtr&, const string&); const string _prog; }; FreezeGenerator::FreezeGenerator(const string& prog, const string& dir) : JavaGenerator(dir), _prog(prog) { } FreezeGenerator::~FreezeGenerator() { } string FreezeGenerator::typeToObjectString(const TypePtr& type) { static const char* builtinTable[] = { "java.lang.Byte", "java.lang.Boolean", "java.lang.Short", "java.lang.Integer", "java.lang.Long", "java.lang.Float", "java.lang.Double", "java.lang.String", "Ice.Object", "Ice.ObjectPrx", "Ice.LocalObject" }; BuiltinPtr b = BuiltinPtr::dynamicCast(type); if(b) { return builtinTable[b->kind()]; } else { return typeToString(type, TypeModeIn); } } string FreezeGenerator::varToObject(const TypePtr& type, const string& param) { string result = param; BuiltinPtr b = BuiltinPtr::dynamicCast(type); if(b != 0) { switch(b->kind()) { case Builtin::KindByte: { result = string("java.lang.Byte.valueOf(") + param + ")"; break; } case Builtin::KindBool: { result = string("java.lang.Boolean.valueOf(") + param + ")"; break; } case Builtin::KindShort: { result = string("java.lang.Short.valueOf(") + param + ")"; break; } case Builtin::KindInt: { result = string("java.lang.Integer.valueOf(") + param + ")"; break; } case Builtin::KindLong: { result = string("java.lang.Long.valueOf(") + param + ")"; break; } case Builtin::KindFloat: { result = string("java.lang.Float.valueOf(") + param + ")"; break; } case Builtin::KindDouble: { result = string("java.lang.Double.valueOf(") + param + ")"; break; } case Builtin::KindString: case Builtin::KindObject: case Builtin::KindObjectProxy: case Builtin::KindLocalObject: break; } } return result; } string FreezeGenerator::objectToVar(const TypePtr& type, const string& param) { string result = param; BuiltinPtr b = BuiltinPtr::dynamicCast(type); if(b != 0) { switch(b->kind()) { case Builtin::KindByte: { result = param + ".byteValue()"; break; } case Builtin::KindBool: { result = param + ".booleanValue()"; break; } case Builtin::KindShort: { result = param + ".shortValue()"; break; } case Builtin::KindInt: { result = param + ".intValue()"; break; } case Builtin::KindLong: { result = param + ".longValue()"; break; } case Builtin::KindFloat: { result = param + ".floatValue()"; break; } case Builtin::KindDouble: { result = param + ".doubleValue()"; break; } case Builtin::KindString: case Builtin::KindObject: case Builtin::KindObjectProxy: case Builtin::KindLocalObject: break; } } return result; } void FreezeGenerator::generate(UnitPtr& u, const Dict& dict) { // // The dictionary name may include a package. // string name; string::size_type pos = dict.name.rfind('.'); if(pos == string::npos) { name = dict.name; } else { name = dict.name.substr(pos + 1); } TypeList keyTypes = u->lookupType(dict.key, false); if(keyTypes.empty()) { ostringstream os; os << "`" << dict.key << "' is not a valid type" << endl; 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" << endl; throw os.str(); } TypePtr valueType = valueTypes.front(); vector indexTypes; vector members; vector capitalizedMembers; vector indexNames; for(size_t i = 0; i < dict.indices.size(); ++i) { const DictIndex& index = dict.indices[i]; const string& member = index.member; if(index.member.empty()) { // // No member was specified, which means we use the map's value type as the index key. // if(dict.indices.size() > 1) { ostringstream os; os << "bad index for dictionary `" << dict.name << "'" << endl; throw os.str(); } bool containsSequence = false; if(!Dictionary::legalKeyType(valueType, containsSequence)) { ostringstream os; os << "`" << dict.value << "' is not a valid index type" << endl; throw os.str(); } if(containsSequence) { getErrorStream() << _prog << ": warning: use of sequences in dictionary keys has been deprecated" << endl; } if(index.caseSensitive == false) { // // Verify that value type is a string. // BuiltinPtr b = BuiltinPtr::dynamicCast(valueType); if(b == 0 || b->kind() != Builtin::KindString) { ostringstream os; os << "VALUE is a `" << dict.value << "', not a string" << endl; throw os.str(); } } indexTypes.push_back(valueType); members.push_back("value"); capitalizedMembers.push_back("Value"); indexNames.push_back("index"); } 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" << endl; throw os.str(); } dataMembers = structDecl->dataMembers(); } DataMemberList::const_iterator q = dataMembers.begin(); while(q != dataMembers.end() && dataMember == 0) { if((*q)->name() == index.member) { dataMember = *q; } else { ++q; } } if(dataMember == 0) { ostringstream os; os << "The value of `" << dict.name << "' has no data member named `" << index.member << "'" << endl; 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 key" << endl; throw os.str(); } if(containsSequence) { getErrorStream() << _prog << ": warning: use of sequences in dictionary keys has been deprecated" << endl; } if(index.caseSensitive == false) { // // Verify that member type is a string. // BuiltinPtr b = BuiltinPtr::dynamicCast(dataMemberType); if(b == 0 || b->kind() != Builtin::KindString) { ostringstream os; os << "`" << index.member << "' is not a string" << endl; throw os.str(); } } indexTypes.push_back(dataMemberType); members.push_back(member); string capitalizedMember = member; capitalizedMember[0] = toupper(static_cast(capitalizedMember[0])); capitalizedMembers.push_back(capitalizedMember); indexNames.push_back(member); } } open(dict.name, u->currentFile()); Output& out = output(); string keyTypeS = typeToObjectString(keyType); string valueTypeS = typeToObjectString(valueType); out << sp << nl << "public class " << name << " extends Freeze.MapInternal.MapI<" << keyTypeS << ", " << valueTypeS << ">"; out << sb; if(dict.indices.size() > 0) { out << sp; out << nl << "/**" << nl << " * Supplies a comparator for each index key." << nl << " */"; out << nl << "public static class IndexComparators"; out << sb; out << sp; out << nl << "/**" << nl << " * Default constructor assigns null to the comparator for each index key." << nl << " */"; out << nl << "public" << nl << "IndexComparators()"; out << sb; out << eb; out << sp; out << nl << "/**" << nl << " * This constructor accepts a comparator for each index key."; for(size_t i = 0; i < dict.indices.size(); ++i) { out << nl << " * @param " << members[i] << "Comparator Comparator for " << members[i] << "."; } out << nl << " */"; out << nl << "public" << nl << "IndexComparators("; for(size_t i = 0; i < dict.indices.size(); ++i) { if(i > 0) { out << ", "; } out << "java.util.Comparator<" << typeToObjectString(indexTypes[i]) << "> " << members[i] << "Comparator"; } out << ")"; out << sb; for(size_t i = 0; i < dict.indices.size(); ++i) { out << nl << "this." << members[i] << "Comparator = " << members[i] << "Comparator;"; } out << eb; out << sp; for(size_t i = 0; i < dict.indices.size(); ++i) { out << nl << "/** Comparator for " << members[i] << ". */"; out << nl << "public java.util.Comparator<" << typeToObjectString(indexTypes[i]) << "> " << members[i] << "Comparator;"; } out << eb; } // // Constructors // out << sp << nl << "private" << nl << name << "(Freeze.Connection __connection, String __dbName, java.util.Comparator<" << keyTypeS << "> __comparator"; if(dict.indices.size() > 0) { out << ", IndexComparators __indexComparators"; } out << ")"; out << sb; out << nl << "super(__connection, __dbName, __comparator);"; if(dict.indices.size() > 0) { out << nl << "_indices = new Freeze.MapIndex[" << dict.indices.size() << "];"; for(size_t i = 0; i < dict.indices.size(); ++i) { out << nl << "_" << members[i] << "Index = new " << capitalizedMembers[i] << "Index(\"" << indexNames[i] << "\", __indexComparators == null ? null : __indexComparators." << members[i] << "Comparator);"; out << nl << "_indices[" << i << "] = _" << members[i] << "Index;"; } } out << eb; if(dict.indices.size() > 0) { out << sp; out << nl << "/**" << nl << " * Instantiates a Freeze map using the given connection. If the database" << nl << " * named in __dbName does not exist and __createDb" << nl << " * is true, the database is created automatically, otherwise this constructor" << nl << " * raises DatabaseException." << nl << " * @param __connection The Freeze connection associated with this map." << nl << " * @param __dbName The name of the Berkeley DB database." << nl << " * @param __createDb True if the database should be created if it does not" << nl << " * already exist, false otherwise." << nl << " * @param __comparator A comparator for the map's main key, or null to use the" << nl << " * default key comparison strategy." << nl << " * @param __indexComparators A map of string to comparator, representing the" << nl << " * key comparator for each of the map's indices. The map uses the default" << nl << " * key comparison strategy for an index if __indexComparators" << nl << " * is null, or if no entry can be found in the comparators map for an index." << nl << " * @throws Freeze.DatabaseException If an error occurs during database operations." << nl << " */" << nl << "public" << nl << name << "(Freeze.Connection __connection, String __dbName, boolean __createDb, " << "java.util.Comparator<" << keyTypeS << "> __comparator, " << "IndexComparators __indexComparators)"; out << sb; out << nl << "this(__connection, __dbName, __comparator, __indexComparators);"; out << nl << "init(_indices, __dbName, \"" << keyType->typeId() << "\", \"" << valueType->typeId() << "\", __createDb);"; out << eb; } out << sp; out << nl << "/**" << nl << " * Instantiates a Freeze map using the given connection. If the database" << nl << " * named in __dbName does not exist and __createDb" << nl << " * is true, the database is created automatically, otherwise this constructor" << nl << " * raises DatabaseException." << nl << " * @param __connection The Freeze connection associated with this map." << nl << " * @param __dbName The name of the Berkeley DB database." << nl << " * @param __createDb True if the database should be created if it does not" << nl << " * already exist, false otherwise." << nl << " * @param __comparator A comparator for the map's main key, or null to use the" << nl << " * default key comparison strategy." << nl << " * @throws Freeze.DatabaseException If an error occurs during database operations." << nl << " */"; out << nl << "public" << nl << name << "(Freeze.Connection __connection, String __dbName, boolean __createDb, " << "java.util.Comparator<" << keyTypeS << "> __comparator)"; out << sb; if(dict.indices.size() > 0) { out << nl << "this(__connection, __dbName, __createDb, __comparator, null);"; } else { out << nl << "super(__connection, __dbName, \"" << keyType->typeId() << "\", \"" << valueType->typeId() << "\", __createDb, __comparator);"; } out << eb; out << sp; out << nl << "/**" << nl << " * Instantiates a Freeze map using the given connection. If the database" << nl << " * named in __dbName does not exist and __createDb" << nl << " * is true, the database is created automatically, otherwise this constructor" << nl << " * raises DatabaseException. The map uses the default key" << nl << " * comparison strategy." << nl << " * @param __connection The Freeze connection associated with this map." << nl << " * @param __dbName The name of the Berkeley DB database." << nl << " * @param __createDb True if the database should be created if it does not" << nl << " * already exist, false otherwise." << nl << " * @throws Freeze.DatabaseException If an error occurs during database operations." << nl << " */"; out << nl << "public" << nl << name << "(Freeze.Connection __connection, String __dbName, boolean __createDb)"; out << sb; out << nl << "this(__connection, __dbName, __createDb, null);"; out << eb; out << sp; out << nl << "/**" << nl << " * Instantiates a Freeze map using the given connection. If the database" << nl << " * named in __dbName does not exist, it is created automatically." << nl << " * The map uses the default key comparison strategy." << nl << " * @param __connection The Freeze connection associated with this map." << nl << " * @param __dbName The name of the Berkeley DB database." << nl << " * @throws Freeze.DatabaseException If an error occurs during database operations." << nl << " */"; out << nl << "public" << nl << name << "(Freeze.Connection __connection, String __dbName)"; out << sb; out << nl << "this(__connection, __dbName, true);"; out << eb; // // recreate // if(dict.indices.size() > 0) { out << sp; out << nl << "/**" << nl << " * Copies an existing database. The new database has the name given in" << nl << " * __dbName, and the old database is renamed with a UUID" << nl << " * suffix." << nl << " * @param __connection The Freeze connection associated with this map." << nl << " * @param __dbName The name of the Berkeley DB database." << nl << " * @param __comparator A comparator for the map's main key, or null to use the" << nl << " * default key comparison strategy." << nl << " * @param __indexComparators A map of string to comparator, representing the" << nl << " * key comparator for each of the map's indices. The map uses the default" << nl << " * key comparison strategy for an index if __indexComparators" << nl << " * is null, or if no entry can be found in the comparators map for an index." << nl << " * @throws Freeze.DatabaseException If an error occurs during database operations." << nl << " */"; out << nl << "public static void" << nl << "recreate(Freeze.Connection __connection, String __dbName, " << "java.util.Comparator<" << keyTypeS << "> __comparator, " << "IndexComparators __indexComparators)"; out << sb; out << nl << name << " __tmpMap = new " << name << "(__connection, __dbName, __comparator, __indexComparators);"; out << nl << "recreate(__tmpMap, __dbName, \"" << keyType->typeId() << "\", \"" << valueType->typeId() << "\", __tmpMap._indices);"; out << eb; } out << sp; out << nl << "/**" << nl << " * Copies an existing database. The new database has the name given in" << nl << " * __dbName, and the old database is renamed with a UUID" << nl << " * suffix." << nl << " * @param __connection The Freeze connection associated with this map." << nl << " * @param __dbName The name of the Berkeley DB database." << nl << " * @param __comparator A comparator for the map's main key, or null to use the" << nl << " * default key comparison strategy." << nl << " * @throws Freeze.DatabaseException If an error occurs during database operations." << nl << " */"; out << nl << "public static void" << nl << "recreate(Freeze.Connection __connection, String __dbName, " << "java.util.Comparator<" << keyTypeS << "> __comparator)"; out << sb; if(dict.indices.size() > 0) { out << nl << "recreate(__connection, __dbName, __comparator, null);"; } else { out << nl << name << " __tmpMap = new " << name << "(__connection, __dbName, __comparator);"; out << nl << "recreate(__tmpMap, __dbName, \"" << keyType->typeId() << "\", \"" << valueType->typeId() << "\", null);"; } out << eb; // // Index methods // for(size_t i = 0; i < capitalizedMembers.size(); ++i) { string indexClassName = capitalizedMembers[i] + "Index"; string indexTypeS = typeToString(indexTypes[i], TypeModeIn); string indexObjTypeS = typeToObjectString(indexTypes[i]); string indexObj = varToObject(indexTypes[i], "__key"); out << sp; out << nl << "/**" << nl << " * Obtains an iterator ordered using the index value." << nl << " * The iterator's initial position is an element whose key matches __key; if" << nl << " * no such element exists, the returned iterator is empty (hasNext returns" << nl << " * false). If __onlyDups is true, the iterator only returns elements whose" << nl << " * key exactly matches __key; otherwise, the iterator continues to iterate over" << nl << " * the remaining elements in the map." << nl << " * @param __key The value at which the iterator begins." << nl << " * @param __onlyDups True if the iterator should be limited to elements whose key" << nl << " * exactly matches __key, false otherwise." << nl << " * @return A new iterator." << nl << " * @throws Freeze.DatabaseException If an error occurs during database operations." << nl << " */"; out << nl << "public Freeze.Map.EntryIterator>"; out << nl << "findBy" << capitalizedMembers[i] << "(" << indexTypeS << " __key, boolean __onlyDups)"; out << sb; out << nl << "return _" << members[i] << "Index.find(" << indexObj << ", __onlyDups);"; out << eb; out << sp; out << nl << "/**" << nl << " * Obtains an iterator ordered using the values of member " << members[i] << "." << nl << " * The iterator's initial position is an element whose key matches __key; if" << nl << " * no such element exists, the returned iterator is empty (hasNext returns" << nl << " * false). This iterator only returns elements whose key exactly matches __key." << nl << " * @param __key The value at which the iterator begins." << nl << " * @return A new iterator." << nl << " * @throws Freeze.DatabaseException If an error occurs during database operations." << nl << " */"; out << nl << "public Freeze.Map.EntryIterator>"; out << nl << "findBy" << capitalizedMembers[i] << "(" << indexTypeS << " __key)"; out << sb; out << nl << "return _" << members[i] << "Index.find(" << indexObj << ", true);"; out << eb; out << sp; out << nl << "/**" << nl << " * Determines the number of elements whose index values match __key." << nl << " * @return The number of matching elements." << nl << " * @throws Freeze.DatabaseException If an error occurs during database operations." << nl << " */"; string countMethod = dict.indices[i].member.empty() ? string("valueCount") : dict.indices[i].member + "Count"; out << nl << "public int"; out << nl << countMethod << "(" << indexTypeS << " __key)"; out << sb; out << nl << "return _" << members[i] << "Index.count(" << indexObj << ");"; out << eb; string subMap = "Freeze.NavigableMap<" + indexObjTypeS + ", java.util.Set>>"; out << sp; out << nl << "/**" << nl << " * Returns a view of the portion of this map whose keys are strictly less than" << nl << " * __toKey, or less than or equal to __toKey if" << nl << " * __inclusive is true. Insertions and removals via this map are" << nl << " * not supported." << nl << " * @param __toKey High endpoint of the keys in the returned map." << nl << " * @param __inclusive If true, the endpoint is included in the returned map;" << nl << " * otherwise, the endpoint is excluded." << nl << " * @return A view of the portion of this map whose keys are strictly less than" << nl << " * __toKey, or less than or equal to __toKey if" << nl << " * __inclusive is true." << nl << " * @throws Freeze.DatabaseException If an error occurs during database operations." << nl << " */"; out << nl << "public " + subMap; out << nl << "headMapFor" << capitalizedMembers[i] << "(" << indexTypeS << " __toKey, boolean __inclusive)"; out << sb; out << nl << "return _" << members[i] << "Index.createHeadMap(" << varToObject(indexTypes[i], "__toKey") << ", __inclusive);"; out << eb; out << sp; out << nl << "/**" << nl << " * Returns a view of the portion of this map whose keys are strictly less than" << nl << " * __toKey. Insertions and removals via this map are not supported." << nl << " * @param __toKey High endpoint of the keys in the returned map." << nl << " * @return A view of the portion of this map whose keys are strictly less than" << nl << " * __toKey>" << nl << " * @throws Freeze.DatabaseException If an error occurs during database operations." << nl << " */"; out << nl << "public " + subMap; out << nl << "headMapFor" << capitalizedMembers[i] << "(" << indexTypeS << " __toKey)"; out << sb; out << nl << "return headMapFor" << capitalizedMembers[i] << "(__toKey, false);"; out << eb; out << sp; out << nl << "/**" << nl << " * Returns a view of the portion of this map whose keys are strictly greater than" << nl << " * __fromKey, or greater than or equal to __fromKey if" << nl << " * __inclusive is true. Insertions and removals via this map are" << nl << " * not supported." << nl << " * @param __fromKey Low endpoint of the keys in the returned map." << nl << " * @param __inclusive If true, the endpoint is included in the returned map;" << nl << " * otherwise, the endpoint is excluded." << nl << " * @return A view of the portion of this map whose keys are strictly greater than" << nl << " * __fromKey, or greater than or equal to __fromKey if" << nl << " * __inclusive is true." << nl << " * @throws Freeze.DatabaseException If an error occurs during database operations." << nl << " */"; out << nl << "public " + subMap; out << nl << "tailMapFor" << capitalizedMembers[i] << "(" << indexTypeS << " __fromKey, boolean __inclusive)"; out << sb; out << nl << "return _" << members[i] << "Index.createTailMap(" << varToObject(indexTypes[i], "__fromKey") << ", __inclusive);"; out << eb; out << sp; out << nl << "/**" << nl << " * Returns a view of the portion of this map whose keys are greater than or equal" << nl << " * to __fromKey. Insertions and removals via this map are not supported." << nl << " * @param __fromKey Low endpoint of the keys in the returned map." << nl << " * @return A view of the portion of this map whose keys are greater than or equal" << nl << " * to __fromKey." << nl << " * @throws Freeze.DatabaseException If an error occurs during database operations." << nl << " */"; out << nl << "public " + subMap; out << nl << "tailMapFor" << capitalizedMembers[i] << "(" << indexTypeS << " __fromKey)"; out << sb; out << nl << "return tailMapFor" << capitalizedMembers[i] << "(__fromKey, true);"; out << eb; out << sp; out << nl << "/**" << nl << " * Returns a view of the portion of this map whose keys range from" << nl << " * __fromKey to __toKey. If __fromKey" << nl << " * and __toKey are equal, the returned map is empty unless" << nl << " * __fromInclusive and __toInclusive are both true." << nl << " * Insertions and removals via this map are not supported." << nl << " * @param __fromKey Low endpoint of the keys in the returned map." << nl << " * @param __fromInclusive If true, the low endpoint is included in the returned map;" << nl << " * otherwise, the endpoint is excluded." << nl << " * @param __toKey High endpoint of the keys in the returned map." << nl << " * @param __toInclusive If true, the high endpoint is included in the returned map;" << nl << " * otherwise, the endpoint is excluded." << nl << " * @return A view of the portion of this map whose keys range from" << nl << " * __fromKey to __toKey." << nl << " * @throws Freeze.DatabaseException If an error occurs during database operations." << nl << " */"; out << nl << "public " + subMap; out << nl << "subMapFor" << capitalizedMembers[i] << "(" << indexTypeS << " __fromKey, boolean __fromInclusive, " << indexTypeS << " __toKey, boolean __toInclusive)"; out << sb; out << nl << "return _" << members[i] << "Index.createSubMap(" << varToObject(indexTypes[i], "__fromKey") << ", __fromInclusive, " << varToObject(indexTypes[i], "__toKey") << ", __toInclusive);"; out << eb; out << sp; out << nl << "/**" << nl << " * Returns a view of the portion of this map whose keys are greater than" << nl << " * or equal to __fromKey and strictly less than __toKey." << nl << " * Insertions and removals via this map are not supported." << nl << " * @param __fromKey Low endpoint of the keys in the returned map." << nl << " * @param __toKey High endpoint of the keys in the returned map." << nl << " * @return A view of the portion of this map whose keys range from" << nl << " * __fromKey to __toKey." << nl << " * @throws Freeze.DatabaseException If an error occurs during database operations." << nl << " */"; out << nl << "public " + subMap; out << nl << "subMapFor" << capitalizedMembers[i] << "(" << indexTypeS << " __fromKey, " << indexTypeS << " __toKey)"; out << sb; out << nl << "return subMapFor" << capitalizedMembers[i] << "(__fromKey, true, __toKey, false);"; out << eb; out << sp; out << nl << "/**" << nl << " * Returns a view of this map whose keys are ordered by the index value." << nl << " * Insertions and removals via this map are not supported." << nl << " * @return A view of this map whose keys range are ordered by the index value." << nl << " * @throws Freeze.DatabaseException If an error occurs during database operations." << nl << " */"; out << nl << "public " + subMap; out << nl << "mapFor" << capitalizedMembers[i] << "()"; out << sb; out << nl << "return _" << members[i] << "Index.createMap();"; out << eb; } // // Top-level encode/decode // for(size_t i = 0; i < 2; i++) { string keyValue; TypePtr type; bool encaps; string typeS; if(i == 0) { keyValue = "Key"; type = keyType; typeS = keyTypeS; encaps = false; // Do not encapsulate keys. } else { keyValue = "Value"; type = valueType; typeS = valueTypeS; encaps = true; } string valS = objectToVar(type, "v"); int iter; // // encode // out << sp << nl << "public void" << nl << "encode" << keyValue << "(" << typeS << " v, IceInternal.BasicStream __os)"; out << sb; if(encaps) { out << nl << "__os.startWriteEncaps();"; } iter = 0; writeMarshalUnmarshalCode(out, "", type, OptionalNone, false, 0, valS, true, iter, false); if(type->usesClasses()) { out << nl << "__os.writePendingObjects();"; } if(encaps) { out << nl << "__os.endWriteEncaps();"; } out << eb; // // decode // out << sp << nl << "public " << typeS << nl << "decode" << keyValue << "(IceInternal.BasicStream __is)"; out << sb; if(type->usesClasses()) { out << nl << "__is.sliceObjects(false);"; } if(encaps) { out << nl << "__is.startReadEncaps();"; } iter = 0; list metaData; string patchParams; BuiltinPtr b = BuiltinPtr::dynamicCast(type); if((b && b->kind() == Builtin::KindObject) || ClassDeclPtr::dynamicCast(type)) { out << nl << "Patcher __p = new Patcher();"; patchParams = "__p"; } else if(StructPtr::dynamicCast(type)) { out << nl << typeS << " __r = null;"; } else { out << nl << typeS << " __r;"; } if(b) { switch(b->kind()) { case Builtin::KindByte: { out << nl << "__r = java.lang.Byte.valueOf(__is.readByte());"; break; } case Builtin::KindBool: { out << nl << "__r = java.lang.Boolean.valueOf(__is.readBool());"; break; } case Builtin::KindShort: { out << nl << "__r = java.lang.Short.valueOf(__is.readShort());"; break; } case Builtin::KindInt: { out << nl << "__r = java.lang.Integer.valueOf(__is.readInt());"; break; } case Builtin::KindLong: { out << nl << "__r = java.lang.Long.valueOf(__is.readLong());"; break; } case Builtin::KindFloat: { out << nl << "__r = java.lang.Float.valueOf(__is.readFloat());"; break; } case Builtin::KindDouble: { out << nl << "__r = java.lang.Double.valueOf(__is.readDouble());"; break; } case Builtin::KindString: case Builtin::KindObject: case Builtin::KindObjectProxy: case Builtin::KindLocalObject: { writeMarshalUnmarshalCode(out, "", type, OptionalNone, false, 0, "__r", false, iter, false, metaData, patchParams); break; } } } else { writeMarshalUnmarshalCode(out, "", type, OptionalNone, false, 0, "__r", false, iter, false, metaData, patchParams); } if(type->usesClasses()) { out << nl << "__is.readPendingObjects();"; } if(encaps) { out << nl << "__is.endReadEncaps();"; } if((b && b->kind() == Builtin::KindObject) || ClassDeclPtr::dynamicCast(type)) { out << nl << "return __p.value;"; } else { out << nl << "return __r;"; } out << eb; } // // Inner index classes // for(size_t i = 0; i < capitalizedMembers.size(); ++i) { string indexClassName = capitalizedMembers[i] + "Index"; string indexKeyTypeS = typeToObjectString(indexTypes[i]); out << sp << nl << "private class " << indexClassName << " extends Freeze.MapInternal.Index<" << keyTypeS << ", " << valueTypeS << ", " << indexKeyTypeS << ">"; out << sb; // // encodeKey // out << sp << nl << "public void"; out << nl << "encodeKey(" << indexKeyTypeS << " key, IceInternal.BasicStream __os)"; out << sb; if(dict.indices[i].member.empty()) { // // Encode the full value (with an encaps!) // string keyS = "key"; if(!dict.indices[i].caseSensitive) { keyS = "key.toLowerCase()"; } out << nl << "encodeValue(" << keyS << ", __os);"; } else { // // No encaps // string keyS = dict.indices[i].caseSensitive ? "key" : "key.toLowerCase()"; keyS = objectToVar(indexTypes[i], keyS); int iter = 0; writeMarshalUnmarshalCode(out, "", indexTypes[i], OptionalNone, false, 0, keyS, true, iter, false); assert(!indexTypes[i]->usesClasses()); } out << eb; // // decodeKey // out << sp << nl << "public " << indexKeyTypeS; out << nl << "decodeKey(IceInternal.BasicStream __is)"; out << sb; if(dict.indices[i].member.empty()) { // // Decode the full value (with an encaps!) // out << nl << "return decodeValue(__is);"; } else { int iter = 0; list metaData; string patchParams; if(StructPtr::dynamicCast(indexTypes[i])) { out << nl << indexKeyTypeS << " r = null;"; } else { out << nl << indexKeyTypeS << " r;"; } BuiltinPtr b = BuiltinPtr::dynamicCast(indexTypes[i]); if(b != 0) { switch(b->kind()) { case Builtin::KindByte: { out << nl << "r = java.lang.Byte.valueOf(__is.readByte());"; break; } case Builtin::KindBool: { out << nl << "r = java.lang.Boolean.valueOf(__is.readBool());"; break; } case Builtin::KindShort: { out << nl << "r = java.lang.Short.valueOf(__is.readShort());"; break; } case Builtin::KindInt: { out << nl << "r = java.lang.Integer.valueOf(__is.readInt());"; break; } case Builtin::KindLong: { out << nl << "r = java.lang.Long.valueOf(__is.readLong());"; break; } case Builtin::KindFloat: { out << nl << "r = java.lang.Float.valueOf(__is.readFloat());"; break; } case Builtin::KindDouble: { out << nl << "r = java.lang.Double.valueOf(__is.readDouble());"; break; } case Builtin::KindString: case Builtin::KindObject: case Builtin::KindObjectProxy: case Builtin::KindLocalObject: { writeMarshalUnmarshalCode(out, "", indexTypes[i], OptionalNone, false, 0, "r", false, iter, false, metaData, patchParams); break; } } } else { writeMarshalUnmarshalCode(out, "", indexTypes[i], OptionalNone, false, 0, "r", false, iter, false, metaData, patchParams); } out << nl << "return r;"; } out << eb; // // extractKey // out << sp << nl << "protected " << indexKeyTypeS; out << nl << "extractKey(" << valueTypeS << " value)"; out << sb; if(dict.indices[i].member.empty()) { if(dict.indices[i].caseSensitive) { out << nl << "return value;"; } else { out << nl << "return value.toLowerCase();"; } } else { string member = "value." + dict.indices[i].member; if(!dict.indices[i].caseSensitive) { member += ".toLowerCase()"; } out << nl << "return " << varToObject(indexTypes[i], member) << ";"; } out << eb; // // marshalKey optimization // if(dict.indices[i].member.empty() && dict.indices[i].caseSensitive) { out << sp << nl << "protected java.nio.ByteBuffer"; out << nl << "marshalKey(java.nio.ByteBuffer value)"; out << sb; out << nl << "return value;"; out << eb; } // // Constructor // out << sp << nl << "private" << nl << indexClassName << "(String name, java.util.Comparator<" << indexKeyTypeS << "> comparator)"; out << sb; out << nl << "super(" << name << ".this, name, comparator);"; out << eb; out << eb; } // // Patcher class. // BuiltinPtr b = BuiltinPtr::dynamicCast(valueType); if((b && b->kind() == Builtin::KindObject) || ClassDeclPtr::dynamicCast(valueType)) { string typeS = typeToString(valueType, TypeModeIn); out << sp << nl << "private static class Patcher implements IceInternal.Patcher"; out << sb; out << sp << nl << "public void" << nl << "patch(Ice.Object v)"; out << sb; if(b) { out << nl << "value = v;"; } else { out << nl << "value = (" << typeS << ")v;"; } out << eb; out << sp << nl << "public String" << nl << "type()"; out << sb; if(b) { out << nl << "return \"::Ice::Object\";"; } else { ClassDeclPtr decl = ClassDeclPtr::dynamicCast(valueType); out << nl << "return \"" << decl->scoped() << "\";"; } out << eb; out << sp << nl << typeS << " value;"; out << eb; } // // Fields // if(!dict.indices.empty()) { out << sp << nl << "private Freeze.MapIndex[] _indices;"; } for(size_t i = 0; i < dict.indices.size(); ++i) { out << nl << "private " << capitalizedMembers[i] << "Index _" << members[i] << "Index;"; } out << eb; close(); } void FreezeGenerator::generate(UnitPtr& u, const Index& index) { string name; string::size_type pos = index.name.rfind('.'); if(pos == string::npos) { name = index.name; } else { name = index.name.substr(pos + 1); } TypeList types = u->lookupType(index.type, false); if(types.empty()) { ostringstream os; os << "`" << index.type << "' is not a valid type" << endl; throw os.str(); } TypePtr type = types.front(); ClassDeclPtr classDecl = ClassDeclPtr::dynamicCast(type); if(classDecl == 0) { ostringstream os; os << "`" << index.type << "' is not a class" << endl; 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 << "'" << endl; 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 " << endl; throw os.str(); } } string memberTypeString = typeToString(dataMember->type(), TypeModeIn); open(index.name, u->currentFile()); Output& out = output(); out << sp << nl << "public class " << name << " extends Freeze.Index"; out << sb; // // Constructors // out << sp << nl << "public" << nl << name << "(String __indexName, String __facet)"; out << sb; out << nl << "super(__indexName, __facet);"; out << eb; out << sp << nl << "public" << nl << name << "(String __indexName)"; out << sb; out << nl << "super(__indexName, \"\");"; out << eb; // // find and count // out << sp << nl << "public Ice.Identity[]" << nl << "findFirst(" << memberTypeString << " __index, int __firstN)"; out << sb; out << nl << "return untypedFindFirst(marshalKey(__index), __firstN);"; out << eb; out << sp << nl << "public Ice.Identity[]" << nl << "find(" << memberTypeString << " __index)"; out << sb; out << nl << "return untypedFind(marshalKey(__index));"; out << eb; out << sp << nl << "public int" << nl << "count(" << memberTypeString << " __index)"; out << sb; out << nl << "return untypedCount(marshalKey(__index));"; out << eb; // // Key marshalling // string typeString = typeToString(type, TypeModeIn); out << sp << nl << "protected java.nio.ByteBuffer" << nl << "marshalKey(Ice.Object __servant)"; out << sb; out << nl << "if(__servant instanceof " << typeString << ")"; out << sb; out << nl << memberTypeString << " __key = ((" << typeString << ")__servant)." << index.member << ";"; out << nl << "return marshalKey(__key);"; out << eb; out << nl << "else"; out << sb; out << nl << "return null;"; out << eb; out << eb; string valueS = index.caseSensitive ? "__key" : "__key.toLowerCase()"; out << sp << nl << "private java.nio.ByteBuffer" << nl << "marshalKey(" << memberTypeString << " __key)"; out << sb; out << nl << "IceInternal.BasicStream __os = " << "new IceInternal.BasicStream(IceInternal.Util.getInstance(communicator()), encoding(), false);"; int iter = 0; writeMarshalUnmarshalCode(out, "", dataMember->type(), OptionalNone, false, 0, valueS, true, iter, false); if(dataMember->type()->usesClasses()) { out << nl << "__os.writePendingObjects();"; } out << nl << "return __os.prepareWrite().b;"; out << eb; out << eb; close(); } void usage(const char* n) { getErrorStream() << "Usage: " << n << " [options] [slice-files...]\n"; getErrorStream() << "Options:\n" "-h, --help Show this message.\n" "-v, --version Display the Ice version.\n" "--validate Validate command line options.\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.\n" "--dict NAME,KEY,VALUE 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" "--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" " 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" "--output-dir DIR Create files in the directory DIR.\n" "--depend Generate Makefile dependencies.\n" "--depend-xml Generate dependencies in XML format.\n" "--depend-file FILE Write dependencies to FILE instead of standard output.\n" "-d, --debug Print debug messages.\n" "--ice Allow reserved Ice prefix in Slice identifiers.\n" "--underscore Allow underscores in Slice identifiers.\n" "--meta META Define global metadata directive META.\n" ; } int compile(int argc, char* argv[]) { IceUtilInternal::Options opts; opts.addOpt("h", "help"); opts.addOpt("v", "version"); opts.addOpt("", "validate"); 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("", "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("", "depend"); opts.addOpt("", "depend-xml"); opts.addOpt("", "depend-file", IceUtilInternal::Options::NeedArg, ""); opts.addOpt("d", "debug"); opts.addOpt("", "ice"); opts.addOpt("", "underscore"); opts.addOpt("", "meta", IceUtilInternal::Options::NeedArg, "", IceUtilInternal::Options::Repeat); bool validate = false; for(int i = 0; i < argc; ++i) { if(string(argv[i]) == "--validate") { validate = true; break; } } vector args; try { args = opts.parse(argc, const_cast(argv)); } catch(const IceUtilInternal::BadOptException& e) { getErrorStream() << argv[0] << ": error: " << e.reason << endl; if(!validate) { 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; } vector cppArgs; 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)); } bool preprocess = opts.isSet("E"); string include = opts.optArg("include-dir"); 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) { dict.key = s.substr(0, pos); s.erase(0, pos + 1); } dict.value = s; if(dict.name.empty()) { getErrorStream() << argv[0] << ": error: " << *i << ": no name specified" << endl; if(!validate) { usage(argv[0]); } return EXIT_FAILURE; } if(dict.key.empty()) { getErrorStream() << argv[0] << ": error: " << *i << ": no key specified" << endl; if(!validate) { usage(argv[0]); } return EXIT_FAILURE; } if(dict.value.empty()) { getErrorStream() << argv[0] << ": error: " << *i << ": no value specified" << endl; if(!validate) { 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; if(!validate) { usage(argv[0]); } return EXIT_FAILURE; } if(index.type.empty()) { getErrorStream() << argv[0] << ": error: " << *i << ": no type specified" << endl; if(!validate) { usage(argv[0]); } return EXIT_FAILURE; } if(index.member.empty()) { getErrorStream() << argv[0] << ": error: " << *i << ": no member specified" << endl; if(!validate) { 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; if(!validate) { usage(argv[0]); } return EXIT_FAILURE; } index.caseSensitive = (caseString == "case-sensitive"); indices.push_back(index); } if(opts.isSet("dict-index")) { vector 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; string::size_type pos; string caseString = "case-sensitive"; pos = s.find(','); if(pos != string::npos) { dictName = s.substr(0, pos); s.erase(0, pos + 1); pos = s.find(','); if(pos != string::npos) { index.member = s.substr(0, pos); s.erase(0, pos + 1); caseString = s; } else { if(s == "case-sensitive" || s == "case-insensitive") { caseString = s; } else { index.member = s; } } } else { dictName = s; } if(dictName.empty()) { getErrorStream() << argv[0] << ": error: " << *i << ": no dictionary specified" << endl; if(!validate) { 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; if(!validate) { usage(argv[0]); } return EXIT_FAILURE; } index.caseSensitive = (caseString == "case-sensitive"); 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; if(!validate) { usage(argv[0]); } return EXIT_FAILURE; } } } string output = opts.optArg("output-dir"); bool depend = opts.isSet("depend"); bool dependxml = opts.isSet("depend-xml"); string dependFile = opts.optArg("depend-file"); bool debug = opts.isSet("debug"); bool ice = opts.isSet("ice"); bool underscore = opts.isSet("underscore"); StringList globalMetadata; vector v = opts.argVec("meta"); copy(v.begin(), v.end(), back_inserter(globalMetadata)); if(dicts.empty() && indices.empty() && !(depend || dependxml)) { getErrorStream() << argv[0] << ": error: no Freeze types specified" << endl; if(!validate) { usage(argv[0]); } return EXIT_FAILURE; } if(depend && dependxml) { getErrorStream() << argv[0] << ": error: cannot specify both --depend and --depend-xml" << endl; if(!validate) { usage(argv[0]); } return EXIT_FAILURE; } if(validate) { return EXIT_SUCCESS; } UnitPtr u = Unit::createUnit(true, false, ice, underscore, globalMetadata); int status = EXIT_SUCCESS; IceUtil::CtrlCHandler ctrlCHandler; ctrlCHandler.setCallback(interruptedCallback); DependOutputUtil out(dependFile); if(dependxml) { out.os() << "\n" << endl; } for(vector::size_type idx = 0; idx < args.size(); ++idx) { if(depend || dependxml) { PreprocessorPtr icecpp = Preprocessor::create(argv[0], args[idx], cppArgs); FILE* cppHandle = icecpp->preprocess(false, "-D__SLICE2FREEZEJ__"); if(cppHandle == 0) { out.cleanup(); u->destroy(); return EXIT_FAILURE; } status = u->parse(args[idx], cppHandle, debug); if(status == EXIT_FAILURE) { out.cleanup(); u->destroy(); return EXIT_FAILURE; } if(!icecpp->printMakefileDependencies(out.os(), depend ? Preprocessor::Java : Preprocessor::SliceXML, includePaths, "-D__SLICE2FREEZEJ__")) { out.cleanup(); u->destroy(); return EXIT_FAILURE; } if(!icecpp->close()) { out.cleanup(); u->destroy(); return EXIT_FAILURE; } } else { PreprocessorPtr icecpp = Preprocessor::create(argv[0], args[idx], cppArgs); FILE* cppHandle = icecpp->preprocess(false, "-DICE_COMPILER=ICE_SLICE2FREEZEJ"); 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); } if(!icecpp->close()) { u->destroy(); return EXIT_FAILURE; } } { IceUtilInternal::MutexPtrLock sync(globalMutex); if(interrupted) { out.cleanup(); return EXIT_FAILURE; } } } if(dependxml) { out.os() << "\n"; } if(depend || dependxml) { u->destroy(); return EXIT_SUCCESS; } if(status == EXIT_SUCCESS && !preprocess) { u->mergeModules(); u->sort(); FreezeGenerator gen(argv[0], output); JavaGenerator::validateMetaData(u); for(vector::const_iterator p = dicts.begin(); p != dicts.end(); ++p) { try { gen.generate(u, *p); } 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(...) { FileTracker::instance()->cleanup(); getErrorStream() << argv[0] << ": error: unknown exception" << endl; u->destroy(); return EXIT_FAILURE; } } for(vector::const_iterator q = indices.begin(); q != indices.end(); ++q) { try { gen.generate(u, *q); } 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; } }