IceE-trans-1.2.0/0000775000076400007640000000000010620635757013031 5ustar dwaynedwayneIceE-trans-1.2.0/INSTALL.LINUX0000664000076400007640000000352410620635757014764 0ustar dwaynedwayne====================================================================== Requirements ====================================================================== Operating System ---------------- The Ice-E translators are expected to build and run properly on any recent Linux distribution for x86 and x86_64. However, only the following operating systems are officially supported: - Red Hat Enterprise Linux Advanced Server 4 Update 4 for x86 or x86_64 (RHEL 4.4) - Novell SuSE Linux Enterprise Server 10 for x86 or x86_64 (SLES 10) C++ compiler ------------ The Ice-E translators are expected to build properly with GCC 3.3 or later. However, only the following compilers are officially supported: - GCC 3.4.6 on RHEL 4.4 - GCC 4.1.x on SLES 10 ====================================================================== Compilation ====================================================================== Extract the Ice-E translator archive in any directory you like (for example, in your home directory): $ tar xvfz IceE-trans-1.2.0.tar.gz Change the working directory to IceE-trans-1.2.0: $ cd IceE-trans-1.2.0 Then build the translators: $ make This will build the Slice-to-C++ and Slice-to-Java translators for Ice-E. ====================================================================== 32 bit builds on x86_64 ====================================================================== By default, builds on x86_64 are 64-bit. To perform a 32-bit build on an x86_64 Linux system, set the environment variable LP64 to no, as shown below: $ export LP64=no ====================================================================== Installation ====================================================================== Simply run "make install". This will install the Ice-E translators in the directory specified by the "prefix" variable in config/Make.rules. IceE-trans-1.2.0/lib/0000775000076400007640000000000010620635757013577 5ustar dwaynedwayneIceE-trans-1.2.0/src/0000775000076400007640000000000010620635756013617 5ustar dwaynedwayneIceE-trans-1.2.0/src/Slice/0000775000076400007640000000000010620635757014657 5ustar dwaynedwayneIceE-trans-1.2.0/src/Slice/CsUtil.cpp0000774000076400007640000011044110560413774016565 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 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 #ifdef _WIN32 #include #endif #ifndef _WIN32 #include #endif using namespace std; using namespace Slice; using namespace IceUtil; static string lookupKwd(const string& name, int baseTypes, bool mangleCasts = false) { // // Keyword list. *Must* be kept in alphabetical order. // static const string keywordList[] = { "abstract", "as", "base", "bool", "break", "byte", "case", "catch", "char", "checked", "class", "const", "continue", "decimal", "default", "delegate", "do", "double", "else", "enum", "event", "explicit", "extern", "false", "finally", "fixed", "float", "for", "foreach", "goto", "if", "implicit", "in", "int", "interface", "internal", "is", "lock", "long", "namespace", "new", "null", "object", "operator", "out", "override", "params", "private", "protected", "public", "readonly", "ref", "return", "sbyte", "sealed", "short", "sizeof", "stackalloc", "static", "string", "struct", "switch", "this", "throw", "true", "try", "typeof", "uint", "ulong", "unchecked", "unsafe", "ushort", "using", "virtual", "void", "volatile", "while" }; bool found = binary_search(&keywordList[0], &keywordList[sizeof(keywordList) / sizeof(*keywordList)], name, Slice::CICompare()); if(found) { return "@" + name; } if(mangleCasts && (name == "checkedCast" || name == "uncheckedCast")) { return string(DotNet::manglePrefix) + name; } return Slice::DotNet::mangleName(name, baseTypes); } // // Split a scoped name into its components and return the components as a list of (unscoped) identifiers. // static StringList splitScopedName(const string& scoped) { assert(scoped[0] == ':'); StringList ids; string::size_type next = 0; string::size_type pos; while((pos = scoped.find("::", next)) != string::npos) { pos += 2; if(pos != scoped.size()) { string::size_type endpos = scoped.find("::", pos); if(endpos != string::npos) { ids.push_back(scoped.substr(pos, endpos - pos)); } } next = pos; } if(next != scoped.size()) { ids.push_back(scoped.substr(next)); } else { ids.push_back(""); } return ids; } // // If the passed name is a scoped name, return the identical scoped name, // but with all components that are C# keywords replaced by // their "@"-prefixed version; otherwise, if the passed name is // not scoped, but a C# keyword, return the "@"-prefixed name; // otherwise, check if the name is one of the method names of baseTypes; // if so, prefix it with _Ice_; otherwise, return the name unchanged. // string Slice::CsGenerator::fixId(const string& name, int baseTypes, bool mangleCasts) { if(name.empty()) { return name; } if(name[0] != ':') { return lookupKwd(name, baseTypes, mangleCasts); } StringList ids = splitScopedName(name); StringList newIds; for(StringList::const_iterator i = ids.begin(); i != ids.end(); ++i) { newIds.push_back(lookupKwd(*i, baseTypes)); } stringstream result; for(StringList::const_iterator j = newIds.begin(); j != newIds.end(); ++j) { if(j != newIds.begin()) { result << '.'; } result << *j; } return result.str(); } string Slice::CsGenerator::typeToString(const TypePtr& type) { if(!type) { return "void"; } static const char* builtinTable[] = { "byte", "bool", "short", "int", "long", "float", "double", "string", "Ice.Object", "Ice.ObjectPrx", "Ice.LocalObject" }; BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); if(builtin) { return builtinTable[builtin->kind()]; } ProxyPtr proxy = ProxyPtr::dynamicCast(type); if(proxy) { return fixId(proxy->_class()->scoped() + "Prx"); } SequencePtr seq = SequencePtr::dynamicCast(type); if(seq && !seq->hasMetaData("clr:collection")) { return typeToString(seq->type()) + "[]"; } ContainedPtr contained = ContainedPtr::dynamicCast(type); if(contained) { return fixId(contained->scoped()); } return "???"; } bool Slice::CsGenerator::isValueType(const TypePtr& type) { BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); if(builtin) { switch(builtin->kind()) { case Builtin::KindString: case Builtin::KindObject: case Builtin::KindObjectProxy: case Builtin::KindLocalObject: { return false; break; } default: { return true; break; } } } StructPtr s = StructPtr::dynamicCast(type); if(s) { if(s->hasMetaData("clr:class")) { return false; } DataMemberList dm = s->dataMembers(); for(DataMemberList::const_iterator i = dm.begin(); i != dm.end(); ++i) { if(!isValueType((*i)->type())) { return false; } } return true; } if(EnumPtr::dynamicCast(type)) { return true; } return false; } void Slice::CsGenerator::writeMarshalUnmarshalCode(Output &out, const TypePtr& type, const string& param, bool marshal, bool streamingAPI, bool isOutParam, const string& patchParams) { string stream; if(marshal) { stream = streamingAPI ? "outS__" : "os__"; } else { stream = streamingAPI ? "inS__" : "is__"; } BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); if(builtin) { switch(builtin->kind()) { case Builtin::KindByte: { if(marshal) { out << nl << stream << ".writeByte(" << param << ");"; } else { out << nl << param << " = " << stream << ".readByte()" << ';'; } break; } case Builtin::KindBool: { if(marshal) { out << nl << stream << ".writeBool(" << param << ");"; } else { out << nl << param << " = " << stream << ".readBool()" << ';'; } break; } case Builtin::KindShort: { if(marshal) { out << nl << stream << ".writeShort(" << param << ");"; } else { out << nl << param << " = " << stream << ".readShort()" << ';'; } break; } case Builtin::KindInt: { if(marshal) { out << nl << stream << ".writeInt(" << param << ");"; } else { out << nl << param << " = " << stream << ".readInt()" << ';'; } break; } case Builtin::KindLong: { if(marshal) { out << nl << stream << ".writeLong(" << param << ");"; } else { out << nl << param << " = " << stream << ".readLong()" << ';'; } break; } case Builtin::KindFloat: { if(marshal) { out << nl << stream << ".writeFloat(" << param << ");"; } else { out << nl << param << " = " << stream << ".readFloat()" << ';'; } break; } case Builtin::KindDouble: { if(marshal) { out << nl << stream << ".writeDouble(" << param << ");"; } else { out << nl << param << " = " << stream << ".readDouble()" << ';'; } break; } case Builtin::KindString: { if(marshal) { out << nl << stream << ".writeString(" << param << ");"; } else { out << nl << param << " = " << stream << ".readString()" << ';'; } break; } case Builtin::KindObject: { if(marshal) { out << nl << stream << ".writeObject(" << param << ");"; } else { if(isOutParam) { out << nl << "IceInternal.ParamPatcher " << param << "_PP = new IceInternal.ParamPatcher(typeof(Ice.Object), \"::Ice::Object\");"; out << nl << stream << ".readObject("; if(streamingAPI) { out << "(Ice.ReadObjectCallback)"; } out << param << "_PP);"; } else { out << nl << stream << ".readObject("; if(streamingAPI) { out << "(Ice.ReadObjectCallback)"; } out << "new Patcher__(" << patchParams << "));"; } } break; } case Builtin::KindObjectProxy: { string typeS = typeToString(type); if(marshal) { out << nl << stream << ".writeProxy(" << param << ");"; } else { out << nl << param << " = " << stream << ".readProxy()" << ';'; } break; } case Builtin::KindLocalObject: { assert(false); break; } } return; } ProxyPtr prx = ProxyPtr::dynamicCast(type); if(prx) { string typeS = typeToString(type); if(marshal) { out << nl << typeS << "Helper.write"; if(!streamingAPI) { out << "__"; } out << "(" << stream << ", " << param << ");"; } else { out << nl << param << " = " << typeS << "Helper.read"; if(!streamingAPI) { out << "__"; } out << "(" << stream << ");"; } return; } ClassDeclPtr cl = ClassDeclPtr::dynamicCast(type); if(cl) { if(marshal) { out << nl << stream << ".writeObject(" << param << ");"; } else { if(isOutParam) { ContainedPtr contained = ContainedPtr::dynamicCast(type); out << nl << "IceInternal.ParamPatcher " << param << "_PP = new IceInternal.ParamPatcher(typeof(" << typeToString(type) << "), \"" << contained->scoped() << "\");"; out << nl << stream << ".readObject("; if(streamingAPI) { out << "(Ice.ReadObjectCallback)"; } out << param << "_PP);"; } else { out << nl << stream << ".readObject("; if(streamingAPI) { out << "(Ice.ReadObjectCallback)"; } out << "new Patcher__(" << patchParams << "));"; } } return; } StructPtr st = StructPtr::dynamicCast(type); if(st) { if(marshal) { if(streamingAPI) { out << nl << param << ".ice_write(" << stream << ");"; } else { out << nl << param << ".write__(" << stream << ");"; } } else { string typeS = typeToString(type); out << nl << param << " = new " << typeS << "();"; if(streamingAPI) { out << nl << param << ".ice_read(" << stream << ");"; } else { out << nl << param << ".read__(" << stream << ");"; } } return; } EnumPtr en = EnumPtr::dynamicCast(type); if(en) { string func; string cast; size_t sz = en->getEnumerators().size(); if(sz <= 0x7f) { func = marshal ? "writeByte" : "readByte"; cast = marshal ? string("(byte)") : "(" + fixId(en->scoped()) + ")"; } else if(sz <= 0x7fff) { func = marshal ? "writeShort" : "readShort"; cast = marshal ? string("(short)") : "(" + fixId(en->scoped()) + ")"; } else { func = marshal ? "writeInt" : "readInt"; cast = marshal ? string("(int)") : "(" + fixId(en->scoped()) + ")"; } if(marshal) { out << nl << stream << '.' << func << '(' << cast << param << ");"; } else { out << nl << param << " = " << cast << stream << '.' << func << "()" << ';'; } return; } SequencePtr seq = SequencePtr::dynamicCast(type); if(seq) { writeSequenceMarshalUnmarshalCode(out, seq, param, marshal, streamingAPI); return; } assert(ConstructedPtr::dynamicCast(type)); string typeS = typeToString(type); if(marshal) { out << nl << typeS << "Helper.write(" << stream << ", " << param << ");"; } else { out << nl << param << " = " << typeS << "Helper.read(" << stream << ')' << ';'; } } void Slice::CsGenerator::writeSequenceMarshalUnmarshalCode(Output& out, const SequencePtr& seq, const string& param, bool marshal, bool streamingAPI) { string stream; if(marshal) { stream = streamingAPI ? "outS__" : "os__"; } else { stream = streamingAPI ? "inS__" : "is__"; } TypePtr type = seq->type(); string typeS = typeToString(type); bool isArray = !seq->hasMetaData("clr:collection"); string limitID = isArray ? "Length" : "Count"; BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); if(builtin) { switch(builtin->kind()) { case Builtin::KindObject: case Builtin::KindObjectProxy: { if(marshal) { out << nl << "if(" << param << " == null)"; out << sb; out << nl << stream << ".writeSize(0);"; out << eb; out << nl << "else"; out << sb; out << nl << stream << ".writeSize(" << param << '.' << limitID << ");"; out << nl << "for(int ix__ = 0; ix__ < " << param << '.' << limitID << "; ++ix__)"; out << sb; string func = builtin->kind() == Builtin::KindObject ? "writeObject" : "writeProxy"; out << nl << stream << '.' << func << '(' << param << "[ix__]);"; out << eb; out << eb; } else { out << nl << "int lenx__ = " << stream << ".readSize();"; if(!streamingAPI) { if(builtin->isVariableLength()) { out << nl << stream << ".startSeq(lenx__, " << static_cast(builtin->minWireSize()) << ");"; } else { out << nl << stream << ".checkFixedSeq(lenx__, " << static_cast(builtin->minWireSize()) << ");"; } } out << nl << param << " = new "; if(builtin->kind() == Builtin::KindObject) { if(isArray) { out << "Ice.Object[lenx__];"; } else { out << typeToString(seq) << "(lenx__);"; } out << nl << "for(int ix__ = 0; ix__ < lenx__; ++ix__)"; out << sb; out << nl << stream << ".readObject("; if(streamingAPI) { out << "(ReadObjectCallback)"; } out << "new IceInternal.SequencePatcher(" << param << ", typeof(Ice.Object), ix__));"; } else { if(isArray) { out << "Ice.ObjectPrx[lenx__];"; } else { out << typeToString(seq) << "(lenx__);"; } out << nl << "for(int ix__ = 0; ix__ < lenx__; ++ix__)"; out << sb; if(isArray) { out << nl << param << "[ix__] = " << stream << ".readProxy();"; } else { out << nl << "Ice.ObjectPrx val__ = new Ice.ObjectPrxHelperBase();"; out << nl << "val__ = " << stream << ".readProxy();"; out << nl << param << ".Add(val__);"; } } if(!streamingAPI && builtin->isVariableLength()) { out << nl << stream << ".checkSeq();"; out << nl << stream << ".endElement();"; } out << eb; if(!streamingAPI && builtin->isVariableLength()) { out << nl << stream << ".endSeq(lenx__);"; } } break; } default: { typeS[0] = toupper(typeS[0]); if(marshal) { out << nl << stream << ".write" << typeS << "Seq(" << param; if(!isArray) { out << " == null ? null : " << param << ".ToArray()"; } out << ");"; } else { if(!isArray) { out << nl << param << " = new " << fixId(seq->scoped()) << '(' << stream << ".read" << typeS << "Seq());"; } else { out << nl << param << " = " << stream << ".read" << typeS << "Seq();"; } } break; } } return; } ClassDeclPtr cl = ClassDeclPtr::dynamicCast(type); if(cl) { if(marshal) { out << nl << "if(" << param << " == null)"; out << sb; out << nl << stream << ".writeSize(0);"; out << eb; out << nl << "else"; out << sb; out << nl << stream << ".writeSize(" << param << '.' << limitID << ");"; out << nl << "for(int ix__ = 0; ix__ < " << param << '.' << limitID << "; ++ix__)"; out << sb; out << nl << stream << ".writeObject(" << param << "[ix__]);"; out << eb; out << eb; } else { out << sb; out << nl << "int szx__ = " << stream << ".readSize();"; if(!streamingAPI) { if(type->isVariableLength()) { out << nl << stream << ".startSeq(szx__, " << static_cast(type->minWireSize()) << ");"; } else { out << nl << stream << ".checkFixedSeq(szx__, " << static_cast(type->minWireSize()) << ");"; } } out << nl << param << " = new "; if(isArray) { out << toArrayAlloc(typeS + "[]", "szx__"); } else { out << fixId(seq->scoped()) << "(szx__)"; } out << ';'; out << nl << "for(int ix__ = 0; ix__ < szx__; ++ix__)"; out << sb; out << nl << "IceInternal.SequencePatcher spx = new IceInternal.SequencePatcher(" << param << ", " << "typeof(" << typeS << "), ix__);"; out << nl << stream << ".readObject("; if(streamingAPI) { out << "(Ice.ReadObjectCallback)"; } out << "spx);"; if(!streamingAPI && type->isVariableLength()) { out << nl << stream << ".checkSeq();"; out << nl << stream << ".endElement();"; } out << eb; if(!streamingAPI && type->isVariableLength()) { out << nl << stream << ".endSeq(szx__);"; } out << eb; } return; } StructPtr st = StructPtr::dynamicCast(type); if(st) { if(marshal) { out << nl << "if(" << param << " == null)"; out << sb; out << nl << stream << ".writeSize(0);"; out << eb; out << nl << "else"; out << sb; out << nl << stream << ".writeSize(" << param << '.' << limitID << ");"; out << nl << "for(int ix__ = 0; ix__ < " << param << '.' << limitID << "; ++ix__)"; out << sb; if(streamingAPI) { out << nl << param << "[ix__].ice_write(" << stream << ");"; } else { out << nl << param << "[ix__].write__(" << stream << ");"; } out << eb; out << eb; } else { out << sb; out << nl << "int szx__ = " << stream << ".readSize();"; if(!streamingAPI) { if(type->isVariableLength()) { out << nl << stream << ".startSeq(szx__, " << static_cast(type->minWireSize()) << ");"; } else { out << nl << stream << ".checkFixedSeq(szx__, " << static_cast(type->minWireSize()) << ");"; } } out << nl << param << " = new "; if(isArray) { out << toArrayAlloc(typeS + "[]", "szx__"); } else { out << fixId(seq->scoped()) << "(szx__)"; } out << ';'; out << nl << "for(int ix__ = 0; ix__ < szx__; ++ix__)"; out << sb; if(isArray) { if(!isValueType(st)) { out << nl << param << "[ix__] = new " << typeS << "();"; } if(streamingAPI) { out << nl << param << "[ix__].ice_read(" << stream << ");"; } else { out << nl << param << "[ix__].read__(" << stream << ");"; } } else { out << nl << typeS << " val__ = new " << typeS << "();"; if(streamingAPI) { out << nl << "val__.ice_read(" << stream << ");"; } else { out << nl << "val__.read__(" << stream << ");"; } out << nl << param << ".Add(val__);"; } if(!streamingAPI && type->isVariableLength()) { out << nl << stream << ".checkSeq();"; out << nl << stream << ".endElement();"; } out << eb; if(!streamingAPI && type->isVariableLength()) { out << nl << stream << ".endSeq(szx__);"; } out << eb; } return; } EnumPtr en = EnumPtr::dynamicCast(type); if(en) { if(marshal) { out << nl << "if(" << param << " == null)"; out << sb; out << nl << stream << ".writeSize(0);"; out << eb; out << nl << "else"; out << sb; out << nl << stream << ".writeSize(" << param << '.'<< limitID << ");"; out << nl << "for(int ix__ = 0; ix__ < " << param << '.' << limitID << "; ++ix__)"; out << sb; out << nl << stream << ".writeByte((byte)" << param << "[ix__]);"; out << eb; out << eb; } else { out << sb; out << nl << "int szx__ = " << stream << ".readSize();"; if(!streamingAPI) { out << nl << stream << ".checkFixedSeq(szx__, " << static_cast(type->minWireSize()) << ");"; } out << nl << param << " = new "; if(isArray) { out << toArrayAlloc(typeS + "[]", "szx__"); } else { out << fixId(seq->scoped()) << "(szx__)"; } out << ';'; out << nl << "for(int ix__ = 0; ix__ < szx__; ++ix__)"; out << sb; if(isArray) { out << nl << param << "[ix__] = (" << typeS << ')' << stream << ".readByte();"; } else { out << nl << param << ".Add((" << typeS << ')' << stream << ".readByte());"; } out << eb; out << eb; } return; } string helperName; if(ProxyPtr::dynamicCast(type)) { helperName = fixId(ProxyPtr::dynamicCast(type)->_class()->scoped() + "PrxHelper"); } else { helperName = fixId(ContainedPtr::dynamicCast(type)->scoped() + "Helper"); } string func; if(marshal) { func = "write"; if(!streamingAPI && ProxyPtr::dynamicCast(type)) { func += "__"; } out << nl << "if(" << param << " == null)"; out << sb; out << nl << stream << ".writeSize(0);"; out << eb; out << nl << "else"; out << sb; out << nl << stream << ".writeSize(" << param << '.' << limitID << ");"; out << nl << "for(int ix__ = 0; ix__ < " << param << '.' << limitID << "; ++ix__)"; out << sb; out << nl << helperName << '.' << func << '(' << stream << ", " << param << "[ix__]);"; out << eb; out << eb; } else { func = "read"; if(!streamingAPI && ProxyPtr::dynamicCast(type)) { func += "__"; } out << sb; out << nl << "int szx__ = " << stream << ".readSize();"; if(!streamingAPI) { if(type->isVariableLength()) { out << nl << stream << ".startSeq(szx__, " << static_cast(type->minWireSize()) << ");"; } else { out << nl << stream << ".checkFixedSeq(szx__, " << static_cast(type->minWireSize()) << ");"; } } out << nl << param << " = new "; if(isArray) { out << toArrayAlloc(typeS + "[]", "szx__"); } else { out << fixId(seq->scoped()) << "(szx__)"; } out << ';'; out << nl << "for(int ix__ = 0; ix__ < szx__; ++ix__)"; out << sb; if(isArray) { out << nl << param << "[ix__] = " << helperName << '.' << func << '(' << stream << ");"; } else { out << nl << param << ".Add(" << helperName << '.' << func << '(' << stream << "));"; } if(!streamingAPI && type->isVariableLength()) { if(!SequencePtr::dynamicCast(type)) { out << nl << stream << ".checkSeq();"; } out << nl << stream << ".endElement();"; } out << eb; if(!streamingAPI && type->isVariableLength()) { out << nl << stream << ".endSeq(szx__);"; } out << eb; } return; } string Slice::CsGenerator::toArrayAlloc(const string& decl, const string& sz) { int count = 0; string::size_type pos = decl.size(); while(pos > 1 && decl.substr(pos - 2, 2) == "[]") { ++count; pos -= 2; } assert(count > 0); ostringstream o; o << decl.substr(0, pos) << '[' << sz << ']' << decl.substr(pos + 2); return o.str(); } void Slice::CsGenerator::validateMetaData(const UnitPtr& u) { MetaDataVisitor visitor; u->visit(&visitor, true); } Slice::CsGenerator::MetaDataVisitor::MetaDataVisitor() : _globalMetaDataDone(false) { } bool Slice::CsGenerator::MetaDataVisitor::visitModuleStart(const ModulePtr& p) { if(!_globalMetaDataDone) { // // Validate global metadata. // DefinitionContextPtr dc = p->definitionContext(); assert(dc); StringList globalMetaData = dc->getMetaData(); string file = dc->filename(); static const string prefix = "cs:"; for(StringList::const_iterator q = globalMetaData.begin(); q != globalMetaData.end(); ++q) { string s = *q; if(_history.count(s) == 0) { if(s.find(prefix) == 0) { static const string attributePrefix = "cs:attribute:"; if(s.find(attributePrefix) != 0 || s.size() == attributePrefix.size()) { cout << file << ": warning: ignoring invalid global metadata `" << s << "'" << endl; } } _history.insert(s); } } _globalMetaDataDone = true; } validate(p); return true; } void Slice::CsGenerator::MetaDataVisitor::visitModuleEnd(const ModulePtr&) { } void Slice::CsGenerator::MetaDataVisitor::visitClassDecl(const ClassDeclPtr& p) { validate(p); } bool Slice::CsGenerator::MetaDataVisitor::visitClassDefStart(const ClassDefPtr& p) { validate(p); return true; } void Slice::CsGenerator::MetaDataVisitor::visitClassDefEnd(const ClassDefPtr&) { } bool Slice::CsGenerator::MetaDataVisitor::visitExceptionStart(const ExceptionPtr& p) { validate(p); return true; } void Slice::CsGenerator::MetaDataVisitor::visitExceptionEnd(const ExceptionPtr&) { } bool Slice::CsGenerator::MetaDataVisitor::visitStructStart(const StructPtr& p) { validate(p); return true; } void Slice::CsGenerator::MetaDataVisitor::visitStructEnd(const StructPtr&) { } void Slice::CsGenerator::MetaDataVisitor::visitOperation(const OperationPtr& p) { validate(p); } void Slice::CsGenerator::MetaDataVisitor::visitParamDecl(const ParamDeclPtr& p) { validate(p); } void Slice::CsGenerator::MetaDataVisitor::visitDataMember(const DataMemberPtr& p) { validate(p); } void Slice::CsGenerator::MetaDataVisitor::visitSequence(const SequencePtr& p) { validate(p); } void Slice::CsGenerator::MetaDataVisitor::visitDictionary(const DictionaryPtr& p) { validate(p); } void Slice::CsGenerator::MetaDataVisitor::visitEnum(const EnumPtr& p) { validate(p); } void Slice::CsGenerator::MetaDataVisitor::visitConst(const ConstPtr& p) { validate(p); } void Slice::CsGenerator::MetaDataVisitor::validate(const ContainedPtr& cont) { DefinitionContextPtr dc = cont->definitionContext(); assert(dc); string file = dc->filename(); StringList localMetaData = cont->getMetaData(); StringList::const_iterator p; for(p = localMetaData.begin(); p != localMetaData.end(); ++p) { string s = *p; if(s.find("cs:") == 0) // TODO: remove this statement once "cs:" is a hard error. { if(SequencePtr::dynamicCast(cont)) { if(s.substr(3) == "collection") { cout << file << ":" << cont->line() << ": warning: `cs:' metadata prefix is deprecated; " << "use `clr:' instead" << endl; cont->addMetaData("clr:collection"); } } else if(StructPtr::dynamicCast(cont)) { if(s.substr(3) == "class") { cout << file << ":" << cont->line() << ": warning: `cs:' metadata prefix is deprecated; " << "use `clr:' instead" << endl; cont->addMetaData("clr:class"); } } else if(s.find("cs:attribute:") == 0) { ; // Do nothing, "cs:attribute:" is OK } else { cout << file << ":" << cont->line() << ": warning: ignoring invalid metadata `" << s << "'" << endl; } } // End TODO string prefix = "clr:"; if(_history.count(s) == 0) { if(s.find(prefix) == 0) { if(SequencePtr::dynamicCast(cont)) { if(s.substr(prefix.size()) == "collection") { continue; } } if(StructPtr::dynamicCast(cont)) { if(s.substr(prefix.size()) == "class") { continue; } if(s.substr(prefix.size()) == "property") { continue; } } if(ClassDefPtr::dynamicCast(cont)) { if(s.substr(prefix.size()) == "property") { continue; } } cout << file << ":" << cont->line() << ": warning: ignoring invalid metadata `" << s << "'" << endl; } _history.insert(s); } prefix = "cs:"; if(_history.count(s) == 0) { if(s.find(prefix) == 0) { if(s.substr(prefix.size()) == "attribute:") { continue; } cout << file << ":" << cont->line() << ": warning: ignoring invalid metadata `" << s << "'" << endl; } _history.insert(s); } } } IceE-trans-1.2.0/src/Slice/.depend0000664000076400007640000000642210552610624016111 0ustar dwaynedwayneScanner$(OBJEXT): Scanner.cpp ../../include/IceUtil/Config.h ../Slice/GrammarUtil.h ../../include/Slice/Parser.h ../../include/IceUtil/Shared.h ../../include/IceUtil/Handle.h ../../include/IceUtil/Exception.h ../../include/IceUtil/InputUtil.h ../Slice/Grammar.h Grammar$(OBJEXT): Grammar.cpp ../Slice/GrammarUtil.h ../../include/Slice/Parser.h ../../include/IceUtil/Shared.h ../../include/IceUtil/Config.h ../../include/IceUtil/Handle.h ../../include/IceUtil/Exception.h ../../include/IceUtil/InputUtil.h ../../include/IceUtil/UUID.h Parser$(OBJEXT): Parser.cpp ../../include/IceUtil/Functional.h ../../include/IceUtil/Handle.h ../../include/IceUtil/Exception.h ../../include/IceUtil/Config.h ../../include/Slice/Parser.h ../../include/IceUtil/Shared.h ../../include/IceUtil/InputUtil.h ../Slice/GrammarUtil.h CPlusPlusUtil$(OBJEXT): CPlusPlusUtil.cpp ../../include/Slice/CPlusPlusUtil.h ../../include/Slice/Parser.h ../../include/IceUtil/Shared.h ../../include/IceUtil/Config.h ../../include/IceUtil/Handle.h ../../include/IceUtil/Exception.h ../../include/IceUtil/InputUtil.h ../../include/IceUtil/OutputUtil.h CsUtil$(OBJEXT): CsUtil.cpp ../../include/Slice/CsUtil.h ../../include/Slice/Parser.h ../../include/IceUtil/Shared.h ../../include/IceUtil/Config.h ../../include/IceUtil/Handle.h ../../include/IceUtil/Exception.h ../../include/IceUtil/InputUtil.h ../../include/IceUtil/OutputUtil.h ../../include/Slice/DotNetNames.h ../../include/IceUtil/Functional.h VbUtil$(OBJEXT): VbUtil.cpp ../../include/Slice/VbUtil.h ../../include/Slice/Parser.h ../../include/IceUtil/Shared.h ../../include/IceUtil/Config.h ../../include/IceUtil/Handle.h ../../include/IceUtil/Exception.h ../../include/IceUtil/InputUtil.h ../../include/IceUtil/OutputUtil.h ../../include/Slice/DotNetNames.h ../../include/IceUtil/Functional.h JavaUtil$(OBJEXT): JavaUtil.cpp ../../include/Slice/JavaUtil.h ../../include/Slice/Parser.h ../../include/IceUtil/Shared.h ../../include/IceUtil/Config.h ../../include/IceUtil/Handle.h ../../include/IceUtil/Exception.h ../../include/IceUtil/InputUtil.h ../../include/IceUtil/OutputUtil.h ../../include/IceUtil/Functional.h Preprocessor$(OBJEXT): Preprocessor.cpp ../../include/Slice/Preprocessor.h ../../include/IceUtil/Config.h ../../include/IceUtil/StringUtil.h Checksum$(OBJEXT): Checksum.cpp ../../include/Slice/Checksum.h ../../include/Slice/Parser.h ../../include/IceUtil/Shared.h ../../include/IceUtil/Config.h ../../include/IceUtil/Handle.h ../../include/IceUtil/Exception.h ../../include/IceUtil/InputUtil.h ../../include/IceUtil/MD5.h PythonUtil$(OBJEXT): PythonUtil.cpp ../../include/Slice/PythonUtil.h ../../include/Slice/Parser.h ../../include/IceUtil/Shared.h ../../include/IceUtil/Config.h ../../include/IceUtil/Handle.h ../../include/IceUtil/Exception.h ../../include/IceUtil/InputUtil.h ../../include/IceUtil/OutputUtil.h ../../include/Slice/Checksum.h ../../include/IceUtil/Functional.h DotNetNames$(OBJEXT): DotNetNames.cpp ../../include/Slice/DotNetNames.h RubyUtil$(OBJEXT): RubyUtil.cpp ../../include/Slice/RubyUtil.h ../../include/Slice/Parser.h ../../include/IceUtil/Shared.h ../../include/IceUtil/Config.h ../../include/IceUtil/Handle.h ../../include/IceUtil/Exception.h ../../include/IceUtil/InputUtil.h ../../include/IceUtil/OutputUtil.h ../../include/Slice/Checksum.h ../../include/IceUtil/Functional.h IceE-trans-1.2.0/src/Slice/Scanner.l0000664000076400007640000002314310550516551016420 0ustar dwaynedwayne%{ // ********************************************************************** // // Copyright (c) 2003-2007 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 // Before Grammer.h, so that YYSTYPE is defined #include #include #include #include #if defined(_MSC_VER) && defined(ICE_64) // // '=' : conversion from 'size_t' to 'int', possible loss of data // The result of fread() is a size_t and gets inserted into an int // # pragma warning( 4 : 4267 ) // // 'initializing' : conversion from '__int64' to 'int', possible loss of data // Puts a pointer-difference into an int // # pragma warning( 4 : 4244 ) #endif using namespace std; using namespace Slice; namespace Slice { // // Definitions for the case-insensitive keyword-token map. // typedef std::map StringTokenMap; static StringTokenMap keywordMap; void initScanner(); void checkIdentifier(const string&); int checkKeyword(string&); } #define YY_USER_INIT initScanner(); %} %option noyywrap %option never-interactive %option prefix="slice_" %option outfile="lex.yy.c" identifier \\?[[:alpha:]_][[:alnum:]_]* integer_constant (\+|-)?((0[0-7]+)|(0x[[:xdigit:]]+)|([[:digit:]]+)) fractional_constant (\+|-)?(([[:digit:]]*\.[[:digit:]]+)|([[:digit:]]+\.)) exponent_part (e|E)(\+|-)?[[:digit:]]+ floating_literal (({fractional_constant}{exponent_part}?)|((\+|-)?[[:digit:]]+{exponent_part}))[fF]? %% ^"#"[[:blank:]]*[[:digit:]]+[[:blank:]]*$ { unit->scanPosition(yytext); } ^"#"[[:blank:]]*[[:digit:]]+[[:blank:]]+"\""[^\"]*"\"".*$ { unit->scanPosition(yytext); } ^"#"[[:blank:]]*"line"[[:blank:]]+[[:digit:]]+[[:blank:]]*$ { unit->scanPosition(yytext); } ^"#"[[:blank:]]*"line"[[:blank:]]+[[:digit:]]+[[:blank:]]+"\""[^\"]*"\"".*$ { unit->scanPosition(yytext); } "//" { // C++-style comment int c; do { c = yyinput(); if(c == '\n') { unit->nextLine(); } } while(c != '\n' && c != EOF); } "/*" { // C-style comment string comment = yytext + 2; while(true) { int c = yyinput(); if(c == '\n') { comment += static_cast(c); unit->nextLine(); } else if(c == '*') { int next = yyinput(); if(next == '/') { break; } else { comment += static_cast(c); unput(next); } } else if(c == EOF) { unit->warning("EOF in comment"); break; } else { comment += static_cast(c); } } if(comment[0] == '*') { unit->setComment(comment); } } "::" { return ICE_SCOPE_DELIMITER; } "[" { return ICE_METADATA_OPEN; } "]" { return ICE_METADATA_CLOSE; } "[[" { return ICE_GLOBAL_METADATA_OPEN; } "]]" { return ICE_GLOBAL_METADATA_CLOSE; } {identifier}[[:space:]]*"(" { StringTokPtr ident = new StringTok; ident->v = *yytext == '\\' ? yytext + 1 : yytext; ident->v.erase(ident->v.find_first_of(" \t\v\n\r\f(")); *yylvalp = ident; checkIdentifier(ident->v); if(*yytext == '\\') { return ICE_IDENT_OP; } return checkKeyword(ident->v) == ICE_IDENTIFIER ? ICE_IDENT_OP : ICE_KEYWORD_OP; } {identifier} { StringTokPtr ident = new StringTok; ident->v = *yytext == '\\' ? yytext + 1 : yytext; *yylvalp = ident; checkIdentifier(ident->v); return *yytext == '\\' ? ICE_IDENTIFIER : checkKeyword(ident->v); } \" { StringTokPtr str = new StringTok; while(true) { char c = static_cast(yyinput()); if(c == '"') { break; } else if(c == EOF) { unit->error("EOF in string"); break; } else if(c == '\n') { unit->error("newline in string"); } else if(c == '\\') { char next = static_cast(yyinput()); switch(next) { case '\\': case '"': case '\'': { str->v += next; break; } case 'n': { str->v += '\n'; break; } case 'r': { str->v += '\r'; break; } case 't': { str->v += '\t'; break; } case 'v': { str->v += '\v'; break; } case 'f': { str->v += '\f'; break; } case 'a': { str->v += '\a'; break; } case 'b': { str->v += '\b'; break; } case '?': { str->v += '\?'; break; } case '0': case '1': case '2': case '3': { static string octalDigits = "01234567"; unsigned short us = next - '0'; if(octalDigits.find_first_of(next = static_cast(yyinput())) != string::npos) { us = us * 8 + next - '0'; if(octalDigits.find_first_of(next = static_cast(yyinput())) != string::npos) { us = us * 8 + next - '0'; } else { unput(next); } } else { unput(next); } if(us == 0) { unit->error("illegal NUL character in string constant"); } str->v += static_cast(us); break; } case 'x': { IceUtil::Int64 ull = 0; while(isxdigit(next = static_cast(yyinput()))) { ull *= 16; if(isdigit(next)) { ull += next - '0'; } else if(islower(next)) { ull += next - 'a' + 10; } else { ull += next - 'A' + 10; } } unput(next); if(ull == 0) { unit->error("illegal NUL character in string constant"); } str->v += static_cast(ull); break; } // TODO: add universal character names default: { str->v += c; unput(next); } } } else { str->v += c; } } *yylvalp = str; return ICE_STRING_LITERAL; } {integer_constant} { IntegerTokPtr itp = new IntegerTok; *yylvalp = itp; if(!IceUtil::stringToInt64(string(yytext), itp->v)) { assert(itp->v != 0); string msg = "integer constant `"; msg += yytext; msg += "' out of range"; unit->error(msg); } return ICE_INTEGER_LITERAL; } {floating_literal} { errno = 0; FloatingTokPtr ftp = new FloatingTok; *yylvalp = ftp; string literal(yytext); char lastChar = literal[literal.size() - 1]; if(lastChar == 'f' || lastChar == 'F') { literal = literal.substr(0, literal.size() - 1); // Clobber trailing 'f' or 'F' suffix } ftp->v = strtod(literal.c_str(), 0); if((ftp->v == HUGE_VAL || ftp->v == -HUGE_VAL) && errno == ERANGE) { string msg = "floating-point constant `"; msg += yytext; msg += "' too large (overflow)"; unit->error(msg); } else if(ftp->v == 0 && errno == ERANGE) { string msg = "floating-point constant `"; msg += yytext; msg += "' too small (underflow)"; unit->error(msg); } return ICE_FLOATING_POINT_LITERAL; } [[:space:]] { // Igore white-space if(yytext[0] == '\n') { unit->nextLine(); } } . { if(yytext[0] < 32 || yytext[0] > 126) { stringstream s; s << "illegal input character: '\\"; s.width(3); s.fill('0'); s << oct << static_cast(static_cast(yytext[0])); s << "'"; unit->error(s.str()); return BAD_CHAR; } return yytext[0]; } %% namespace Slice { // // initScanner() fills the keyword map with all keyword-token pairs. // void initScanner() { keywordMap["module"] = ICE_MODULE; keywordMap["class"] = ICE_CLASS; keywordMap["interface"] = ICE_INTERFACE; keywordMap["exception"] = ICE_EXCEPTION; keywordMap["struct"] = ICE_STRUCT; keywordMap["sequence"] = ICE_SEQUENCE; keywordMap["dictionary"] = ICE_DICTIONARY; keywordMap["enum"] = ICE_ENUM; keywordMap["out"] = ICE_OUT; keywordMap["extends"] = ICE_EXTENDS; keywordMap["implements"] = ICE_IMPLEMENTS; keywordMap["throws"] = ICE_THROWS; keywordMap["void"] = ICE_VOID; keywordMap["byte"] = ICE_BYTE; keywordMap["bool"] = ICE_BOOL; keywordMap["short"] = ICE_SHORT; keywordMap["int"] = ICE_INT; keywordMap["long"] = ICE_LONG; keywordMap["float"] = ICE_FLOAT; keywordMap["double"] = ICE_DOUBLE; keywordMap["string"] = ICE_STRING; keywordMap["Object"] = ICE_OBJECT; keywordMap["LocalObject"] = ICE_LOCAL_OBJECT; keywordMap["local"] = ICE_LOCAL; keywordMap["const"] = ICE_CONST; keywordMap["false"] = ICE_FALSE; keywordMap["true"] = ICE_TRUE; keywordMap["nonmutating"] = ICE_NONMUTATING; keywordMap["idempotent"] = ICE_IDEMPOTENT; } // // Check if an identifier is well-formed. // void checkIdentifier(const string& id) { if(id.find('_') != string::npos) { unit->error("illegal underscore in identifier `" + id + "'"); } // // Weed out identifiers with reserved suffixes. // static const string suffixBlacklist[] = { "Helper", "Holder", "Prx", "Ptr" }; for(size_t i = 0; i < sizeof(suffixBlacklist) / sizeof(*suffixBlacklist); ++i) { if(id.find(suffixBlacklist[i], id.size() - suffixBlacklist[i].size()) != string::npos) { unit->error("illegal identifier `" + id + "': `" + suffixBlacklist[i] + "' suffix is reserved"); } } } // // Check if an identifier looks like a keyword. // If the identifier is a keyword, return the // corresponding keyword token; otherwise, return // an identifier token. // int checkKeyword(string& id) { StringTokenMap::const_iterator pos = keywordMap.find(id); if(pos != keywordMap.end()) { if(pos->first != id) { string msg; msg = "illegal identifier: `" + id + "' differs from keyword `"; msg += pos->first + "' only in capitalization"; unit->error(msg); id = pos->first; } return pos->second; } return ICE_IDENTIFIER; } } IceE-trans-1.2.0/src/Slice/VbUtil.cpp0000774000076400007640000011540110560413774016570 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 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 #ifdef _WIN32 #include #endif #ifndef _WIN32 #include #endif using namespace std; using namespace Slice; using namespace IceUtil; static string lookupKwd(const string& name, int baseTypes, bool mangleCasts = false) { // // Keyword list. *Must* be kept in alphabetical order. // static const string keywordList[] = { "AddHandler", "AddressOf", "Alias", "And", "AndAlso", "Ansi", "As", "Assembly", "Auto", "Boolean", "ByRef", "Byte", "ByVal", "Call", "Case", "Catch", "CBool", "CByte", "CChar", "CDate", "CDbl", "CDec", "Char", "CInt", "Class", "CLng", "CObj", "Const", "CShort", "CSng", "CStr", "CType", "Date", "Decimal", "Declare", "Default", "Delegate", "Dim", "DirectCast", "Do", "Double", "Each", "Else", "ElseIf", "End", "EndIf", "Enum", "Erase", "Error", "Event", "Exit", "False", "Finally", "For", "Friend", "Function", "Get", "GetType", "GoSub", "GoTo", "Handles", "If", "Implements", "Imports", "In", "Inherits", "Integer", "Interface", "Is", "Let", "Lib", "Like", "Long", "Loop", "Me", "Mod", "Module", "MustInherit", "MustOverride", "MyBase", "MyClass", "Namespace", "New", "Next", "Not", "Nothing", "NotInheritable", "NotOverridable", "Object", "On", "Option", "Optional", "Or", "OrElse", "Overloads", "Overridable", "Overrides", "ParamArray", "Preserve", "Private", "Property", "Protected", "Public", "RaiseEvent", "ReadOnly", "ReDim", "REM", "RemoveHandler", "Resume", "Return", "Select", "Set", "Shadows", "Shared", "Short", "Single", "Static", "Step", "Stop", "String", "Structure", "Sub", "SyncLock", "Then", "Throw", "To", "True", "Try", "TypeOf", "Unicode", "Until", "Variant", "Wend", "When", "While", "With", "WithEvents", "WriteOnly", "Xor" }; bool found = binary_search(&keywordList[0], &keywordList[sizeof(keywordList) / sizeof(*keywordList)], name, Slice::CICompare()); if(found) { return "[" + name + "]"; } if(mangleCasts && (name == "checkedCast" || name == "uncheckedCast")) { return string(DotNet::manglePrefix) + name; } return Slice::DotNet::mangleName(name, baseTypes); } // // Split a scoped name into its components and return the components as a list of (unscoped) identifiers. // static StringList splitScopedName(const string& scoped) { assert(scoped[0] == ':'); StringList ids; string::size_type next = 0; string::size_type pos; while((pos = scoped.find("::", next)) != string::npos) { pos += 2; if(pos != scoped.size()) { string::size_type endpos = scoped.find("::", pos); if(endpos != string::npos) { ids.push_back(scoped.substr(pos, endpos - pos)); } } next = pos; } if(next != scoped.size()) { ids.push_back(scoped.substr(next)); } else { ids.push_back(""); } return ids; } // // If the passed name is a scoped name, return the identical scoped name, // but with all components that are VB keywords replaced by // their "[]"-surrounded version; otherwise, if the passed name is // not scoped, but a VB keyword, return the "[]"-surrounded name; // otherwise, check if the name is one of the method names of baseTypes; // if so, prefix it with _Ice_; otherwise, reutrn the name unchanged. // string Slice::VbGenerator::fixId(const string& name, int baseTypes, bool mangleCasts) { if(name.empty()) { return name; } if(name[0] != ':') { return lookupKwd(name, baseTypes, mangleCasts); } StringList ids = splitScopedName(name); StringList newIds; for(StringList::const_iterator i = ids.begin(); i != ids.end(); ++i) { newIds.push_back(lookupKwd(*i, baseTypes)); } stringstream result; for(StringList::const_iterator j = ids.begin(); j != ids.end(); ++j) { if(j != ids.begin()) { result << '.'; } result << *j; } return result.str(); } string Slice::VbGenerator::typeToString(const TypePtr& type) { if(!type) { return ""; } static const char* builtinTable[] = { "Byte", "Boolean", "Short", "Integer", "Long", "Single", "Double", "String", "Ice.Object", "Ice.ObjectPrx", "Ice.LocalObject" }; BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); if(builtin) { return builtinTable[builtin->kind()]; } ProxyPtr proxy = ProxyPtr::dynamicCast(type); if(proxy) { return fixId(proxy->_class()->scoped() + "Prx"); } SequencePtr seq = SequencePtr::dynamicCast(type); if(seq && !seq->hasMetaData("clr:collection")) { return typeToString(seq->type()) + "()"; } ContainedPtr contained = ContainedPtr::dynamicCast(type); if(contained) { return fixId(contained->scoped()); } return "???"; } bool Slice::VbGenerator::isValueType(const TypePtr& type) { BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); if(builtin) { switch(builtin->kind()) { case Builtin::KindString: case Builtin::KindObject: case Builtin::KindObjectProxy: case Builtin::KindLocalObject: { return false; break; } default: { return true; break; } } } StructPtr s = StructPtr::dynamicCast(type); if(s) { if(s->hasMetaData("clr:class")) { return false; } DataMemberList dm = s->dataMembers(); for(DataMemberList::const_iterator i = dm.begin(); i != dm.end(); ++i) { if(!isValueType((*i)->type())) { return false; } } return true; } if(EnumPtr::dynamicCast(type)) { return true; } return false; } void Slice::VbGenerator::writeMarshalUnmarshalCode(Output &out, const TypePtr& type, const string& param, bool marshal, bool streamingAPI, bool isOutParam, const string& patchParams) { string stream; if(marshal) { stream = streamingAPI ? "outS__" : "os__"; } else { stream = streamingAPI ? "inS__" : "is__"; } BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); if(builtin) { switch(builtin->kind()) { case Builtin::KindByte: { if(marshal) { out << nl << stream << ".writeByte(" << param << ')'; } else { out << nl << param << " = " << stream << ".readByte()"; } break; } case Builtin::KindBool: { if(marshal) { out << nl << stream << ".writeBool(" << param << ')'; } else { out << nl << param << " = " << stream << ".readBool()"; } break; } case Builtin::KindShort: { if(marshal) { out << nl << stream << ".writeShort(" << param << ')'; } else { out << nl << param << " = " << stream << ".readShort()"; } break; } case Builtin::KindInt: { if(marshal) { out << nl << stream << ".writeInt(" << param << ')'; } else { out << nl << param << " = " << stream << ".readInt()"; } break; } case Builtin::KindLong: { if(marshal) { out << nl << stream << ".writeLong(" << param << ')'; } else { out << nl << param << " = " << stream << ".readLong()"; } break; } case Builtin::KindFloat: { if(marshal) { out << nl << stream << ".writeFloat(" << param << ')'; } else { out << nl << param << " = " << stream << ".readFloat()"; } break; } case Builtin::KindDouble: { if(marshal) { out << nl << stream << ".writeDouble(" << param << ')'; } else { out << nl << param << " = " << stream << ".readDouble()"; } break; } case Builtin::KindString: { if(marshal) { out << nl << stream << ".writeString(" << param << ')'; } else { out << nl << param << " = " << stream << ".readString()"; } break; } case Builtin::KindObject: { if(marshal) { out << nl << stream << ".writeObject(" << param << ')'; } else { if(isOutParam) { out << nl << "Dim " << param << "_PP As IceInternal.ParamPatcher = New IceInternal.ParamPatcher(GetType(Ice.Object), " << "\"::Ice::Object\")"; if(streamingAPI) { out << nl << stream << ".readObject(CType(" << param << "_PP, Ice.ReadObjectCallback))"; } else { out << nl << stream << ".readObject(" << param << "_PP)"; } } else { if(streamingAPI) { out << nl << stream << ".readObject(CType(New Patcher__(" << patchParams << ", Ice.ReadObjectCallback)))"; } else { out << nl << stream << ".readObject(New Patcher__(" << patchParams << "))"; } } } break; } case Builtin::KindObjectProxy: { if(marshal) { out << nl << stream << ".writeProxy(" << param << ')'; } else { out << nl << param << " = " << stream << ".readProxy()"; } break; } case Builtin::KindLocalObject: { assert(false); break; } } return; } ProxyPtr prx = ProxyPtr::dynamicCast(type); if(prx) { ContainedPtr contained = ContainedPtr::dynamicCast(type); string helperName = fixId((contained ? contained->scoped() : typeToString(type)) + "Helper"); if(marshal) { out << nl << helperName << ".write"; if(!streamingAPI) { out << "__"; } out << '(' << stream << ", " << param << ')'; } else { out << nl << param << " = " << helperName << ".read"; if(!streamingAPI) { out << "__"; } out << "(" << stream << ')'; } return; } ClassDeclPtr cl = ClassDeclPtr::dynamicCast(type); if(cl) { if(marshal) { out << nl << stream << ".writeObject(" << param << ")"; } else { if(isOutParam) { ContainedPtr contained = ContainedPtr::dynamicCast(type); out << nl << "Dim " << param << "_PP As IceInternal.ParamPatcher = New IceInternal.ParamPatcher(GetType(" << typeToString(type) << "), \"" << contained->scoped() << "\")"; if(streamingAPI) { out << nl << stream << ".readObject(CType(" << param << "_PP, Ice.ReadObjectCallback))"; } else { out << nl << stream << ".readObject(" << param << "_PP)"; } } else { if(streamingAPI) { out << nl << stream << ".readObject(New Patcher__(CType(" << patchParams << ", Ice.ReadObjectCallback)))"; } else { out << nl << stream << ".readObject(New Patcher__(" << patchParams << "))"; } } } return; } StructPtr st = StructPtr::dynamicCast(type); if(st) { if(marshal) { if(streamingAPI) { out << nl << param << ".ice_write(" << stream << ')'; } else { out << nl << param << ".write__(" << stream << ')'; } } else { string typeS = typeToString(type); out << nl << param << " = New " << typeS; if(streamingAPI) { out << nl << param << ".ice_read(" << stream << ")"; } else { out << nl << param << ".read__(" << stream << ")"; } } return; } EnumPtr en = EnumPtr::dynamicCast(type); if(en) { string func; string cast; size_t sz = en->getEnumerators().size(); if(sz <= 0x7f) { func = marshal ? "writeByte" : "readByte"; cast = marshal ? string("Byte") : fixId(en->scoped()); } else if(sz <= 0x7fff) { func = marshal ? "writeShort" : "readShort"; cast = marshal ? string("Short") : fixId(en->scoped()); } else { func = marshal ? "writeInt" : "readInt"; cast = marshal ? string("Integer") : fixId(en->scoped()); } if(marshal) { out << nl << stream << '.' << func << "(CType(" << param << ", " << cast << "))"; } else { out << nl << param << " = CType(" << stream << '.' << func << "(), " << cast << ')'; } return; } SequencePtr seq = SequencePtr::dynamicCast(type); if(seq) { writeSequenceMarshalUnmarshalCode(out, seq, param, marshal, streamingAPI); return; } assert(ConstructedPtr::dynamicCast(type)); string helperName = fixId(ContainedPtr::dynamicCast(type)->scoped() + "Helper"); if(marshal) { out << nl << helperName << ".write(" << stream << ", " << param << ')'; } else { out << nl << param << " = " << helperName << ".read(" << stream << ')'; } } void Slice::VbGenerator::writeSequenceMarshalUnmarshalCode(Output& out, const SequencePtr& seq, const string& param, bool marshal, bool streamingAPI) { string stream; if(marshal) { stream = streamingAPI ? "outS__" : "os__"; } else { stream = streamingAPI ? "inS__" : "is__"; } TypePtr type = seq->type(); string typeS = typeToString(type); bool isArray = !seq->hasMetaData("clr:collection"); string limitID = isArray ? "Length" : "Count"; BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); if(builtin) { switch(builtin->kind()) { case Builtin::KindObject: case Builtin::KindObjectProxy: { if(marshal) { out << nl << "If " << param << " Is Nothing Then"; out.inc(); out << nl << stream << ".writeSize(0)"; out.dec(); out << nl << "Else"; out.inc(); out << nl << stream << ".writeSize(" << param << '.' << limitID << ")"; out << nl << "For ix__ As Integer = 0 To " << param << '.' << limitID << " - 1"; out.inc(); string func = builtin->kind() == Builtin::KindObject ? "writeObject" : "writeProxy"; out << nl << stream << '.' << func << '(' << param << "(ix__))"; out.dec(); out << nl << "Next"; out.dec(); out << nl << "End If"; } else { out << nl << "For block__ As Integer = 0 To 0"; out.inc(); out << nl << "Dim lenx__ As Integer = " << stream << ".readSize()"; if(!streamingAPI) { if(builtin->isVariableLength()) { out << nl << stream << ".startSeq(lenx__, " << static_cast(builtin->minWireSize()) << ")"; } else { out << nl << stream << ".checkFixedSeq(lenx__, " << static_cast(builtin->minWireSize()) << ")"; } } out << nl << param << " = New "; if(builtin->kind() == Builtin::KindObject) { if(isArray) { out << "Ice.Object(lenx__ - 1) {}"; } else { out << typeToString(seq); } out << nl << "For ix__ As Integer = 0 To lenx__ - 1"; out.inc(); if(streamingAPI) { out << nl << stream << ".readObject(CType(New IceInternal.SequencePatcher(" << param << ", GetType(Ice.Object), ix__), Ice.ReadObjectCallback))"; } else { out << nl << stream << ".readObject(New IceInternal.SequencePatcher(" << param << ", GetType(Ice.Object), ix__))"; } out.dec(); out << nl << "Next"; } else { if(isArray) { out << "Ice.ObjectPrx(lenx__ - 1) {}"; } else { out << typeToString(seq); } out << nl << "For ix__ As Integer = 0 To lenx__ - 1"; out.inc(); if(isArray) { out << nl << param << "(ix__) = " << stream << ".readProxy()"; } else { out << nl << "Dim val__ As Ice.ObjectPrx = New Ice.ObjectPrxHelperBase"; out << nl << "val__ = " << stream << ".readProxy()"; out << nl << param << ".Add(val__)"; } out.dec(); out << nl << "Next"; } if(!streamingAPI && builtin->isVariableLength()) { out << nl << stream << ".checkSeq()"; out << nl << stream << ".endElement()"; out << nl << stream << ".endSeq(lenx__)"; } out.dec(); out << nl << "Next"; } break; } default: { string marshalName = builtin->kindAsString(); marshalName[0] = toupper(marshalName[0]); if(marshal) { out << nl << stream << ".write" << marshalName << "Seq(" << param; if(!isArray) { out << ".ToArray()"; } out << ')'; } else { if(!isArray) { out << nl << param << " = New " << fixId(seq->scoped()) << '(' << stream << ".read" << marshalName << "Seq())"; } else { out << nl << param << " = " << stream << ".read" << marshalName << "Seq()"; } } break; } } return; } ClassDeclPtr cl = ClassDeclPtr::dynamicCast(type); if(cl) { out << nl << "For block__ As Integer = 0 To 0"; out.inc(); if(marshal) { out << nl << "If " << param << " Is Nothing"; out.inc(); out << nl << stream << ".writeSize(0)"; out.dec(); out << nl << "Else"; out.inc(); out << nl << stream << ".writeSize(" << param << '.' << limitID << ")"; out << nl << "For ix__ As Integer = 0 To " << param << '.' << limitID << " - 1"; out.inc(); out << nl << stream << ".writeObject(" << param << "(ix__))"; out.dec(); out << nl << "Next"; out.dec(); out << nl << "End If"; } else { out << nl << "Dim szx__ As Integer = " << stream << ".readSize()"; if(!streamingAPI) { if(type->isVariableLength()) { out << nl << stream << ".startSeq(szx__, " << static_cast(type->minWireSize()) << ')'; } else { out << nl << stream << ".checkFixedSeq(szx__, " << static_cast(type->minWireSize()) << ')'; } } out << nl << param << " = New "; if(isArray) { out << toArrayAlloc(typeS + "()", "szx__ - 1") << " {}"; } else { out << fixId(seq->scoped()) << "(szx__)"; } out << nl << "For ix__ As Integer = 0 To szx__ - 1"; out.inc(); out << nl << "Dim spx__ As IceInternal.SequencePatcher = New IceInternal.SequencePatcher(" << param << ", " << "GetType(" << typeS << "), ix__)"; if(streamingAPI) { out << nl << stream << ".readObject(CType(spx__, Ice.ReadObjectCallback))"; } else { out << nl << stream << ".readObject(spx__)"; } if(!streamingAPI && type->isVariableLength()) { out << nl << stream << ".checkSeq()"; out << nl << stream << ".endElement()"; } out.dec(); out << nl << "Next"; if(!streamingAPI && type->isVariableLength()) { out << nl << stream << ".endSeq(szx__)"; } } out.dec(); out << nl << "Next"; return; } StructPtr st = StructPtr::dynamicCast(type); if(st) { out << nl << "For block__ As Integer = 0 To 0"; out.inc(); if(marshal) { out << nl << "If " << param << " Is Nothing"; out.inc(); out << nl << stream << ".writeSize(0)"; out.dec(); out << nl << "Else"; out.inc(); out << nl << stream << ".writeSize(" << param << '.' << limitID << ")"; out << nl << "For ix__ As Integer = 0 To " << param << '.' << limitID << " - 1"; out.inc(); if(streamingAPI) { out << nl << param << "(ix__).ice_write(" << stream << ")"; } else { out << nl << param << "(ix__).write__(" << stream << ")"; } out.dec(); out << nl << "Next"; out.dec(); out << nl << "End If"; } else { out << nl << "Dim szx__ As Integer = " << stream << ".readSize()"; if(!streamingAPI) { if(type->isVariableLength()) { out << nl << stream << ".startSeq(szx__, " << static_cast(type->minWireSize()) << ')'; } else { out << nl << stream << ".checkFixedSeq(szx__, " << static_cast(type->minWireSize()) << ')'; } } out << nl << param << " = New "; if(isArray) { out << toArrayAlloc(typeS + "()", "szx__ - 1") << " {}"; } else { out << fixId(seq->scoped()) << "(szx__)"; } out << nl << "For ix__ As Integer = 0 To szx__ - 1"; out.inc(); if(isArray) { if(!isValueType(st)) { out << nl << param << "(ix__) = New " << typeS; } if(streamingAPI) { out << nl << param << "(ix__).ice_read(" << stream << ")"; } else { out << nl << param << "(ix__).read__(" << stream << ")"; } } else { out << nl << "Dim val__ As " << typeS << " = New " << typeS; if(streamingAPI) { out << nl << "val__.ice_read(" << stream << ')'; } else { out << nl << "val__.read__(" << stream << ')'; } out << nl << param << ".Add(val__)"; } if(!streamingAPI && type->isVariableLength()) { out << nl << stream << ".checkSeq()"; out << nl << stream << ".endElement()"; } out.dec(); out << nl << "Next"; if(!streamingAPI && type->isVariableLength()) { out << nl << stream << ".endSeq(szx__)"; } } out.dec(); out << nl << "Next"; return; } EnumPtr en = EnumPtr::dynamicCast(type); if(en) { out << nl << "For block__ As Integer = 0 To 0"; out.inc(); if(marshal) { out << nl << "If " << param << " Is Nothing"; out.inc(); out << nl << stream << ".writeSize(0)"; out.dec(); out << nl << "Else"; out.inc(); out << nl << stream << ".writeSize(" << param << '.'<< limitID << ')'; out << nl << "For ix__ As Integer = 0 To " << param << '.' << limitID << " - 1"; out.inc(); out << nl << stream << ".writeByte(CType(" << param << "(ix__), Byte))"; out.dec(); out << nl << "Next"; out.dec(); out << nl << "End If"; } else { out << nl << "Dim szx__ As Integer = " << stream << ".readSize()"; if(!streamingAPI) { out << nl << stream << ".checkFixedSeq(szx__, " << static_cast(type->minWireSize()) << ')'; } out << nl << param << " = New "; if(isArray) { out << toArrayAlloc(typeS + "()", "szx__ - 1") << " {}"; } else { out << fixId(seq->scoped()) << "(szx__)"; } out << nl << "For ix__ As Integer = 0 To szx__ - 1"; out.inc(); if(isArray) { out << nl << param << "(ix__) = CType(" << stream << ".readByte(), " << typeS << ')'; } else { out << nl << param << ".Add(CType(" << stream << ".readByte(), " << typeS << "))"; } out.dec(); out << nl << "Next"; } out.dec(); out << nl << "Next"; return; } string helperName; if(ProxyPtr::dynamicCast(type)) { helperName = fixId(ProxyPtr::dynamicCast(type)->_class()->scoped() + "PrxHelper"); } else { helperName = fixId(ContainedPtr::dynamicCast(type)->scoped() + "Helper"); } string func; if(marshal) { func = "write"; if(!streamingAPI && ProxyPtr::dynamicCast(type)) { func += "__"; } out << nl << "If " << param << " Is Nothing"; out.inc(); out << nl << stream << ".writeSize(0)"; out.dec(); out << nl << "Else"; out.inc(); out << nl << stream << ".writeSize(" << param << '.' << limitID << ")"; out << nl << "For ix__ As Integer = 0 To " << param << '.' << limitID << " - 1"; out.inc(); out << nl << helperName << '.' << func << '(' << stream << ", " << param << "(ix__))"; out.dec(); out << nl << "Next"; out.dec(); out << nl << "End If"; } else { func = "read"; if(!streamingAPI && ProxyPtr::dynamicCast(type)) { func += "__"; } out << nl << "For block__ As Integer = 0 To 0"; out.inc(); out << nl << "Dim szx__ As Integer = " << stream << ".readSize()"; if(!streamingAPI) { if(type->isVariableLength()) { out << nl << stream << ".startSeq(szx__, " << static_cast(type->minWireSize()) << ")"; } else { out << nl << stream << ".checkFixedSeq(szx__, " << static_cast(type->minWireSize()) << ")"; } } out << nl << param << " = New "; if(isArray) { out << toArrayAlloc(typeS + "()", "szx__ - 1") << " {}"; } else { out << fixId(seq->scoped()) << "(szx__)"; } out << nl << "For ix__ As Integer = 0 To szx__ - 1"; out.inc(); if(isArray) { out << nl << param << "(ix__) = " << helperName << '.' << func << '(' << stream << ")"; } else { out << nl << param << ".Add(" << helperName << '.' << func << '(' << stream << "))"; } if(!streamingAPI && type->isVariableLength()) { if(!SequencePtr::dynamicCast(type)) { out << nl << stream << ".checkSeq()"; } out << nl << stream << ".endElement()"; } out.dec(); out << nl << "Next"; if(!streamingAPI && type->isVariableLength()) { out << nl << stream << ".endSeq(szx__)"; } out.dec(); out << nl << "Next"; } return; } string Slice::VbGenerator::toArrayAlloc(const string& decl, const string& sz) { int count = 0; string::size_type pos = decl.size(); while(pos > 1 && decl.substr(pos - 2, 2) == "()") { ++count; pos -= 2; } assert(count > 0); ostringstream o; o << decl.substr(0, pos) << '(' << sz << ')' << decl.substr(pos + 2); return o.str(); } void Slice::VbGenerator::validateMetaData(const UnitPtr& u) { MetaDataVisitor visitor; u->visit(&visitor, false); } Slice::VbGenerator::MetaDataVisitor::MetaDataVisitor() : _globalMetaDataDone(false) { } bool Slice::VbGenerator::MetaDataVisitor::visitModuleStart(const ModulePtr& p) { if(!_globalMetaDataDone) { // // Validate global metadata. // DefinitionContextPtr dc = p->definitionContext(); assert(dc); StringList globalMetaData = dc->getMetaData(); string file = dc->filename(); static const string prefix = "vb:"; for(StringList::const_iterator q = globalMetaData.begin(); q != globalMetaData.end(); ++q) { string s = *q; if(_history.count(s) == 0) { if(s.find(prefix) == 0) { static const string attributePrefix = "vb:attribute:"; if(s.find(attributePrefix) != 0 || s.size() == attributePrefix.size()) { cout << file << ": warning: ignoring invalid global metadata `" << s << "'" << endl; } } _history.insert(s); } } _globalMetaDataDone = true; } validate(p); return true; } void Slice::VbGenerator::MetaDataVisitor::visitModuleEnd(const ModulePtr&) { } void Slice::VbGenerator::MetaDataVisitor::visitClassDecl(const ClassDeclPtr& p) { validate(p); } bool Slice::VbGenerator::MetaDataVisitor::visitClassDefStart(const ClassDefPtr& p) { validate(p); return true; } void Slice::VbGenerator::MetaDataVisitor::visitClassDefEnd(const ClassDefPtr&) { } bool Slice::VbGenerator::MetaDataVisitor::visitExceptionStart(const ExceptionPtr& p) { validate(p); return true; } void Slice::VbGenerator::MetaDataVisitor::visitExceptionEnd(const ExceptionPtr&) { } bool Slice::VbGenerator::MetaDataVisitor::visitStructStart(const StructPtr& p) { validate(p); return true; } void Slice::VbGenerator::MetaDataVisitor::visitStructEnd(const StructPtr&) { } void Slice::VbGenerator::MetaDataVisitor::visitOperation(const OperationPtr& p) { validate(p); } void Slice::VbGenerator::MetaDataVisitor::visitParamDecl(const ParamDeclPtr& p) { validate(p); } void Slice::VbGenerator::MetaDataVisitor::visitDataMember(const DataMemberPtr& p) { validate(p); } void Slice::VbGenerator::MetaDataVisitor::visitSequence(const SequencePtr& p) { validate(p); } void Slice::VbGenerator::MetaDataVisitor::visitDictionary(const DictionaryPtr& p) { validate(p); } void Slice::VbGenerator::MetaDataVisitor::visitEnum(const EnumPtr& p) { validate(p); } void Slice::VbGenerator::MetaDataVisitor::visitConst(const ConstPtr& p) { validate(p); } void Slice::VbGenerator::MetaDataVisitor::validate(const ContainedPtr& cont) { DefinitionContextPtr dc = cont->definitionContext(); assert(dc); string file = dc->filename(); StringList localMetaData = cont->getMetaData(); StringList::const_iterator p; for(p = localMetaData.begin(); p != localMetaData.end(); ++p) { string s = *p; if(s.find("vb:") == 0) // TODO: remove this statement once "vb:" is a hard error. { if(SequencePtr::dynamicCast(cont)) { if(s.substr(3) == "collection") { cout << file << ":" << cont->line() << ": warning: `vb:' metadata prefix is deprecated; " << "use `clr:' instead" << endl; cont->addMetaData("clr:collection"); } } else if(StructPtr::dynamicCast(cont)) { if(s.substr(3) == "class") { cout << file << ":" << cont->line() << ": warning: `vb:' metadata prefix is deprecated; " << "use `clr:' instead" << endl; cont->addMetaData("clr:class"); } } else if(s.find("vb:attribute:") == 0) { ; // Do nothing, "vb:attribute:" is OK } else { cout << file << ":" << cont->line() << ": warning: ignoring invalid metadata `" << s << "'" << endl; } } // End TODO string prefix = "clr:"; if(_history.count(s) == 0) { if(s.find(prefix) == 0) { if(SequencePtr::dynamicCast(cont)) { if(s.substr(prefix.size()) == "collection") { continue; } } if(StructPtr::dynamicCast(cont)) { if(s.substr(prefix.size()) == "class") { continue; } if(s.substr(prefix.size()) == "property") { continue; } } if(ClassDefPtr::dynamicCast(cont)) { if(s.substr(prefix.size()) == "property") { continue; } } cout << file << ":" << cont->line() << ": warning: ignoring invalid metadata `" << s << "'" << endl; } _history.insert(s); } prefix = "vb:"; if(_history.count(s) == 0) { if(s.find(prefix) == 0) { if(s.substr(prefix.size()) == "attribute:") { continue; } cout << file << ":" << cont->line() << ": warning: ignoring invalid metadata `" << s << "'" << endl; } _history.insert(s); } } } IceE-trans-1.2.0/src/Slice/Preprocessor.cpp0000664000076400007640000002177410561612334020052 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 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 #ifndef _WIN32 # include #endif using namespace std; using namespace Slice; Slice::Preprocessor::Preprocessor(const string& path, const string& fileName, const string& args) : _path(path), _fileName(fileName), _args(args), _cppHandle(0) { } Slice::Preprocessor::~Preprocessor() { if(_cppHandle) { close(); } } string Slice::Preprocessor::getBaseName() { string base(_fileName); string suffix; string::size_type pos = base.rfind('.'); if(pos != string::npos) { base.erase(pos); } return base; } string Slice::Preprocessor::addQuotes(const string& arg) { // // Add quotes around the given argument to ensure that arguments // with spaces will be preserved as a single argument. We also // escape the "\" character to ensure that we don't end up with a // \" at the end of the string. // return "\"" + IceUtil::escapeString(arg, "\\") + "\""; } string Slice::Preprocessor::normalizeIncludePath(const string& path) { string result = path; replace(result.begin(), result.end(), '\\', '/'); string::size_type pos; while((pos = result.find("//")) != string::npos) { result.replace(pos, 2, "/"); } if(result == "/" || result.size() == 3 && isalpha(result[0]) && result[1] == ':' && result[2] == '/') { return result; } if(result.size() > 1 && result[result.size() - 1] == '/') { result.erase(result.size() - 1); } return "\"" + result + "\""; } FILE* Slice::Preprocessor::preprocess(bool keepComments) { if(!checkInputFile()) { return 0; } string cmd = searchIceCpp(); if(cmd.empty()) { return 0; } if(keepComments) { cmd += " -C"; } cmd += " " + _args + " \"" + _fileName + "\""; // // Open a pipe for reading to redirect icecpp output to _cppHandle. // #ifdef _WIN32 _cppHandle = _popen(cmd.c_str(), "r"); #else _cppHandle = popen(cmd.c_str(), "r"); #endif return _cppHandle; } void Slice::Preprocessor::printMakefileDependencies(Language lang) { if(!checkInputFile()) { return; } string cmd = searchIceCpp(); if(cmd.empty()) { return; } cmd += " -M " + _args + " \"" + _fileName + "\""; #ifdef _WIN32 FILE* cppHandle = _popen(cmd.c_str(), "r"); #else FILE* cppHandle = popen(cmd.c_str(), "r"); #endif /* * icecpp emits dependencies in any of the following formats, depending on the * length of the filenames: * * x.cpp: /path/x.ice /path/y.ice * * x.cpp: /path/x.ice \ * /path/y.ice * * x.cpp: /path/x.ice /path/y.ice \ * /path/z.ice * * x.cpp: \ * /path/x.ice * * x.cpp: \ * /path/x.ice \ * /path/y.ice * * Spaces embedded within filenames are escaped with a backslash. Note that * Windows filenames may contain colons. * */ switch(lang) { case CPlusPlus: { char buf[1024]; while(fgets(buf, static_cast(sizeof(buf)), cppHandle) != NULL) { fputs(buf, stdout); } break; } case Java: { // // We want to shift the files left one position, so that // "x.cpp: x.ice y.ice" becomes "x.ice: y.ice". // // Since the pipe input can be returned a line at a time, we collect // all of the output into one string before manipulating it. // string deps; char buf[1024]; while(fgets(buf, static_cast(sizeof(buf)), cppHandle) != NULL) { deps.append(buf, strlen(buf)); } // // Remove the first file. // string::size_type start = deps.find(".cpp:"); assert(start != string::npos); start = deps.find_first_not_of(" \t\r\n\\", start + 5); // Skip to beginning of next file. assert(start != string::npos); deps.erase(0, start); // // Find end of next file. // string::size_type pos = 0; while((pos = deps.find_first_of(" :\t\r\n\\", pos + 1)) != string::npos) { if(deps[pos] == ':') { deps.insert(pos, 1, '\\'); // Escape colons. ++pos; } else if(deps[pos] == '\\') // Ignore escaped characters. { ++pos; } else { break; } } if(pos == string::npos) { deps.append(":"); } else { deps.insert(pos, 1, ':'); } fputs(deps.c_str(), stdout); break; } case CSharp: { // // Change .cpp suffix to .cs suffix. // char buf[1024]; while(fgets(buf, static_cast(sizeof(buf)), cppHandle) != NULL) { char* dot; char* colon = strchr(buf, ':'); if(colon != NULL) { *colon = '\0'; dot = strrchr(buf, '.'); *colon = ':'; if(dot != NULL) { if(strncmp(dot, ".cpp:", 5) == 0) { *dot = '\0'; fputs(buf, stdout); fputs(".cs", stdout); fputs(colon, stdout); continue; } } } fputs(buf, stdout); } break; } case VisualBasic: { // // Change .cpp suffix to .vb suffix. // char buf[1024]; while(fgets(buf, static_cast(sizeof(buf)), cppHandle) != NULL) { char* dot; char* colon = strchr(buf, ':'); if(colon != NULL) { *colon = '\0'; dot = strrchr(buf, '.'); *colon = ':'; if(dot != NULL) { if(strncmp(dot, ".cpp:", 5) == 0) { *dot = '\0'; fputs(buf, stdout); fputs(".vb", stdout); fputs(colon, stdout); continue; } } } fputs(buf, stdout); } break; } default: { abort(); break; } } } bool Slice::Preprocessor::close() { assert(_cppHandle); #ifndef _WIN32 int status = pclose(_cppHandle); _cppHandle = 0; if(WIFEXITED(status) && WEXITSTATUS(status) != 0) { return false; } #else int status = _pclose(_cppHandle); _cppHandle = 0; if(status != 0) { return false; } #endif return true; } bool Slice::Preprocessor::checkInputFile() { string base(_fileName); string suffix; string::size_type pos = base.rfind('.'); if(pos != string::npos) { suffix = base.substr(pos); transform(suffix.begin(), suffix.end(), suffix.begin(), ::tolower); } if(suffix != ".ice") { cerr << _path << ": input files must end with `.ice'" << endl; return false; } ifstream test(_fileName.c_str()); if(!test) { cerr << _path << ": can't open `" << _fileName << "' for reading" << endl; return false; } test.close(); return true; } string Slice::Preprocessor::searchIceCpp() { #ifndef _WIN32 const char* icecpp = "icecpp"; #else const char* icecpp = "icecpp.exe"; #endif string::size_type pos = _path.find_last_of("/\\"); if(pos != string::npos) { string path = _path.substr(0, pos + 1); path += icecpp; struct stat st; if(stat(path.c_str(), &st) == 0) { #ifndef _WIN32 if(st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) #else if(st.st_mode & (S_IEXEC)) #endif { return path; } } } return icecpp; } IceE-trans-1.2.0/src/Slice/Parser.cpp0000664000076400007640000040432710560413774016625 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 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 #ifdef __BCPLUSPLUS__ # include #endif using namespace std; using namespace Slice; extern FILE* slice_in; extern int slice_debug; namespace Slice { Unit* unit; } // ---------------------------------------------------------------------- // toLower() helper function // ---------------------------------------------------------------------- static void toLower(string& s) { transform(s.begin(), s.end(), s.begin(), ::tolower); } // ---------------------------------------------------------------------- // DefinitionContext // ---------------------------------------------------------------------- Slice::DefinitionContext::DefinitionContext(int includeLevel, const StringList& metaData) : _includeLevel(includeLevel), _metaData(metaData), _seenDefinition(false) { } string Slice::DefinitionContext::filename() const { return _filename; } int Slice::DefinitionContext::includeLevel() const { return _includeLevel; } bool Slice::DefinitionContext::seenDefinition() const { return _seenDefinition; } void Slice::DefinitionContext::setFilename(const string& filename) { _filename = filename; } void Slice::DefinitionContext::setSeenDefinition() { _seenDefinition = true; } bool Slice::DefinitionContext::hasMetaData() const { return !_metaData.empty(); } void Slice::DefinitionContext::setMetaData(const StringList& metaData) { _metaData = metaData; } string Slice::DefinitionContext::findMetaData(const string& prefix) const { for(StringList::const_iterator p = _metaData.begin(); p != _metaData.end(); ++p) { if((*p).find(prefix) == 0) { return *p; } } return string(); } StringList Slice::DefinitionContext::getMetaData() const { return _metaData; } // ---------------------------------------------------------------------- // SyntaxTreeBase // ---------------------------------------------------------------------- void Slice::SyntaxTreeBase::destroy() { _unit = 0; } UnitPtr Slice::SyntaxTreeBase::unit() const { return _unit; } DefinitionContextPtr Slice::SyntaxTreeBase::definitionContext() const { return _definitionContext; } void Slice::SyntaxTreeBase::visit(ParserVisitor*, bool) { } Slice::SyntaxTreeBase::SyntaxTreeBase(const UnitPtr& unit) : _unit(unit) { if(_unit) { _definitionContext = unit->currentDefinitionContext(); } } // ---------------------------------------------------------------------- // Type // ---------------------------------------------------------------------- Slice::Type::Type(const UnitPtr& unit) : SyntaxTreeBase(unit) { } // ---------------------------------------------------------------------- // Builtin // ---------------------------------------------------------------------- bool Slice::Builtin::isLocal() const { return _kind == KindLocalObject; } string Slice::Builtin::typeId() const { switch(_kind) { case KindByte: { return "byte"; break; } case KindBool: { return "bool"; break; } case KindShort: { return "short"; break; } case KindInt: { return "int"; break; } case KindLong: { return "long"; break; } case KindFloat: { return "float"; break; } case KindDouble: { return "double"; break; } case KindString: { return "string"; break; } case KindObject: { return "::Ice::Object"; break; } case KindObjectProxy: { return "::Ice::Object*"; break; } case KindLocalObject: { return "::Ice::LocalObject"; break; } } assert(false); return ""; // Keep the compiler happy. } bool Slice::Builtin::usesClasses() const { return _kind == KindObject; } size_t Slice::Builtin::minWireSize() const { static size_t minWireSizeTable[] = { 1, // KindByte 1, // KindBool 2, // KindShort 4, // KindInt 8, // KindLong 4, // KindFloat 8, // KindDouble 1, // KindString: at least one byte for an empty string. 4, // KindObject: at least 4 bytes (to marshal an index instead of an instance). 2 // KindObjectProxy: at least an empty identity for a nil proxy, that is, 2 bytes. }; assert(_kind != KindLocalObject); return minWireSizeTable[_kind]; } bool Slice::Builtin::isVariableLength() const { return _kind == KindString || _kind == KindObject || _kind == KindObjectProxy; } Builtin::Kind Slice::Builtin::kind() const { return _kind; } string Builtin::kindAsString() const { return builtinTable[_kind]; } const char* Slice::Builtin::builtinTable[] = { "byte", "bool", "short", "int", "long", "float", "double", "string", "Object", "Object*", "LocalObject" }; Slice::Builtin::Builtin(const UnitPtr& unit, Kind kind) : SyntaxTreeBase(unit), Type(unit), _kind(kind) { // // Builtin types do not have a definition context. // _definitionContext = 0; } // ---------------------------------------------------------------------- // Contained // ---------------------------------------------------------------------- ContainerPtr Slice::Contained::container() const { return _container; } string Slice::Contained::name() const { return _name; } string Slice::Contained::scoped() const { return _scoped; } string Slice::Contained::scope() const { string::size_type idx = _scoped.rfind("::"); assert(idx != string::npos); return string(_scoped, 0, idx + 2); } string Slice::Contained::flattenedScope() const { string s = scope(); string flattenedScope; for(string::const_iterator r = s.begin(); r != s.end(); ++r) { flattenedScope += ((*r) == ':') ? '_' : *r; } return flattenedScope; } string Slice::Contained::file() const { return _file; } string Slice::Contained::line() const { return _line; } string Slice::Contained::comment() const { return _comment; } int Slice::Contained::includeLevel() const { return _includeLevel; } void Slice::Contained::updateIncludeLevel() { _includeLevel = min(_includeLevel, _unit->currentIncludeLevel()); } bool Slice::Contained::hasMetaData(const string& meta) const { return find(_metaData.begin(), _metaData.end(), meta) != _metaData.end(); } bool Slice::Contained::findMetaData(const string& prefix, string& meta) const { for(list::const_iterator p = _metaData.begin(); p != _metaData.end(); ++p) { if(p->find(prefix) == 0) { meta = *p; return true; } } return false; } list Slice::Contained::getMetaData() const { return _metaData; } void Slice::Contained::setMetaData(const list& metaData) { _metaData = metaData; } // // TODO: remove this method once "cs:" and "vb:" prefix are hard errors. // void Slice::Contained::addMetaData(const string& s) { _metaData.push_back(s); } bool Slice::Contained::operator<(const Contained& rhs) const { return _scoped < rhs._scoped; } bool Slice::Contained::operator==(const Contained& rhs) const { return _scoped == rhs._scoped; } bool Slice::Contained::operator!=(const Contained& rhs) const { return _scoped != rhs._scoped; } Slice::Contained::Contained(const ContainerPtr& container, const string& name) : SyntaxTreeBase(container->unit()), _container(container), _name(name) { ContainedPtr cont = ContainedPtr::dynamicCast(_container); if(cont) { _scoped = cont->scoped(); } _scoped += "::" + _name; assert(_unit); _unit->addContent(this); _file = _unit->currentFile(); ostringstream s; s << _unit->currentLine(); _line = s.str(); _comment = _unit->currentComment(); _includeLevel = _unit->currentIncludeLevel(); } // ---------------------------------------------------------------------- // Container // ---------------------------------------------------------------------- void Slice::Container::destroy() { for_each(_contents.begin(), _contents.end(), ::IceUtil::voidMemFun(&SyntaxTreeBase::destroy)); _contents.clear(); _introducedMap.clear(); SyntaxTreeBase::destroy(); } ModulePtr Slice::Container::createModule(const string& name) { checkPrefix(name); ContainedList matches = _unit->findContents(thisScope() + name); matches.sort(); // Modules can occur many times... matches.unique(); // ... but we only want one instance of each. for(ContainedList::const_iterator p = matches.begin(); p != matches.end(); ++p) { bool differsOnlyInCase = !_unit->caseSensitive() && matches.front()->name() != name; ModulePtr module = ModulePtr::dynamicCast(*p); if(module) { if(differsOnlyInCase) // Modules can be reopened only if they are capitalized correctly. { string msg = "module `" + name + "' is capitalized inconsistently with its previous name: `"; msg += module->name() + "'"; _unit->error(msg); return 0; } } else if(!differsOnlyInCase) { string msg = "redefinition of " + matches.front()->kindOf() + " `" + matches.front()->name(); msg += "' as module"; _unit->error(msg); return 0; } else { string msg = "module `" + name + "' differs only in capitalization from "; msg += matches.front()->kindOf() + " name `" + matches.front()->name() + "'"; _unit->error(msg); return 0; } } if(!nameIsLegal(name, "module")) { return 0; } ModulePtr q = new Module(this, name); _contents.push_back(q); return q; } ClassDefPtr Slice::Container::createClassDef(const string& name, bool intf, const ClassList& bases, bool local) { checkPrefix(name); ContainedList matches = _unit->findContents(thisScope() + name); for(ContainedList::const_iterator p = matches.begin(); p != matches.end(); ++p) { ClassDeclPtr decl = ClassDeclPtr::dynamicCast(*p); if(decl) { if(checkInterfaceAndLocal(name, false, intf, decl->isInterface(), local, decl->isLocal())) { continue; } return 0; } bool differsOnlyInCase = !_unit->caseSensitive() && matches.front()->name() != name; ClassDefPtr def = ClassDefPtr::dynamicCast(*p); if(def) { if(differsOnlyInCase) { string msg = intf ? "interface" : "class"; msg += " definition `" + name + "' is capitalized inconsistently with its previous name: `"; msg += def->name() + "'"; _unit->error(msg); } else { if(_unit->ignRedefs()) { def->updateIncludeLevel(); return def; } string msg = "redefinition of "; msg += intf ? "interface" : "class"; msg += " `" + name + "'"; _unit->error(msg); } } else if(!_unit->caseSensitive() && differsOnlyInCase) { string msg = intf ? "interface" : "class"; msg = " definition `" + name + "' differs only in capitalization from "; msg += matches.front()->kindOf() + " name `" + matches.front()->name() + "'"; _unit->error(msg); } else { string msg = "redefinition of " + matches.front()->kindOf() + " `" + matches.front()->name() + "' as "; msg += intf ? "interface" : "class"; _unit->error(msg); } return 0; } if(!nameIsLegal(name, intf ? "interface" : "class")) { return 0; } if(!checkForGlobalDef(name, intf ? "interface" : "class")) { return 0; } ClassDecl::checkBasesAreLegal(name, intf, local, bases, _unit); ClassDefPtr def = new ClassDef(this, name, intf, bases, local); _contents.push_back(def); for(ContainedList::const_iterator q = matches.begin(); q != matches.end(); ++q) { ClassDeclPtr decl = ClassDeclPtr::dynamicCast(*q); decl->_definition = def; } // // Implicitly create a class declaration for each class // definition. This way the code generator can rely on always // having a class declaration available for lookup. // ClassDeclPtr decl = createClassDecl(name, intf, local); def->_declaration = decl; return def; } ClassDeclPtr Slice::Container::createClassDecl(const string& name, bool intf, bool local) { checkPrefix(name); ClassDefPtr def; ContainedList matches = _unit->findContents(thisScope() + name); for(ContainedList::const_iterator p = matches.begin(); p != matches.end(); ++p) { ClassDefPtr clDef = ClassDefPtr::dynamicCast(*p); if(clDef) { if(checkInterfaceAndLocal(name, true, intf, clDef->isInterface(), local, clDef->isLocal())) { assert(!def); def = clDef; continue; } return 0; } ClassDeclPtr clDecl = ClassDeclPtr::dynamicCast(*p); if(clDecl) { if(checkInterfaceAndLocal(name, false, intf, clDecl->isInterface(), local, clDecl->isLocal())) { continue; } return 0; } bool differsOnlyInCase = !_unit->caseSensitive() && matches.front()->name() != name; if(differsOnlyInCase) { string msg = "class declaration `" + name + "' differs only in capitalization from "; msg += matches.front()->kindOf() + " name `" + matches.front()->name() + "'"; _unit->error(msg); } else { string msg = "declaration of already defined `"; msg += name; msg += "' as "; msg += intf ? "interface" : "class"; _unit->error(msg); return 0; } } if(!nameIsLegal(name, intf ? "interface" : "class")) { return 0; } if(!checkForGlobalDef(name, intf ? "interface" : "class")) { return 0; } // // Multiple declarations are permissible. But if we do already // have a declaration for the class in this container, we don't // create another one. // for(ContainedList::const_iterator q = _contents.begin(); q != _contents.end(); ++q) { if((*q)->name() == name) { ClassDeclPtr decl = ClassDeclPtr::dynamicCast(*q); if(decl) { return decl; } assert(ClassDefPtr::dynamicCast(*q)); } } _unit->currentContainer(); ClassDeclPtr decl = new ClassDecl(this, name, intf, local); _contents.push_back(decl); if(def) { decl->_definition = def; } return decl; } ExceptionPtr Slice::Container::createException(const string& name, const ExceptionPtr& base, bool local) { checkPrefix(name); ContainedList matches = _unit->findContents(thisScope() + name); if(!matches.empty()) { ExceptionPtr p = ExceptionPtr::dynamicCast(matches.front()); if(p) { if(_unit->ignRedefs()) { p->updateIncludeLevel(); return p; } } if(matches.front()->name() == name) { string msg = "redefinition of " + matches.front()->kindOf() + " `" + matches.front()->name(); msg += "' as exception"; _unit->error(msg); } else if(!_unit->caseSensitive()) { string msg = "exception `" + name + "' differs only in capitalization from "; msg += matches.front()->kindOf() + " `" + matches.front()->name() + "'"; _unit->error(msg); } } nameIsLegal(name, "exception"); // Don't return here -- we create the exception anyway checkForGlobalDef(name, "exception"); // Don't return here -- we create the exception anyway // // If this definition is non-local, base cannot be local. // if(!local && base && base->isLocal()) { _unit->error("non-local exception `" + name + "' cannot have local base exception `" + base->name() + "'"); } ExceptionPtr p = new Exception(this, name, base, local); _contents.push_back(p); return p; } StructPtr Slice::Container::createStruct(const string& name, bool local) { checkPrefix(name); ContainedList matches = _unit->findContents(thisScope() + name); if(!matches.empty()) { StructPtr p = StructPtr::dynamicCast(matches.front()); if(p) { if(_unit->ignRedefs()) { p->updateIncludeLevel(); return p; } } if(matches.front()->name() == name) { string msg = "redefinition of " + matches.front()->kindOf() + " `" + matches.front()->name(); msg += "' as struct"; _unit->error(msg); } else if(!_unit->caseSensitive()) { string msg = "struct `" + name + "' differs only in capitalization from "; msg += matches.front()->kindOf() + " `" + matches.front()->name() + "'"; _unit->error(msg); } } nameIsLegal(name, "structure"); // Don't return here -- we create the struct anyway. checkForGlobalDef(name, "structure"); // Don't return here -- we create the struct anyway. StructPtr p = new Struct(this, name, local); _contents.push_back(p); return p; } SequencePtr Slice::Container::createSequence(const string& name, const TypePtr& type, const StringList& metaData, bool local) { checkPrefix(name); if(_unit->profile() == IceE && !local) { BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); if((builtin && builtin->kind() == Builtin::KindObject) || ClassDeclPtr::dynamicCast(type)) { string msg = "Sequence `" + name + "' cannot contain object values."; _unit->error(msg); return 0; } } ContainedList matches = _unit->findContents(thisScope() + name); if(!matches.empty()) { SequencePtr p = SequencePtr::dynamicCast(matches.front()); if(p) { if(_unit->ignRedefs()) { p->updateIncludeLevel(); return p; } } if(matches.front()->name() == name) { string msg = "redefinition of " + matches.front()->kindOf() + " `" + matches.front()->name(); msg += "' as sequence"; _unit->error(msg); } else if(!_unit->caseSensitive()) { string msg = "sequence `" + name + "' differs only in capitalization from "; msg += matches.front()->kindOf() + " `" + matches.front()->name() + "'"; _unit->error(msg); } } nameIsLegal(name, "sequence"); // Don't return here -- we create the sequence anyway. checkForGlobalDef(name, "sequence"); // Don't return here -- we create the sequence anyway. // // If sequence is non-local, element type cannot be local. // if(!local && type->isLocal()) { string msg = "non-local sequence `" + name + "' cannot have local element type"; _unit->error(msg); } SequencePtr p = new Sequence(this, name, type, metaData, local); _contents.push_back(p); return p; } DictionaryPtr Slice::Container::createDictionary(const string& name, const TypePtr& keyType, const StringList& keyMetaData, const TypePtr& valueType, const StringList& valueMetaData, bool local) { checkPrefix(name); if(_unit->profile() == IceE && !local) { BuiltinPtr builtin = BuiltinPtr::dynamicCast(valueType); if((builtin && builtin->kind() == Builtin::KindObject) || ClassDeclPtr::dynamicCast(valueType)) { string msg = "Dictionary `" + name + "' cannot contain object values."; _unit->error(msg); return 0; } } ContainedList matches = _unit->findContents(thisScope() + name); if(!matches.empty()) { DictionaryPtr p = DictionaryPtr::dynamicCast(matches.front()); if(p) { if(_unit->ignRedefs()) { p->updateIncludeLevel(); return p; } } if(matches.front()->name() == name) { string msg = "redefinition of " + matches.front()->kindOf() + " `" + matches.front()->name(); msg += "' as dictionary"; _unit->error(msg); } else if(!_unit->caseSensitive()) { string msg = "dictionary `" + name + "' differs only in capitalization from "; msg += matches.front()->kindOf() + " `" + matches.front()->name() + "'"; _unit->error(msg); } } nameIsLegal(name, "dictionary"); // Don't return here -- we create the dictionary anyway. checkForGlobalDef(name, "dictionary"); // Don't return here -- we create the dictionary anyway. if(!Dictionary::legalKeyType(keyType)) { _unit->error("dictionary `" + name + "' uses an illegal key type"); return 0; } if(!local) { if(keyType->isLocal()) { string msg = "non-local dictionary `" + name + "' cannot have local key type"; _unit->error(msg); } if(valueType->isLocal()) { string msg = "non-local dictionary `" + name + "' cannot have local value type"; _unit->error(msg); } } DictionaryPtr p = new Dictionary(this, name, keyType, keyMetaData, valueType, valueMetaData, local); _contents.push_back(p); return p; } EnumPtr Slice::Container::createEnum(const string& name, bool local) { checkPrefix(name); ContainedList matches = _unit->findContents(thisScope() + name); if(!matches.empty()) { EnumPtr p = EnumPtr::dynamicCast(matches.front()); if(p) { if(_unit->ignRedefs()) { p->updateIncludeLevel(); return p; } } if(matches.front()->name() == name) { string msg = "redefinition of " + matches.front()->kindOf() + " `" + matches.front()->name(); msg += "' as enumeration"; _unit->error(msg); } else if(!_unit->caseSensitive()) { string msg = "enumeration `" + name + "' differs only in capitalization from "; msg += matches.front()->kindOf() + " `" + matches.front()->name() + "'"; _unit->error(msg); } } nameIsLegal(name, "enumeration"); // Don't return here -- we create the enumeration anyway. checkForGlobalDef(name, "enumeration"); // Don't return here -- we create the enumeration anyway. EnumPtr p = new Enum(this, name, local); _contents.push_back(p); return p; } EnumeratorPtr Slice::Container::createEnumerator(const string& name) { checkPrefix(name); ContainedList matches = _unit->findContents(thisScope() + name); if(!matches.empty()) { EnumeratorPtr p = EnumeratorPtr::dynamicCast(matches.front()); if(p) { if(_unit->ignRedefs()) { p->updateIncludeLevel(); return p; } } if(matches.front()->name() == name) { string msg = "redefinition of " + matches.front()->kindOf() + " `" + matches.front()->name(); msg += "' as enumerator"; _unit->error(msg); } else if(!_unit->caseSensitive()) { string msg = "enumerator `" + name + "' differs only in capitalization from "; msg += matches.front()->kindOf() + " `" + matches.front()->name() + "'"; _unit->error(msg); } } nameIsLegal(name, "enumerator"); // Don't return here -- we create the enumerator anyway. EnumeratorPtr p = new Enumerator(this, name); _contents.push_back(p); return p; } ConstPtr Slice::Container::createConst(const string name, const TypePtr& constType, const StringList& metaData, const SyntaxTreeBasePtr& literalType, const string& value) { checkPrefix(name); ContainedList matches = _unit->findContents(thisScope() + name); if(!matches.empty()) { ConstPtr p = ConstPtr::dynamicCast(matches.front()); if(p) { if(_unit->ignRedefs()) { p->updateIncludeLevel(); return p; } } if(matches.front()->name() == name) { string msg = "redefinition of " + matches.front()->kindOf() + " `" + matches.front()->name(); msg += "' as constant"; _unit->error(msg); } else if(!_unit->caseSensitive()) { string msg = "constant `" + name + "' differs only in capitalization from "; msg += matches.front()->kindOf() + " `" + matches.front()->name() + "'"; _unit->error(msg); } } nameIsLegal(name, "constant"); // Don't return here -- we create the constant anyway. checkForGlobalDef(name, "constant"); // Don't return here -- we create the constant anyway. // // Check that the constant type is legal. // if(!Const::isLegalType(name, constType, _unit)) { return 0; } // // Check that the type of the constant is compatible with the type of the initializer. // if(!Const::typesAreCompatible(name, constType, literalType, value, _unit)) { return 0; } // // Check that the initializer is in range. // if(!Const::isInRange(name, constType, value, _unit)) { return 0; } ConstPtr p = new Const(this, name, constType, metaData, value); _contents.push_back(p); return p; } TypeList Slice::Container::lookupType(const string& scoped, bool printError) { // // Remove whitespace. // string sc = scoped; string::size_type pos; while((pos = sc.find_first_of(" \t\r\n")) != string::npos) { sc.erase(pos, 1); } // // Check for builtin type. // for(unsigned int i = 0; i < sizeof(Builtin::builtinTable) / sizeof(const char*); ++i) { if(sc == Builtin::builtinTable[i]) { TypeList result; result.push_back(_unit->builtin(static_cast(i))); return result; } } // // Not a builtin type, try to look up a constructed type. // return lookupTypeNoBuiltin(scoped, printError); } TypeList Slice::Container::lookupTypeNoBuiltin(const string& scoped, bool printError) { // // Remove whitespace. // string sc = scoped; string::size_type pos; while((pos = sc.find_first_of(" \t\r\n")) != string::npos) { sc.erase(pos, 1); } // // Absolute scoped name? // if(sc.size() >= 2 && sc[0] == ':') { return _unit->lookupTypeNoBuiltin(sc.substr(2), printError); } TypeList results; if(sc.rfind('*') == sc.length() - 1) { // // Proxies. // ContainedList matches = _unit->findContents(thisScope() + sc.substr(0, sc.length() - 1)); for(ContainedList::const_iterator p = matches.begin(); p != matches.end(); ++p) { ClassDefPtr def = ClassDefPtr::dynamicCast(*p); if(def) { continue; // Ignore class definitions. } if(printError && !_unit->caseSensitive() && matches.front()->scoped() != (thisScope() + sc)) { string msg = (*p)->kindOf() + " name `" + scoped; msg += "' is capitalized inconsistently with its previous name: `"; msg += matches.front()->scoped() + "'"; _unit->error(msg); } ClassDeclPtr cl = ClassDeclPtr::dynamicCast(*p); if(!cl) { if(printError) { string msg = "`"; msg += sc; msg += "' must be class or interface"; _unit->error(msg); } return TypeList(); } results.push_back(new Proxy(cl)); } } else { // // Non-Proxies. // ContainedList matches = _unit->findContents(thisScope() + sc); for(ContainedList::const_iterator p = matches.begin(); p != matches.end(); ++p) { ClassDefPtr def = ClassDefPtr::dynamicCast(*p); if(def) { continue; // Ignore class definitions. } if(printError && !_unit->caseSensitive() && matches.front()->scoped() != (thisScope() + sc)) { string msg = (*p)->kindOf() + " name `" + scoped; msg += "' is capitalized inconsistently with its previous name: `"; msg += matches.front()->scoped() + "'"; _unit->error(msg); } ExceptionPtr ex = ExceptionPtr::dynamicCast(*p); if(ex) { if(printError) { string msg = "`"; msg += sc; msg += "' is an exception, which cannot be used as a type"; _unit->error(msg); } return TypeList(); } TypePtr type = TypePtr::dynamicCast(*p); if(!type) { if(printError) { string msg = "`"; msg += sc; msg += "' is not a type"; _unit->error(msg); } return TypeList(); } results.push_back(type); } } if(results.empty()) { ContainedPtr contained = ContainedPtr::dynamicCast(this); if(!contained) { if(printError) { string msg = "`"; msg += sc; msg += "' is not defined"; _unit->error(msg); } return TypeList(); } return contained->container()->lookupTypeNoBuiltin(sc, printError); } else { return results; } } ContainedList Slice::Container::lookupContained(const string& scoped, bool printError) { // // Remove whitespace. // string sc = scoped; string::size_type pos; while((pos = sc.find_first_of(" \t\r\n")) != string::npos) { sc.erase(pos, 1); } // // Absolute scoped name? // if(sc.size() >= 2 && sc[0] == ':') { return _unit->lookupContained(sc.substr(2), printError); } ContainedList matches = _unit->findContents(thisScope() + sc); ContainedList results; for(ContainedList::const_iterator p = matches.begin(); p != matches.end(); ++p) { if(!ClassDefPtr::dynamicCast(*p)) // Ignore class definitions. { results.push_back(*p); if(printError && !_unit->caseSensitive() && (*p)->scoped() != (thisScope() + sc)) { string msg = (*p)->kindOf() + " name `" + scoped; msg += "' is capitalized inconsistently with its previous name: `" + (*p)->scoped() + "'"; _unit->error(msg); } } } if(results.empty()) { ContainedPtr contained = ContainedPtr::dynamicCast(this); if(!contained) { if(printError) { string msg = "`"; msg += sc; msg += "' is not defined"; _unit->error(msg); } return ContainedList(); } return contained->container()->lookupContained(sc, printError); } else { return results; } } ExceptionPtr Slice::Container::lookupException(const string& scoped, bool printError) { ContainedList contained = lookupContained(scoped, printError); if(contained.empty()) { return 0; } ExceptionList exceptions; for(ContainedList::iterator p = contained.begin(); p != contained.end(); ++p) { ExceptionPtr ex = ExceptionPtr::dynamicCast(*p); if(!ex) { if(printError) { string msg = "`"; msg += scoped; msg += "' is not an exception"; _unit->error(msg); } return 0; } exceptions.push_back(ex); } assert(exceptions.size() == 1); return exceptions.front(); } ModuleList Slice::Container::modules() const { ModuleList result; for(ContainedList::const_iterator p = _contents.begin(); p != _contents.end(); ++p) { ModulePtr q = ModulePtr::dynamicCast(*p); if(q) { result.push_back(q); } } return result; } ClassList Slice::Container::classes() const { ClassList result; for(ContainedList::const_iterator p = _contents.begin(); p != _contents.end(); ++p) { ClassDefPtr q = ClassDefPtr::dynamicCast(*p); if(q) { result.push_back(q); } } return result; } ExceptionList Slice::Container::exceptions() const { ExceptionList result; for(ContainedList::const_iterator p = _contents.begin(); p != _contents.end(); ++p) { ExceptionPtr q = ExceptionPtr::dynamicCast(*p); if(q) { result.push_back(q); } } return result; } StructList Slice::Container::structs() const { StructList result; for(ContainedList::const_iterator p = _contents.begin(); p != _contents.end(); ++p) { StructPtr q = StructPtr::dynamicCast(*p); if(q) { result.push_back(q); } } return result; } SequenceList Slice::Container::sequences() const { SequenceList result; for(ContainedList::const_iterator p = _contents.begin(); p != _contents.end(); ++p) { SequencePtr q = SequencePtr::dynamicCast(*p); if(q) { result.push_back(q); } } return result; } DictionaryList Slice::Container::dictionaries() const { DictionaryList result; for(ContainedList::const_iterator p = _contents.begin(); p != _contents.end(); ++p) { DictionaryPtr q = DictionaryPtr::dynamicCast(*p); if(q) { result.push_back(q); } } return result; } EnumList Slice::Container::enums() const { EnumList result; for(ContainedList::const_iterator p = _contents.begin(); p != _contents.end(); ++p) { EnumPtr q = EnumPtr::dynamicCast(*p); if(q) { result.push_back(q); } } return result; } ContainedList Slice::Container::contents() const { return _contents; } bool Slice::Container::hasNonLocalClassDecls() const { for(ContainedList::const_iterator p = _contents.begin(); p != _contents.end(); ++p) { ClassDeclPtr cl = ClassDeclPtr::dynamicCast(*p); if(cl && !cl->isLocal()) { return true; } ContainerPtr container = ContainerPtr::dynamicCast(*p); if(container && container->hasNonLocalClassDecls()) { return true; } } return false; } bool Slice::Container::hasNonLocalClassDefs() const { for(ContainedList::const_iterator p = _contents.begin(); p != _contents.end(); ++p) { ClassDefPtr cl = ClassDefPtr::dynamicCast(*p); if(cl && !cl->isLocal()) { return true; } ContainerPtr container = ContainerPtr::dynamicCast(*p); if(container && container->hasNonLocalClassDefs()) { return true; } } return false; } bool Slice::Container::hasNonLocalSequences() const { for(ContainedList::const_iterator p = _contents.begin(); p != _contents.end(); ++p) { SequencePtr s = SequencePtr::dynamicCast(*p); if(s && !s->isLocal()) { return true; } ContainerPtr container = ContainerPtr::dynamicCast(*p); if(container && container->hasNonLocalSequences()) { return true; } } return false; } bool Slice::Container::hasNonLocalDictionaries() const { for(ContainedList::const_iterator p = _contents.begin(); p != _contents.end(); ++p) { DictionaryPtr d = DictionaryPtr::dynamicCast(*p); if(d && !d->isLocal()) { return true; } ContainerPtr container = ContainerPtr::dynamicCast(*p); if(container && container->hasNonLocalDictionaries()) { return true; } } return false; } bool Slice::Container::hasNonLocalExceptions() const { for(ContainedList::const_iterator p = _contents.begin(); p != _contents.end(); ++p) { ExceptionPtr q = ExceptionPtr::dynamicCast(*p); if(q && !q->isLocal()) { return true; } ContainerPtr container = ContainerPtr::dynamicCast(*p); if(container && container->hasNonLocalExceptions()) { return true; } } return false; } bool Slice::Container::hasClassDecls() const { for(ContainedList::const_iterator p = _contents.begin(); p != _contents.end(); ++p) { if(ClassDeclPtr::dynamicCast(*p)) { return true; } ContainerPtr container = ContainerPtr::dynamicCast(*p); if(container && container->hasClassDecls()) { return true; } } return false; } bool Slice::Container::hasClassDefs() const { for(ContainedList::const_iterator p = _contents.begin(); p != _contents.end(); ++p) { if(ClassDefPtr::dynamicCast(*p)) { return true; } ContainerPtr container = ContainerPtr::dynamicCast(*p); if(container && container->hasClassDefs()) { return true; } } return false; } bool Slice::Container::hasAbstractClassDefs() const { for(ContainedList::const_iterator p = _contents.begin(); p != _contents.end(); ++p) { ClassDefPtr cl = ClassDefPtr::dynamicCast(*p); if(cl && cl->isAbstract()) { return true; } ContainerPtr container = ContainerPtr::dynamicCast(*p); if(container && container->hasAbstractClassDefs()) { return true; } } return false; } bool Slice::Container::hasDataOnlyClasses() const { for(ContainedList::const_iterator p = _contents.begin(); p != _contents.end(); ++p) { ClassDefPtr q = ClassDefPtr::dynamicCast(*p); if(q) { if(!q->isAbstract()) { return true; } } ContainerPtr container = ContainerPtr::dynamicCast(*p); if(container && container->hasDataOnlyClasses()) { return true; } } return false; } bool Slice::Container::hasOtherConstructedOrExceptions() const { for(ContainedList::const_iterator p = _contents.begin(); p != _contents.end(); ++p) { if(ConstructedPtr::dynamicCast(*p) && !ClassDeclPtr::dynamicCast(*p) && !ClassDefPtr::dynamicCast(*p)) { return true; } if(ExceptionPtr::dynamicCast(*p)) { return true; } if(ConstPtr::dynamicCast(*p)) { return true; } ContainerPtr container = ContainerPtr::dynamicCast(*p); if(container && container->hasOtherConstructedOrExceptions()) { return true; } } return false; } bool Slice::Container::hasContentsWithMetaData(const string& meta) const { for(ContainedList::const_iterator p = _contents.begin(); p != _contents.end(); ++p) { if((*p)->hasMetaData(meta)) { return true; } ContainerPtr container = ContainerPtr::dynamicCast(*p); if(container && container->hasContentsWithMetaData(meta)) { return true; } } return false; } bool Slice::Container::hasAsyncOps() const { for(ContainedList::const_iterator p = _contents.begin(); p != _contents.end(); ++p) { ClassDefPtr cl = ClassDefPtr::dynamicCast(*p); if(cl && !cl->isLocal()) { OperationList ops = cl->operations(); if(!ops.empty() && (cl->hasMetaData("ami") || cl->hasMetaData("amd"))) { return true; } for(OperationList::const_iterator i = ops.begin(); i != ops.end(); ++i) { OperationPtr op = *i; if(op->hasMetaData("ami") || op->hasMetaData("amd")) { return true; } } } ContainerPtr container = ContainerPtr::dynamicCast(*p); if(container && container->hasAsyncOps()) { return true; } } return false; } string Slice::Container::thisScope() const { string s; ContainedPtr contained = ContainedPtr::dynamicCast(const_cast(this)); if(contained) { s = contained->scoped(); } s += "::"; return s; } void Slice::Container::mergeModules() { for(ContainedList::iterator p = _contents.begin(); p != _contents.end(); ++p) { ModulePtr mod1 = ModulePtr::dynamicCast(*p); if(!mod1) { continue; } DefinitionContextPtr dc1 = mod1->definitionContext(); assert(dc1); StringList metaData1 = dc1->getMetaData(); metaData1.sort(); metaData1.unique(); ContainedList::iterator q = p; ++q; while(q != _contents.end()) { ModulePtr mod2 = ModulePtr::dynamicCast(*q); if(!mod2) { ++q; continue; } if(mod1->name() != mod2->name()) { ++q; continue; } // // Compare the global metadata of the two modules being merged. // DefinitionContextPtr dc2 = mod2->definitionContext(); assert(dc2); StringList metaData2 = dc2->getMetaData(); metaData2.sort(); metaData2.unique(); if(metaData1 != metaData2) { unit()->warning("global metadata mismatch for module `" + mod1->name() + "' in files " + dc1->filename() + " and " + dc2->filename()); } mod1->_contents.splice(mod1->_contents.end(), mod2->_contents); if(mod1->_comment.length() < mod2->_comment.length()) { mod1->_comment.swap(mod2->_comment); } mod1->_includeLevel = min(mod1->_includeLevel, mod2->_includeLevel); _unit->removeContent(*q); q = _contents.erase(q); } mod1->mergeModules(); } } void Slice::Container::sort() { _contents.sort(); } void Slice::Container::sortContents(bool sortFields) { for(ContainedList::const_iterator p = _contents.begin(); p != _contents.end(); ++p) { ContainerPtr container = ContainerPtr::dynamicCast(*p); if(container) { if(!sortFields) { if(StructPtr::dynamicCast(container) || ClassDefPtr::dynamicCast(container) || ExceptionPtr::dynamicCast(container)) { continue; } } // // Don't sort operation definitions, otherwise parameters are shown in the // wrong order in the synopsis. // if(!OperationPtr::dynamicCast(container)) { container->sort(); } container->sortContents(sortFields); } } } void Slice::Container::visit(ParserVisitor* visitor, bool all) { for(ContainedList::const_iterator p = _contents.begin(); p != _contents.end(); ++p) { if(all || (*p)->includeLevel() == 0) { (*p)->visit(visitor, all); } } } void Slice::Container::containerRecDependencies(set& dependencies) { ContainedList::iterator p; for(p = _contents.begin(); p != _contents.end(); ++p) { ConstructedPtr constructed = ConstructedPtr::dynamicCast(*p); if(constructed && dependencies.find(constructed) != dependencies.end()) { dependencies.insert(constructed); constructed->recDependencies(dependencies); } } } bool Slice::Container::checkIntroduced(const string& scoped, ContainedPtr namedThing) { if(scoped[0] == ':') // Only unscoped names introduce anything. { return true; } // // Split off first component. // string::size_type pos = scoped.find("::"); string firstComponent = pos == string::npos ? scoped : scoped.substr(0, pos); // // If we don't have a type, the thing that is introduced is the contained for // the first component. // if(namedThing == 0) { ContainedList cl = lookupContained(firstComponent, false); if(namedThing == 0) { if(cl.empty()) { return true; // Ignore types whose creation failed previously. } } namedThing = cl.front(); } else { // // For each scope, get the container until we have the container // for the first scope (which is the introduced one). // ContainerPtr c; bool first = true; while(pos != string::npos) { if(first) { c = namedThing->container(); } else { ContainedPtr contained = ContainedPtr::dynamicCast(c); if(contained) { c = contained->container(); } } first = false; if(pos != string::npos) { pos = scoped.find("::", pos + 2); } } if(ContainedPtr::dynamicCast(c)) { namedThing = ContainedPtr::dynamicCast(c); } } // // Check if the first component is in the introduced map of this scope. // map::const_iterator it = _introducedMap.find(firstComponent); if(it == _introducedMap.end()) { // // We've just introduced the first component to the current scope. // _introducedMap[firstComponent] = namedThing; // No, insert it } else { // // We've previously introduced the first component to the current scope, // check that it has not changed meaning. // if(!_unit->caseSensitive() && it->second != namedThing) { _unit->error("`" + firstComponent + "' has changed meaning"); return false; } } return true; } bool Slice::Container::nameIsLegal(const string& newName, const char* newConstruct) { ModulePtr module = ModulePtr::dynamicCast(this); // // Check whether the enclosing module has the same name. // if(module) { if(newName == module->name()) { string msg = newConstruct; msg += " name `" + newName + "' must differ from the name of its immediately enclosing module"; _unit->error(msg); return false; } if(!_unit->caseSensitive()) { string name = newName; toLower(name); string thisName = module->name(); toLower(thisName); if(name == thisName) { string msg = newConstruct; msg += " name `" + name + "' cannot differ only in capitalization from its immediately enclosing " "module name `" + module->name() + "'"; _unit->error(msg); return false; } } module = ModulePtr::dynamicCast(module->container()); // Get enclosing module for test below. } // // Check whether any of the enclosing modules have the same name. // while(module) { if(newName == module->name()) { string msg = newConstruct; msg += " name `" + newName + "' must differ from the name of enclosing module `" + module->name() + "' (first defined at " + module->file() + ":" + module->line() + ")"; _unit->error(msg); return false; } if(!_unit->caseSensitive()) { string name = newName; toLower(name); string thisName = module->name(); toLower(thisName); if(name == thisName) { string msg = newConstruct; msg += " name `" + name + "' cannot differ only in capitalization from enclosing module `" + module->name() + "' (first defined at " + module->file() + ":" + module->line() + ")"; _unit->error(msg); return false; } } module = ModulePtr::dynamicCast(module->container()); } return true; } bool Slice::Container::checkForGlobalDef(const string& name, const char* newConstruct) { if(dynamic_cast(this) && strcmp(newConstruct, "module")) { static const string vowels = "aeiou"; string glottalStop; if(vowels.find_first_of(newConstruct[0]) != string::npos) { glottalStop = "n"; } _unit->error("`" + name + "': a" + glottalStop + " " + newConstruct + " can be defined only at module scope"); return false; } return true; } Slice::Container::Container(const UnitPtr& unit) : SyntaxTreeBase(unit) { } bool Slice::Container::checkInterfaceAndLocal(const string& name, bool defined, bool intf, bool intfOther, bool local, bool localOther) { string definedOrDeclared; if(defined) { definedOrDeclared = "defined"; } else { definedOrDeclared = "declared"; } if(!intf && intfOther) { string msg = "class `"; msg += name; msg += "' was "; msg += definedOrDeclared; msg += " as interface"; _unit->error(msg); return false; } if(intf && !intfOther) { string msg = "interface `"; msg += name; msg += "' was "; msg += definedOrDeclared; msg += " as class"; _unit->error(msg); return false; } if(!local && localOther) { string msg = "non-local `"; msg += name; msg += "' was "; msg += definedOrDeclared; msg += " local"; _unit->error(msg); return false; } if(local && !localOther) { string msg = "local `"; msg += name; msg += "' was "; msg += definedOrDeclared; msg += " non-local"; _unit->error(msg); return false; } return true; } void Slice::Container::checkPrefix(const string& name) const { if(_unit->currentIncludeLevel() == 0 && !_unit->allowIcePrefix()) { if(name.size() >= 3) { string prefix3; prefix3 += ::tolower(name[0]); prefix3 += ::tolower(name[1]); prefix3 += ::tolower(name[2]); if(prefix3 == "ice") { _unit->error("illegal identifier `" + name + "': `" + name.substr(0, 3) + "' prefix is reserved"); } } } } // ---------------------------------------------------------------------- // Module // ---------------------------------------------------------------------- Contained::ContainedType Slice::Module::containedType() const { return ContainedTypeModule; } bool Slice::Module::uses(const ContainedPtr&) const { return false; } string Slice::Module::kindOf() const { return "module"; } void Slice::Module::visit(ParserVisitor* visitor, bool all) { if(visitor->visitModuleStart(this)) { Container::visit(visitor, all); visitor->visitModuleEnd(this); } } Slice::Module::Module(const ContainerPtr& container, const string& name) : SyntaxTreeBase(container->unit()), Container(container->unit()), Contained(container, name) { } // ---------------------------------------------------------------------- // Constructed // ---------------------------------------------------------------------- bool Slice::Constructed::isLocal() const { return _local; } string Slice::Constructed::typeId() const { return scoped(); } ConstructedList Slice::Constructed::dependencies() { set resultSet; recDependencies(resultSet); #if defined(__SUNPRO_CC) && defined(_RWSTD_NO_MEMBER_TEMPLATES) // TODO: find a more usable work-around for this std lib limitation. ConstructedList result; set::iterator it = resultSet.begin(); while(it != resultSet.end()) { result.push_back(*it++); } return result; #else return ConstructedList(resultSet.begin(), resultSet.end()); #endif } Slice::Constructed::Constructed(const ContainerPtr& container, const string& name, bool local) : SyntaxTreeBase(container->unit()), Type(container->unit()), Contained(container, name), _local(local) { } // ---------------------------------------------------------------------- // ClassDecl // ---------------------------------------------------------------------- void Slice::ClassDecl::destroy() { _definition = 0; SyntaxTreeBase::destroy(); } ClassDefPtr Slice::ClassDecl::definition() const { return _definition; } bool Slice::ClassDecl::isInterface() const { return _interface; } Contained::ContainedType Slice::ClassDecl::containedType() const { return ContainedTypeClass; } bool Slice::ClassDecl::uses(const ContainedPtr&) const { return false; } bool Slice::ClassDecl::usesClasses() const { return true; } size_t Slice::ClassDecl::minWireSize() const { return 4; // At least four bytes for an instance, if the instance is marshaled as an index. } bool Slice::ClassDecl::isVariableLength() const { return true; } string Slice::ClassDecl::kindOf() const { string s; if(isLocal()) { s += "local "; } s += _interface ? "interface" : "class"; return s; } void Slice::ClassDecl::visit(ParserVisitor* visitor, bool) { visitor->visitClassDecl(this); } void Slice::ClassDecl::recDependencies(set& dependencies) { if(_definition) { _definition->containerRecDependencies(dependencies); ClassList bases = _definition->bases(); ClassList::iterator p; for(p = bases.begin(); p != bases.end(); ++p) { (*p)->declaration()->recDependencies(dependencies); } } } void Slice::ClassDecl::checkBasesAreLegal(const string& name, bool intf, bool local, const ClassList& bases, const UnitPtr& unit) { // // Local definitions cannot have non-local bases, and vice versa. // for(ClassList::const_iterator p = bases.begin(); p != bases.end(); ++p) { if(local != (*p)->isLocal()) { ostringstream msg; msg << (local ? "local" : "non-local") << " " << (intf ? "interface" : "class") << " `" << name << "' cannot have " << ((*p)->isLocal() ? "local" : "non-local") << " base " << ((*p)->isInterface() ? "interface" : "class") << " `" << (*p)->name() << "'"; unit->error(msg.str()); } } // // Check whether, for multiple inheritance, any of the bases define // the same operations. // if(bases.size() > 1) { // // We have multiple inheritance. Build a list of paths through the // inheritance graph, such that multiple inheritance is legal if // the union of the names defined in classes on each path are disjoint. // GraphPartitionList gpl; for(ClassList::const_iterator p = bases.begin(); p != bases.end(); ++p) { ClassList cl; gpl.push_back(cl); addPartition(gpl, gpl.rbegin(), *p); } // // We now have a list of partitions, with each partition containing // a list of class definitions. Turn the list of partitions of class // definitions into a list of sets of strings, with each // set containing the names of operations and data members defined in // the classes in each partition. // StringPartitionList spl = toStringPartitionList(gpl); // // Multiple inheritance is legal if no two partitions contain a common // name (that is, if the union of the intersections of all possible pairs // of partitions is empty). // checkPairIntersections(spl, name, unit); } } Slice::ClassDecl::ClassDecl(const ContainerPtr& container, const string& name, bool intf, bool local) : SyntaxTreeBase(container->unit()), Type(container->unit()), Contained(container, name), Constructed(container, name, local), _interface(intf) { _unit->currentContainer(); } // // Return true if the class definition cdp is on one of the class lists in gpl, false otherwise. // bool Slice::ClassDecl::isInList(const GraphPartitionList& gpl, const ClassDefPtr cdp) { for(GraphPartitionList::const_iterator i = gpl.begin(); i != gpl.end(); ++i) { if(find(i->begin(), i->end(), cdp) != i->end()) { return true; } } return false; } void Slice::ClassDecl::addPartition(GraphPartitionList& gpl, GraphPartitionList::reverse_iterator tail, const ClassDefPtr base) { // // If this base is on one of the partition lists already, do nothing. // if(isInList(gpl, base)) { return; } // // Put the current base at the end of the current partition. // tail->push_back(base); // // If the base has bases in turn, recurse, adding the first base // of base (the left-most "grandbase") to the current partition. // if(base->bases().size()) { addPartition(gpl, tail, *(base->bases().begin())); } // // If the base has multiple bases, each of the "grandbases" // except for the left-most (which we just dealt with) // adds a new partition. // if(base->bases().size() > 1) { ClassList grandBases = base->bases(); ClassList::const_iterator i = grandBases.begin(); while(++i != grandBases.end()) { ClassList cl; gpl.push_back(cl); addPartition(gpl, gpl.rbegin(), *i); } } } // // Convert the list of partitions of class definitions into a // list of lists, with each member list containing the operation // names defined by the interfaces in each partition. // Slice::ClassDecl::StringPartitionList Slice::ClassDecl::toStringPartitionList(const GraphPartitionList& gpl) { StringPartitionList spl; for(GraphPartitionList::const_iterator i = gpl.begin(); i != gpl.end(); ++i) { StringList sl; spl.push_back(sl); for(ClassList::const_iterator j = i->begin(); j != i->end(); ++j) { OperationList operations = (*j)->operations(); for(OperationList::const_iterator l = operations.begin(); l != operations.end(); ++l) { spl.rbegin()->push_back((*l)->name()); } } } return spl; } // // For all (unique) pairs of string lists, check whether an identifier in one list occurs // in the other and, if so, complain. // void Slice::ClassDecl::checkPairIntersections(const StringPartitionList& l, const string& name, const UnitPtr& unit) { set reported; for(StringPartitionList::const_iterator i = l.begin(); i != l.end(); ++i) { StringPartitionList::const_iterator cursor = i; ++cursor; for(StringPartitionList::const_iterator j = cursor; j != l.end(); ++j) { for(StringList::const_iterator s1 = i->begin(); s1 != i->end(); ++s1) { for(StringList::const_iterator s2 = j->begin(); s2 != j->end(); ++s2) { if((*s1) == (*s2) && reported.find(*s1) == reported.end()) { string msg = "ambiguous multiple inheritance: `" + name; msg += "' inherits operation `" + *s1 + "' from two or more unrelated base interfaces"; unit->error(msg); reported.insert(*s1); } else if(!unit->caseSensitive() && !CICompare()(*s1, *s2) && !CICompare()(*s2, *s1) && reported.find(*s1) == reported.end() && reported.find(*s2) == reported.end()) { string msg = "ambiguous multiple inheritance: `" + name; msg += "' inherits operations `" + *s1 + "' and `" + *s2; msg += "', which differ only in capitalization, from unrelated base interfaces"; unit->error(msg); reported.insert(*s1); reported.insert(*s2); } } } } } } // ---------------------------------------------------------------------- // ClassDef // ---------------------------------------------------------------------- void Slice::ClassDef::destroy() { _declaration = 0; _bases.empty(); Container::destroy(); } OperationPtr Slice::ClassDef::createOperation(const string& name, const TypePtr& returnType, Operation::Mode mode) { checkPrefix(name); ContainedList matches = _unit->findContents(thisScope() + name); if(!matches.empty()) { OperationPtr p = OperationPtr::dynamicCast(matches.front()); if(p) { if(_unit->ignRedefs()) { p->updateIncludeLevel(); return p; } } if(!_unit->caseSensitive() && matches.front()->name() != name) { string msg = "operation `" + name + "' differs only in capitalization from "; msg += matches.front()->kindOf() + " `" + matches.front()->name() + "'"; _unit->error(msg); } string msg = "redefinition of " + matches.front()->kindOf() + " `" + matches.front()->name(); msg += "' as operation `" + name + "'"; _unit->error(msg); return 0; } // // Check whether enclosing interface/class has the same name. // if(name == this->name()) { string msg = isInterface() ? "interface" : "class"; msg += " name `" + name + "' cannot be used as operation name"; _unit->error(msg); return 0; } if(!_unit->caseSensitive()) { string newName = name; toLower(newName); string thisName = this->name(); toLower(thisName); if(newName == thisName) { string msg = "operation `" + name + "' differs only in capitalization from enclosing "; msg += isInterface() ? "interface" : "class"; msg += " name `" + this->name() + "'"; _unit->error(msg); } } // // Check whether any bases have defined something with the same name already. // for(ClassList::const_iterator p = _bases.begin(); p != _bases.end(); ++p) { ContainedList cl; OperationList ol = (*p)->allOperations(); copy(ol.begin(), ol.end(), back_inserter(cl)); DataMemberList dml = (*p)->allDataMembers(); copy(dml.begin(), dml.end(), back_inserter(cl)); for(ContainedList::const_iterator q = cl.begin(); q != cl.end(); ++q) { if((*q)->name() == name) { string msg = "operation `" + name; msg += "' is already defined as a"; static const string vowels = "aeiou"; string kindOf = (*q)->kindOf(); if(vowels.find_first_of(kindOf[0]) != string::npos) { msg += "n"; } msg += " " + kindOf + " in a base interface or class"; _unit->error(msg); return 0; } if(!_unit->caseSensitive()) { string baseName = (*q)->name(); toLower(baseName); string newName = name; toLower(newName); if(baseName == newName) { string msg = "operation `" + name + "' differs only in capitalization from " + (*q)->kindOf(); msg += " `" + (*q)->name() + "', which is defined in a base interface or class"; _unit->error(msg); } } } } // // Non-local class/interface cannot have operation with local return type. // if(!isLocal() && returnType && returnType->isLocal()) { string msg = "non-local " + this->kindOf() + " `" + this->name() + "' cannot have operation `"; msg += name + "' with local return type"; _unit->error(msg); } _hasOperations = true; OperationPtr op = new Operation(this, name, returnType, mode); _contents.push_back(op); return op; } DataMemberPtr Slice::ClassDef::createDataMember(const string& name, const TypePtr& type) { checkPrefix(name); if(_unit->profile() == IceE) { if(!isLocal()) { BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); if((builtin && builtin->kind() == Builtin::KindObject)) { string msg = "Class data member `" + name + "' cannot be a value object."; _unit->error(msg); return 0; } ClassDeclPtr classDecl = ClassDeclPtr::dynamicCast(type); if(classDecl != 0 && !classDecl->isLocal()) { string msg = "Class data member `" + name + "' cannot be a value object."; _unit->error(msg); return 0; } } } assert(!isInterface()); ContainedList matches = _unit->findContents(thisScope() + name); if(!matches.empty()) { DataMemberPtr p = DataMemberPtr::dynamicCast(matches.front()); if(p) { if(_unit->ignRedefs()) { p->updateIncludeLevel(); return p; } } if(!_unit->caseSensitive() && matches.front()->name() != name) { string msg = "data member `" + name + "' differs only in capitalization from "; msg += matches.front()->kindOf() + " `" + matches.front()->name() + "'"; _unit->error(msg); } else { string msg = "redefinition of " + matches.front()->kindOf() + " `" + matches.front()->name(); msg += "' as data member `" + name + "'"; _unit->error(msg); return 0; } } // // Check whether enclosing class has the same name. // if(name == this->name()) { string msg = "class name `"; msg += name; msg += "' cannot be used as data member name"; _unit->error(msg); return 0; } if(!_unit->caseSensitive()) { string newName = name; toLower(newName); string thisName = this->name(); toLower(thisName); if(newName == thisName) { string msg = "data member `" + name + "' differs only in capitalization from enclosing class name `"; msg += this->name() + "'"; _unit->error(msg); } } // // Check whether any bases have defined something with the same name already. // for(ClassList::const_iterator p = _bases.begin(); p != _bases.end(); ++p) { ContainedList cl; OperationList ol = (*p)->allOperations(); copy(ol.begin(), ol.end(), back_inserter(cl)); DataMemberList dml = (*p)->allDataMembers(); copy(dml.begin(), dml.end(), back_inserter(cl)); for(ContainedList::const_iterator q = cl.begin(); q != cl.end(); ++q) { if((*q)->name() == name) { string msg = "data member `" + name; msg += "' is already defined as a"; static const string vowels = "aeiou"; string kindOf = (*q)->kindOf(); if(vowels.find_first_of(kindOf[0]) != string::npos) { msg += "n"; } msg += " " + kindOf + " in a base interface or class"; _unit->error(msg); return 0; } if(!_unit->caseSensitive()) { string baseName = (*q)->name(); toLower(baseName); string newName = name; toLower(newName); if(baseName == newName) { string msg = "data member `" + name + "' differs only in capitalization from " + (*q)->kindOf(); msg += " `" + (*q)->name() + "', which is defined in a base interface or class"; _unit->error(msg); } } } } // // If data member is local, enclosing class/interface must be local. // if(!isLocal() && type->isLocal()) { string msg = "non-local " + kindOf() + "`" + this->name() + "' cannot contain local member `" + name + "'"; _unit->error(msg); } _hasDataMembers = true; DataMemberPtr member = new DataMember(this, name, type); _contents.push_back(member); return member; } ClassDeclPtr Slice::ClassDef::declaration() const { return _declaration; } ClassList Slice::ClassDef::bases() const { return _bases; } ClassList Slice::ClassDef::allBases() const { ClassList result = _bases; result.sort(); result.unique(); for(ClassList::const_iterator p = _bases.begin(); p != _bases.end(); ++p) { ClassList li = (*p)->allBases(); result.merge(li); result.unique(); } return result; } OperationList Slice::ClassDef::operations() const { OperationList result; for(ContainedList::const_iterator p = _contents.begin(); p != _contents.end(); ++p) { OperationPtr q = OperationPtr::dynamicCast(*p); if(q) { result.push_back(q); } } return result; } OperationList Slice::ClassDef::allOperations() const { OperationList result = operations(); result.sort(); result.unique(); for(ClassList::const_iterator p = _bases.begin(); p != _bases.end(); ++p) { OperationList li = (*p)->allOperations(); result.merge(li); result.unique(); } return result; } DataMemberList Slice::ClassDef::dataMembers() const { DataMemberList result; for(ContainedList::const_iterator p = _contents.begin(); p != _contents.end(); ++p) { DataMemberPtr q = DataMemberPtr::dynamicCast(*p); if(q) { result.push_back(q); } } return result; } // // Return the data members of this class and its parent classes, in base-to-derived order. // DataMemberList Slice::ClassDef::allDataMembers() const { DataMemberList result; // // Check if we have a base class. If so, recursively // get the data members of the base(s). // if(!_bases.empty() && !_bases.front()->isInterface()) { result = _bases.front()->allDataMembers(); } // // Append this class's data members. // DataMemberList myMembers = dataMembers(); result.splice(result.end(), myMembers); return result; } DataMemberList Slice::ClassDef::classDataMembers() const { DataMemberList result; for(ContainedList::const_iterator p = _contents.begin(); p != _contents.end(); ++p) { DataMemberPtr q = DataMemberPtr::dynamicCast(*p); if(q) { BuiltinPtr builtin = BuiltinPtr::dynamicCast(q->type()); if((builtin && builtin->kind() == Builtin::KindObject) || ClassDeclPtr::dynamicCast(q->type())) { result.push_back(q); } } } return result; } // // Return the class data members of this class and its parent classes, in base-to-derived order. // DataMemberList Slice::ClassDef::allClassDataMembers() const { DataMemberList result; // // Check if we have a base class. If so, recursively // get the class data members of the base(s). // if(!_bases.empty() && !_bases.front()->isInterface()) { result = _bases.front()->allClassDataMembers(); } // // Append this class's class members. // DataMemberList myMembers = classDataMembers(); result.splice(result.end(), myMembers); return result; } bool Slice::ClassDef::canBeCyclic() const { if(!_bases.empty() && !_bases.front()->isInterface() && _bases.front()->canBeCyclic()) { return true; } DataMemberList dml = dataMembers(); for(DataMemberList::const_iterator i = dml.begin(); i != dml.end(); ++i) { if((*i)->type()->usesClasses()) { return true; } } return false; } bool Slice::ClassDef::isAbstract() const { if(isInterface() || _bases.size() > 1) // Is this an interface, or does it derive from interfaces? { return true; } if(!_bases.empty() && _bases.front()->isAbstract()) { return true; } for(ContainedList::const_iterator p = _contents.begin(); p != _contents.end(); ++p) { if(OperationPtr::dynamicCast(*p)) { return true; } } return false; } bool Slice::ClassDef::isInterface() const { return _interface; } bool Slice::ClassDef::isA(const string& id) const { if(id == _scoped) { return true; } for(ClassList::const_iterator p = _bases.begin(); p != _bases.end(); ++p) { if((*p)->isA(id)) { return true; } } return false; } bool Slice::ClassDef::isLocal() const { return _local; } bool Slice::ClassDef::hasDataMembers() const { return _hasDataMembers; } bool Slice::ClassDef::hasOperations() const { return _hasOperations; } Contained::ContainedType Slice::ClassDef::containedType() const { return ContainedTypeClass; } bool Slice::ClassDef::uses(const ContainedPtr&) const { // No uses() implementation here. DataMember and Operation have // their own uses(). return false; } string Slice::ClassDef::kindOf() const { string s; if(isLocal()) { s += "local "; } s += isInterface() ? "interface" : "class"; return s; } void Slice::ClassDef::visit(ParserVisitor* visitor, bool all) { if(visitor->visitClassDefStart(this)) { Container::visit(visitor, all); visitor->visitClassDefEnd(this); } } Slice::ClassDef::ClassDef(const ContainerPtr& container, const string& name, bool intf, const ClassList& bases, bool local) : SyntaxTreeBase(container->unit()), Container(container->unit()), Contained(container, name), _interface(intf), _hasDataMembers(false), _hasOperations(false), _bases(bases), _local(local) { // // First element of bases may be a class, all others must be // interfaces. // #ifndef NDEBUG for(ClassList::const_iterator p = _bases.begin(); p != _bases.end(); ++p) { assert(p == _bases.begin() || (*p)->isInterface()); } #endif } // ---------------------------------------------------------------------- // Proxy // ---------------------------------------------------------------------- bool Slice::Proxy::isLocal() const { return __class->isLocal(); } string Slice::Proxy::typeId() const { return __class->scoped(); } bool Slice::Proxy::usesClasses() const { return false; } size_t Slice::Proxy::minWireSize() const { return 2; // At least two bytes for a nil proxy (empty name and empty category strings). } bool Slice::Proxy::isVariableLength() const { return true; } ClassDeclPtr Slice::Proxy::_class() const { return __class; } Slice::Proxy::Proxy(const ClassDeclPtr& cl) : SyntaxTreeBase(cl->unit()), Type(cl->unit()), __class(cl) { } // ---------------------------------------------------------------------- // Exception // ---------------------------------------------------------------------- void Slice::Exception::destroy() { _base = 0; Container::destroy(); } DataMemberPtr Slice::Exception::createDataMember(const string& name, const TypePtr& type) { checkPrefix(name); if(_unit->profile() == IceE) { if(!isLocal()) { BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); if((builtin && builtin->kind() == Builtin::KindObject)) { string msg = "Exception data member `" + name + "' cannot be a value object."; _unit->error(msg); return 0; } ClassDeclPtr classDecl = ClassDeclPtr::dynamicCast(type); if(classDecl != 0 && !classDecl->isLocal()) { string msg = "Exception data member `" + name + "' cannot be a value object."; _unit->error(msg); return 0; } } } ContainedList matches = _unit->findContents(thisScope() + name); if(!matches.empty()) { DataMemberPtr p = DataMemberPtr::dynamicCast(matches.front()); if(p) { if(_unit->ignRedefs()) { p->updateIncludeLevel(); return p; } } if(!_unit->caseSensitive() && matches.front()->name() != name) { string msg = "exception member `" + name + "' differs only in capitalization from "; msg += "exception member `" + matches.front()->name() + "'"; _unit->error(msg); } else { string msg = "redefinition of exception member `" + name + "'"; _unit->error(msg); return 0; } } // // Check whether enclosing exception has the same name. // if(name == this->name()) { string msg = "exception name `"; msg += name; msg += "' cannot be used as exception member name"; _unit->error(msg); return 0; } if(!_unit->caseSensitive()) { string newName = name; toLower(newName); string thisName = this->name(); toLower(thisName); if(newName == thisName) { string msg = "exception member `" + name + "' differs only in capitalization "; msg += "from enclosing exception name `" + this->name() + "'"; _unit->error(msg); } } // // Check whether any bases have defined a member with the same name already. // ExceptionList bl = allBases(); for(ExceptionList::const_iterator q = bl.begin(); q != bl.end(); ++q) { ContainedList cl; DataMemberList dml = (*q)->dataMembers(); copy(dml.begin(), dml.end(), back_inserter(cl)); for(ContainedList::const_iterator r = cl.begin(); r != cl.end(); ++r) { if((*r)->name() == name) { string msg = "exception member `" + name + "' is already defined in a base exception"; _unit->error(msg); return 0; } if(!_unit->caseSensitive()) { string baseName = (*r)->name(); toLower(baseName); string newName = name; toLower(newName); if(baseName == newName) { string msg = "exception member `" + name + "' differs only in capitalization from exception member `"; msg += (*r)->name() + "', which is defined in a base exception"; _unit->error(msg); } } } } // // If data member is local, enclosing class/interface must be local. // if(!isLocal() && type->isLocal()) { string msg = "non-local " + kindOf() + "`" + this->name() + "' cannot contain local member `" + name + "'"; _unit->error(msg); } DataMemberPtr p = new DataMember(this, name, type); _contents.push_back(p); return p; } DataMemberList Slice::Exception::dataMembers() const { DataMemberList result; for(ContainedList::const_iterator p = _contents.begin(); p != _contents.end(); ++p) { DataMemberPtr q = DataMemberPtr::dynamicCast(*p); if(q) { result.push_back(q); } } return result; } // // Return the data members of this exception and its parent exceptions, in base-to-derived order. // DataMemberList Slice::Exception::allDataMembers() const { DataMemberList result; // // Check if we have a base exception. If so, recursively // get the data members of the base exception(s). // if(base()) { result = base()->allDataMembers(); } // // Append this exceptions's data members. // DataMemberList myMembers = dataMembers(); result.splice(result.end(), myMembers); return result; } DataMemberList Slice::Exception::classDataMembers() const { DataMemberList result; for(ContainedList::const_iterator p = _contents.begin(); p != _contents.end(); ++p) { DataMemberPtr q = DataMemberPtr::dynamicCast(*p); if(q) { BuiltinPtr builtin = BuiltinPtr::dynamicCast(q->type()); if((builtin && builtin->kind() == Builtin::KindObject) || ClassDeclPtr::dynamicCast(q->type())) { result.push_back(q); } } } return result; } // // Return the class data members of this exception and its parent exceptions, in base-to-derived order. // DataMemberList Slice::Exception::allClassDataMembers() const { DataMemberList result; // // Check if we have a base exception. If so, recursively // get the class data members of the base exception(s). // if(base()) { result = base()->allClassDataMembers(); } // // Append this exceptions's class data members. // DataMemberList myMembers = classDataMembers(); result.splice(result.end(), myMembers); return result; } ExceptionPtr Slice::Exception::base() const { return _base; } ExceptionList Slice::Exception::allBases() const { ExceptionList result; if(_base) { result = _base->allBases(); result.push_front(_base); } return result; } bool Slice::Exception::isBaseOf(const ExceptionPtr& other) const { if(this->scoped() == other->scoped()) { return false; } ExceptionList bases = other->allBases(); for(ExceptionList::const_iterator i = bases.begin(); i != bases.end(); ++i) { if((*i)->scoped() == scoped()) { return true; } } return false; } bool Slice::Exception::isLocal() const { return _local; } Contained::ContainedType Slice::Exception::containedType() const { return ContainedTypeException; } bool Slice::Exception::uses(const ContainedPtr&) const { // No uses() implementation here. DataMember has its own uses(). return false; } bool Slice::Exception::usesClasses() const { DataMemberList dml = dataMembers(); for(DataMemberList::const_iterator i = dml.begin(); i != dml.end(); ++i) { if((*i)->type()->usesClasses()) { return true; } } if(_base) { return _base->usesClasses(); } return false; } string Slice::Exception::kindOf() const { return "exception"; } void Slice::Exception::visit(ParserVisitor* visitor, bool all) { if(visitor->visitExceptionStart(this)) { Container::visit(visitor, all); visitor->visitExceptionEnd(this); } } Slice::Exception::Exception(const ContainerPtr& container, const string& name, const ExceptionPtr& base, bool local) : SyntaxTreeBase(container->unit()), Container(container->unit()), Contained(container, name), _base(base), _local(local) { } // ---------------------------------------------------------------------- // Struct // ---------------------------------------------------------------------- DataMemberPtr Slice::Struct::createDataMember(const string& name, const TypePtr& type) { checkPrefix(name); if(_unit->profile() == IceE) { if(!isLocal()) { BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); if((builtin && builtin->kind() == Builtin::KindObject)) { string msg = "Struct data member `" + name + "' cannot be a value object."; _unit->error(msg); return 0; } ClassDeclPtr classDecl = ClassDeclPtr::dynamicCast(type); if(classDecl != 0 && !classDecl->isLocal()) { string msg = "Struct data member `" + name + "' cannot be a value object."; _unit->error(msg); return 0; } } } ContainedList matches = _unit->findContents(thisScope() + name); if(!matches.empty()) { DataMemberPtr p = DataMemberPtr::dynamicCast(matches.front()); if(p) { if(_unit->ignRedefs()) { p->updateIncludeLevel(); return p; } } if(!_unit->caseSensitive() && matches.front()->name() != name) { string msg = "member `" + name + "' differs only in capitalization from "; msg += "member `" + matches.front()->name() + "'"; _unit->error(msg); } else { string msg = "redefinition of struct member `" + name + "'"; _unit->error(msg); return 0; } } // // Check whether enclosing struct has the same name. // if(name == this->name()) { string msg = "struct name `"; msg += name; msg += "' cannot be used as member name"; _unit->error(msg); return 0; } if(!_unit->caseSensitive()) { string newName = name; toLower(newName); string thisName = this->name(); toLower(thisName); if(newName == thisName) { string msg = "struct member `" + name + "' differs only in capitalization from enclosing struct name `"; msg += this->name() + "'"; _unit->error(msg); } } // // Structures cannot contain themselves. // if(type.get() == this) { string msg = "struct `"; msg += this->name(); msg += "' cannot contain itself"; _unit->error(msg); return 0; } // // If data member is local, enclosing class/interface must be local. // if(!isLocal() && type->isLocal()) { string msg = "non-local " + kindOf() + "`" + this->name() + "' cannot contain local member `" + name + "'"; _unit->error(msg); } DataMemberPtr p = new DataMember(this, name, type); _contents.push_back(p); return p; } DataMemberList Slice::Struct::dataMembers() const { DataMemberList result; for(ContainedList::const_iterator p = _contents.begin(); p != _contents.end(); ++p) { DataMemberPtr q = DataMemberPtr::dynamicCast(*p); if(q) { result.push_back(q); } } return result; } DataMemberList Slice::Struct::classDataMembers() const { DataMemberList result; for(ContainedList::const_iterator p = _contents.begin(); p != _contents.end(); ++p) { DataMemberPtr q = DataMemberPtr::dynamicCast(*p); if(q) { BuiltinPtr builtin = BuiltinPtr::dynamicCast(q->type()); if((builtin && builtin->kind() == Builtin::KindObject) || ClassDeclPtr::dynamicCast(q->type())) { result.push_back(q); } } } return result; } Contained::ContainedType Slice::Struct::containedType() const { return ContainedTypeStruct; } bool Slice::Struct::uses(const ContainedPtr&) const { return false; } bool Slice::Struct::usesClasses() const { for(ContainedList::const_iterator p = _contents.begin(); p != _contents.end(); ++p) { DataMemberPtr q = DataMemberPtr::dynamicCast(*p); if(q) { TypePtr t = q->type(); if(t->usesClasses()) { return true; } } } return false; } size_t Slice::Struct::minWireSize() const { // // At least the sum of the minimum member sizes. // size_t sz = 0; DataMemberList dml = dataMembers(); for(DataMemberList::const_iterator i = dml.begin(); i != dml.end(); ++i) { sz += (*i)->type()->minWireSize(); } return sz; } bool Slice::Struct::isVariableLength() const { DataMemberList dml = dataMembers(); for(DataMemberList::const_iterator i = dml.begin(); i != dml.end(); ++i) { if((*i)->type()->isVariableLength()) { return true; } } return false; } string Slice::Struct::kindOf() const { return "struct"; } void Slice::Struct::visit(ParserVisitor* visitor, bool all) { if(visitor->visitStructStart(this)) { Container::visit(visitor, all); visitor->visitStructEnd(this); } } void Slice::Struct::recDependencies(set& dependencies) { containerRecDependencies(dependencies); } Slice::Struct::Struct(const ContainerPtr& container, const string& name, bool local) : SyntaxTreeBase(container->unit()), Container(container->unit()), Type(container->unit()), Contained(container, name), Constructed(container, name, local) { } // ---------------------------------------------------------------------- // Sequence // ---------------------------------------------------------------------- TypePtr Slice::Sequence::type() const { return _type; } StringList Slice::Sequence::typeMetaData() const { return _typeMetaData; } Contained::ContainedType Slice::Sequence::containedType() const { return ContainedTypeSequence; } bool Slice::Sequence::uses(const ContainedPtr& contained) const { ContainedPtr contained2 = ContainedPtr::dynamicCast(_type); if(contained2 && contained2 == contained) { return true; } return false; } bool Slice::Sequence::usesClasses() const { return _type->usesClasses(); } size_t Slice::Sequence::minWireSize() const { return 1; // An empty sequence. } bool Slice::Sequence::isVariableLength() const { return true; } string Slice::Sequence::kindOf() const { return "sequence"; } void Slice::Sequence::visit(ParserVisitor* visitor, bool) { visitor->visitSequence(this); } void Slice::Sequence::recDependencies(set& dependencies) { ConstructedPtr constructed = ConstructedPtr::dynamicCast(_type); if(constructed && dependencies.find(constructed) != dependencies.end()) { dependencies.insert(constructed); constructed->recDependencies(dependencies); } } Slice::Sequence::Sequence(const ContainerPtr& container, const string& name, const TypePtr& type, const StringList& typeMetaData, bool local) : SyntaxTreeBase(container->unit()), Type(container->unit()), Contained(container, name), Constructed(container, name, local), _type(type), _typeMetaData(typeMetaData) { } // ---------------------------------------------------------------------- // Dictionary // ---------------------------------------------------------------------- TypePtr Slice::Dictionary::keyType() const { return _keyType; } TypePtr Slice::Dictionary::valueType() const { return _valueType; } StringList Slice::Dictionary::keyMetaData() const { return _keyMetaData; } StringList Slice::Dictionary::valueMetaData() const { return _valueMetaData; } Contained::ContainedType Slice::Dictionary::containedType() const { return ContainedTypeDictionary; } bool Slice::Dictionary::uses(const ContainedPtr& contained) const { { ContainedPtr contained2 = ContainedPtr::dynamicCast(_keyType); if(contained2 && contained2 == contained) { return true; } } { ContainedPtr contained2 = ContainedPtr::dynamicCast(_valueType); if(contained2 && contained2 == contained) { return true; } } return false; } bool Slice::Dictionary::usesClasses() const { return _valueType->usesClasses(); } size_t Slice::Dictionary::minWireSize() const { return 1; // An empty dictionary. } bool Slice::Dictionary::isVariableLength() const { return true; } string Slice::Dictionary::kindOf() const { return "dictionary"; } void Slice::Dictionary::visit(ParserVisitor* visitor, bool) { visitor->visitDictionary(this); } void Slice::Dictionary::recDependencies(set& dependencies) { { ConstructedPtr constructed = ConstructedPtr::dynamicCast(_keyType); if(constructed && dependencies.find(constructed) != dependencies.end()) { dependencies.insert(constructed); constructed->recDependencies(dependencies); } } { ConstructedPtr constructed = ConstructedPtr::dynamicCast(_valueType); if(constructed && dependencies.find(constructed) != dependencies.end()) { dependencies.insert(constructed); constructed->recDependencies(dependencies); } } } // // Check that the key type of a dictionary is legal. Legal types are // integral types, string, and sequences and structs containing only // other legal key types. // bool Slice::Dictionary::legalKeyType(const TypePtr& type) { BuiltinPtr bp = BuiltinPtr::dynamicCast(type); if(bp) { switch(bp->kind()) { case Builtin::KindByte: case Builtin::KindBool: case Builtin::KindShort: case Builtin::KindInt: case Builtin::KindLong: case Builtin::KindString: { return true; break; } case Builtin::KindFloat: case Builtin::KindDouble: case Builtin::KindObject: case Builtin::KindObjectProxy: case Builtin::KindLocalObject: { return false; break; } } } EnumPtr ep = EnumPtr::dynamicCast(type); if(ep) { return true; } SequencePtr seqp = SequencePtr::dynamicCast(type); if(seqp && legalKeyType(seqp->type())) { return true; } StructPtr strp = StructPtr::dynamicCast(type); if(strp) { DataMemberList dml = strp->dataMembers(); for(DataMemberList::const_iterator mem = dml.begin(); mem != dml.end(); ++mem) { if(!legalKeyType((*mem)->type())) { return false; } } return true; } return false; } Slice::Dictionary::Dictionary(const ContainerPtr& container, const string& name, const TypePtr& keyType, const StringList& keyMetaData, const TypePtr& valueType, const StringList& valueMetaData, bool local) : SyntaxTreeBase(container->unit()), Type(container->unit()), Contained(container, name), Constructed(container, name, local), _keyType(keyType), _valueType(valueType), _keyMetaData(keyMetaData), _valueMetaData(valueMetaData) { } // ---------------------------------------------------------------------- // Enum // ---------------------------------------------------------------------- void Slice::Enum::destroy() { _enumerators.clear(); SyntaxTreeBase::destroy(); } EnumeratorList Slice::Enum::getEnumerators() { return _enumerators; } void Slice::Enum::setEnumerators(const EnumeratorList& ens) { _enumerators = ens; for(EnumeratorList::iterator p = _enumerators.begin(); p != _enumerators.end(); ++p) { (*p)->_type = this; } } Contained::ContainedType Slice::Enum::containedType() const { return ContainedTypeEnum; } bool Slice::Enum::uses(const ContainedPtr&) const { return false; } bool Slice::Enum::usesClasses() const { return false; } size_t Slice::Enum::minWireSize() const { size_t sz = _enumerators.size(); if(sz <= 0x7f) { return 1; } if(sz <= 0x7fff) { return 2; } return 4; } bool Slice::Enum::isVariableLength() const { return false; } string Slice::Enum::kindOf() const { return "enumeration"; } void Slice::Enum::visit(ParserVisitor* visitor, bool) { visitor->visitEnum(this); } void Slice::Enum::recDependencies(set&) { // An Enum does not have any dependencies. } Slice::Enum::Enum(const ContainerPtr& container, const string& name, bool local) : SyntaxTreeBase(container->unit()), Type(container->unit()), Contained(container, name), Constructed(container, name, local) { } // ---------------------------------------------------------------------- // Enumerator // ---------------------------------------------------------------------- EnumPtr Slice::Enumerator::type() const { return _type; } Contained::ContainedType Slice::Enumerator::containedType() const { return ContainedTypeEnumerator; } bool Slice::Enumerator::uses(const ContainedPtr&) const { return false; } string Slice::Enumerator::kindOf() const { return "enumerator"; } Slice::Enumerator::Enumerator(const ContainerPtr& container, const string& name) : SyntaxTreeBase(container->unit()), Contained(container, name) { } // ---------------------------------------------------------------------- // Const // ---------------------------------------------------------------------- TypePtr Slice::Const::type() const { return _type; } StringList Slice::Const::typeMetaData() const { return _typeMetaData; } string Slice::Const::value() const { return _value; } Contained::ContainedType Slice::Const::containedType() const { return ContainedTypeConstant; } bool Slice::Const::uses(const ContainedPtr& contained) const { ContainedPtr contained2 = ContainedPtr::dynamicCast(_type); return (contained2 && contained2 == contained); } string Slice::Const::kindOf() const { return "constant"; } void Slice::Const::visit(ParserVisitor* visitor, bool) { visitor->visitConst(this); } bool Slice::Const::isLegalType(const string& name, const TypePtr& constType, const UnitPtr& unit) { if(constType == 0) { return false; } BuiltinPtr ct = BuiltinPtr::dynamicCast(constType); if(ct) { switch(ct->kind()) { case Builtin::KindBool: case Builtin::KindByte: case Builtin::KindShort: case Builtin::KindInt: case Builtin::KindLong: case Builtin::KindFloat: case Builtin::KindDouble: case Builtin::KindString: { return true; break; } default: { string msg = "constant `" + name + "' has illegal type: `" + ct->kindAsString() + "'"; unit->error(msg); return false; break; } } } EnumPtr ep = EnumPtr::dynamicCast(constType); if(!ep) { string msg = "constant `" + name + "' has illegal type"; unit->error(msg); return false; } return true; } bool Slice::Const::typesAreCompatible(const string& name, const TypePtr& constType, const SyntaxTreeBasePtr& literalType, const string& value, const UnitPtr& unit) { BuiltinPtr ct = BuiltinPtr::dynamicCast(constType); #if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x530) // Strange Sun C++ 5.3 bug. const IceUtil::HandleBase& hb = literalType; BuiltinPtr lt = BuiltinPtr::dynamicCast(hb); #else BuiltinPtr lt = BuiltinPtr::dynamicCast(literalType); #endif if(ct && lt) { switch(ct->kind()) { case Builtin::KindBool: { if(lt->kind() == Builtin::KindBool) { return true; } break; } case Builtin::KindByte: case Builtin::KindShort: case Builtin::KindInt: case Builtin::KindLong: { if(lt->kind() == Builtin::KindLong) { return true; } break; } case Builtin::KindFloat: case Builtin::KindDouble: { if(lt->kind() == Builtin::KindDouble) { return true; } break; } case Builtin::KindString: { if(lt->kind() == Builtin::KindString) { return true; } break; } case Builtin::KindObject: case Builtin::KindObjectProxy: case Builtin::KindLocalObject: { assert(false); break; } } string msg = "initializer of type `" + lt->kindAsString(); msg += "' is incompatible with the type `" + ct->kindAsString() + "' of constant `" + name + "'"; unit->error(msg); return false; } if(ct && !lt) { string msg = "type of initializer is incompatible with the type `" + ct->kindAsString(); msg += "' of constant `" + name + "'"; unit->error(msg); return false; } EnumPtr enumP = EnumPtr::dynamicCast(constType); assert(enumP); EnumeratorPtr enumeratorP = EnumeratorPtr::dynamicCast(literalType); if(!enumeratorP) { string msg = "type of initializer is incompatible with the type of constant `" + name + "'"; unit->error(msg); return false; } EnumeratorList elist = enumP->getEnumerators(); if(find(elist.begin(), elist.end(), enumeratorP) == elist.end()) { string msg = "enumerator `" + value + "' is not defined in enumeration `" + enumP->scoped() + "'"; unit->error(msg); return false; } return true; } bool Slice::Const::isInRange(const string& name, const TypePtr& constType, const string& value, const UnitPtr& unit) { BuiltinPtr ct = BuiltinPtr::dynamicCast(constType); if (!ct) { return true; // Enums are checked elsewhere. } switch(ct->kind()) { case Builtin::KindByte: { IceUtil::Int64 l = IceUtil::strToInt64(value.c_str(), 0, 0); if(l < ByteMin || l > ByteMax) { string msg = "initializer `" + value + "' for constant `" + name + "' out of range for type byte"; unit->error(msg); return false; } break; } case Builtin::KindShort: { IceUtil::Int64 l = IceUtil::strToInt64(value.c_str(), 0, 0); if(l < Int16Min || l > Int16Max) { string msg = "initializer `" + value + "' for constant `" + name + "' out of range for type short"; unit->error(msg); return false; } break; } case Builtin::KindInt: { IceUtil::Int64 l = IceUtil::strToInt64(value.c_str(), 0, 0); if(l < Int32Min || l > Int32Max) { string msg = "initializer `" + value + "' for constant `" + name + "' out of range for type int"; unit->error(msg); return false; } break; } default: { break; } } return true; // Everything else is either in range or doesn't need checking. } Slice::Const::Const(const ContainerPtr& container, const string& name, const TypePtr& type, const StringList& typeMetaData, const string& value) : SyntaxTreeBase(container->unit()), Contained(container, name), _type(type), _typeMetaData(typeMetaData), _value(value) { } // ---------------------------------------------------------------------- // Operation // ---------------------------------------------------------------------- TypePtr Slice::Operation::returnType() const { return _returnType; } Operation::Mode Slice::Operation::mode() const { return _mode; } Operation::Mode Slice::Operation::sendMode() const { if(_mode == Operation::Idempotent && hasMetaData("nonmutating")) { return Operation::Nonmutating; } else { return _mode; } } ParamDeclPtr Slice::Operation::createParamDecl(const string& name, const TypePtr& type, bool isOutParam) { checkPrefix(name); if(_unit->profile() == IceE) { ClassDefPtr cl = ClassDefPtr::dynamicCast(this->container()); assert(cl); if(!cl->isLocal()) { BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); if((builtin && builtin->kind() == Builtin::KindObject)) { string msg = "Object `" + name + "' cannot be passed by value."; _unit->error(msg); return 0; } ClassDeclPtr classDecl = ClassDeclPtr::dynamicCast(type); if(classDecl != 0 && !classDecl->isLocal()) { string msg = "Object `" + name + "' cannot be passed by value."; _unit->error(msg); return 0; } } } ContainedList matches = _unit->findContents(thisScope() + name); if(!matches.empty()) { ParamDeclPtr p = ParamDeclPtr::dynamicCast(matches.front()); if(p) { if(_unit->ignRedefs()) { p->updateIncludeLevel(); return p; } } if(!_unit->caseSensitive() && matches.front()->name() != name) { string msg = "parameter `" + name + "' differs only in capitalization from "; msg += "parameter `" + matches.front()->name() + "'"; _unit->error(msg); } else { string msg = "redefinition of parameter `" + name + "'"; _unit->error(msg); return 0; } } // // Check whether enclosing operation has the same name. // if(name == this->name()) { string msg = "operation name `"; msg += name; msg += "' cannot be used as parameter name"; _unit->error(msg); return 0; } if(!_unit->caseSensitive()) { string newName = name; toLower(newName); string thisName = this->name(); toLower(thisName); if(newName == thisName) { string msg = "parameter `" + name + "' differs only in capitalization from operation name `"; msg += this->name() + "'"; _unit->error(msg); } } // // Check that in parameters don't follow out parameters. // if(!_contents.empty()) { ParamDeclPtr p = ParamDeclPtr::dynamicCast(_contents.back()); assert(p); if(p->isOutParam() && !isOutParam) { _unit->error("`" + name + "': in parameters cannot follow out parameters"); } } // // Non-local class/interface cannot have operation with local parameters. // ClassDefPtr cl = ClassDefPtr::dynamicCast(this->container()); assert(cl); if(type->isLocal() && !cl->isLocal()) { string msg = "non-local " + cl->kindOf() + " `" + cl->name() + "' cannot have local parameter `"; msg += name + "' in operation `" + this->name() + "'"; _unit->error(msg); } ParamDeclPtr p = new ParamDecl(this, name, type, isOutParam); _contents.push_back(p); return p; } ParamDeclList Slice::Operation::parameters() const { ParamDeclList result; for(ContainedList::const_iterator p = _contents.begin(); p != _contents.end(); ++p) { ParamDeclPtr q = ParamDeclPtr::dynamicCast(*p); if(q) { result.push_back(q); } } return result; } ExceptionList Slice::Operation::throws() const { return _throws; } void Slice::Operation::setExceptionList(const ExceptionList& el) { _throws = el; // // Check that no exception occurs more than once in the throws clause. // ExceptionList uniqueExceptions = el; uniqueExceptions.sort(); uniqueExceptions.unique(); if(uniqueExceptions.size() != el.size()) { // // At least one exception appears twice. // ExceptionList tmp = el; tmp.sort(); ExceptionList duplicates; set_difference(tmp.begin(), tmp.end(), uniqueExceptions.begin(), uniqueExceptions.end(), back_inserter(duplicates)); string msg = "operation `" + name() + "' has a throws clause with "; if(duplicates.size() == 1) { msg += "a "; } msg += "duplicate exception"; if(duplicates.size() > 1) { msg += "s"; } ExceptionList::const_iterator i = duplicates.begin(); msg += ": `" + (*i)->name() + "'"; for(i = ++i; i != duplicates.end(); ++i) { msg += ", `" + (*i)->name() + "'"; } _unit->error(msg); } // // If the interface is non-local, no local exception can be thrown. // ClassDefPtr cl = ClassDefPtr::dynamicCast(container()); assert(cl); if(!cl->isLocal()) { for(ExceptionList::const_iterator ep = el.begin(); ep != el.end(); ++ep) { if((*ep)->isLocal()) { string msg = "non-local " + cl->kindOf() + " `" + cl->name() + "' cannot have operation `"; msg += name() + "' throwing local exception `" + (*ep)->name() + "'"; _unit->error(msg); } } } } Contained::ContainedType Slice::Operation::containedType() const { return ContainedTypeOperation; } bool Slice::Operation::uses(const ContainedPtr& contained) const { { ContainedPtr contained2 = ContainedPtr::dynamicCast(_returnType); if(contained2 && contained2 == contained) { return true; } } ExceptionList::const_iterator q; for(q = _throws.begin(); q != _throws.end(); ++q) { ContainedPtr contained2 = ContainedPtr::dynamicCast(*q); if(contained2 && contained2 == contained) { return true; } } return false; } bool Slice::Operation::sendsClasses() const { ParamDeclList pdl = parameters(); for(ParamDeclList::const_iterator i = pdl.begin(); i != pdl.end(); ++i) { if(!(*i)->isOutParam() && (*i)->type()->usesClasses()) { return true; } } return false; } bool Slice::Operation::returnsClasses() const { TypePtr t = returnType(); if(t && t->usesClasses()) { return true; } ParamDeclList pdl = parameters(); for(ParamDeclList::const_iterator i = pdl.begin(); i != pdl.end(); ++i) { if((*i)->isOutParam() && (*i)->type()->usesClasses()) { return true; } } return false; } bool Slice::Operation::returnsData() const { TypePtr t = returnType(); if(t) { return true; } ParamDeclList pdl = parameters(); for(ParamDeclList::const_iterator i = pdl.begin(); i != pdl.end(); ++i) { if((*i)->isOutParam()) { return true; } } if(!throws().empty()) { return true; } return false; } string Slice::Operation::kindOf() const { return "operation"; } void Slice::Operation::visit(ParserVisitor* visitor, bool) { visitor->visitOperation(this); } Slice::Operation::Operation(const ContainerPtr& container, const string& name, const TypePtr& returnType, Mode mode) : SyntaxTreeBase(container->unit()), Contained(container, name), Container(container->unit()), _returnType(returnType), _mode(mode) { if(_unit->profile() == IceE) { ClassDefPtr cl = ClassDefPtr::dynamicCast(this->container()); assert(cl); if(!cl->isLocal()) { BuiltinPtr builtin = BuiltinPtr::dynamicCast(returnType); if((builtin && builtin->kind() == Builtin::KindObject)) { string msg = "Method `" + name + "' cannot return an object by value."; _unit->error(msg); } ClassDeclPtr classDecl = ClassDeclPtr::dynamicCast(returnType); if(classDecl != 0 && !classDecl->isLocal()) { string msg = "Method `" + name + "' cannot return an object by value."; _unit->error(msg); } } } } // ---------------------------------------------------------------------- // ParamDecl // ---------------------------------------------------------------------- TypePtr Slice::ParamDecl::type() const { return _type; } bool Slice::ParamDecl::isOutParam() const { return _isOutParam; } Contained::ContainedType Slice::ParamDecl::containedType() const { return ContainedTypeDataMember; } bool Slice::ParamDecl::uses(const ContainedPtr& contained) const { ContainedPtr contained2 = ContainedPtr::dynamicCast(_type); if(contained2 && contained2 == contained) { return true; } return false; } string Slice::ParamDecl::kindOf() const { return "parameter declaration"; } void Slice::ParamDecl::visit(ParserVisitor* visitor, bool) { visitor->visitParamDecl(this); } Slice::ParamDecl::ParamDecl(const ContainerPtr& container, const string& name, const TypePtr& type, bool isOutParam) : SyntaxTreeBase(container->unit()), Contained(container, name), _type(type), _isOutParam(isOutParam) { } // ---------------------------------------------------------------------- // DataMember // ---------------------------------------------------------------------- TypePtr Slice::DataMember::type() const { return _type; } Contained::ContainedType Slice::DataMember::containedType() const { return ContainedTypeDataMember; } bool Slice::DataMember::uses(const ContainedPtr& contained) const { ContainedPtr contained2 = ContainedPtr::dynamicCast(_type); if(contained2 && contained2 == contained) { return true; } return false; } string Slice::DataMember::kindOf() const { return "data member"; } void Slice::DataMember::visit(ParserVisitor* visitor, bool) { visitor->visitDataMember(this); } Slice::DataMember::DataMember(const ContainerPtr& container, const string& name, const TypePtr& type) : SyntaxTreeBase(container->unit()), Contained(container, name), _type(type) { } // ---------------------------------------------------------------------- // Unit // ---------------------------------------------------------------------- UnitPtr Slice::Unit::createUnit(bool ignRedefs, bool all, bool allowIcePrefix, bool caseSensitive, const StringList& defaultGlobalMetadata) { return new Unit(ignRedefs, all, allowIcePrefix, caseSensitive, defaultGlobalMetadata); } bool Slice::Unit::ignRedefs() const { return _ignRedefs; } bool Slice::Unit::allowIcePrefix() const { return _allowIcePrefix; } bool Slice::Unit::caseSensitive() const { return _caseSensitive; } void Slice::Unit::setComment(const string& comment) { _currentComment = ""; string::size_type end = 0; while(true) { string::size_type begin = comment.find_first_not_of(" \t\r\n*", end); if(begin == string::npos) { break; } end = comment.find('\n', begin); if(end != string::npos) { if(end + 1 > begin) { _currentComment += comment.substr(begin, end + 1 - begin); } } else { end = comment.find_last_not_of(" \t\r\n*"); if(end != string::npos) { if(end + 1 > begin) { _currentComment += comment.substr(begin, end + 1 - begin); } } break; } } } string Slice::Unit::currentComment() { string comment = ""; comment.swap(_currentComment); return comment; } string Slice::Unit::currentFile() const { DefinitionContextPtr dc = currentDefinitionContext(); if(dc) { return dc->filename(); } else { return string(); } } int Slice::Unit::currentLine() const { return _currentLine; } void Slice::Unit::nextLine() { _currentLine++; } void Slice::Unit::scanPosition(const char* s) { assert(*s == '#'); string line(s + 1); // Skip leading # eraseWhiteSpace(line); if(line.find("line", 0) == 0) // Erase optional "line" { line.erase(0, 4); eraseWhiteSpace(line); } string::size_type idx; _currentLine = atoi(line.c_str()) - 1; // Read line number idx = line.find_first_of(" \t\r"); // Erase line number if(idx != string::npos) { line.erase(0, idx); } eraseWhiteSpace(line); // // If the string ends in 1 or 2, it is a push or pop directive. // enum LineType { File, Push, Pop }; LineType type = File; idx = line.find_last_of(" \t\r"); if(idx != string::npos) { ++idx; if(line.substr(idx) == "1") { type = Push; line.erase(idx); eraseWhiteSpace(line); } else if(line.substr(idx) == "2") { type = Pop; line.erase(idx); eraseWhiteSpace(line); } } string currentFile; if(!line.empty()) { if(line[0] == '"') { idx = line.rfind('"'); if(idx != string::npos) { currentFile = line.substr(1, idx - 1); } } else { currentFile = line; } } switch(type) { case Push: { if(++_currentIncludeLevel == 1) { if(find(_includeFiles.begin(), _includeFiles.end(), currentFile) == _includeFiles.end()) { _includeFiles.push_back(currentFile); } } pushDefinitionContext(); _currentComment = ""; break; } case Pop: { --_currentIncludeLevel; popDefinitionContext(); _currentComment = ""; break; } default: { break; // Do nothing } } if(!currentFile.empty()) { DefinitionContextPtr dc = currentDefinitionContext(); assert(dc); dc->setFilename(currentFile); } } int Slice::Unit::currentIncludeLevel() const { if(_all) { return 0; } else { return _currentIncludeLevel; } } void Slice::Unit::addGlobalMetaData(const StringList& metaData) { DefinitionContextPtr dc = currentDefinitionContext(); assert(dc); if(dc->seenDefinition()) { error("global metadata must appear before any definitions"); } else { StringList l = dc->getMetaData(); copy(metaData.begin(), metaData.end(), back_inserter(l)); dc->setMetaData(l); } } void Slice::Unit::setSeenDefinition() { DefinitionContextPtr dc = currentDefinitionContext(); assert(dc); dc->setSeenDefinition(); } void Slice::Unit::error(const char* s) { string file = currentFile(); if(!file.empty()) { cout << file << ':' << _currentLine << ": "; } cout << s << endl; _errors++; } void Slice::Unit::error(const string& s) { error(s.c_str()); } void Slice::Unit::warning(const char* s) const { string file = currentFile(); if(!file.empty()) { cout << file << ':' << _currentLine << ": "; } cout << "warning: " << s << endl; } void Slice::Unit::warning(const string& s) const { warning(s.c_str()); } ContainerPtr Slice::Unit::currentContainer() const { assert(!_containerStack.empty()); return _containerStack.top(); } void Slice::Unit::pushContainer(const ContainerPtr& cont) { _containerStack.push(cont); } void Slice::Unit::popContainer() { assert(!_containerStack.empty()); _containerStack.pop(); } DefinitionContextPtr Slice::Unit::currentDefinitionContext() const { DefinitionContextPtr dc; if(!_definitionContextStack.empty()) { dc = _definitionContextStack.top(); } return dc; } void Slice::Unit::pushDefinitionContext() { _definitionContextStack.push(new DefinitionContext(_currentIncludeLevel, _defaultGlobalMetadata)); } void Slice::Unit::popDefinitionContext() { assert(!_definitionContextStack.empty()); _definitionContextStack.pop(); } void Slice::Unit::addContent(const ContainedPtr& contained) { string scoped = contained->scoped(); if(!caseSensitive()) { toLower(scoped); } _contentMap[scoped].push_back(contained); } void Slice::Unit::removeContent(const ContainedPtr& contained) { string scoped = contained->scoped(); if(!caseSensitive()) { toLower(scoped); } map::iterator p = _contentMap.find(scoped); assert(p != _contentMap.end()); ContainedList::iterator q; for(q = p->second.begin(); q != p->second.end(); ++q) { if(q->get() == contained.get()) { p->second.erase(q); return; } } assert(false); } ContainedList Slice::Unit::findContents(const string& scoped) const { assert(!scoped.empty()); assert(scoped[0] == ':'); string name = scoped; if(!_unit->caseSensitive()) { toLower(name); } map::const_iterator p = _contentMap.find(name); if(p != _contentMap.end()) { return p->second; } else { return ContainedList(); } } ClassList Slice::Unit::findDerivedClasses(const ClassDefPtr& cl) const { ClassList derived; for(map::const_iterator p = _contentMap.begin(); p != _contentMap.end(); ++p) { for(ContainedList::const_iterator q = p->second.begin(); q != p->second.end(); ++q) { ClassDefPtr r = ClassDefPtr::dynamicCast(*q); if(r) { ClassList bases = r->bases(); if(find(bases.begin(), bases.end(), cl) != bases.end()) { derived.push_back(r); } } } } derived.sort(); derived.unique(); return derived; } ExceptionList Slice::Unit::findDerivedExceptions(const ExceptionPtr& ex) const { ExceptionList derived; for(map::const_iterator p = _contentMap.begin(); p != _contentMap.end(); ++p) { for(ContainedList::const_iterator q = p->second.begin(); q != p->second.end(); ++q) { ExceptionPtr r = ExceptionPtr::dynamicCast(*q); if(r) { ExceptionPtr base = r->base(); if(base && base == ex) { derived.push_back(r); } } } } derived.sort(); derived.unique(); return derived; } ContainedList Slice::Unit::findUsedBy(const ContainedPtr& contained) const { ContainedList usedBy; for(map::const_iterator p = _contentMap.begin(); p != _contentMap.end(); ++p) { for(ContainedList::const_iterator q = p->second.begin(); q != p->second.end(); ++q) { if((*q)->uses(contained)) { usedBy.push_back(*q); } } } usedBy.sort(); usedBy.unique(); return usedBy; } bool Slice::Unit::usesProxies() const { for(map::const_iterator p = _contentMap.begin(); p != _contentMap.end(); ++p) { for(ContainedList::const_iterator q = p->second.begin(); q != p->second.end(); ++q) { ClassDeclPtr decl = ClassDeclPtr::dynamicCast(*q); if(decl && !decl->isLocal()) { return true; } } } if(_builtins.find(Builtin::KindObjectProxy) != _builtins.end()) { return true; } return false; } bool Slice::Unit::usesNonLocals() const { for(map::const_iterator p = _contentMap.begin(); p != _contentMap.end(); ++p) { for(ContainedList::const_iterator q = p->second.begin(); q != p->second.end(); ++q) { ConstructedPtr constr = ConstructedPtr::dynamicCast(*q); if(constr && !constr->isLocal()) { return true; } ExceptionPtr exc = ExceptionPtr::dynamicCast(*q); if(exc && !exc->isLocal()) { return true; } } } if(_builtins.find(Builtin::KindObject) != _builtins.end()) { return true; } if(_builtins.find(Builtin::KindObjectProxy) != _builtins.end()) { return true; } return false; } bool Slice::Unit::usesConsts() const { for(map::const_iterator p = _contentMap.begin(); p != _contentMap.end(); ++p) { for(ContainedList::const_iterator q = p->second.begin(); q != p->second.end(); ++q) { ConstPtr cd = ConstPtr::dynamicCast(*q); if(cd) { return true; } } } return false; } FeatureProfile Slice::Unit::profile() const { return _featureProfile; } StringList Slice::Unit::includeFiles() const { return _includeFiles; } int Slice::Unit::parse(FILE* file, bool debug, Slice::FeatureProfile profile) { slice_debug = debug ? 1 : 0; assert(!Slice::unit); Slice::unit = this; _currentComment = ""; _currentLine = 1; _currentIncludeLevel = 0; _featureProfile = profile; pushContainer(this); pushDefinitionContext(); slice_in = file; int status = slice_parse(); if(_errors) { status = EXIT_FAILURE; } if(status == EXIT_FAILURE) { while(!_containerStack.empty()) { popContainer(); } while(!_definitionContextStack.empty()) { popDefinitionContext(); } } else { assert(_containerStack.size() == 1); popContainer(); assert(_definitionContextStack.size() == 1); popDefinitionContext(); } Slice::unit = 0; return status; } void Slice::Unit::destroy() { _contentMap.clear(); _builtins.clear(); Container::destroy(); } void Slice::Unit::visit(ParserVisitor* visitor, bool all) { if(visitor->visitUnitStart(this)) { Container::visit(visitor, all); visitor->visitUnitEnd(this); } } BuiltinPtr Slice::Unit::builtin(Builtin::Kind kind) { map::const_iterator p = _builtins.find(kind); if(p != _builtins.end()) { return p->second; } BuiltinPtr builtin = new Builtin(this, kind); _builtins.insert(make_pair(kind, builtin)); return builtin; } Slice::Unit::Unit(bool ignRedefs, bool all, bool allowIcePrefix, bool caseSensitive, const StringList& defaultGlobalMetadata) : SyntaxTreeBase(0), Container(0), _ignRedefs(ignRedefs), _all(all), _allowIcePrefix(allowIcePrefix), _caseSensitive(caseSensitive), _defaultGlobalMetadata(defaultGlobalMetadata), _errors(0) { _unit = this; } void Slice::Unit::eraseWhiteSpace(string& s) { string::size_type idx = s.find_first_not_of(" \t\r"); if(idx != string::npos) { s.erase(0, idx); } idx = s.find_last_not_of(" \t\r"); if(idx != string::npos) { s.erase(++idx); } } // ---------------------------------------------------------------------- // CICompare // ---------------------------------------------------------------------- bool Slice::CICompare::operator()(const string& s1, const string& s2) const { string::const_iterator p1 = s1.begin(); string::const_iterator p2 = s2.begin(); while(p1 != s1.end() && p2 != s2.end() && ::tolower(*p1) == ::tolower(*p2)) { ++p1; ++p2; } if(p1 == s1.end() && p2 == s2.end()) { return false; } else if(p1 == s1.end()) { return true; } else if(p2 == s2.end()) { return false; } else { return ::tolower(*p1) < ::tolower(*p2); } } #if defined(__SUNPRO_CC) bool Slice::cICompare(const std::string& s1, const std::string& s2) { CICompare c; return c(s1, s2); } #endif // ---------------------------------------------------------------------- // DerivedToBaseCompare // ---------------------------------------------------------------------- bool Slice::DerivedToBaseCompare::operator()(const ExceptionPtr& e1, const ExceptionPtr& e2) const { return e2->isBaseOf(e1); } #if defined(__SUNPRO_CC) bool Slice::derivedToBaseCompare(const ExceptionPtr& e1, const ExceptionPtr& e2) { return e2->isBaseOf(e1); } #endif IceE-trans-1.2.0/src/Slice/DotNetNames.cpp0000774000076400007640000000737210560413774017553 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 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 using namespace std; namespace Slice { namespace DotNet { struct Node { const char** names; const Node** parents; }; static const char* ObjectNames[] = { "Equals", "Finalize", "GetHashCode", "GetType", "MemberwiseClone", "ReferenceEquals", "ToString", 0 }; static const Node* ObjectParents[] = { 0 }; static const Node ObjectNode = { ObjectNames, &ObjectParents[0] }; static const char* ICloneableNames[] = { "Clone", 0 }; static const Node* ICloneableParents[] = { &ObjectNode, 0 }; static const Node ICloneableNode = { ICloneableNames, &ICloneableParents[0] }; static const char* ExceptionNames[] = { "GetBaseException", "GetObjectData", "HelpLink", "HResult", "InnerException", "Message", "Source", "StackTrace", "TargetSite", 0 }; static const Node* ExceptionParents[] = { &ObjectNode, 0 }; static const Node ExceptionNode = { ExceptionNames, &ExceptionParents[0] }; static const char* ApplicationExceptionNames[] = { 0 }; static const Node* ApplicationExceptionParents[] = { &ExceptionNode, 0 }; static const Node ApplicationExceptionNode = { ApplicationExceptionNames, &ApplicationExceptionParents[0] }; // // Must be kept in same order as definition of BaseType in header file! // static const Node* nodes[] = { &ObjectNode, &ICloneableNode, &ExceptionNode, &ApplicationExceptionNode }; static bool ciEquals(const string& s, const char* p) { if(s.size() != strlen(p)) { return false; } string::const_iterator i = s.begin(); while(i != s.end()) { if(tolower(*i++) != tolower(*p++)) { return false; } } return true; } const char* manglePrefix = "ice_"; const char* mangleSuffix = "_"; static bool mangle(const string& s, const Node* np, string& newName) { const char** namep = np->names; while(*namep) { if(ciEquals(s, *namep)) { newName = manglePrefix + s + mangleSuffix; return true; } ++namep; } const Node** parentp = np->parents; while(*parentp) { if(mangle(s, *parentp, newName)) { return true; } ++parentp; } return false; } } } string Slice::DotNet::mangleName(const string& s, int baseTypes) { if(baseTypes == 0) { return s; } string newName; for(unsigned int mask = 1, i=0; mask < END; mask <<= 1, ++i) { if(baseTypes & mask) { if(mangle(s, nodes[i], newName)) { return newName; } } } return s; } IceE-trans-1.2.0/src/Slice/CPlusPlusUtil.cpp0000664000076400007640000015016710616353534020120 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 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 using namespace std; using namespace Slice; using namespace IceUtil; Slice::FeatureProfile Slice::featureProfile = Slice::Ice; char Slice::ToIfdef::operator()(char c) { if(!isalnum(c)) { return '_'; } else { return c; } } string Slice::normalizePath(const string& path) { string result = path; replace(result.begin(), result.end(), '\\', '/'); string::size_type pos; while((pos = result.find("//")) != string::npos) { result.replace(pos, 2, "/"); } if(result.size() > 1 && isalpha(result[0]) && result[1] == ':') { result = result.substr(2); } return result; } string Slice::changeInclude(const string& orig, const vector& includePaths) { string file = normalizePath(orig); string::size_type pos; // // Compare each include path against the included file and select // the path that produces the shortest relative filename. // string result = file; for(vector::const_iterator p = includePaths.begin(); p != includePaths.end(); ++p) { string includePath = normalizePath(*p); if(file.compare(0, includePath.length(), includePath) == 0) { string s = file.substr(includePath.length()); if(s.size() < result.size()) { result = s; } } } if((pos = result.rfind('.')) != string::npos) { result.erase(pos); } return result; } void Slice::printHeader(Output& out) { static const char* header = "// **********************************************************************\n" "//\n" "// Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved.\n" "//\n" "// This copy of Ice is licensed to you under the terms described in the\n" "// ICE_LICENSE file included in this distribution.\n" "//\n" "// **********************************************************************\n" ; out << header; out << "\n// Ice version " << ICE_STRING_VERSION; } void Slice::printVersionCheck(Output& out) { out << "\n"; out << "\n#ifndef ICE_IGNORE_VERSION"; if(ICE_INT_VERSION % 100 > 50) { // // Beta version: exact match required // out << "\n# if ICE_INT_VERSION != " << ICE_INT_VERSION; out << "\n# error Ice version mismatch: an exact match is required for beta generated code"; out << "\n# endif"; } else { out << "\n# if ICE_INT_VERSION / 100 != " << ICE_INT_VERSION / 100; out << "\n# error Ice version mismatch!"; out << "\n# endif"; // // Generated code is release; reject beta header // out << "\n# if ICE_INT_VERSION % 100 > 50"; out << "\n# error Beta header file detected"; out << "\n# endif"; out << "\n# if ICE_INT_VERSION % 100 < " << ICE_INT_VERSION % 100; out << "\n# error Ice patch level mismatch!"; out << "\n# endif"; } out << "\n#endif"; } void Slice::printDllExportStuff(Output& out, const string& dllExport) { if(dllExport.size()) { out << sp; out << "\n#ifndef " << dllExport; out << "\n# ifdef " << dllExport << "_EXPORTS"; out << "\n# define " << dllExport << " ICE_DECLSPEC_EXPORT"; out << "\n# else"; out << "\n# define " << dllExport << " ICE_DECLSPEC_IMPORT"; out << "\n# endif"; out << "\n#endif"; } } string Slice::typeToString(const TypePtr& type, bool useWstring, const StringList& metaData, bool inParam) { static const char* builtinTable[] = { "::Ice::Byte", "bool", "::Ice::Short", "::Ice::Int", "::Ice::Long", "::Ice::Float", "::Ice::Double", "::std::string", "::Ice::ObjectPtr", "::Ice::ObjectPrx", "::Ice::LocalObjectPtr" }; BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); if(builtin) { if(builtin->kind() == Builtin::KindString) { string strType = findMetaData(metaData, true); if(strType != "string" && (useWstring || strType == "wstring")) { if(featureProfile == IceE) { return "::Ice::Wstring"; } else { return "::std::wstring"; } } } return builtinTable[builtin->kind()]; } ClassDeclPtr cl = ClassDeclPtr::dynamicCast(type); if(cl) { return fixKwd(cl->scoped() + "Ptr"); } StructPtr st = StructPtr::dynamicCast(type); if(st) { if(findMetaData(st->getMetaData(), false) == "class") { return fixKwd(st->scoped() + "Ptr"); } return fixKwd(st->scoped()); } ProxyPtr proxy = ProxyPtr::dynamicCast(type); if(proxy) { return fixKwd(proxy->_class()->scoped() + "Prx"); } SequencePtr seq = SequencePtr::dynamicCast(type); if(seq) { string seqType = findMetaData(metaData, true); if(!seqType.empty()) { if(seqType == "array" || seqType == "range:array") { if(inParam) { TypePtr elemType = seq->type(); string s = typeToString(elemType, inWstringModule(seq), seq->typeMetaData()); return "::std::pair"; } else { return fixKwd(seq->scoped()); } } else if(seqType.find("range") == 0) { if(inParam) { string s; if(seqType.find("range:") == 0) { s = seqType.substr(strlen("range:")); } else { s = fixKwd(seq->scoped()); } if(s[0] == ':') { s = " " + s; } return "::std::pair<" + s + "::const_iterator, " + s + "::const_iterator>"; } else { return fixKwd(seq->scoped()); } } else { return seqType; } } else { return fixKwd(seq->scoped()); } } ContainedPtr contained = ContainedPtr::dynamicCast(type); if(contained) { return fixKwd(contained->scoped()); } EnumPtr en = EnumPtr::dynamicCast(type); if(en) { return fixKwd(en->scoped()); } return "???"; } string Slice::returnTypeToString(const TypePtr& type, bool useWstring, const StringList& metaData) { if(!type) { return "void"; } return typeToString(type, useWstring, metaData, false); } string Slice::inputTypeToString(const TypePtr& type, bool useWstring, const StringList& metaData) { static const char* inputBuiltinTable[] = { "::Ice::Byte", "bool", "::Ice::Short", "::Ice::Int", "::Ice::Long", "::Ice::Float", "::Ice::Double", "const ::std::string&", "const ::Ice::ObjectPtr&", "const ::Ice::ObjectPrx&", "const ::Ice::LocalObjectPtr&" }; BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); if(builtin) { if(builtin->kind() == Builtin::KindString) { string strType = findMetaData(metaData, true); if(strType != "string" && (useWstring || strType == "wstring")) { if(featureProfile == IceE) { return "const ::Ice::Wstring&"; } else { return "const ::std::wstring&"; } } } return inputBuiltinTable[builtin->kind()]; } ClassDeclPtr cl = ClassDeclPtr::dynamicCast(type); if(cl) { return "const " + fixKwd(cl->scoped()) + "Ptr&"; } StructPtr st = StructPtr::dynamicCast(type); if(st) { if(findMetaData(st->getMetaData(), false) == "class") { return "const " + fixKwd(st->scoped()) + "Ptr&"; } return "const " + fixKwd(st->scoped()) + "&"; } ProxyPtr proxy = ProxyPtr::dynamicCast(type); if(proxy) { return "const " + fixKwd(proxy->_class()->scoped()) + "Prx&"; } EnumPtr en = EnumPtr::dynamicCast(type); if(en) { return fixKwd(en->scoped()); } SequencePtr seq = SequencePtr::dynamicCast(type); if(seq) { string seqType = findMetaData(metaData, true); if(!seqType.empty()) { if(seqType == "array" || seqType == "range:array") { TypePtr elemType = seq->type(); string s = typeToString(elemType, inWstringModule(seq), seq->typeMetaData()); return "const ::std::pair&"; } else if(seqType.find("range") == 0) { string s; if(seqType.find("range:") == 0) { s = seqType.substr(strlen("range:")); } else { s = fixKwd(seq->scoped()); } if(s[0] == ':') { s = " " + s; } return "const ::std::pair<" + s + "::const_iterator, " + s + "::const_iterator>&"; } else { return "const " + seqType + "&"; } } else { return "const " + fixKwd(seq->scoped()) + "&"; } } ContainedPtr contained = ContainedPtr::dynamicCast(type); if(contained) { return "const " + fixKwd(contained->scoped()) + "&"; } return "???"; } string Slice::outputTypeToString(const TypePtr& type, bool useWstring, const StringList& metaData) { static const char* outputBuiltinTable[] = { "::Ice::Byte&", "bool&", "::Ice::Short&", "::Ice::Int&", "::Ice::Long&", "::Ice::Float&", "::Ice::Double&", "::std::string&", "::Ice::ObjectPtr&", "::Ice::ObjectPrx&", "::Ice::LocalObjectPtr&" }; BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); if(builtin) { if(builtin->kind() == Builtin::KindString) { string strType = findMetaData(metaData, true); if(strType != "string" && (useWstring || strType == "wstring")) { if(featureProfile == IceE) { return "::Ice::Wstring&"; } else { return "::std::wstring&"; } } } return outputBuiltinTable[builtin->kind()]; } ClassDeclPtr cl = ClassDeclPtr::dynamicCast(type); if(cl) { return fixKwd(cl->scoped()) + "Ptr&"; } StructPtr st = StructPtr::dynamicCast(type); if(st) { if(findMetaData(st->getMetaData(), false) == "class") { return fixKwd(st->scoped()) + "Ptr&"; } return fixKwd(st->scoped()) + "&"; } ProxyPtr proxy = ProxyPtr::dynamicCast(type); if(proxy) { return fixKwd(proxy->_class()->scoped()) + "Prx&"; } SequencePtr seq = SequencePtr::dynamicCast(type); if(seq) { string seqType = findMetaData(metaData, false); if(!seqType.empty()) { return seqType + "&"; } else { return fixKwd(seq->scoped()) + "&"; } } ContainedPtr contained = ContainedPtr::dynamicCast(type); if(contained) { return fixKwd(contained->scoped()) + "&"; } return "???"; } string Slice::operationModeToString(Operation::Mode mode) { switch(mode) { case Operation::Normal: { return "::Ice::Normal"; } case Operation::Nonmutating: { return "::Ice::Nonmutating"; } case Operation::Idempotent: { return "::Ice::Idempotent"; } default: { assert(false); } } return "???"; } // // If the passed name is a keyword, return the name with a "_cxx_" prefix; // otherwise, return the name unchanged. // static string lookupKwd(const string& name) { // // Keyword list. *Must* be kept in alphabetical order. // static const string keywordList[] = { "and", "and_eq", "asm", "auto", "bit_and", "bit_or", "bool", "break", "case", "catch", "char", "class", "compl", "const", "const_cast", "continue", "default", "delete", "do", "double", "dynamic_cast", "else", "enum", "explicit", "export", "extern", "false", "float", "for", "friend", "goto", "if", "inline", "int", "long", "mutable", "namespace", "new", "not", "not_eq", "operator", "or", "or_eq", "private", "protected", "public", "register", "reinterpret_cast", "return", "short", "signed", "sizeof", "static", "static_cast", "struct", "switch", "template", "this", "throw", "true", "try", "typedef", "typeid", "typename", "union", "unsigned", "using", "virtual", "void", "volatile", "wchar_t", "while", "xor", "xor_eq" }; bool found = binary_search(&keywordList[0], &keywordList[sizeof(keywordList) / sizeof(*keywordList)], name); return found ? "_cpp_" + name : name; } // // Split a scoped name into its components and return the components as a list of (unscoped) identifiers. // static StringList splitScopedName(const string& scoped) { assert(scoped[0] == ':'); StringList ids; string::size_type next = 0; string::size_type pos; while((pos = scoped.find("::", next)) != string::npos) { pos += 2; if(pos != scoped.size()) { string::size_type endpos = scoped.find("::", pos); if(endpos != string::npos) { ids.push_back(scoped.substr(pos, endpos - pos)); } } next = pos; } if(next != scoped.size()) { ids.push_back(scoped.substr(next)); } else { ids.push_back(""); } return ids; } // // If the passed name is a scoped name, return the identical scoped name, // but with all components that are C++ keywords replaced by // their "_cxx_"-prefixed version; otherwise, if the passed name is // not scoped, but a C++ keyword, return the "_cxx_"-prefixed name; // otherwise, return the name unchanged. // string Slice::fixKwd(const string& name) { if(name[0] != ':') { return lookupKwd(name); } StringList ids = splitScopedName(name); transform(ids.begin(), ids.end(), ids.begin(), ptr_fun(lookupKwd)); stringstream result; for(StringList::const_iterator i = ids.begin(); i != ids.end(); ++i) { result << "::" + *i; } return result.str(); } void Slice::writeMarshalUnmarshalCode(Output& out, const TypePtr& type, const string& param, bool marshal, const string& str, bool pointer, const StringList& metaData, bool inParam) { string fixedParam = fixKwd(param); string stream; if(str.empty()) { stream = marshal ? "__os" : "__is"; } else { stream = str; } string deref; if(pointer) { deref = "->"; } else { deref = '.'; } string func = marshal ? "write(" : "read("; BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); if(builtin) { if(builtin->kind() == Builtin::KindObject) { if(marshal) { out << nl << stream << deref << func << fixedParam << ");"; } else { out << nl << stream << deref << func << "::Ice::__patch__ObjectPtr, &" << fixedParam << ");"; } return; } else { out << nl << stream << deref << func << fixedParam << ");"; return; } } ClassDeclPtr cl = ClassDeclPtr::dynamicCast(type); if(cl) { string scope = fixKwd(cl->scope()); if(marshal) { out << nl << stream << deref << "write(::Ice::ObjectPtr(::IceInternal::upCast(" << fixedParam << ".get())));"; } else { out << nl << stream << deref << "read(" << scope << "__patch__" << cl->name() << "Ptr, &" << fixedParam << ");"; } return; } ProxyPtr px = ProxyPtr::dynamicCast(type); if(px) { string scope = fixKwd(px->_class()->scope()); if(marshal) { out << nl << stream << deref << "write(::Ice::ObjectPrx(::IceInternal::upCast(" << fixedParam << ".get())));"; } else { out << nl << scope << "__read(" << (pointer ? "" : "&") << stream << ", " << fixedParam << ");"; } return; } StructPtr st = StructPtr::dynamicCast(type); if(st) { string deref; if(findMetaData(st->getMetaData(), false) == "class") { if(!marshal) { out << nl << fixedParam << " = new " << fixKwd(st->scoped()) << ";"; } out << nl << fixedParam << "->__" << func << (pointer ? "" : "&") << stream << ");"; } else { out << nl << fixedParam << ".__" << func << (pointer ? "" : "&") << stream << ");"; } return; } SequencePtr seq = SequencePtr::dynamicCast(type); if(seq) { string seqType = findMetaData(metaData, inParam); builtin = BuiltinPtr::dynamicCast(seq->type()); string funcSeq = (marshal ? "write" : "read") + fixKwd(seq->name()) + "("; if(marshal) { string scope = fixKwd(seq->scope()); if(seqType == "array" || seqType == "range:array") { // // Use array (pair). In parameters only. // if(!builtin || builtin->kind() == Builtin::KindObject || builtin->kind() == Builtin::KindObjectProxy) { // // Sequence type in not handled by BasicStream functions. If the sequence is the // default vector than we can use the sequences generated write function. Otherwise // we need to generate marshal code to write each element. // StringList l = seq->getMetaData(); seqType = findMetaData(l, false); if(seqType.empty()) { out << nl << scope << "__" << funcSeq << (pointer ? "" : "&") << stream << ", " << fixedParam << ".first, " << fixedParam << ".second);"; } else { out << nl << "::Ice::Int __sz_" << fixedParam << " = static_cast< ::Ice::Int>(" << fixedParam << ".second - " << fixedParam << ".first);"; out << nl << stream << deref << "writeSize(__sz_" << fixedParam << ");"; out << nl << "for(int __i_" << fixedParam << " = 0; __i_" << fixedParam << " < __sz_" << fixedParam << "; ++__i_" << fixedParam << ")"; out << sb; writeMarshalUnmarshalCode(out, seq->type(), fixedParam + ".first[__i_" + fixedParam + "]", true); out << eb; } } else { // // Use BasicStream write functions. // out << nl << stream << deref << func << fixedParam << ".first, " << fixedParam << ".second);"; } } else if(seqType.find("range") == 0) { // // Use range (pairscoped()); } out << nl << stream << deref << "writeSize(static_cast< ::Ice::Int>(ice_distance(" << fixedParam << ".first, " << fixedParam << ".second)));"; out << nl << "for(" << seqType << "::const_iterator ___" << fixedParam << " = " << fixedParam << ".first; ___" << fixedParam << " != " << fixedParam << ".second; ++___" << fixedParam << ")"; out << sb; writeMarshalUnmarshalCode(out, seq->type(), "(*___" + fixedParam + ")", true, "", true, l, false); out << eb; } else if(!seqType.empty()) { out << nl << stream << deref << "writeSize(static_cast< ::Ice::Int>(" << fixedParam << ".size()));"; out << nl << seqType << "::const_iterator __p_" << fixedParam << ";"; out << nl << "for(__p_" << fixedParam << " = " << fixedParam << ".begin(); __p_" << fixedParam << " != " << fixedParam << ".end(); ++__p_" << fixedParam << ")"; out << sb; writeMarshalUnmarshalCode(out, seq->type(), "(*__p_" + fixedParam + ")", true); out << eb; } else { // // No modifying metadata specified. Use appropriate write methods for type. // StringList l = seq->getMetaData(); seqType = findMetaData(l, false); if(!seqType.empty()) { out << nl << scope << "__" << funcSeq << (pointer ? "" : "&") << stream << ", " << fixedParam << ");"; } else if(!builtin || builtin->kind() == Builtin::KindObject || builtin->kind() == Builtin::KindObjectProxy) { out << nl << "if(" << fixedParam << ".size() == 0)"; out << sb; out << nl << stream << deref << "writeSize(0);"; out << eb; out << nl << "else"; out << sb; out << nl << scope << "__" << funcSeq << (pointer ? "" : "&") << stream << ", &" << fixedParam << "[0], &" << fixedParam << "[0] + " << fixedParam << ".size());"; out << eb; } else if(builtin->kind() == Builtin::KindBool) { out << nl << stream << deref << func << fixedParam << ");"; } else { out << nl << "if(" << fixedParam << ".size() == 0)"; out << sb; out << nl << stream << deref << "writeSize(0);"; out << eb; out << nl << "else"; out << sb; out << nl << stream << deref << func << "&" << fixedParam << "[0], &" << fixedParam << "[0] + " << fixedParam << ".size());"; out << eb; } } } else { string scope = fixKwd(seq->scope()); if(seqType == "array" || seqType == "range:array") { // // Use array (pair). In paramters only. // if(!builtin || builtin->kind() == Builtin::KindObject || builtin->kind() == Builtin::KindObjectProxy) { StringList l = seq->getMetaData(); seqType = findMetaData(l, false); if(seqType.empty()) { out << nl << typeToString(type, false) << " ___" << fixedParam << ";"; out << nl << scope << "__" << funcSeq << (pointer ? "" : "&") << stream << ", ___" << fixedParam << ");"; } else { seqType = "::std::vector< " + typeToString(seq->type(), false) + ">"; StringList l; l.push_back("cpp:type:" + seqType); out << nl << seqType << " ___" << fixedParam << ";"; writeMarshalUnmarshalCode(out, seq, "___" + fixedParam, false, "", true, l, false); } } else if(builtin->kind() == Builtin::KindByte) { out << nl << stream << deref << func << fixedParam << ");"; } else if(builtin->kind() != Builtin::KindString && builtin->kind() != Builtin::KindObject && builtin->kind() != Builtin::KindObjectProxy) { string s = typeToString(builtin, false); if(s[0] == ':') { s = " " + s; } out << nl << "::IceUtil::ScopedArray<" << s << "> ___" << fixedParam << '(' << stream << deref << func << fixedParam << "));"; } else { out << nl << "::std::vector< " << typeToString(seq->type(), inWstringModule(seq), seq->typeMetaData()) << "> ___" << fixedParam << ";"; out << nl << stream << deref << func << "___" << fixedParam << ");"; } if(!builtin || builtin->kind() == Builtin::KindString || builtin->kind() == Builtin::KindObject || builtin->kind() == Builtin::KindObjectProxy) { out << nl << fixedParam << ".first" << " = &___" << fixedParam << "[0];"; out << nl << fixedParam << ".second" << " = " << fixedParam << ".first + " << "___" << fixedParam << ".size();"; } } else if(seqType.find("range") == 0) { // // Use range (pair). In paramters only. // Need to check if iterator type other than default is specified. // StringList md; if(seqType.find("range:") == 0) { md.push_back("cpp:type:" + seqType.substr(strlen("range:"))); } writeMarshalUnmarshalCode(out, seq, "___" + fixedParam, false, "", true, md, false); out << nl << fixedParam << ".first = ___" << fixedParam << ".begin();"; out << nl << fixedParam << ".second = ___" << fixedParam << ".end();"; } else if(!seqType.empty()) { // // Using alternate sequence type. // out << nl << "::Ice::Int __sz_" << fixedParam << ";"; out << nl << stream << deref << "readSize(__sz_" << fixedParam << ");"; out << nl << seqType << "(__sz_" << fixedParam << ").swap(" << fixedParam << ");"; if(seq->type()->isVariableLength()) { out << nl << stream << deref << "startSeq(__sz_" << fixedParam << ", " << seq->type()->minWireSize() << ");"; } else { out << nl << stream << deref << "checkFixedSeq(__sz_" << fixedParam << ", " << seq->type()->minWireSize() << ");"; } out << nl << seqType << "::iterator __p_" << fixedParam << ";"; out << nl << "for(__p_" << fixedParam << " = " << fixedParam << ".begin(); __p_" << fixedParam << " != " << fixedParam << ".end(); ++__p_" << fixedParam << ")"; out << sb; writeMarshalUnmarshalCode(out, seq->type(), "(*__p_" + fixedParam + ")", false); if(seq->type()->isVariableLength()) { if(!SequencePtr::dynamicCast(seq->type())) { out << nl << stream << deref << "checkSeq();"; } out << nl << stream << deref << "endElement();"; } out << eb; if(seq->type()->isVariableLength()) { out << nl << stream << deref << "endSeq(__sz_" << fixedParam << ");"; } } else { // // No modifying metadata supplied. Just use appropriate read function. // StringList l = seq->getMetaData(); seqType = findMetaData(l, false); if(!seqType.empty() || !builtin || builtin->kind() == Builtin::KindObject || builtin->kind() == Builtin::KindObjectProxy) { out << nl << scope << "__" << funcSeq << (pointer ? "" : "&") << stream << ", " << fixedParam << ");"; } else if(builtin->kind() == Builtin::KindByte) { StringList md; md.push_back("cpp:array"); string tmpParam = "___"; // // Catch some case in which it is not possible to just prepend // underscores to param to use as temporary variable. // if(fixedParam.find("(*") == 0) { tmpParam += fixedParam.substr(2, fixedParam.length() - 3); } else if(fixedParam.find("[i]") != string::npos) { tmpParam += fixedParam.substr(0, fixedParam.length() - 3); } else if(fixedParam.find("->second") != string::npos) { tmpParam += fixedParam.substr(0, fixedParam.length() - 8); } else { tmpParam += fixedParam; } out << nl << typeToString(type, false, md) << " " << tmpParam << ";"; out << nl << stream << deref << func << tmpParam << ");"; out << nl << "::std::vector< ::Ice::Byte>(" << tmpParam << ".first, " << tmpParam << ".second).swap(" << fixedParam << ");"; } else { out << nl << stream << deref << func << fixedParam << ");"; } } } return; } DictionaryPtr dict = DictionaryPtr::dynamicCast(type); if(dict) { string scope = fixKwd(dict->scope()); string funcDict = (marshal ? "write" : "read") + fixKwd(dict->name()) + "("; out << nl << scope << "__" << funcDict << (pointer ? "" : "&") << stream << ", " << fixedParam << ");"; return; } ConstructedPtr constructed = ConstructedPtr::dynamicCast(type); assert(constructed); out << nl << fixKwd(constructed->scope()) << "__" << func << (pointer ? "" : "&") << stream << ", " << fixedParam << ");"; } void Slice::writeMarshalCode(Output& out, const ParamDeclList& params, const TypePtr& ret, const StringList& metaData, bool inParam) { for(ParamDeclList::const_iterator p = params.begin(); p != params.end(); ++p) { writeMarshalUnmarshalCode(out, (*p)->type(), fixKwd((*p)->name()), true, "", true, (*p)->getMetaData(), inParam); } if(ret) { writeMarshalUnmarshalCode(out, ret, "__ret", true, "", true, metaData, false); } } void Slice::writeUnmarshalCode(Output& out, const ParamDeclList& params, const TypePtr& ret, const StringList& metaData, bool inParam) { for(ParamDeclList::const_iterator p = params.begin(); p != params.end(); ++p) { writeMarshalUnmarshalCode(out, (*p)->type(), fixKwd((*p)->name()), false, "", true, (*p)->getMetaData(), inParam); } if(ret) { writeMarshalUnmarshalCode(out, ret, "__ret", false, "", true, metaData, false); } } static void writeRangeAllocateCode(Output& out, const TypePtr& type, const string& fixedName, const StringList& metaData, bool inParam) { if(!inParam) { return; } SequencePtr seq = SequencePtr::dynamicCast(type); if(seq) { string seqType = findMetaData(metaData, true); if(seqType.find("range") == 0 && seqType != "range:array") { StringList md; if(seqType.find("range:") == 0) { md.push_back("cpp:type:" + seqType.substr(strlen("range:"))); } out << nl << typeToString(seq, false, md, false) << " ___" << fixedName << ";"; } } } void Slice::writeAllocateCode(Output& out, const ParamDeclList& params, const TypePtr& ret, const StringList& metaData, bool useWstring, bool inParam) { for(ParamDeclList::const_iterator p = params.begin(); p != params.end(); ++p) { out << nl << typeToString((*p)->type(), useWstring, (*p)->getMetaData(), inParam) << ' ' << fixKwd((*p)->name()); StructPtr st = StructPtr::dynamicCast((*p)->type()); if(st && findMetaData(st->getMetaData(), false) == "class") { out << " = new " << fixKwd(st->scoped()); } out << ';'; // // If using a range we need to allocate the range container as well now to ensure they // are always in the same scope. // writeRangeAllocateCode(out, (*p)->type(), fixKwd((*p)->name()), (*p)->getMetaData(), inParam); } if(ret) { out << nl << typeToString(ret, useWstring, metaData, inParam) << " __ret"; StructPtr st = StructPtr::dynamicCast(ret); if(st && findMetaData(st->getMetaData(), false) == "class") { out << " = new " << fixKwd(st->scoped()); } out << ";"; // // If using a range we need to allocate the range container as well now to ensure they // are always in the same scope. // writeRangeAllocateCode(out, ret, "__ret", metaData, inParam); } } void Slice::writeStreamMarshalUnmarshalCode(Output& out, const TypePtr& type, const string& param, bool marshal, const string& str, bool useWstring, const StringList& metaData) { string fixedParam = fixKwd(param); string stream; if(str.empty()) { stream = marshal ? "__outS" : "__inS"; } else { stream = str; } BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); if(builtin) { switch(builtin->kind()) { case Builtin::KindByte: { if(marshal) { out << nl << stream << "->writeByte(" << fixedParam << ");"; } else { out << nl << fixedParam << " = " << stream << "->readByte();"; } break; } case Builtin::KindBool: { if(marshal) { out << nl << stream << "->writeBool(" << fixedParam << ");"; } else { out << nl << fixedParam << " = " << stream << "->readBool();"; } break; } case Builtin::KindShort: { if(marshal) { out << nl << stream << "->writeShort(" << fixedParam << ");"; } else { out << nl << fixedParam << " = " << stream << "->readShort();"; } break; } case Builtin::KindInt: { if(marshal) { out << nl << stream << "->writeInt(" << fixedParam << ");"; } else { out << nl << fixedParam << " = " << stream << "->readInt();"; } break; } case Builtin::KindLong: { if(marshal) { out << nl << stream << "->writeLong(" << fixedParam << ");"; } else { out << nl << fixedParam << " = " << stream << "->readLong();"; } break; } case Builtin::KindFloat: { if(marshal) { out << nl << stream << "->writeFloat(" << fixedParam << ");"; } else { out << nl << fixedParam << " = " << stream << "->readFloat();"; } break; } case Builtin::KindDouble: { if(marshal) { out << nl << stream << "->writeDouble(" << fixedParam << ");"; } else { out << nl << fixedParam << " = " << stream << "->readDouble();"; } break; } case Builtin::KindString: { string strType = findMetaData(metaData, true); if(strType != "string" && (useWstring || strType == "wstring")) { if(marshal) { out << nl << stream << "->writeWstring(" << fixedParam << ");"; } else { out << nl << fixedParam << " = " << stream << "->readWstring();"; } } else { if(marshal) { out << nl << stream << "->writeString(" << fixedParam << ");"; } else { out << nl << fixedParam << " = " << stream << "->readString();"; } } break; } case Builtin::KindObject: { if(marshal) { out << nl << "::Ice::ice_writeObject(" << stream << ", " << fixedParam << ");"; } else { out << nl << "::Ice::ice_readObject(" << stream << ", " << fixedParam << ");"; } break; } case Builtin::KindObjectProxy: { // TODO if(marshal) { out << nl << stream << "->writeProxy(" << fixedParam << ");"; } else { out << nl << fixedParam << " = " << stream << "->readProxy();"; } break; } case Builtin::KindLocalObject: { assert(false); break; } } return; } ClassDeclPtr cl = ClassDeclPtr::dynamicCast(type); if(cl) { string scope = fixKwd(cl->scope()); if(marshal) { out << nl << scope << "ice_write" << cl->name() << "(" << stream << ", " << fixedParam << ");"; } else { out << nl << scope << "ice_read" << cl->name() << "(" << stream << ", " << fixedParam << ");"; } return; } StructPtr st = StructPtr::dynamicCast(type); if(st) { string scope = fixKwd(st->scope()); if(marshal) { out << nl << scope << "ice_write" << st->name() << "(" << stream << ", " << fixedParam << ");"; } else { if(findMetaData(st->getMetaData(), false) == "class") { out << nl << fixedParam << " = new " << fixKwd(st->scoped()) << ";"; } out << nl << scope << "ice_read" << st->name() << "(" << stream << ", " << fixedParam << ");"; } return; } SequencePtr seq = SequencePtr::dynamicCast(type); if(seq) { string seqType = findMetaData(metaData, false); if(!seqType.empty()) { if(marshal) { out << nl << stream << "->writeSize(static_cast< ::Ice::Int>(" << fixedParam << ".size()));"; out << nl << seqType << "::const_iterator ___" << fixedParam << ";"; out << nl << "for(___" << fixedParam << " = " << fixedParam << ".begin(); ___" << fixedParam << " != " << fixedParam << ".end(); ++___" << fixedParam << ")"; out << sb; writeStreamMarshalUnmarshalCode(out, seq->type(), "(*___" + fixedParam + ")", true); out << eb; } else { out << nl << seqType << "(static_cast< ::Ice::Int>(" << stream << "->readSize())).swap(" << fixedParam << ");"; out << nl << seqType << "::iterator ___" << fixedParam << ";"; out << nl << "for(___" << fixedParam << " = " << fixedParam << ".begin(); ___" << fixedParam << " != " << fixedParam << ".end(); ++___" << fixedParam << ")"; out << sb; writeStreamMarshalUnmarshalCode(out, seq->type(), "(*___" + fixedParam + ")", false); out << eb; } } else { seqType = findMetaData(seq->getMetaData(), false); builtin = BuiltinPtr::dynamicCast(seq->type()); if(!seqType.empty() || !builtin || (builtin->kind() == Builtin::KindObject || builtin->kind() == Builtin::KindObjectProxy)) { string scope = fixKwd(seq->scope()); if(marshal) { out << nl << scope << "ice_write" << seq->name() << '(' << stream << ", " << fixedParam << ");"; } else { out << nl << scope << "ice_read" << seq->name() << '(' << stream << ", " << fixedParam << ");"; } } else { switch(builtin->kind()) { case Builtin::KindByte: { if(marshal) { out << nl << stream << "->writeByteSeq(" << fixedParam << ");"; } else { out << nl << fixedParam << " = " << stream << "->readByteSeq();"; } break; } case Builtin::KindBool: { if(marshal) { out << nl << stream << "->writeBoolSeq(" << fixedParam << ");"; } else { out << nl << fixedParam << " = " << stream << "->readBoolSeq();"; } break; } case Builtin::KindShort: { if(marshal) { out << nl << stream << "->writeShortSeq(" << fixedParam << ");"; } else { out << nl << fixedParam << " = " << stream << "->readShortSeq();"; } break; } case Builtin::KindInt: { if(marshal) { out << nl << stream << "->writeIntSeq(" << fixedParam << ");"; } else { out << nl << fixedParam << " = " << stream << "->readIntSeq();"; } break; } case Builtin::KindLong: { if(marshal) { out << nl << stream << "->writeLongSeq(" << fixedParam << ");"; } else { out << nl << fixedParam << " = " << stream << "->readLongSeq();"; } break; } case Builtin::KindFloat: { if(marshal) { out << nl << stream << "->writeFloatSeq(" << fixedParam << ");"; } else { out << nl << fixedParam << " = " << stream << "->readFloatSeq();"; } break; } case Builtin::KindDouble: { if(marshal) { out << nl << stream << "->writeDoubleSeq(" << fixedParam << ");"; } else { out << nl << fixedParam << " = " << stream << "->readDoubleSeq();"; } break; } case Builtin::KindString: { string strType = findMetaData(seq->typeMetaData(), true); if(strType != "string" && (useWstring || strType == "wstring")) { if(marshal) { out << nl << stream << "->writeWstringSeq(" << fixedParam << ");"; } else { out << nl << fixedParam << " = " << stream << "->readWstringSeq();"; } } else { if(marshal) { out << nl << stream << "->writeStringSeq(" << fixedParam << ");"; } else { out << nl << fixedParam << " = " << stream << "->readStringSeq();"; } } break; } case Builtin::KindObject: case Builtin::KindObjectProxy: case Builtin::KindLocalObject: { assert(false); break; } } } } return; } DictionaryPtr dict = DictionaryPtr::dynamicCast(type); if(dict) { string scope = fixKwd(dict->scope()); if(marshal) { out << nl << scope << "ice_write" << dict->name() << "(" << stream << ", " << fixedParam << ");"; } else { out << nl << scope << "ice_read" << dict->name() << "(" << stream << ", " << fixedParam << ");"; } return; } EnumPtr en = EnumPtr::dynamicCast(type); if(en) { string scope = fixKwd(en->scope()); if(marshal) { out << nl << scope << "ice_write" << en->name() << "(" << stream << ", " << fixedParam << ");"; } else { out << nl << scope << "ice_read" << en->name() << "(" << stream << ", " << fixedParam << ");"; } return; } ProxyPtr prx = ProxyPtr::dynamicCast(type); if(prx) { ClassDeclPtr cls = prx->_class(); string scope = fixKwd(cls->scope()); if(marshal) { out << nl << scope << "ice_write" << cls->name() << "Prx(" << stream << ", " << fixedParam << ");"; } else { out << nl << scope << "ice_read" << cls->name() << "Prx(" << stream << ", " << fixedParam << ");"; } return; } assert(false); } string Slice::findMetaData(const StringList& metaData, bool inParam) { static const string prefix = "cpp:"; for(StringList::const_iterator q = metaData.begin(); q != metaData.end(); ++q) { string str = *q; if(str.find(prefix) == 0) { string::size_type pos = str.find(':', prefix.size()); // // If the form is cpp:type:<...> the data after cpp:type: // is returned. If the form is cpp:range:<...> (and this // is an inParam) the data after cpp: is returned. // if(pos != string::npos) { string ss = str.substr(prefix.size(), pos - prefix.size()); if(ss == "type") { return str.substr(pos + 1); } else if(inParam && ss == "range") { return str.substr(prefix.size()); } } // // If the data is an inParam and the metadata is cpp:array // or cpp:range then array or range is returned. // else if(inParam) { string ss = str.substr(prefix.size()); if(ss == "array" || ss == "range") { return ss; } } // // Otherwise if the data is "class" it is returned. // else { string ss = str.substr(prefix.size()); if(ss == "class") { return ss; } } } } return ""; } bool Slice::inWstringModule(const SequencePtr& seq) { ContainerPtr cont = seq->container(); while(cont) { ModulePtr mod = ModulePtr::dynamicCast(cont); if(!mod) { break; } StringList metaData = mod->getMetaData(); if(find(metaData.begin(), metaData.end(), "cpp:type:wstring") != metaData.end()) { return true; } else if(find(metaData.begin(), metaData.end(), "cpp:type:string") != metaData.end()) { return false; } cont = mod->container(); } return false; } IceE-trans-1.2.0/src/Slice/RubyUtil.cpp0000664000076400007640000013723510613357063017146 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 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 #ifdef __BCPLUSPLUS__ #include #endif using namespace std; using namespace Slice; using namespace IceUtil; namespace Slice { namespace Ruby { // // CodeVisitor generates the Ruby mapping for a translation unit. // class CodeVisitor : public ParserVisitor { public: CodeVisitor(IceUtil::Output&); virtual bool visitModuleStart(const ModulePtr&); virtual void visitModuleEnd(const ModulePtr&); virtual void visitClassDecl(const ClassDeclPtr&); virtual bool visitClassDefStart(const ClassDefPtr&); virtual bool visitExceptionStart(const ExceptionPtr&); virtual bool visitStructStart(const StructPtr&); virtual void visitSequence(const SequencePtr&); virtual void visitDictionary(const DictionaryPtr&); virtual void visitEnum(const EnumPtr&); virtual void visitConst(const ConstPtr&); private: // // Return a Python symbol for the given parser element. // string getSymbol(const ContainedPtr&); // // Emit Python code to assign the given symbol in the current module. // void registerName(const string&); // // Emit the array that describes a Slice type. // void writeType(const TypePtr&); // // Get a default value for a given type. // string getDefaultValue(const TypePtr&); // // Add a value to a hash code. // void writeHash(const string&, const TypePtr&, int&); struct MemberInfo { string lowerName; // Mapped name beginning with a lower-case letter for use as the name of a local variable. string fixedName; TypePtr type; bool inherited; }; typedef list MemberInfoList; void collectClassMembers(const ClassDefPtr&, MemberInfoList&, bool); void collectExceptionMembers(const ExceptionPtr&, MemberInfoList&, bool); Output& _out; set _classHistory; }; } } static string lookupKwd(const string& name) { // // Keyword list. *Must* be kept in alphabetical order. // // This list only contains keywords that might conflict with a Slice // identifier, so keywords like "defined?" are not necessary. // // This list also contains the names of methods on Object that might // conflict with a Slice identifier, so names such as "inspect" and // "send" are included but "to_s" is not. // static const string keywordList[] = { "BEGIN", "END", "alias", "and", "begin", "break", "case", "class", "clone", "def", "display", "do", "dup", "else", "elsif", "end", "ensure", "extend", "false", "for", "freeze", "hash", "if", "in", "inspect", "method", "methods", "module", "next", "new", "nil", "not", "or", "redo", "rescue", "retry", "return", "self", "send", "super", "taint", "then", "true", "undef", "unless", "untaint", "until", "when", "while", "yield" }; bool found = binary_search(&keywordList[0], &keywordList[sizeof(keywordList) / sizeof(*keywordList)], name); return found ? "_" + name : name; } // // Split a scoped name into its components and return the components as a list of (unscoped) identifiers. // static vector splitScopedName(const string& scoped) { assert(scoped[0] == ':'); vector ids; string::size_type next = 0; string::size_type pos; while((pos = scoped.find("::", next)) != string::npos) { pos += 2; if(pos != scoped.size()) { string::size_type endpos = scoped.find("::", pos); if(endpos != string::npos && endpos > pos) { ids.push_back(scoped.substr(pos, endpos - pos)); } } next = pos; } if(next != scoped.size()) { ids.push_back(scoped.substr(next)); } return ids; } // // CodeVisitor implementation. // Slice::Ruby::CodeVisitor::CodeVisitor(Output& out) : _out(out) { } bool Slice::Ruby::CodeVisitor::visitModuleStart(const ModulePtr& p) { _out << sp << nl << "module " << fixIdent(p->name(), IdentToUpper); _out.inc(); return true; } void Slice::Ruby::CodeVisitor::visitModuleEnd(const ModulePtr& p) { _out.dec(); _out << nl << "end"; } void Slice::Ruby::CodeVisitor::visitClassDecl(const ClassDeclPtr& p) { // // Emit forward declarations. // string scoped = p->scoped(); if(_classHistory.count(scoped) == 0) { string name = "T_" + fixIdent(p->name(), IdentToUpper); _out << sp << nl << "if not defined?(" << getAbsolute(p, IdentToUpper, "T_") << ')'; _out.inc(); _out << nl << name << " = ::Ice::__declareClass('" << scoped << "')"; if(!p->isLocal()) { _out << nl << name << "Prx = ::Ice::__declareProxy('" << scoped << "')"; } _out.dec(); _out << nl << "end"; _classHistory.insert(scoped); // Avoid redundant declarations. } } bool Slice::Ruby::CodeVisitor::visitClassDefStart(const ClassDefPtr& p) { string scoped = p->scoped(); string name = fixIdent(p->name(), IdentToUpper); ClassList bases = p->bases(); ClassDefPtr base; OperationList ops = p->operations(); OperationList::iterator oli; // // Define a mix-in module for the class. // _out << sp << nl << "if not defined?(" << getAbsolute(p, IdentToUpper) << "_mixin)"; _out.inc(); _out << nl << "module " << name << "_mixin"; _out.inc(); if(!p->isLocal()) { if(!bases.empty() && !bases.front()->isInterface()) { base = bases.front(); _out << nl << "include " << getAbsolute(bases.front(), IdentToUpper) << "_mixin"; } else { _out << nl << "include ::Ice::Object_mixin"; } // // ice_ids // ClassList allBases = p->allBases(); StringList ids; #if defined(__IBMCPP__) && defined(NDEBUG) // // VisualAge C++ 6.0 does not see that ClassDef is a Contained, // when inlining is on. The code below issues a warning: better // than an error! // transform(allBases.begin(), allBases.end(), back_inserter(ids), IceUtil::constMemFun(&Contained::scoped)); #else transform(allBases.begin(), allBases.end(), back_inserter(ids), IceUtil::constMemFun(&Contained::scoped)); #endif StringList other; other.push_back(scoped); other.push_back("::Ice::Object"); other.sort(); ids.merge(other); ids.unique(); _out << sp << nl << "def ice_ids(current=nil)"; _out.inc(); _out << nl << "["; for(StringList::iterator q = ids.begin(); q != ids.end(); ++q) { if(q != ids.begin()) { _out << ", "; } _out << "'" << *q << "'"; } _out << ']'; _out.dec(); _out << nl << "end"; // // ice_id // _out << sp << nl << "def ice_id(current=nil)"; _out.inc(); _out << nl << "'" << scoped << "'"; _out.dec(); _out << nl << "end"; } if(!ops.empty()) { // // Emit a comment for each operation. // _out << sp << nl << "#" << nl << "# Operation signatures." << nl << "#"; for(oli = ops.begin(); oli != ops.end(); ++oli) { string fixedOpName = fixIdent((*oli)->name(), IdentNormal); /* If AMI/AMD is ever implemented... if(!p->isLocal() && (p->hasMetaData("amd") || (*oli)->hasMetaData("amd"))) { _out << nl << "# def " << fixedOpName << "_async(_cb"; ParamDeclList params = (*oli)->parameters(); for(ParamDeclList::iterator pli = params.begin(); pli != params.end(); ++pli) { if(!(*pli)->isOutParam()) { _out << ", " << fixIdent((*pli)->name(), IdentToLower); } } if(!p->isLocal()) { _out << ", current=nil"; } _out << ")"; } else */ { _out << nl << "# def " << fixedOpName << "("; ParamDeclList params = (*oli)->parameters(); bool first = true; for(ParamDeclList::iterator pli = params.begin(); pli != params.end(); ++pli) { if(!(*pli)->isOutParam()) { if(first) { first = false; } else { _out << ", "; } _out << fixIdent((*pli)->name(), IdentToLower); } } if(!p->isLocal()) { if(!first) { _out << ", "; } _out << "current=nil"; } _out << ")"; } } } // // inspect // _out << sp << nl << "def inspect"; _out.inc(); _out << nl << "::Ice::__stringify(self, T_" << name << ")"; _out.dec(); _out << nl << "end"; // // read/write accessors for data members. // DataMemberList members = p->dataMembers(); if(!members.empty()) { _out << sp << nl << "attr_accessor "; for(DataMemberList::iterator q = members.begin(); q != members.end(); ++q) { if(q != members.begin()) { _out << ", "; } _out << ":" << fixIdent((*q)->name(), IdentNormal); } } _out.dec(); _out << nl << "end"; // End of mix-in module for class. if(p->isInterface()) { // // Class. // _out << nl << "class " << name; _out.inc(); _out << nl << "include " << name << "_mixin"; _out.dec(); _out << nl << "end"; } else { // // Class. // _out << nl << "class " << name; if(base) { _out << " < " << getAbsolute(base, IdentToUpper); } _out.inc(); _out << nl << "include " << name << "_mixin"; // // initialize // MemberInfoList allMembers; collectClassMembers(p, allMembers, false); bool inheritsMembers = false; if(!allMembers.empty()) { _out << sp << nl << "def initialize"; _out << spar; MemberInfoList::iterator q; for(q = allMembers.begin(); q != allMembers.end(); ++q) { ostringstream ostr; ostr << q->lowerName << '=' << getDefaultValue(q->type); _out << ostr.str(); if(q->inherited) { inheritsMembers = true; } } _out << epar; _out.inc(); if(inheritsMembers) { _out << nl << "super" << spar; for(q = allMembers.begin(); q != allMembers.end(); ++q) { if(q->inherited) { _out << q->lowerName; } } _out << epar; } for(q = allMembers.begin(); q != allMembers.end(); ++q) { if(!q->inherited) { _out << nl << '@' << q->fixedName << " = " << q->lowerName; } } _out.dec(); _out << nl << "end"; } _out.dec(); _out << nl << "end"; // End of class. } // // Generate proxy support. This includes a mix-in module for the proxy's // operations and a class for the proxy itself. // if(!p->isLocal()) { _out << nl << "module " << name << "Prx_mixin"; _out.inc(); for(ClassList::iterator cli = bases.begin(); cli != bases.end(); ++cli) { _out << nl << "include " << getAbsolute(*cli, IdentToUpper) << "Prx_mixin"; } for(oli = ops.begin(); oli != ops.end(); ++oli) { string fixedOpName = fixIdent((*oli)->name(), IdentNormal); if(fixedOpName == "checkedCast" || fixedOpName == "uncheckedCast") { fixedOpName.insert(0, "_"); } TypePtr ret = (*oli)->returnType(); ParamDeclList paramList = (*oli)->parameters(); string inParams; for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q) { if(!(*q)->isOutParam()) { if(!inParams.empty()) { inParams.append(", "); } inParams.append(fixIdent((*q)->name(), IdentToLower)); } } _out << sp << nl << "def " << fixedOpName << "("; if(!inParams.empty()) { _out << inParams << ", "; } _out << "_ctx=nil)"; _out.inc(); _out << nl << name << "_mixin::OP_" << (*oli)->name() << ".invoke(self, [" << inParams; _out << "], _ctx)"; _out.dec(); _out << nl << "end"; /* If AMI/AMD is ever implemented... if(p->hasMetaData("ami") || (*oli)->hasMetaData("ami")) { _out << sp << nl << "def " << fixedOpName << "_async(_cb"; if(!inParams.empty()) { _out << ", " << inParams; } _out << ", _ctx=nil)"; _out.inc(); _out << nl << name << "_mixin::OP_" << (*oli)->name() << ".invokeAsync(self, _cb, [" << inParams; if(!inParams.empty() && inParams.find(',') == string::npos) { _out << ", "; } _out << "], _ctx)"; _out.dec(); _out << nl << "end"; } */ } _out.dec(); _out << nl << "end"; // End of mix-in module for proxy. _out << nl << "class " << name << "Prx < ::Ice::ObjectPrx"; _out.inc(); _out << nl << "include " << name << "Prx_mixin"; _out << sp << nl << "def " << name << "Prx.checkedCast(proxy, facetOrCtx=nil, _ctx=nil)"; _out.inc(); _out << nl << "ice_checkedCast(proxy, '" << scoped << "', facetOrCtx, _ctx)"; _out.dec(); _out << nl << "end"; _out << sp << nl << "def " << name << "Prx.uncheckedCast(proxy, facet='')"; _out.inc(); _out << nl << "ice_uncheckedCast(proxy, facet)"; _out.dec(); _out << nl << "end"; _out.dec(); _out << nl << "end"; // End of proxy class. } // // Emit type descriptions. // _out << sp << nl << "if not defined?(" << getAbsolute(p, IdentToUpper, "T_") << ')'; _out.inc(); _out << nl << "T_" << name << " = ::Ice::__declareClass('" << scoped << "')"; if(!p->isLocal()) { _out << nl << "T_" << name << "Prx = ::Ice::__declareProxy('" << scoped << "')"; } _out.dec(); _out << nl << "end"; _classHistory.insert(scoped); // Avoid redundant declarations. _out << sp << nl << "T_" << name << ".defineClass(" << name << ", " << (p->isAbstract() ? "true" : "false") << ", "; if(!base) { _out << "nil"; } else { _out << getAbsolute(base, IdentToUpper, "T_"); } _out << ", ["; // // Interfaces // // TODO: Necessary? // { int interfaceCount = 0; for(ClassList::const_iterator q = bases.begin(); q != bases.end(); ++q) { if((*q)->isInterface()) { if(interfaceCount > 0) { _out << ", "; } _out << getAbsolute(*q, IdentToUpper, "T_"); ++interfaceCount; } } } // // Members // // Data members are represented as an array: // // ['MemberName', MemberType] // // where MemberType is either a primitive type constant (T_INT, etc.) or the id of a constructed type. // _out << "], ["; if(members.size() > 1) { _out.inc(); _out << nl; } { for(DataMemberList::iterator q = members.begin(); q != members.end(); ++q) { if(q != members.begin()) { _out << ',' << nl; } _out << "['" << fixIdent((*q)->name(), IdentNormal) << "', "; writeType((*q)->type()); _out << ']'; } } if(members.size() > 1) { _out.dec(); _out << nl; } _out << "])"; _out << nl << name << "_mixin::ICE_TYPE = T_" << name; // // Define each operation. The arguments to __defineOperation are: // // 'opName', Mode, [InParams], [OutParams], ReturnType, [Exceptions] // // where InParams and OutParams are arrays of type descriptions, and Exceptions // is an array of exception types. // if(!p->isLocal()) { _out << sp << nl << "T_" << name << "Prx.defineProxy(" << name << "Prx, T_" << name << ')'; _out << nl << name << "Prx::ICE_TYPE = T_" << name << "Prx"; if(!ops.empty()) { _out << sp; } for(OperationList::iterator s = ops.begin(); s != ops.end(); ++s) { ParamDeclList params = (*s)->parameters(); ParamDeclList::iterator t; int count; _out << nl << name << "_mixin::OP_" << (*s)->name() << " = ::Ice::__defineOperation('" << (*s)->name() << "', "; switch((*s)->mode()) { case Operation::Normal: _out << "::Ice::OperationMode::Normal"; break; case Operation::Nonmutating: _out << "::Ice::OperationMode::Nonmutating"; break; case Operation::Idempotent: _out << "::Ice::OperationMode::Idempotent"; break; } _out << ", "; switch((*s)->sendMode()) { case Operation::Normal: _out << "::Ice::OperationMode::Normal"; break; case Operation::Nonmutating: _out << "::Ice::OperationMode::Nonmutating"; break; case Operation::Idempotent: _out << "::Ice::OperationMode::Idempotent"; break; } _out << ", " << ((p->hasMetaData("amd") || (*s)->hasMetaData("amd")) ? "true" : "false") << ", ["; for(t = params.begin(), count = 0; t != params.end(); ++t) { if(!(*t)->isOutParam()) { if(count > 0) { _out << ", "; } writeType((*t)->type()); ++count; } } _out << "], ["; for(t = params.begin(), count = 0; t != params.end(); ++t) { if((*t)->isOutParam()) { if(count > 0) { _out << ", "; } writeType((*t)->type()); ++count; } } _out << "], "; TypePtr returnType = (*s)->returnType(); if(returnType) { writeType(returnType); } else { _out << "nil"; } _out << ", ["; ExceptionList exceptions = (*s)->throws(); for(ExceptionList::iterator u = exceptions.begin(); u != exceptions.end(); ++u) { if(u != exceptions.begin()) { _out << ", "; } _out << getAbsolute(*u, IdentToUpper, "T_"); } _out << "])"; string deprecateMetadata; if((*s)->findMetaData("deprecate", deprecateMetadata) || p->findMetaData("deprecate", deprecateMetadata)) { string msg; string::size_type pos = deprecateMetadata.find(':'); if(pos != string::npos && pos < deprecateMetadata.size() - 1) { msg = deprecateMetadata.substr(pos + 1); } _out << nl << name << "_mixin::OP_" << (*s)->name() << ".deprecate(\"" << msg << "\")"; } } } _out.dec(); _out << nl << "end"; // if not defined?() return false; } bool Slice::Ruby::CodeVisitor::visitExceptionStart(const ExceptionPtr& p) { string scoped = p->scoped(); string name = fixIdent(p->name(), IdentToUpper); _out << sp << nl << "if not defined?(" << getAbsolute(p, IdentToUpper) << ')'; _out.inc(); _out << nl << "class " << name << " < "; ExceptionPtr base = p->base(); string baseName; if(base) { baseName = getAbsolute(base, IdentToUpper); _out << baseName; } else if(p->isLocal()) { _out << "Ice::LocalException"; } else { _out << "Ice::UserException"; } _out.inc(); DataMemberList members = p->dataMembers(); DataMemberList::iterator dmli; // // initialize // _out << nl << "def initialize"; MemberInfoList allMembers; collectExceptionMembers(p, allMembers, false); bool inheritsMembers = false; if(!allMembers.empty()) { _out << spar; for(MemberInfoList::iterator q = allMembers.begin(); q != allMembers.end(); ++q) { ostringstream ostr; ostr << q->lowerName << '=' << getDefaultValue(q->type); _out << ostr.str(); if(q->inherited) { inheritsMembers = true; } } _out << epar; } _out.inc(); if(!allMembers.empty()) { if(inheritsMembers) { _out << nl << "super" << spar; for(MemberInfoList::iterator q = allMembers.begin(); q != allMembers.end(); ++q) { if(q->inherited) { _out << q->lowerName; } } _out << epar; } for(MemberInfoList::iterator q = allMembers.begin(); q != allMembers.end(); ++q) { if(!q->inherited) { _out << nl << '@' << q->fixedName << " = " << q->lowerName; } } } _out.dec(); _out << nl << "end"; // // to_s // _out << sp << nl << "def to_s"; _out.inc(); _out << nl << "'" << scoped.substr(2) << "'"; _out.dec(); _out << nl << "end"; // // inspect // _out << sp << nl << "def inspect"; _out.inc(); _out << nl << "return ::Ice::__stringifyException(self)"; _out.dec(); _out << nl << "end"; // // read/write accessors for data members. // if(!members.empty()) { _out << sp << nl << "attr_accessor "; for(dmli = members.begin(); dmli != members.end(); ++dmli) { if(dmli != members.begin()) { _out << ", "; } _out << ':' << fixIdent((*dmli)->name(), IdentNormal); } } _out.dec(); _out << nl << "end"; // End of class. // // Emit the type information. // _out << sp << nl << "T_" << name << " = ::Ice::__defineException('" << scoped << "', " << name << ", "; if(!base) { _out << "nil"; } else { _out << getAbsolute(base, IdentToUpper, "T_"); } _out << ", ["; if(members.size() > 1) { _out.inc(); _out << nl; } // // Data members are represented as an array: // // ['MemberName', MemberType] // // where MemberType is either a primitive type constant (T_INT, etc.) or the id of a constructed type. // for(dmli = members.begin(); dmli != members.end(); ++dmli) { if(dmli != members.begin()) { _out << ',' << nl; } _out << "[\"" << fixIdent((*dmli)->name(), IdentNormal) << "\", "; writeType((*dmli)->type()); _out << ']'; } if(members.size() > 1) { _out.dec(); _out << nl; } _out << "])"; _out << nl << name << "::ICE_TYPE = T_" << name; _out.dec(); _out << nl << "end"; // if not defined?() return false; } bool Slice::Ruby::CodeVisitor::visitStructStart(const StructPtr& p) { string scoped = p->scoped(); string name = fixIdent(p->name(), IdentToUpper); MemberInfoList memberList; MemberInfoList::iterator r; { DataMemberList members = p->dataMembers(); for(DataMemberList::iterator q = members.begin(); q != members.end(); ++q) { memberList.push_back(MemberInfo()); memberList.back().lowerName = fixIdent((*q)->name(), IdentToLower); memberList.back().fixedName = fixIdent((*q)->name(), IdentNormal); memberList.back().type = (*q)->type(); } } _out << sp << nl << "if not defined?(" << getAbsolute(p, IdentToUpper) << ')'; _out.inc(); _out << nl << "class " << name; _out.inc(); if(!memberList.empty()) { _out << nl << "def initialize("; for(r = memberList.begin(); r != memberList.end(); ++r) { if(r != memberList.begin()) { _out << ", "; } _out << r->lowerName << '=' << getDefaultValue(r->type); } _out << ")"; _out.inc(); for(r = memberList.begin(); r != memberList.end(); ++r) { _out << nl << '@' << r->fixedName << " = " << r->lowerName; } _out.dec(); _out << nl << "end"; } // // hash // _out << sp << nl << "def hash"; _out.inc(); _out << nl << "_h = 0"; int iter = 0; for(r = memberList.begin(); r != memberList.end(); ++r) { writeHash("@" + r->fixedName, r->type, iter); } _out << nl << "_h % 0x7fffffff"; _out.dec(); _out << nl << "end"; // // == // _out << sp << nl << "def ==(other)"; _out.inc(); _out << nl << "return false if"; _out.inc(); for(r = memberList.begin(); r != memberList.end(); ++r) { if(r != memberList.begin()) { _out << " or"; } _out << nl << "@" << r->fixedName << " != other." << r->fixedName; } _out.dec(); _out << nl << "true"; _out.dec(); _out << nl << "end"; // // inspect // _out << sp << nl << "def inspect"; _out.inc(); _out << nl << "::Ice::__stringify(self, T_" << name << ")"; _out.dec(); _out << nl << "end"; // // read/write accessors for data members. // if(!memberList.empty()) { _out << sp << nl << "attr_accessor "; for(r = memberList.begin(); r != memberList.end(); ++r) { if(r != memberList.begin()) { _out << ", "; } _out << ':' << r->fixedName; } } _out.dec(); _out << nl << "end"; // End of class. // // Emit the type information. // _out << sp << nl << "T_" << name << " = ::Ice::__defineStruct('" << scoped << "', " << name << ", ["; // // Data members are represented as an array: // // ['MemberName', MemberType] // // where MemberType is either a primitive type constant (T_INT, etc.) or the id of a constructed type. // if(memberList.size() > 1) { _out.inc(); _out << nl; } for(r = memberList.begin(); r != memberList.end(); ++r) { if(r != memberList.begin()) { _out << ',' << nl; } _out << "[\"" << r->fixedName << "\", "; writeType(r->type); _out << ']'; } if(memberList.size() > 1) { _out.dec(); _out << nl; } _out << "])"; _out.dec(); _out << nl << "end"; // if not defined?() return false; } void Slice::Ruby::CodeVisitor::visitSequence(const SequencePtr& p) { // // Emit the type information. // string name = fixIdent(p->name(), IdentToUpper); string scoped = p->scoped(); _out << sp << nl << "if not defined?(" << getAbsolute(p, IdentToUpper, "T_") << ')'; _out.inc(); _out << nl << "T_" << name << " = ::Ice::__defineSequence('" << scoped << "', "; writeType(p->type()); _out << ")"; _out.dec(); _out << nl << "end"; // if not defined?() } void Slice::Ruby::CodeVisitor::visitDictionary(const DictionaryPtr& p) { // // Emit the type information. // string name = fixIdent(p->name(), IdentToUpper); string scoped = p->scoped(); _out << sp << nl << "if not defined?(" << getAbsolute(p, IdentToUpper, "T_") << ')'; _out.inc(); _out << nl << "T_" << name << " = ::Ice::__defineDictionary('" << scoped << "', "; writeType(p->keyType()); _out << ", "; writeType(p->valueType()); _out << ")"; _out.dec(); _out << nl << "end"; // if not defined?() } void Slice::Ruby::CodeVisitor::visitEnum(const EnumPtr& p) { string scoped = p->scoped(); string name = fixIdent(p->name(), IdentToUpper); EnumeratorList enums = p->getEnumerators(); EnumeratorList::iterator q; int i; _out << sp << nl << "if not defined?(" << getAbsolute(p, IdentToUpper) << ')'; _out.inc(); _out << nl << "class " << name; _out.inc(); _out << nl << "include Comparable"; _out << sp << nl << "def initialize(val)"; _out.inc(); { ostringstream assertion; assertion << "fail(\"invalid value #{val} for " << name << "\") unless(val >= 0 and val < " << enums.size() << ')'; _out << nl << assertion.str(); } _out << nl << "@val = val"; _out.dec(); _out << nl << "end"; // // from_int // { _out << sp << nl << "def " << name << ".from_int(val)"; ostringstream sz; sz << enums.size() - 1; _out.inc(); _out << nl << "raise IndexError, \"#{val} is out of range 0.." << sz.str() << "\" if(val < 0 || val > " << sz.str() << ')'; _out << nl << "@@_values[val]"; _out.dec(); _out << nl << "end"; } // // to_s // _out << sp << nl << "def to_s"; _out.inc(); _out << nl << "@@_names[@val]"; _out.dec(); _out << nl << "end"; // // to_i // _out << sp << nl << "def to_i"; _out.inc(); _out << nl << "@val"; _out.dec(); _out << nl << "end"; // // <=> // _out << sp << nl << "def <=>(other)"; _out.inc(); _out << nl << "other.is_a?(" << name << ") or raise ArgumentError, \"value must be a " << name << "\""; _out << nl << "@val <=> other.to_i"; _out.dec(); _out << nl << "end"; // // hash // _out << sp << nl << "def hash"; _out.inc(); _out << nl << "@val.hash"; _out.dec(); _out << nl << "end"; // // inspect // _out << sp << nl << "def inspect"; _out.inc(); _out << nl << "@@_names[@val] + \"(#{@val})\""; _out.dec(); _out << nl << "end"; // // each // _out << sp << nl << "def " << name << ".each(&block)"; _out.inc(); _out << nl << "@@_values.each(&block)"; _out.dec(); _out << nl << "end"; _out << sp << nl << "@@_names = ["; for(q = enums.begin(); q != enums.end(); ++q) { if(q != enums.begin()) { _out << ", "; } _out << "'" << (*q)->name() << "'"; } _out << ']'; _out << nl << "@@_values = ["; for(EnumeratorList::size_type j = 0; j < enums.size(); ++j) { if(j > 0) { _out << ", "; } ostringstream idx; idx << j; _out << name << ".new(" << idx.str() << ')'; } _out << ']'; // // Constant for each enumerator. // _out << sp; for(q = enums.begin(), i = 0; q != enums.end(); ++q, ++i) { ostringstream idx; idx << i; _out << nl << fixIdent((*q)->name(), IdentToUpper) << " = @@_values[" << idx.str() << "]"; } _out << sp << nl << "private_class_method :new"; _out.dec(); _out << nl << "end"; // End of class. // // Emit the type information. // _out << sp << nl << "T_" << name << " = ::Ice::__defineEnum('" << scoped << "', " << name << ", ["; for(q = enums.begin(); q != enums.end(); ++q) { if(q != enums.begin()) { _out << ", "; } _out << name << "::" << fixIdent((*q)->name(), IdentToUpper); } _out << "])"; _out.dec(); _out << nl << "end"; // if not defined?() } void Slice::Ruby::CodeVisitor::visitConst(const ConstPtr& p) { Slice::TypePtr type = p->type(); string value = p->value(); string name = fixIdent(p->name(), IdentToUpper); _out << sp << nl << name << " = "; Slice::BuiltinPtr b = Slice::BuiltinPtr::dynamicCast(type); Slice::EnumPtr en = Slice::EnumPtr::dynamicCast(type); if(b) { switch(b->kind()) { case Slice::Builtin::KindBool: { _out << value; break; } case Slice::Builtin::KindByte: case Slice::Builtin::KindShort: case Slice::Builtin::KindInt: case Slice::Builtin::KindFloat: case Slice::Builtin::KindDouble: { _out << value; break; } case Slice::Builtin::KindLong: { IceUtil::Int64 l; IceUtil::stringToInt64(value, l); _out << value; break; } case Slice::Builtin::KindString: { // // Expand strings into the basic source character set. We can't use isalpha() and the like // here because they are sensitive to the current locale. // static const string basicSourceChars = "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789" "_{}[]#()<>%:;.?*+-/^&|~!=, '"; static const set charSet(basicSourceChars.begin(), basicSourceChars.end()); _out << "\""; // Opening " for(string::const_iterator c = value.begin(); c != value.end(); ++c) { switch(*c) { case '"': { _out << "\\\""; break; } case '\\': { _out << "\\\\"; break; } case '\r': { _out << "\\r"; break; } case '\n': { _out << "\\n"; break; } case '\t': { _out << "\\t"; break; } case '\b': { _out << "\\b"; break; } case '\f': { _out << "\\f"; break; } default: { if(charSet.find(*c) == charSet.end()) { unsigned char uc = *c; // Char may be signed, so make it positive. stringstream s; s << "\\"; // Print as octal if not in basic source character set. s.flags(ios_base::oct); s.width(3); s.fill('0'); s << static_cast(uc); _out << s.str(); } else { _out << *c; // Print normally if in basic source character set. } break; } } } _out << "\""; // Closing " break; } case Slice::Builtin::KindObject: case Slice::Builtin::KindObjectProxy: case Slice::Builtin::KindLocalObject: assert(false); } } else if(en) { _out << getAbsolute(en, IdentToUpper) << "::"; string::size_type colon = value.rfind(':'); if(colon != string::npos) { _out << fixIdent(value.substr(colon + 1), IdentToUpper); } else { _out << fixIdent(value, IdentToUpper); } } else { assert(false); // Unknown const type. } } void Slice::Ruby::CodeVisitor::writeType(const TypePtr& p) { BuiltinPtr builtin = BuiltinPtr::dynamicCast(p); if(builtin) { switch(builtin->kind()) { case Builtin::KindBool: { _out << "::Ice::T_bool"; break; } case Builtin::KindByte: { _out << "::Ice::T_byte"; break; } case Builtin::KindShort: { _out << "::Ice::T_short"; break; } case Builtin::KindInt: { _out << "::Ice::T_int"; break; } case Builtin::KindLong: { _out << "::Ice::T_long"; break; } case Builtin::KindFloat: { _out << "::Ice::T_float"; break; } case Builtin::KindDouble: { _out << "::Ice::T_double"; break; } case Builtin::KindString: { _out << "::Ice::T_string"; break; } case Builtin::KindObject: { _out << "::Ice::T_Object"; break; } case Builtin::KindObjectProxy: { _out << "::Ice::T_ObjectPrx"; break; } case Builtin::KindLocalObject: { _out << "::Ice::T_LocalObject"; break; } } return; } ProxyPtr prx = ProxyPtr::dynamicCast(p); if(prx) { _out << getAbsolute(prx->_class(), IdentToUpper, "T_") << "Prx"; return; } ContainedPtr cont = ContainedPtr::dynamicCast(p); assert(cont); _out << getAbsolute(cont, IdentToUpper, "T_"); } string Slice::Ruby::CodeVisitor::getDefaultValue(const TypePtr& p) { BuiltinPtr builtin = BuiltinPtr::dynamicCast(p); if(builtin) { switch(builtin->kind()) { case Builtin::KindBool: { return "false"; } case Builtin::KindByte: case Builtin::KindShort: case Builtin::KindInt: case Builtin::KindLong: { return "0"; } case Builtin::KindFloat: case Builtin::KindDouble: { return "0.0"; } case Builtin::KindString: { return "''"; } case Builtin::KindObject: case Builtin::KindObjectProxy: case Builtin::KindLocalObject: { return "nil"; } } } EnumPtr en = EnumPtr::dynamicCast(p); if(en) { EnumeratorList enums = en->getEnumerators(); return getAbsolute(en, IdentToUpper) + "::" + fixIdent(enums.front()->name(), IdentToUpper); } StructPtr st = StructPtr::dynamicCast(p); if(st) { return getAbsolute(st, IdentToUpper) + ".new"; } return "nil"; } void Slice::Ruby::CodeVisitor::writeHash(const string& name, const TypePtr& p, int& iter) { _out << nl << "_h = 5 * _h + " << name << ".hash"; } void Slice::Ruby::CodeVisitor::collectClassMembers(const ClassDefPtr& p, MemberInfoList& allMembers, bool inherited) { ClassList bases = p->bases(); if(!bases.empty() && !bases.front()->isInterface()) { collectClassMembers(bases.front(), allMembers, true); } DataMemberList members = p->dataMembers(); for(DataMemberList::iterator q = members.begin(); q != members.end(); ++q) { MemberInfo m; m.lowerName = fixIdent((*q)->name(), IdentToLower); m.fixedName = fixIdent((*q)->name(), IdentNormal); m.type = (*q)->type(); m.inherited = inherited; allMembers.push_back(m); } } void Slice::Ruby::CodeVisitor::collectExceptionMembers(const ExceptionPtr& p, MemberInfoList& allMembers, bool inherited) { ExceptionPtr base = p->base(); if(base) { collectExceptionMembers(base, allMembers, true); } DataMemberList members = p->dataMembers(); for(DataMemberList::iterator q = members.begin(); q != members.end(); ++q) { MemberInfo m; m.lowerName = fixIdent((*q)->name(), IdentToLower); m.fixedName = fixIdent((*q)->name(), IdentNormal); m.type = (*q)->type(); m.inherited = inherited; allMembers.push_back(m); } } static string normalizePath(const string& path) { string result = path; replace(result.begin(), result.end(), '\\', '/'); string::size_type pos; while((pos = result.find("//")) != string::npos) { result.replace(pos, 2, "/"); } return result; } static string changeInclude(const string& inc, const vector& includePaths) { string orig = normalizePath(inc); string curr = orig; // The current shortest pathname. // // Compare the pathname of the included file against each of the include directories. // If any of the include directories match the leading part of the included file, // then select the include directory whose removal results in the shortest pathname. // for(vector::const_iterator p = includePaths.begin(); p != includePaths.end(); ++p) { string includePath = *p; if(orig.compare(0, p->size(), *p) == 0) { string s = orig.substr(p->size()); if(s.size() < curr.size()) { curr = s; } } } string::size_type pos = curr.rfind('.'); if(pos != string::npos) { curr.erase(pos); } return curr; } void Slice::Ruby::generate(const UnitPtr& un, bool all, bool checksum, const vector& includePaths, Output& out) { out << nl << "require 'Ice'"; if(!all) { vector paths = includePaths; for(vector::iterator p = paths.begin(); p != paths.end(); ++p) { if(p->size() && (*p)[p->size() - 1] != '/') { *p += '/'; } *p = normalizePath(*p); } StringList includes = un->includeFiles(); for(StringList::const_iterator q = includes.begin(); q != includes.end(); ++q) { string file = changeInclude(*q, paths); out << nl << "require '" << file << ".rb'"; } } CodeVisitor codeVisitor(out); un->visit(&codeVisitor, false); if(checksum) { ChecksumMap checksums = createChecksums(un); if(!checksums.empty()) { out << sp; for(ChecksumMap::const_iterator p = checksums.begin(); p != checksums.end(); ++p) { out << nl << "::Ice::SliceChecksums[\"" << p->first << "\"] = \""; ostringstream str; str.flags(ios_base::hex); str.fill('0'); for(vector::const_iterator q = p->second.begin(); q != p->second.end(); ++q) { str << (int)(*q); } out << str.str() << "\""; } } } out << nl; // Trailing newline. } bool Slice::Ruby::splitString(const string& str, vector& args, const string& delim) { string::size_type beg; string::size_type end = 0; while(true) { beg = str.find_first_not_of(delim, end); if(beg == string::npos) { break; } // // Check for quoted argument. // char ch = str[beg]; if(ch == '"' || ch == '\'') { beg++; end = str.find(ch, beg); if(end == string::npos) { return false; } args.push_back(str.substr(beg, end - beg)); end++; // Skip end quote. } else { end = str.find_first_of(delim + "'\"", beg); if(end == string::npos) { end = str.length(); } args.push_back(str.substr(beg, end - beg)); } } return true; } string Slice::Ruby::fixIdent(const string& ident, IdentStyle style) { assert(!ident.empty()); if(ident[0] != ':') { string id = ident; switch(style) { case IdentNormal: break; case IdentToUpper: if(id[0] >= 'a' && id[0] <= 'z') { id[0] += 'A' - 'a'; } break; case IdentToLower: if(id[0] >= 'A' && id[0] <= 'Z') { id[0] += 'a' - 'A'; } break; } return lookupKwd(id); } vector ids = splitScopedName(ident); assert(!ids.empty()); ostringstream result; for(vector::size_type i = 0; i < ids.size() - 1; ++i) { // // We assume all intermediate names must be upper-case (i.e., they represent // the names of modules or classes). // result << "::" << fixIdent(ids[i], IdentToUpper); } result << "::" << fixIdent(ids[ids.size() - 1], style); // // Preserve trailing scope resolution operator if necessary. // if(ident.rfind("::") == ident.size() - 2) { result << "::"; } return result.str(); } string Slice::Ruby::getAbsolute(const ContainedPtr& cont, IdentStyle style, const string& prefix) { string scope = fixIdent(cont->scope(), IdentToUpper); if(prefix.empty()) { return scope + fixIdent(cont->name(), style); } else { return scope + prefix + fixIdent(cont->name(), style); } } void Slice::Ruby::printHeader(IceUtil::Output& out) { static const char* header = "# **********************************************************************\n" "#\n" "# Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved.\n" "#\n" "# This copy of Ice is licensed to you under the terms described in the\n" "# ICE_LICENSE file included in this distribution.\n" "#\n" "# **********************************************************************\n" ; out << header; out << "\n# Ice version " << ICE_STRING_VERSION; } IceE-trans-1.2.0/src/Slice/Checksum.cpp0000664000076400007640000001610510550516551017120 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 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 using namespace std; using namespace Slice; namespace Slice { class ChecksumVisitor : public ParserVisitor { public: ChecksumVisitor(ChecksumMap&); virtual bool visitClassDefStart(const ClassDefPtr&); virtual bool visitExceptionStart(const ExceptionPtr&); virtual bool visitStructStart(const StructPtr&); virtual void visitSequence(const SequencePtr&); virtual void visitDictionary(const DictionaryPtr&); virtual void visitEnum(const EnumPtr&); virtual void visitConst(const ConstPtr&); private: string typeToString(const TypePtr&); void updateMap(const string&, const string&); ChecksumMap& _map; }; } Slice::ChecksumVisitor::ChecksumVisitor(ChecksumMap& m) : _map(m) { } bool Slice::ChecksumVisitor::visitClassDefStart(const ClassDefPtr& p) { if(p->isLocal()) { return false; } ClassList bases = p->bases(); ostringstream ostr; if(p->isInterface()) { ostr << "interface "; } else { ostr << "class "; } ostr << p->name(); if(!bases.empty()) { if(!bases.front()->isInterface()) { ostr << " extends " << bases.front()->scoped(); bases.erase(bases.begin()); } if(!bases.empty()) { if(p->isInterface()) { ostr << " extends "; } else { ostr << " implements "; } for(ClassList::iterator q = bases.begin(); q != bases.end(); ++q) { if(q != bases.begin()) { ostr << ", "; } ostr << (*q)->scoped(); } } } ostr << endl; if(p->hasDataMembers()) { DataMemberList members = p->dataMembers(); for(DataMemberList::iterator q = members.begin(); q != members.end(); ++q) { ostr << typeToString((*q)->type()) << ' ' << (*q)->name() << endl; } } if(p->hasOperations()) { OperationList ops = p->operations(); for(OperationList::iterator q = ops.begin(); q != ops.end(); ++q) { ostr << typeToString((*q)->returnType()) << ' ' << (*q)->name() << '('; ParamDeclList params = (*q)->parameters(); for(ParamDeclList::iterator r = params.begin(); r != params.end(); ++r) { if(r != params.begin()) { ostr << ", "; } if((*r)->isOutParam()) { ostr << "out "; } ostr << typeToString((*r)->type()) << ' ' << (*r)->name(); } ostr << ')'; ExceptionList ex = (*q)->throws(); if(!ex.empty()) { ostr << " throws "; for(ExceptionList::iterator s = ex.begin(); s != ex.end(); ++s) { if(s != ex.begin()) { ostr << ", "; } ostr << (*s)->scoped(); } } ostr << endl; } } updateMap(p->scoped(), ostr.str()); return false; } bool Slice::ChecksumVisitor::visitExceptionStart(const ExceptionPtr& p) { if(p->isLocal()) { return false; } ExceptionPtr base = p->base(); ostringstream ostr; ostr << "exception " << p->name(); if(base) { ostr << " extends " << base->scoped(); } ostr << endl; DataMemberList members = p->dataMembers(); for(DataMemberList::iterator q = members.begin(); q != members.end(); ++q) { ostr << typeToString((*q)->type()) << ' ' << (*q)->name() << endl; } updateMap(p->scoped(), ostr.str()); return false; } bool Slice::ChecksumVisitor::visitStructStart(const StructPtr& p) { if(p->isLocal()) { return false; } ostringstream ostr; ostr << "struct " << p->name() << endl; DataMemberList members = p->dataMembers(); for(DataMemberList::iterator q = members.begin(); q != members.end(); ++q) { ostr << typeToString((*q)->type()) << ' ' << (*q)->name() << endl; } updateMap(p->scoped(), ostr.str()); return false; } void Slice::ChecksumVisitor::visitSequence(const SequencePtr& p) { if(p->isLocal()) { return; } ostringstream ostr; ostr << "sequence<" << typeToString(p->type()) << "> " << p->name() << endl; updateMap(p->scoped(), ostr.str()); } void Slice::ChecksumVisitor::visitDictionary(const DictionaryPtr& p) { if(p->isLocal()) { return; } ostringstream ostr; ostr << "dictionary<" << typeToString(p->keyType()) << ", " << typeToString(p->valueType()) << "> " << p->name() << endl; updateMap(p->scoped(), ostr.str()); } void Slice::ChecksumVisitor::visitEnum(const EnumPtr& p) { if(p->isLocal()) { return; } ostringstream ostr; ostr << "enum " << p->name() << endl; EnumeratorList enums = p->getEnumerators(); for(EnumeratorList::iterator q = enums.begin(); q != enums.end(); ++q) { ostr << (*q)->name() << endl; } updateMap(p->scoped(), ostr.str()); } void Slice::ChecksumVisitor::visitConst(const ConstPtr& p) { ostringstream ostr; ostr << "const " << typeToString(p->type()) << ' ' << p->name() << " = " << p->value() << endl; updateMap(p->scoped(), ostr.str()); } string Slice::ChecksumVisitor::typeToString(const TypePtr& type) { static const char* builtinTable[] = { "byte", "boolean", "short", "int", "long", "float", "double", "string", "Object", "Object*", "LocalObject" }; if(!type) { return "void"; } BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); if(builtin) { return builtinTable[builtin->kind()]; } ProxyPtr proxy = ProxyPtr::dynamicCast(type); if(proxy) { return proxy->_class()->scoped() + "*"; } ContainedPtr cont = ContainedPtr::dynamicCast(type); assert(cont); return cont->scoped(); } void Slice::ChecksumVisitor::updateMap(const string& scoped, const string& data) { IceUtil::MD5 md5(reinterpret_cast(data.c_str()), static_cast(data.size())); vector bytes; bytes.resize(16); md5.getDigest(reinterpret_cast(&bytes[0])); _map.insert(ChecksumMap::value_type(scoped, bytes)); } Slice::ChecksumMap Slice::createChecksums(const UnitPtr& u) { ChecksumMap result; ChecksumVisitor visitor(result); u->visit(&visitor, false); return result; } IceE-trans-1.2.0/src/Slice/Makefile0000664000076400007640000000313210620635757016316 0ustar dwaynedwayne# ********************************************************************** # # Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. # # This copy of Ice is licensed to you under the terms described in the # ICE_LICENSE file included in this distribution. # # ********************************************************************** top_srcdir = ../.. LIBFILENAME = $(call mklibfilename,Slice,$(VERSION)) SONAME = $(call mksoname,Slice,$(SOVERSION)) LIBNAME = $(call mklibname,Slice) TARGETS = $(call mklibtargets,$(libdir)/$(LIBFILENAME),$(libdir)/$(SONAME),$(libdir)/$(LIBNAME)) OBJS = Scanner.o \ Grammar.o \ Parser.o \ CPlusPlusUtil.o \ CsUtil.o \ VbUtil.o \ JavaUtil.o \ Preprocessor.o \ Checksum.o \ PythonUtil.o \ DotNetNames.o \ RubyUtil.o SRCS = $(OBJS:.o=.cpp) include $(top_srcdir)/config/Make.rules CPPFLAGS := -I.. $(CPPFLAGS) -DSLICE_API_EXPORTS LINKWITH := -lIceUtil BISONFLAGS := --name-prefix "slice_" $(BISONFLAGS) ifeq ($(STATICLIBS),yes) $(libdir)/$(LIBNAME): $(OBJS) rm -f $@ $(call mklib,$@,$(OBJS)) else $(libdir)/$(LIBFILENAME): $(OBJS) rm -f $@ $(call mkshlib,$@,$(SONAME),$(OBJS),$(LINKWITH)) $(libdir)/$(SONAME): $(libdir)/$(LIBFILENAME) rm -f $@ ln -s $(LIBFILENAME) $@ $(libdir)/$(LIBNAME): $(libdir)/$(SONAME) rm -f $@ ln -s $(SONAME) $@ endif # # The .y rule does not work well with parallel builds; need to investigate # .NOTPARALLEL: clean:: # rm -f Grammar.cpp Grammar.h # rm -f Scanner.cpp install:: all # $(call installlib,$(install_libdir),$(libdir),$(LIBFILENAME),$(SONAME),$(LIBNAME)) include .depend IceE-trans-1.2.0/src/Slice/GrammarUtil.h0000664000076400007640000001207610550516551017252 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** #ifndef SLICE_GRAMMAR_UTIL_H #define SLICE_GRAMMAR_UTIL_H #include namespace Slice { class StringTok; class StringListTok; class TypeStringTok; class TypeStringListTok; class BoolTok; class IntegerTok; class FloatingTok; class ExceptionListTok; class ClassListTok; class EnumeratorListTok; class SyntaxTreeBaseStringTok; typedef ::IceUtil::Handle StringTokPtr; typedef ::IceUtil::Handle StringListTokPtr; typedef ::IceUtil::Handle TypeStringTokPtr; typedef ::IceUtil::Handle TypeStringListTokPtr; typedef ::IceUtil::Handle BoolTokPtr; typedef ::IceUtil::Handle IntegerTokPtr; typedef ::IceUtil::Handle FloatingTokPtr; typedef ::IceUtil::Handle ExceptionListTokPtr; typedef ::IceUtil::Handle ClassListTokPtr; typedef ::IceUtil::Handle EnumeratorListTokPtr; typedef ::IceUtil::Handle SyntaxTreeBaseStringTokPtr; // ---------------------------------------------------------------------- // StringTok // ---------------------------------------------------------------------- class SLICE_API StringTok : public GrammarBase { public: StringTok() { } std::string v; }; // ---------------------------------------------------------------------- // StringListTok // ---------------------------------------------------------------------- class SLICE_API StringListTok : public GrammarBase { public: StringListTok() { } StringList v; }; // ---------------------------------------------------------------------- // TypeStringTok // ---------------------------------------------------------------------- class SLICE_API TypeStringTok : public GrammarBase { public: TypeStringTok() { } TypeString v; }; // ---------------------------------------------------------------------- // TypeStringListTok // ---------------------------------------------------------------------- class SLICE_API TypeStringListTok : public GrammarBase { public: TypeStringListTok() { } TypeStringList v; }; // ---------------------------------------------------------------------- // IntegerTok // ---------------------------------------------------------------------- class SLICE_API IntegerTok : public GrammarBase { public: IntegerTok() { } IceUtil::Int64 v; }; // ---------------------------------------------------------------------- // FloatingTok // ---------------------------------------------------------------------- class SLICE_API FloatingTok : public GrammarBase { public: FloatingTok() { } double v; }; // ---------------------------------------------------------------------- // BoolTok // ---------------------------------------------------------------------- class SLICE_API BoolTok : public GrammarBase { public: BoolTok() { } bool v; }; // ---------------------------------------------------------------------- // ExceptionListTok // ---------------------------------------------------------------------- class SLICE_API ExceptionListTok : public GrammarBase { public: ExceptionListTok() { } ExceptionList v; }; // ---------------------------------------------------------------------- // ClassListTok // ---------------------------------------------------------------------- class SLICE_API ClassListTok : public GrammarBase { public: ClassListTok() { } ClassList v; }; // ---------------------------------------------------------------------- // EnumeratorListTok // ---------------------------------------------------------------------- class SLICE_API EnumeratorListTok : public GrammarBase { public: EnumeratorListTok() { } EnumeratorList v; }; // ---------------------------------------------------------------------- // SyntaxTreeBaseStringTok // ---------------------------------------------------------------------- class SLICE_API SyntaxTreeBaseStringTok : public GrammarBase { public: SyntaxTreeBaseStringTok() { } SyntaxTreeBaseString v; }; } // // Stuff for flex and bison // #define YYSTYPE Slice::GrammarBasePtr #define YY_DECL int slice_lex(YYSTYPE* yylvalp) YY_DECL; int slice_parse(); // // I must set the initial stack depth to the maximum stack depth to // disable bison stack resizing. The bison stack resizing routines use // simple malloc/alloc/memcpy calls, which do not work for the // YYSTYPE, since YYSTYPE is a C++ type, with constructor, destructor, // assignment operator, etc. // #define YYMAXDEPTH 20000 // 20000 should suffice. Bison default is 10000 as maximum. #define YYINITDEPTH YYMAXDEPTH // Initial depth is set to max depth, for the reasons described above. // // Newer bison versions allow to disable stack resizing by defining // yyoverflow. // #define yyoverflow(a, b, c, d, e, f) yyerror(a) #endif IceE-trans-1.2.0/src/Slice/Scanner.cpp0000664000076400007640000014361110620635757016762 0ustar dwaynedwayne#include #define yy_create_buffer slice__create_buffer #define yy_delete_buffer slice__delete_buffer #define yy_scan_buffer slice__scan_buffer #define yy_scan_string slice__scan_string #define yy_scan_bytes slice__scan_bytes #define yy_flex_debug slice__flex_debug #define yy_init_buffer slice__init_buffer #define yy_flush_buffer slice__flush_buffer #define yy_load_buffer_state slice__load_buffer_state #define yy_switch_to_buffer slice__switch_to_buffer #define yyin slice_in #define yyleng slice_leng #define yylex slice_lex #define yyout slice_out #define yyrestart slice_restart #define yytext slice_text #line 19 "lex.yy.c" /* A lexical scanner generated by flex */ /* Scanner skeleton version: * $Header: /home/daffy/u0/vern/flex/RCS/flex.skl,v 2.91 96/09/10 16:58:48 vern Exp $ */ #define FLEX_SCANNER #define YY_FLEX_MAJOR_VERSION 2 #define YY_FLEX_MINOR_VERSION 5 #include #include /* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ #ifdef c_plusplus #ifndef __cplusplus #define __cplusplus #endif #endif #ifdef __cplusplus #include /* Use prototypes in function declarations. */ #define YY_USE_PROTOS /* The "const" storage-class-modifier is valid. */ #define YY_USE_CONST #else /* ! __cplusplus */ #if __STDC__ #define YY_USE_PROTOS #define YY_USE_CONST #endif /* __STDC__ */ #endif /* ! __cplusplus */ #ifdef __TURBOC__ #pragma warn -rch #pragma warn -use #include #include #define YY_USE_CONST #define YY_USE_PROTOS #endif #ifdef YY_USE_CONST #define yyconst const #else #define yyconst #endif #ifdef YY_USE_PROTOS #define YY_PROTO(proto) proto #else #define YY_PROTO(proto) () #endif /* Returned upon end-of-file. */ #define YY_NULL 0 /* Promotes a possibly negative, possibly signed char to an unsigned * integer for use as an array index. If the signed char is negative, * we want to instead treat it as an 8-bit unsigned char, hence the * double cast. */ #define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) /* Enter a start condition. This macro really ought to take a parameter, * but we do it the disgusting crufty way forced on us by the ()-less * definition of BEGIN. */ #define BEGIN yy_start = 1 + 2 * /* Translate the current start state into a value that can be later handed * to BEGIN to return to the state. The YYSTATE alias is for lex * compatibility. */ #define YY_START ((yy_start - 1) / 2) #define YYSTATE YY_START /* Action number for EOF rule of a given start state. */ #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) /* Special action meaning "start processing a new file". */ #define YY_NEW_FILE yyrestart( yyin ) #define YY_END_OF_BUFFER_CHAR 0 /* Size of default input buffer. */ #define YY_BUF_SIZE 16384 typedef struct yy_buffer_state *YY_BUFFER_STATE; extern int yyleng; extern FILE *yyin, *yyout; #define EOB_ACT_CONTINUE_SCAN 0 #define EOB_ACT_END_OF_FILE 1 #define EOB_ACT_LAST_MATCH 2 /* The funky do-while in the following #define is used to turn the definition * int a single C statement (which needs a semi-colon terminator). This * avoids problems with code like: * * if ( condition_holds ) * yyless( 5 ); * else * do_something_else(); * * Prior to using the do-while the compiler would get upset at the * "else" because it interpreted the "if" statement as being all * done when it reached the ';' after the yyless() call. */ /* Return all but the first 'n' matched characters back to the input stream. */ #define yyless(n) \ do \ { \ /* Undo effects of setting up yytext. */ \ *yy_cp = yy_hold_char; \ YY_RESTORE_YY_MORE_OFFSET \ yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \ YY_DO_BEFORE_ACTION; /* set up yytext again */ \ } \ while ( 0 ) #define unput(c) yyunput( c, yytext_ptr ) /* The following is because we cannot portably get our hands on size_t * (without autoconf's help, which isn't available because we want * flex-generated scanners to compile on their own). */ typedef unsigned int yy_size_t; struct yy_buffer_state { FILE *yy_input_file; char *yy_ch_buf; /* input buffer */ char *yy_buf_pos; /* current position in input buffer */ /* Size of input buffer in bytes, not including room for EOB * characters. */ yy_size_t yy_buf_size; /* Number of characters read into yy_ch_buf, not including EOB * characters. */ int yy_n_chars; /* Whether we "own" the buffer - i.e., we know we created it, * and can realloc() it to grow it, and should free() it to * delete it. */ int yy_is_our_buffer; /* Whether this is an "interactive" input source; if so, and * if we're using stdio for input, then we want to use getc() * instead of fread(), to make sure we stop fetching input after * each newline. */ int yy_is_interactive; /* Whether we're considered to be at the beginning of a line. * If so, '^' rules will be active on the next match, otherwise * not. */ int yy_at_bol; /* Whether to try to fill the input buffer when we reach the * end of it. */ int yy_fill_buffer; int yy_buffer_status; #define YY_BUFFER_NEW 0 #define YY_BUFFER_NORMAL 1 /* When an EOF's been seen but there's still some text to process * then we mark the buffer as YY_EOF_PENDING, to indicate that we * shouldn't try reading from the input source any more. We might * still have a bunch of tokens to match, though, because of * possible backing-up. * * When we actually see the EOF, we change the status to "new" * (via yyrestart()), so that the user can continue scanning by * just pointing yyin at a new input file. */ #define YY_BUFFER_EOF_PENDING 2 }; static YY_BUFFER_STATE yy_current_buffer = 0; /* We provide macros for accessing buffer states in case in the * future we want to put the buffer states in a more general * "scanner state". */ #define YY_CURRENT_BUFFER yy_current_buffer /* yy_hold_char holds the character lost when yytext is formed. */ static char yy_hold_char; static int yy_n_chars; /* number of characters read into yy_ch_buf */ int yyleng; /* Points to current character in buffer. */ static char *yy_c_buf_p = (char *) 0; static int yy_init = 1; /* whether we need to initialize */ static int yy_start = 0; /* start state number */ /* Flag which is used to allow yywrap()'s to do buffer switches * instead of setting up a fresh yyin. A bit of a hack ... */ static int yy_did_buffer_switch_on_eof; void yyrestart YY_PROTO(( FILE *input_file )); void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer )); void yy_load_buffer_state YY_PROTO(( void )); YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size )); void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b )); void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file )); void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b )); #define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer ) YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size )); YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str )); YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len )); static void *yy_flex_alloc YY_PROTO(( yy_size_t )); static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t )); static void yy_flex_free YY_PROTO(( void * )); #define yy_new_buffer yy_create_buffer #define yy_set_interactive(is_interactive) \ { \ if ( ! yy_current_buffer ) \ yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ yy_current_buffer->yy_is_interactive = is_interactive; \ } #define yy_set_bol(at_bol) \ { \ if ( ! yy_current_buffer ) \ yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ yy_current_buffer->yy_at_bol = at_bol; \ } #define YY_AT_BOL() (yy_current_buffer->yy_at_bol) #define yywrap() 1 #define YY_SKIP_YYWRAP typedef unsigned char YY_CHAR; FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; typedef int yy_state_type; extern char *yytext; #define yytext_ptr yytext static yy_state_type yy_get_previous_state YY_PROTO(( void )); static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state )); static int yy_get_next_buffer YY_PROTO(( void )); static void yy_fatal_error YY_PROTO(( yyconst char msg[] )); /* Done after the current pattern has been matched and before the * corresponding action - sets up yytext. */ #define YY_DO_BEFORE_ACTION \ yytext_ptr = yy_bp; \ yyleng = (int) (yy_cp - yy_bp); \ yy_hold_char = *yy_cp; \ *yy_cp = '\0'; \ yy_c_buf_p = yy_cp; #define YY_NUM_RULES 19 #define YY_END_OF_BUFFER 20 static yyconst short int yy_accept[66] = { 0, 0, 0, 20, 18, 17, 17, 14, 18, 18, 18, 15, 15, 18, 13, 8, 18, 9, 18, 0, 15, 15, 16, 6, 5, 16, 15, 0, 0, 7, 0, 12, 13, 10, 13, 11, 0, 0, 0, 0, 16, 0, 16, 15, 0, 1, 0, 0, 16, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 4, 0 } ; static yyconst int yy_ec[256] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 5, 6, 1, 1, 1, 1, 7, 1, 8, 9, 1, 10, 11, 12, 13, 14, 14, 14, 14, 14, 14, 14, 15, 15, 16, 1, 1, 1, 1, 1, 1, 17, 17, 17, 17, 18, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 22, 23, 1, 20, 1, 17, 17, 17, 17, 24, 19, 20, 20, 25, 20, 20, 26, 20, 27, 20, 20, 20, 20, 20, 20, 20, 20, 20, 28, 20, 20, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } ; static yyconst int yy_meta[29] = { 0, 1, 2, 3, 4, 1, 1, 4, 1, 5, 5, 1, 1, 6, 6, 6, 1, 7, 7, 7, 8, 1, 1, 1, 7, 8, 9, 8, 8 } ; static yyconst short int yy_base[78] = { 0, 0, 177, 182, 184, 184, 184, 184, 18, 21, 29, 31, 25, 165, 54, 159, 0, 137, 28, 37, 0, 0, 49, 184, 184, 0, 131, 38, 0, 184, 67, 184, 73, 184, 0, 184, 58, 63, 110, 69, 184, 68, 72, 0, 87, 184, 107, 80, 83, 121, 101, 118, 119, 119, 109, 184, 86, 101, 103, 184, 102, 67, 40, 37, 184, 184, 107, 110, 118, 123, 124, 130, 132, 138, 147, 155, 161, 170 } ; static yyconst short int yy_def[78] = { 0, 65, 1, 65, 65, 65, 65, 65, 65, 65, 65, 65, 11, 65, 66, 65, 67, 65, 68, 65, 11, 12, 65, 65, 65, 22, 11, 69, 70, 65, 65, 65, 66, 65, 32, 65, 68, 71, 65, 72, 65, 65, 65, 70, 65, 65, 65, 65, 65, 73, 65, 73, 74, 65, 74, 65, 65, 75, 65, 65, 76, 76, 77, 77, 65, 0, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65 } ; static yyconst short int yy_nxt[213] = { 0, 4, 5, 6, 5, 7, 4, 4, 4, 8, 8, 9, 10, 11, 12, 12, 13, 14, 14, 14, 14, 15, 16, 17, 14, 14, 14, 14, 14, 19, 36, 20, 21, 21, 22, 22, 22, 23, 21, 21, 64, 24, 25, 64, 26, 26, 21, 41, 41, 27, 22, 22, 22, 65, 38, 27, 30, 30, 30, 28, 36, 31, 22, 22, 22, 44, 45, 39, 40, 30, 30, 30, 62, 39, 31, 30, 30, 30, 47, 47, 31, 42, 42, 42, 38, 42, 42, 42, 56, 44, 45, 40, 49, 48, 48, 48, 48, 48, 48, 57, 57, 57, 40, 58, 59, 58, 59, 62, 60, 32, 32, 32, 55, 32, 32, 32, 32, 34, 34, 34, 37, 56, 55, 52, 37, 53, 52, 37, 42, 42, 43, 43, 37, 37, 50, 46, 37, 48, 48, 51, 51, 51, 51, 51, 51, 51, 51, 51, 54, 54, 54, 54, 54, 54, 54, 54, 54, 57, 57, 65, 35, 57, 61, 61, 61, 61, 61, 61, 61, 61, 61, 63, 63, 63, 63, 63, 63, 63, 63, 63, 33, 29, 65, 18, 3, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65 } ; static yyconst short int yy_chk[213] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 8, 18, 8, 8, 8, 9, 9, 9, 10, 12, 12, 63, 10, 11, 62, 11, 11, 11, 27, 27, 11, 19, 19, 19, 12, 18, 11, 14, 14, 14, 11, 36, 14, 22, 22, 22, 37, 37, 22, 22, 30, 30, 30, 61, 22, 30, 32, 32, 32, 39, 39, 32, 41, 41, 41, 36, 42, 42, 42, 56, 44, 44, 42, 44, 47, 47, 47, 48, 48, 48, 56, 56, 56, 48, 57, 57, 58, 58, 60, 58, 66, 66, 66, 54, 66, 66, 66, 66, 67, 67, 67, 68, 53, 52, 51, 68, 50, 49, 68, 69, 69, 70, 70, 71, 71, 46, 38, 71, 72, 72, 73, 73, 73, 73, 73, 73, 73, 73, 73, 74, 74, 74, 74, 74, 74, 74, 74, 74, 75, 75, 26, 17, 75, 76, 76, 76, 76, 76, 76, 76, 76, 76, 77, 77, 77, 77, 77, 77, 77, 77, 77, 15, 13, 3, 2, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65 } ; static yy_state_type yy_last_accepting_state; static char *yy_last_accepting_cpos; /* The intent behind this definition is that it'll catch * any uses of REJECT which flex missed. */ #define REJECT reject_used_but_not_detected #define yymore() yymore_used_but_not_detected #define YY_MORE_ADJ 0 #define YY_RESTORE_YY_MORE_OFFSET char *yytext; #line 1 "Scanner.l" #define INITIAL 0 #line 2 "Scanner.l" // ********************************************************************** // // Copyright (c) 2003-2007 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 // Before Grammer.h, so that YYSTYPE is defined #include #include #include #include #if defined(_MSC_VER) && defined(ICE_64) // // '=' : conversion from 'size_t' to 'int', possible loss of data // The result of fread() is a size_t and gets inserted into an int // # pragma warning( 4 : 4267 ) // // 'initializing' : conversion from '__int64' to 'int', possible loss of data // Puts a pointer-difference into an int // # pragma warning( 4 : 4244 ) #endif using namespace std; using namespace Slice; namespace Slice { // // Definitions for the case-insensitive keyword-token map. // typedef std::map StringTokenMap; static StringTokenMap keywordMap; void initScanner(); void checkIdentifier(const string&); int checkKeyword(string&); } #define YY_USER_INIT initScanner(); #define YY_NEVER_INTERACTIVE 1 #line 504 "lex.yy.c" /* Macros after this point can all be overridden by user definitions in * section 1. */ #ifndef YY_SKIP_YYWRAP #ifdef __cplusplus extern "C" int yywrap YY_PROTO(( void )); #else extern int yywrap YY_PROTO(( void )); #endif #endif #ifndef YY_NO_UNPUT static void yyunput YY_PROTO(( int c, char *buf_ptr )); #endif #ifndef yytext_ptr static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int )); #endif #ifdef YY_NEED_STRLEN static int yy_flex_strlen YY_PROTO(( yyconst char * )); #endif #ifndef YY_NO_INPUT #ifdef __cplusplus static int yyinput YY_PROTO(( void )); #else static int input YY_PROTO(( void )); #endif #endif #if YY_STACK_USED static int yy_start_stack_ptr = 0; static int yy_start_stack_depth = 0; static int *yy_start_stack = 0; #ifndef YY_NO_PUSH_STATE static void yy_push_state YY_PROTO(( int new_state )); #endif #ifndef YY_NO_POP_STATE static void yy_pop_state YY_PROTO(( void )); #endif #ifndef YY_NO_TOP_STATE static int yy_top_state YY_PROTO(( void )); #endif #else #define YY_NO_PUSH_STATE 1 #define YY_NO_POP_STATE 1 #define YY_NO_TOP_STATE 1 #endif #ifdef YY_MALLOC_DECL YY_MALLOC_DECL #else #if __STDC__ #ifndef __cplusplus #include #endif #else /* Just try to get by without declaring the routines. This will fail * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int) * or sizeof(void*) != sizeof(int). */ #endif #endif /* Amount of stuff to slurp up with each read. */ #ifndef YY_READ_BUF_SIZE #define YY_READ_BUF_SIZE 8192 #endif /* Copy whatever the last rule matched to the standard output. */ #ifndef ECHO /* This used to be an fputs(), but since the string might contain NUL's, * we now use fwrite(). */ #define ECHO (void) fwrite( yytext, yyleng, 1, yyout ) #endif /* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, * is returned in "result". */ #ifndef YY_INPUT #define YY_INPUT(buf,result,max_size) \ if ( yy_current_buffer->yy_is_interactive ) \ { \ int c = '*', n; \ for ( n = 0; n < max_size && \ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ buf[n] = (char) c; \ if ( c == '\n' ) \ buf[n++] = (char) c; \ if ( c == EOF && ferror( yyin ) ) \ YY_FATAL_ERROR( "input in flex scanner failed" ); \ result = n; \ } \ else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \ && ferror( yyin ) ) \ YY_FATAL_ERROR( "input in flex scanner failed" ); #endif /* No semi-colon after return; correct usage is to write "yyterminate();" - * we don't want an extra ';' after the "return" because that will cause * some compilers to complain about unreachable statements. */ #ifndef yyterminate #define yyterminate() return YY_NULL #endif /* Number of entries by which start-condition stack grows. */ #ifndef YY_START_STACK_INCR #define YY_START_STACK_INCR 25 #endif /* Report a fatal error. */ #ifndef YY_FATAL_ERROR #define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) #endif /* Default declaration of generated scanner - a define so the user can * easily add parameters. */ #ifndef YY_DECL #define YY_DECL int yylex YY_PROTO(( void )) #endif /* Code executed at the beginning of each rule, after yytext and yyleng * have been set up. */ #ifndef YY_USER_ACTION #define YY_USER_ACTION #endif /* Code executed at the end of each rule. */ #ifndef YY_BREAK #define YY_BREAK break; #endif #define YY_RULE_SETUP \ if ( yyleng > 0 ) \ yy_current_buffer->yy_at_bol = \ (yytext[yyleng - 1] == '\n'); \ YY_USER_ACTION YY_DECL { register yy_state_type yy_current_state; register char *yy_cp = NULL, *yy_bp = NULL; register int yy_act; #line 65 "Scanner.l" #line 661 "lex.yy.c" if ( yy_init ) { yy_init = 0; #ifdef YY_USER_INIT YY_USER_INIT; #endif if ( ! yy_start ) yy_start = 1; /* first start state */ if ( ! yyin ) yyin = stdin; if ( ! yyout ) yyout = stdout; if ( ! yy_current_buffer ) yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); yy_load_buffer_state(); } while ( 1 ) /* loops until end-of-file is reached */ { yy_cp = yy_c_buf_p; /* Support of yytext. */ *yy_cp = yy_hold_char; /* yy_bp points to the position in yy_ch_buf of the start of * the current run. */ yy_bp = yy_cp; yy_current_state = yy_start; yy_current_state += YY_AT_BOL(); yy_match: do { register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; if ( yy_accept[yy_current_state] ) { yy_last_accepting_state = yy_current_state; yy_last_accepting_cpos = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 66 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; ++yy_cp; } while ( yy_base[yy_current_state] != 184 ); yy_find_action: yy_act = yy_accept[yy_current_state]; if ( yy_act == 0 ) { /* have to back up */ yy_cp = yy_last_accepting_cpos; yy_current_state = yy_last_accepting_state; yy_act = yy_accept[yy_current_state]; } YY_DO_BEFORE_ACTION; do_action: /* This label is used only to access EOF actions. */ switch ( yy_act ) { /* beginning of action switch */ case 0: /* must back up */ /* undo the effects of YY_DO_BEFORE_ACTION */ *yy_cp = yy_hold_char; yy_cp = yy_last_accepting_cpos; yy_current_state = yy_last_accepting_state; goto yy_find_action; case 1: *yy_cp = yy_hold_char; /* undo effects of setting up yytext */ yy_c_buf_p = yy_cp -= 1; YY_DO_BEFORE_ACTION; /* set up yytext again */ YY_RULE_SETUP #line 67 "Scanner.l" { unit->scanPosition(yytext); } YY_BREAK case 2: *yy_cp = yy_hold_char; /* undo effects of setting up yytext */ yy_c_buf_p = yy_cp -= 1; YY_DO_BEFORE_ACTION; /* set up yytext again */ YY_RULE_SETUP #line 71 "Scanner.l" { unit->scanPosition(yytext); } YY_BREAK case 3: *yy_cp = yy_hold_char; /* undo effects of setting up yytext */ yy_c_buf_p = yy_cp -= 1; YY_DO_BEFORE_ACTION; /* set up yytext again */ YY_RULE_SETUP #line 75 "Scanner.l" { unit->scanPosition(yytext); } YY_BREAK case 4: *yy_cp = yy_hold_char; /* undo effects of setting up yytext */ yy_c_buf_p = yy_cp -= 1; YY_DO_BEFORE_ACTION; /* set up yytext again */ YY_RULE_SETUP #line 79 "Scanner.l" { unit->scanPosition(yytext); } YY_BREAK case 5: YY_RULE_SETUP #line 83 "Scanner.l" { // C++-style comment int c; do { c = yyinput(); if(c == '\n') { unit->nextLine(); } } while(c != '\n' && c != EOF); } YY_BREAK case 6: YY_RULE_SETUP #line 97 "Scanner.l" { // C-style comment string comment = yytext + 2; while(true) { int c = yyinput(); if(c == '\n') { comment += static_cast(c); unit->nextLine(); } else if(c == '*') { int next = yyinput(); if(next == '/') { break; } else { comment += static_cast(c); unput(next); } } else if(c == EOF) { unit->warning("EOF in comment"); break; } else { comment += static_cast(c); } } if(comment[0] == '*') { unit->setComment(comment); } } YY_BREAK case 7: YY_RULE_SETUP #line 137 "Scanner.l" { return ICE_SCOPE_DELIMITER; } YY_BREAK case 8: YY_RULE_SETUP #line 141 "Scanner.l" { return ICE_METADATA_OPEN; } YY_BREAK case 9: YY_RULE_SETUP #line 145 "Scanner.l" { return ICE_METADATA_CLOSE; } YY_BREAK case 10: YY_RULE_SETUP #line 149 "Scanner.l" { return ICE_GLOBAL_METADATA_OPEN; } YY_BREAK case 11: YY_RULE_SETUP #line 153 "Scanner.l" { return ICE_GLOBAL_METADATA_CLOSE; } YY_BREAK case 12: YY_RULE_SETUP #line 157 "Scanner.l" { StringTokPtr ident = new StringTok; ident->v = *yytext == '\\' ? yytext + 1 : yytext; ident->v.erase(ident->v.find_first_of(" \t\v\n\r\f(")); *yylvalp = ident; checkIdentifier(ident->v); if(*yytext == '\\') { return ICE_IDENT_OP; } return checkKeyword(ident->v) == ICE_IDENTIFIER ? ICE_IDENT_OP : ICE_KEYWORD_OP; } YY_BREAK case 13: YY_RULE_SETUP #line 170 "Scanner.l" { StringTokPtr ident = new StringTok; ident->v = *yytext == '\\' ? yytext + 1 : yytext; *yylvalp = ident; checkIdentifier(ident->v); return *yytext == '\\' ? ICE_IDENTIFIER : checkKeyword(ident->v); } YY_BREAK case 14: YY_RULE_SETUP #line 178 "Scanner.l" { StringTokPtr str = new StringTok; while(true) { char c = static_cast(yyinput()); if(c == '"') { break; } else if(c == EOF) { unit->error("EOF in string"); break; } else if(c == '\n') { unit->error("newline in string"); } else if(c == '\\') { char next = static_cast(yyinput()); switch(next) { case '\\': case '"': case '\'': { str->v += next; break; } case 'n': { str->v += '\n'; break; } case 'r': { str->v += '\r'; break; } case 't': { str->v += '\t'; break; } case 'v': { str->v += '\v'; break; } case 'f': { str->v += '\f'; break; } case 'a': { str->v += '\a'; break; } case 'b': { str->v += '\b'; break; } case '?': { str->v += '\?'; break; } case '0': case '1': case '2': case '3': { static string octalDigits = "01234567"; unsigned short us = next - '0'; if(octalDigits.find_first_of(next = static_cast(yyinput())) != string::npos) { us = us * 8 + next - '0'; if(octalDigits.find_first_of(next = static_cast(yyinput())) != string::npos) { us = us * 8 + next - '0'; } else { unput(next); } } else { unput(next); } if(us == 0) { unit->error("illegal NUL character in string constant"); } str->v += static_cast(us); break; } case 'x': { IceUtil::Int64 ull = 0; while(isxdigit(next = static_cast(yyinput()))) { ull *= 16; if(isdigit(next)) { ull += next - '0'; } else if(islower(next)) { ull += next - 'a' + 10; } else { ull += next - 'A' + 10; } } unput(next); if(ull == 0) { unit->error("illegal NUL character in string constant"); } str->v += static_cast(ull); break; } // TODO: add universal character names default: { str->v += c; unput(next); } } } else { str->v += c; } } *yylvalp = str; return ICE_STRING_LITERAL; } YY_BREAK case 15: YY_RULE_SETUP #line 333 "Scanner.l" { IntegerTokPtr itp = new IntegerTok; *yylvalp = itp; if(!IceUtil::stringToInt64(string(yytext), itp->v)) { assert(itp->v != 0); string msg = "integer constant `"; msg += yytext; msg += "' out of range"; unit->error(msg); } return ICE_INTEGER_LITERAL; } YY_BREAK case 16: YY_RULE_SETUP #line 347 "Scanner.l" { errno = 0; FloatingTokPtr ftp = new FloatingTok; *yylvalp = ftp; string literal(yytext); char lastChar = literal[literal.size() - 1]; if(lastChar == 'f' || lastChar == 'F') { literal = literal.substr(0, literal.size() - 1); // Clobber trailing 'f' or 'F' suffix } ftp->v = strtod(literal.c_str(), 0); if((ftp->v == HUGE_VAL || ftp->v == -HUGE_VAL) && errno == ERANGE) { string msg = "floating-point constant `"; msg += yytext; msg += "' too large (overflow)"; unit->error(msg); } else if(ftp->v == 0 && errno == ERANGE) { string msg = "floating-point constant `"; msg += yytext; msg += "' too small (underflow)"; unit->error(msg); } return ICE_FLOATING_POINT_LITERAL; } YY_BREAK case 17: YY_RULE_SETUP #line 375 "Scanner.l" { // Igore white-space if(yytext[0] == '\n') { unit->nextLine(); } } YY_BREAK case 18: YY_RULE_SETUP #line 384 "Scanner.l" { if(yytext[0] < 32 || yytext[0] > 126) { stringstream s; s << "illegal input character: '\\"; s.width(3); s.fill('0'); s << oct << static_cast(static_cast(yytext[0])); s << "'"; unit->error(s.str()); return BAD_CHAR; } return yytext[0]; } YY_BREAK case 19: YY_RULE_SETUP #line 399 "Scanner.l" ECHO; YY_BREAK #line 1148 "lex.yy.c" case YY_STATE_EOF(INITIAL): yyterminate(); case YY_END_OF_BUFFER: { /* Amount of text matched not including the EOB char. */ int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1; /* Undo the effects of YY_DO_BEFORE_ACTION. */ *yy_cp = yy_hold_char; YY_RESTORE_YY_MORE_OFFSET if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW ) { /* We're scanning a new file or input source. It's * possible that this happened because the user * just pointed yyin at a new source and called * yylex(). If so, then we have to assure * consistency between yy_current_buffer and our * globals. Here is the right place to do so, because * this is the first action (other than possibly a * back-up) that will match for the new input source. */ yy_n_chars = yy_current_buffer->yy_n_chars; yy_current_buffer->yy_input_file = yyin; yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL; } /* Note that here we test for yy_c_buf_p "<=" to the position * of the first EOB in the buffer, since yy_c_buf_p will * already have been incremented past the NUL character * (since all states make transitions on EOB to the * end-of-buffer state). Contrast this with the test * in input(). */ if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] ) { /* This was really a NUL. */ yy_state_type yy_next_state; yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state(); /* Okay, we're now positioned to make the NUL * transition. We couldn't have * yy_get_previous_state() go ahead and do it * for us because it doesn't know how to deal * with the possibility of jamming (and we don't * want to build jamming into it because then it * will run more slowly). */ yy_next_state = yy_try_NUL_trans( yy_current_state ); yy_bp = yytext_ptr + YY_MORE_ADJ; if ( yy_next_state ) { /* Consume the NUL. */ yy_cp = ++yy_c_buf_p; yy_current_state = yy_next_state; goto yy_match; } else { yy_cp = yy_c_buf_p; goto yy_find_action; } } else switch ( yy_get_next_buffer() ) { case EOB_ACT_END_OF_FILE: { yy_did_buffer_switch_on_eof = 0; if ( yywrap() ) { /* Note: because we've taken care in * yy_get_next_buffer() to have set up * yytext, we can now set up * yy_c_buf_p so that if some total * hoser (like flex itself) wants to * call the scanner after we return the * YY_NULL, it'll still work - another * YY_NULL will get returned. */ yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; yy_act = YY_STATE_EOF(YY_START); goto do_action; } else { if ( ! yy_did_buffer_switch_on_eof ) YY_NEW_FILE; } break; } case EOB_ACT_CONTINUE_SCAN: yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state(); yy_cp = yy_c_buf_p; yy_bp = yytext_ptr + YY_MORE_ADJ; goto yy_match; case EOB_ACT_LAST_MATCH: yy_c_buf_p = &yy_current_buffer->yy_ch_buf[yy_n_chars]; yy_current_state = yy_get_previous_state(); yy_cp = yy_c_buf_p; yy_bp = yytext_ptr + YY_MORE_ADJ; goto yy_find_action; } break; } default: YY_FATAL_ERROR( "fatal flex scanner internal error--no action found" ); } /* end of action switch */ } /* end of scanning one token */ } /* end of yylex */ /* yy_get_next_buffer - try to read in a new buffer * * Returns a code representing an action: * EOB_ACT_LAST_MATCH - * EOB_ACT_CONTINUE_SCAN - continue scanning from current position * EOB_ACT_END_OF_FILE - end of file */ static int yy_get_next_buffer() { register char *dest = yy_current_buffer->yy_ch_buf; register char *source = yytext_ptr; register int number_to_move, i; int ret_val; if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] ) YY_FATAL_ERROR( "fatal flex scanner internal error--end of buffer missed" ); if ( yy_current_buffer->yy_fill_buffer == 0 ) { /* Don't try to fill the buffer, so this is an EOF. */ if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 ) { /* We matched a single character, the EOB, so * treat this as a final EOF. */ return EOB_ACT_END_OF_FILE; } else { /* We matched some text prior to the EOB, first * process it. */ return EOB_ACT_LAST_MATCH; } } /* Try to read more data. */ /* First move last chars to start of buffer. */ number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1; for ( i = 0; i < number_to_move; ++i ) *(dest++) = *(source++); if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING ) /* don't do the read, it's not guaranteed to return an EOF, * just force an EOF */ yy_current_buffer->yy_n_chars = yy_n_chars = 0; else { int num_to_read = yy_current_buffer->yy_buf_size - number_to_move - 1; while ( num_to_read <= 0 ) { /* Not enough room in the buffer - grow it. */ #ifdef YY_USES_REJECT YY_FATAL_ERROR( "input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); #else /* just a shorter name for the current buffer */ YY_BUFFER_STATE b = yy_current_buffer; int yy_c_buf_p_offset = (int) (yy_c_buf_p - b->yy_ch_buf); if ( b->yy_is_our_buffer ) { int new_size = b->yy_buf_size * 2; if ( new_size <= 0 ) b->yy_buf_size += b->yy_buf_size / 8; else b->yy_buf_size *= 2; b->yy_ch_buf = (char *) /* Include room in for 2 EOB chars. */ yy_flex_realloc( (void *) b->yy_ch_buf, b->yy_buf_size + 2 ); } else /* Can't grow it, we don't own it. */ b->yy_ch_buf = 0; if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "fatal error - scanner input buffer overflow" ); yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; num_to_read = yy_current_buffer->yy_buf_size - number_to_move - 1; #endif } if ( num_to_read > YY_READ_BUF_SIZE ) num_to_read = YY_READ_BUF_SIZE; /* Read in more data. */ YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]), yy_n_chars, num_to_read ); yy_current_buffer->yy_n_chars = yy_n_chars; } if ( yy_n_chars == 0 ) { if ( number_to_move == YY_MORE_ADJ ) { ret_val = EOB_ACT_END_OF_FILE; yyrestart( yyin ); } else { ret_val = EOB_ACT_LAST_MATCH; yy_current_buffer->yy_buffer_status = YY_BUFFER_EOF_PENDING; } } else ret_val = EOB_ACT_CONTINUE_SCAN; yy_n_chars += number_to_move; yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR; yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; yytext_ptr = &yy_current_buffer->yy_ch_buf[0]; return ret_val; } /* yy_get_previous_state - get the state just before the EOB char was reached */ static yy_state_type yy_get_previous_state() { register yy_state_type yy_current_state; register char *yy_cp; yy_current_state = yy_start; yy_current_state += YY_AT_BOL(); for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp ) { register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); if ( yy_accept[yy_current_state] ) { yy_last_accepting_state = yy_current_state; yy_last_accepting_cpos = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 66 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; } return yy_current_state; } /* yy_try_NUL_trans - try to make a transition on the NUL character * * synopsis * next_state = yy_try_NUL_trans( current_state ); */ #ifdef YY_USE_PROTOS static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state ) #else static yy_state_type yy_try_NUL_trans( yy_current_state ) yy_state_type yy_current_state; #endif { register int yy_is_jam; register char *yy_cp = yy_c_buf_p; register YY_CHAR yy_c = 1; if ( yy_accept[yy_current_state] ) { yy_last_accepting_state = yy_current_state; yy_last_accepting_cpos = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 66 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; yy_is_jam = (yy_current_state == 65); return yy_is_jam ? 0 : yy_current_state; } #ifndef YY_NO_UNPUT #ifdef YY_USE_PROTOS static void yyunput( int c, register char *yy_bp ) #else static void yyunput( c, yy_bp ) int c; register char *yy_bp; #endif { register char *yy_cp = yy_c_buf_p; /* undo effects of setting up yytext */ *yy_cp = yy_hold_char; if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) { /* need to shift things up to make room */ /* +2 for EOB chars. */ register int number_to_move = yy_n_chars + 2; register char *dest = &yy_current_buffer->yy_ch_buf[ yy_current_buffer->yy_buf_size + 2]; register char *source = &yy_current_buffer->yy_ch_buf[number_to_move]; while ( source > yy_current_buffer->yy_ch_buf ) *--dest = *--source; yy_cp += (int) (dest - source); yy_bp += (int) (dest - source); yy_current_buffer->yy_n_chars = yy_n_chars = yy_current_buffer->yy_buf_size; if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) YY_FATAL_ERROR( "flex scanner push-back overflow" ); } *--yy_cp = (char) c; yytext_ptr = yy_bp; yy_hold_char = *yy_cp; yy_c_buf_p = yy_cp; } #endif /* ifndef YY_NO_UNPUT */ #ifndef YY_NO_INPUT #ifdef __cplusplus static int yyinput() #else static int input() #endif { int c; *yy_c_buf_p = yy_hold_char; if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) { /* yy_c_buf_p now points to the character we want to return. * If this occurs *before* the EOB characters, then it's a * valid NUL; if not, then we've hit the end of the buffer. */ if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] ) /* This was really a NUL. */ *yy_c_buf_p = '\0'; else { /* need more input */ int offset = yy_c_buf_p - yytext_ptr; ++yy_c_buf_p; switch ( yy_get_next_buffer() ) { case EOB_ACT_LAST_MATCH: /* This happens because yy_g_n_b() * sees that we've accumulated a * token and flags that we need to * try matching the token before * proceeding. But for input(), * there's no matching to consider. * So convert the EOB_ACT_LAST_MATCH * to EOB_ACT_END_OF_FILE. */ /* Reset buffer status. */ yyrestart( yyin ); /* fall through */ case EOB_ACT_END_OF_FILE: { if ( yywrap() ) return EOF; if ( ! yy_did_buffer_switch_on_eof ) YY_NEW_FILE; #ifdef __cplusplus return yyinput(); #else return input(); #endif } case EOB_ACT_CONTINUE_SCAN: yy_c_buf_p = yytext_ptr + offset; break; } } } c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */ *yy_c_buf_p = '\0'; /* preserve yytext */ yy_hold_char = *++yy_c_buf_p; yy_current_buffer->yy_at_bol = (c == '\n'); return c; } #endif /* YY_NO_INPUT */ #ifdef YY_USE_PROTOS void yyrestart( FILE *input_file ) #else void yyrestart( input_file ) FILE *input_file; #endif { if ( ! yy_current_buffer ) yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); yy_init_buffer( yy_current_buffer, input_file ); yy_load_buffer_state(); } #ifdef YY_USE_PROTOS void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) #else void yy_switch_to_buffer( new_buffer ) YY_BUFFER_STATE new_buffer; #endif { if ( yy_current_buffer == new_buffer ) return; if ( yy_current_buffer ) { /* Flush out information for old buffer. */ *yy_c_buf_p = yy_hold_char; yy_current_buffer->yy_buf_pos = yy_c_buf_p; yy_current_buffer->yy_n_chars = yy_n_chars; } yy_current_buffer = new_buffer; yy_load_buffer_state(); /* We don't actually know whether we did this switch during * EOF (yywrap()) processing, but the only time this flag * is looked at is after yywrap() is called, so it's safe * to go ahead and always set it. */ yy_did_buffer_switch_on_eof = 1; } #ifdef YY_USE_PROTOS void yy_load_buffer_state( void ) #else void yy_load_buffer_state() #endif { yy_n_chars = yy_current_buffer->yy_n_chars; yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos; yyin = yy_current_buffer->yy_input_file; yy_hold_char = *yy_c_buf_p; } #ifdef YY_USE_PROTOS YY_BUFFER_STATE yy_create_buffer( FILE *file, int size ) #else YY_BUFFER_STATE yy_create_buffer( file, size ) FILE *file; int size; #endif { YY_BUFFER_STATE b; b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); b->yy_buf_size = size; /* yy_ch_buf has to be 2 characters longer than the size given because * we need to put in 2 end-of-buffer characters. */ b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 ); if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); b->yy_is_our_buffer = 1; yy_init_buffer( b, file ); return b; } #ifdef YY_USE_PROTOS void yy_delete_buffer( YY_BUFFER_STATE b ) #else void yy_delete_buffer( b ) YY_BUFFER_STATE b; #endif { if ( ! b ) return; if ( b == yy_current_buffer ) yy_current_buffer = (YY_BUFFER_STATE) 0; if ( b->yy_is_our_buffer ) yy_flex_free( (void *) b->yy_ch_buf ); yy_flex_free( (void *) b ); } #ifdef YY_USE_PROTOS void yy_init_buffer( YY_BUFFER_STATE b, FILE *file ) #else void yy_init_buffer( b, file ) YY_BUFFER_STATE b; FILE *file; #endif { yy_flush_buffer( b ); b->yy_input_file = file; b->yy_fill_buffer = 1; #if YY_ALWAYS_INTERACTIVE b->yy_is_interactive = 1; #else #if YY_NEVER_INTERACTIVE b->yy_is_interactive = 0; #else b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; #endif #endif } #ifdef YY_USE_PROTOS void yy_flush_buffer( YY_BUFFER_STATE b ) #else void yy_flush_buffer( b ) YY_BUFFER_STATE b; #endif { if ( ! b ) return; b->yy_n_chars = 0; /* We always need two end-of-buffer characters. The first causes * a transition to the end-of-buffer state. The second causes * a jam in that state. */ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; b->yy_buf_pos = &b->yy_ch_buf[0]; b->yy_at_bol = 1; b->yy_buffer_status = YY_BUFFER_NEW; if ( b == yy_current_buffer ) yy_load_buffer_state(); } #ifndef YY_NO_SCAN_BUFFER #ifdef YY_USE_PROTOS YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size ) #else YY_BUFFER_STATE yy_scan_buffer( base, size ) char *base; yy_size_t size; #endif { YY_BUFFER_STATE b; if ( size < 2 || base[size-2] != YY_END_OF_BUFFER_CHAR || base[size-1] != YY_END_OF_BUFFER_CHAR ) /* They forgot to leave room for the EOB's. */ return 0; b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ b->yy_buf_pos = b->yy_ch_buf = base; b->yy_is_our_buffer = 0; b->yy_input_file = 0; b->yy_n_chars = b->yy_buf_size; b->yy_is_interactive = 0; b->yy_at_bol = 1; b->yy_fill_buffer = 0; b->yy_buffer_status = YY_BUFFER_NEW; yy_switch_to_buffer( b ); return b; } #endif #ifndef YY_NO_SCAN_STRING #ifdef YY_USE_PROTOS YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str ) #else YY_BUFFER_STATE yy_scan_string( yy_str ) yyconst char *yy_str; #endif { int len; for ( len = 0; yy_str[len]; ++len ) ; return yy_scan_bytes( yy_str, len ); } #endif #ifndef YY_NO_SCAN_BYTES #ifdef YY_USE_PROTOS YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len ) #else YY_BUFFER_STATE yy_scan_bytes( bytes, len ) yyconst char *bytes; int len; #endif { YY_BUFFER_STATE b; char *buf; yy_size_t n; int i; /* Get memory for full buffer, including space for trailing EOB's. */ n = len + 2; buf = (char *) yy_flex_alloc( n ); if ( ! buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); for ( i = 0; i < len; ++i ) buf[i] = bytes[i]; buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR; b = yy_scan_buffer( buf, n ); if ( ! b ) YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); /* It's okay to grow etc. this buffer, and we should throw it * away when we're done. */ b->yy_is_our_buffer = 1; return b; } #endif #ifndef YY_NO_PUSH_STATE #ifdef YY_USE_PROTOS static void yy_push_state( int new_state ) #else static void yy_push_state( new_state ) int new_state; #endif { if ( yy_start_stack_ptr >= yy_start_stack_depth ) { yy_size_t new_size; yy_start_stack_depth += YY_START_STACK_INCR; new_size = yy_start_stack_depth * sizeof( int ); if ( ! yy_start_stack ) yy_start_stack = (int *) yy_flex_alloc( new_size ); else yy_start_stack = (int *) yy_flex_realloc( (void *) yy_start_stack, new_size ); if ( ! yy_start_stack ) YY_FATAL_ERROR( "out of memory expanding start-condition stack" ); } yy_start_stack[yy_start_stack_ptr++] = YY_START; BEGIN(new_state); } #endif #ifndef YY_NO_POP_STATE static void yy_pop_state() { if ( --yy_start_stack_ptr < 0 ) YY_FATAL_ERROR( "start-condition stack underflow" ); BEGIN(yy_start_stack[yy_start_stack_ptr]); } #endif #ifndef YY_NO_TOP_STATE static int yy_top_state() { return yy_start_stack[yy_start_stack_ptr - 1]; } #endif #ifndef YY_EXIT_FAILURE #define YY_EXIT_FAILURE 2 #endif #ifdef YY_USE_PROTOS static void yy_fatal_error( yyconst char msg[] ) #else static void yy_fatal_error( msg ) char msg[]; #endif { (void) fprintf( stderr, "%s\n", msg ); exit( YY_EXIT_FAILURE ); } /* Redefine yyless() so it works in section 3 code. */ #undef yyless #define yyless(n) \ do \ { \ /* Undo effects of setting up yytext. */ \ yytext[yyleng] = yy_hold_char; \ yy_c_buf_p = yytext + n; \ yy_hold_char = *yy_c_buf_p; \ *yy_c_buf_p = '\0'; \ yyleng = n; \ } \ while ( 0 ) /* Internal utility routines. */ #ifndef yytext_ptr #ifdef YY_USE_PROTOS static void yy_flex_strncpy( char *s1, yyconst char *s2, int n ) #else static void yy_flex_strncpy( s1, s2, n ) char *s1; yyconst char *s2; int n; #endif { register int i; for ( i = 0; i < n; ++i ) s1[i] = s2[i]; } #endif #ifdef YY_NEED_STRLEN #ifdef YY_USE_PROTOS static int yy_flex_strlen( yyconst char *s ) #else static int yy_flex_strlen( s ) yyconst char *s; #endif { register int n; for ( n = 0; s[n]; ++n ) ; return n; } #endif #ifdef YY_USE_PROTOS static void *yy_flex_alloc( yy_size_t size ) #else static void *yy_flex_alloc( size ) yy_size_t size; #endif { return (void *) malloc( size ); } #ifdef YY_USE_PROTOS static void *yy_flex_realloc( void *ptr, yy_size_t size ) #else static void *yy_flex_realloc( ptr, size ) void *ptr; yy_size_t size; #endif { /* The cast to (char *) in the following accommodates both * implementations that use char* generic pointers, and those * that use void* generic pointers. It works with the latter * because both ANSI C and C++ allow castless assignment from * any pointer type to void*, and deal with argument conversions * as though doing an assignment. */ return (void *) realloc( (char *) ptr, size ); } #ifdef YY_USE_PROTOS static void yy_flex_free( void *ptr ) #else static void yy_flex_free( ptr ) void *ptr; #endif { free( ptr ); } #if YY_MAIN int main() { yylex(); return 0; } #endif #line 399 "Scanner.l" namespace Slice { // // initScanner() fills the keyword map with all keyword-token pairs. // void initScanner() { keywordMap["module"] = ICE_MODULE; keywordMap["class"] = ICE_CLASS; keywordMap["interface"] = ICE_INTERFACE; keywordMap["exception"] = ICE_EXCEPTION; keywordMap["struct"] = ICE_STRUCT; keywordMap["sequence"] = ICE_SEQUENCE; keywordMap["dictionary"] = ICE_DICTIONARY; keywordMap["enum"] = ICE_ENUM; keywordMap["out"] = ICE_OUT; keywordMap["extends"] = ICE_EXTENDS; keywordMap["implements"] = ICE_IMPLEMENTS; keywordMap["throws"] = ICE_THROWS; keywordMap["void"] = ICE_VOID; keywordMap["byte"] = ICE_BYTE; keywordMap["bool"] = ICE_BOOL; keywordMap["short"] = ICE_SHORT; keywordMap["int"] = ICE_INT; keywordMap["long"] = ICE_LONG; keywordMap["float"] = ICE_FLOAT; keywordMap["double"] = ICE_DOUBLE; keywordMap["string"] = ICE_STRING; keywordMap["Object"] = ICE_OBJECT; keywordMap["LocalObject"] = ICE_LOCAL_OBJECT; keywordMap["local"] = ICE_LOCAL; keywordMap["const"] = ICE_CONST; keywordMap["false"] = ICE_FALSE; keywordMap["true"] = ICE_TRUE; keywordMap["nonmutating"] = ICE_NONMUTATING; keywordMap["idempotent"] = ICE_IDEMPOTENT; } // // Check if an identifier is well-formed. // void checkIdentifier(const string& id) { if(id.find('_') != string::npos) { unit->error("illegal underscore in identifier `" + id + "'"); } // // Weed out identifiers with reserved suffixes. // static const string suffixBlacklist[] = { "Helper", "Holder", "Prx", "Ptr" }; for(size_t i = 0; i < sizeof(suffixBlacklist) / sizeof(*suffixBlacklist); ++i) { if(id.find(suffixBlacklist[i], id.size() - suffixBlacklist[i].size()) != string::npos) { unit->error("illegal identifier `" + id + "': `" + suffixBlacklist[i] + "' suffix is reserved"); } } } // // Check if an identifier looks like a keyword. // If the identifier is a keyword, return the // corresponding keyword token; otherwise, return // an identifier token. // int checkKeyword(string& id) { StringTokenMap::const_iterator pos = keywordMap.find(id); if(pos != keywordMap.end()) { if(pos->first != id) { string msg; msg = "illegal identifier: `" + id + "' differs from keyword `"; msg += pos->first + "' only in capitalization"; unit->error(msg); id = pos->first; } return pos->second; } return ICE_IDENTIFIER; } } IceE-trans-1.2.0/src/Slice/Makefile.mak0000664000076400007640000000433610620635757017074 0ustar dwaynedwayne# ********************************************************************** # # Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. # # This copy of Ice is licensed to you under the terms described in the # ICE_LICENSE file included in this distribution. # # ********************************************************************** top_srcdir = ..\.. LIBNAME = $(top_srcdir)\lib\slice$(LIBSUFFIX).lib DLLNAME = $(top_srcdir)\bin\slice$(SOVERSION)$(LIBSUFFIX).dll TARGETS = $(LIBNAME) $(DLLNAME) OBJS = Scanner.obj \ Grammar.obj \ Parser.obj \ CPlusPlusUtil.obj \ CsUtil.obj \ VbUtil.obj \ JavaUtil.obj \ Preprocessor.obj \ Checksum.obj \ PythonUtil.obj \ DotNetNames.obj \ RubyUtil.obj SRCS = $(OBJS:.obj=.cpp) !include $(top_srcdir)/config/Make.rules.mak CPPFLAGS = -I.. -Idummyinclude $(CPPFLAGS) -DSLICE_API_EXPORTS -DWIN32_LEAN_AND_MEAN !if "$(CPP_COMPILER)" != "BCC2006" & "$(OPTIMIZE)" != "yes" PDBFLAGS = /pdb:$(DLLNAME:.dll=.pdb) !endif !if "$(STATICLIBS)" == "yes" $(DLLNAME): $(LIBNAME): $(OBJS) $(AR) $(ARFLAGS) $(PDBFLAGS) $(OBJS) $(PREOUT)$@ !else $(LIBNAME): $(DLLNAME) $(DLLNAME): $(OBJS) $(LINK) $(LD_DLLFLAGS) $(PDBFLAGS) $(OBJS) $(PREOUT)$@ $(PRELIBS)$(BASELIBS) move $(DLLNAME:.dll=.lib) $(LIBNAME) @if exist $@.manifest echo ^ ^ ^ Embedding manifest using $(MT) && \ $(MT) -nologo -manifest $@.manifest -outputresource:$@;#2 && del /q $@.manifest @if exist $(DLLNAME:.dll=.exp) del /q $(DLLNAME:.dll=.exp) !endif #Scanner.cpp : Scanner.l # flex Scanner.l # del /q $@ # echo #include "IceUtil/Config.h" > Scanner.cpp # type lex.yy.c >> Scanner.cpp # del /q lex.yy.c #Grammar.cpp Grammar.h: Grammar.y # del /q Grammar.h Grammar.cpp # bison -dvt --name-prefix "slice_" Grammar.y # move Grammar.tab.c Grammar.cpp # move Grammar.tab.h Grammar.h # del /q Grammar.output clean:: # del /q Grammar.cpp Grammar.h # del /q Scanner.cpp del /q $(DLLNAME:.dll=.*) install:: all # copy $(LIBNAME) $(install_libdir) # copy $(DLLNAME) $(install_bindir) !if "$(OPTIMIZE)" != "yes" !if "$(CPP_COMPILER)" == "BCC2006" install:: all # copy $(DLLNAME:.dll=.tds) $(install_bindir) !else install:: all # copy $(DLLNAME:.dll=.pdb) $(install_bindir) !endif !endif !include .depend IceE-trans-1.2.0/src/Slice/PythonUtil.cpp0000664000076400007640000016154710560413774017514 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 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 #ifdef __BCPLUSPLUS__ # include #endif using namespace std; using namespace Slice; using namespace IceUtil; namespace Slice { namespace Python { class MetaDataVisitor : public ParserVisitor { public: virtual bool visitModuleStart(const ModulePtr&); virtual void visitClassDecl(const ClassDeclPtr&); virtual bool visitClassDefStart(const ClassDefPtr&); virtual bool visitExceptionStart(const ExceptionPtr&); virtual bool visitStructStart(const StructPtr&); virtual void visitOperation(const OperationPtr&); virtual void visitDataMember(const DataMemberPtr&); virtual void visitSequence(const SequencePtr&); virtual void visitDictionary(const DictionaryPtr&); virtual void visitEnum(const EnumPtr&); virtual void visitConst(const ConstPtr&); private: // // Validates global metadata. // void validateGlobal(const DefinitionContextPtr&); // // Validates sequence metadata. // void validateSequence(const DefinitionContextPtr&, const string&, const TypePtr&, const StringList&); // // Checks a definition that doesn't currently support Python metadata. // void reject(const ContainedPtr&); StringSet _history; }; // // ModuleVisitor finds all of the Slice modules whose include level is greater // than 0 and emits a statement of the following form: // // _M_Foo = Ice.openModule('Foo') // // This statement allows the code generated for this translation unit to refer // to types residing in those included modules. // class ModuleVisitor : public ParserVisitor { public: ModuleVisitor(Output&, set&); virtual bool visitModuleStart(const ModulePtr&); private: Output& _out; set& _history; }; // // CodeVisitor generates the Python mapping for a translation unit. // class CodeVisitor : public ParserVisitor { public: CodeVisitor(IceUtil::Output&, set&); virtual bool visitModuleStart(const ModulePtr&); virtual void visitModuleEnd(const ModulePtr&); virtual void visitClassDecl(const ClassDeclPtr&); virtual bool visitClassDefStart(const ClassDefPtr&); virtual bool visitExceptionStart(const ExceptionPtr&); virtual bool visitStructStart(const StructPtr&); virtual void visitSequence(const SequencePtr&); virtual void visitDictionary(const DictionaryPtr&); virtual void visitEnum(const EnumPtr&); virtual void visitConst(const ConstPtr&); private: // // Return a Python symbol for the given parser element. // string getSymbol(const ContainedPtr&); // // Emit Python code to assign the given symbol in the current module. // void registerName(const string&); // // Emit the tuple for a Slice type. // void writeType(const TypePtr&); // // Write a default value for a given type. // void writeDefaultValue(const TypePtr&); // // Add a value to a hash code. // void writeHash(const string&, const TypePtr&, int&); // // Write Python metadata as a tuple. // void writeMetaData(const StringList&); // // Convert an operation mode into a string. // string getOperationMode(Slice::Operation::Mode); struct MemberInfo { string fixedName; TypePtr type; bool inherited; StringList metaData; }; typedef list MemberInfoList; void collectClassMembers(const ClassDefPtr&, MemberInfoList&, bool); void collectExceptionMembers(const ExceptionPtr&, MemberInfoList&, bool); Output& _out; set& _moduleHistory; list _moduleStack; set _classHistory; }; } } static string lookupKwd(const string& name) { // // Keyword list. *Must* be kept in alphabetical order. // static const string keywordList[] = { "and", "assert", "break", "class", "continue", "def", "del", "elif", "else", "except", "exec", "finally", "for", "from", "global", "if", "import", "in", "is", "lambda", "not", "or", "pass", "print", "raise", "return", "try", "while", "yield" }; bool found = binary_search(&keywordList[0], &keywordList[sizeof(keywordList) / sizeof(*keywordList)], name); return found ? "_" + name : name; } // // Split a scoped name into its components and return the components as a list of (unscoped) identifiers. // static vector splitScopedName(const string& scoped) { assert(scoped[0] == ':'); vector ids; string::size_type next = 0; string::size_type pos; while((pos = scoped.find("::", next)) != string::npos) { pos += 2; if(pos != scoped.size()) { string::size_type endpos = scoped.find("::", pos); if(endpos != string::npos) { ids.push_back(scoped.substr(pos, endpos - pos)); } } next = pos; } if(next != scoped.size()) { ids.push_back(scoped.substr(next)); } else { ids.push_back(""); } return ids; } static string getDictLookup(const ContainedPtr& cont, const string& suffix = string()) { string scope = Slice::Python::scopedToName(cont->scope()); assert(!scope.empty()); string package = Slice::Python::getPackageMetadata(cont); if(!package.empty()) { scope = package + "." + scope; } return "_M_" + scope + "__dict__.has_key('" + suffix + Slice::Python::fixIdent(cont->name()) + "')"; } // // ModuleVisitor implementation. // Slice::Python::ModuleVisitor::ModuleVisitor(Output& out, set& history) : _out(out), _history(history) { } bool Slice::Python::ModuleVisitor::visitModuleStart(const ModulePtr& p) { if(p->includeLevel() > 0) { string abs = getAbsolute(p); if(_history.count(abs) == 0) { // // If this is a top-level module, then we check if it has package metadata. // If so, we need to emit statements to open each of the modules in the // package before we can open this module. // if(UnitPtr::dynamicCast(p->container())) { string pkg = getPackageMetadata(p); if(!pkg.empty()) { vector v; splitString(pkg, v, "."); string mod; for(vector::iterator q = v.begin(); q != v.end(); ++q) { mod = mod.empty() ? *q : mod + "." + *q; if(_history.count(mod) == 0) { _out << nl << "_M_" << mod << " = Ice.openModule('" << mod << "')"; _history.insert(mod); } } } } _out << sp << nl << "# Included module " << abs; _out << nl << "_M_" << abs << " = Ice.openModule('" << abs << "')"; _history.insert(abs); } } return true; } // // CodeVisitor implementation. // Slice::Python::CodeVisitor::CodeVisitor(Output& out, set& moduleHistory) : _out(out), _moduleHistory(moduleHistory) { } bool Slice::Python::CodeVisitor::visitModuleStart(const ModulePtr& p) { // // As each module is opened, we emit the statement // // __name__ = 'Foo' // // This renames the current module to 'Foo' so that subsequent // type definitions have the proper fully-qualified name. // // We also emit the statement // // _M_Foo = Ice.openModule('Foo') // // This allows us to create types in the module Foo. // string abs = getAbsolute(p); _out << sp << nl << "# Start of module " << abs; if(_moduleHistory.count(abs) == 0) // Don't emit this more than once for each module. { // // If this is a top-level module, then we check if it has package metadata. // If so, we need to emit statements to open each of the modules in the // package before we can open this module. // if(UnitPtr::dynamicCast(p->container())) { string pkg = getPackageMetadata(p); if(!pkg.empty()) { vector v; splitString(pkg, v, "."); string mod; for(vector::iterator q = v.begin(); q != v.end(); ++q) { mod = mod.empty() ? *q : mod + "." + *q; if(_moduleHistory.count(mod) == 0) // Don't emit this more than once for each module. { _out << nl << "_M_" << mod << " = Ice.openModule('" << mod << "')"; _moduleHistory.insert(mod); } } } } _out << nl << "_M_" << abs << " = Ice.openModule('" << abs << "')"; _moduleHistory.insert(abs); } _out << nl << "__name__ = '" << abs << "'"; _moduleStack.push_front(abs); return true; } void Slice::Python::CodeVisitor::visitModuleEnd(const ModulePtr& p) { assert(!_moduleStack.empty()); _out << sp << nl << "# End of module " << _moduleStack.front(); _moduleStack.pop_front(); if(!_moduleStack.empty()) { _out << sp << nl << "__name__ = '" << _moduleStack.front() << "'"; } } void Slice::Python::CodeVisitor::visitClassDecl(const ClassDeclPtr& p) { // // Emit forward declarations. // string scoped = p->scoped(); if(_classHistory.count(scoped) == 0) { _out << sp << nl << "if not " << getDictLookup(p) << ':'; _out.inc(); string type = getAbsolute(p, "_t_"); _out << nl << "_M_" << type << " = IcePy.declareClass('" << scoped << "')"; if(!p->isLocal()) { _out << nl << "_M_" << type << "Prx = IcePy.declareProxy('" << scoped << "')"; } _out.dec(); _classHistory.insert(scoped); // Avoid redundant declarations. } } bool Slice::Python::CodeVisitor::visitClassDefStart(const ClassDefPtr& p) { string scoped = p->scoped(); string type = getAbsolute(p, "_t_"); string abs = getAbsolute(p); string name = fixIdent(p->name()); ClassList bases = p->bases(); ClassDefPtr base; OperationList ops = p->operations(); OperationList::iterator oli; // // Define the class. // _out << sp << nl << "if not " << getDictLookup(p) << ':'; _out.inc(); _out << nl << "_M_" << abs << " = Ice.createTempClass()"; _out << nl << "class " << name << '('; if(bases.empty()) { if(p->isLocal()) { _out << "Ice.LocalObject"; } else { _out << "Ice.Object"; } } else { for(ClassList::const_iterator q = bases.begin(); q != bases.end(); ++q) { if(q != bases.begin()) { _out << ", "; } _out << getSymbol(*q); } if(!bases.front()->isInterface()) { base = bases.front(); } } _out << "):"; _out.inc(); // // __init__ // _out << nl << "def __init__(self"; MemberInfoList allMembers; collectClassMembers(p, allMembers, false); if(!allMembers.empty()) { for(MemberInfoList::iterator q = allMembers.begin(); q != allMembers.end(); ++q) { _out << ", " << q->fixedName << '='; writeDefaultValue(q->type); } } _out << "):"; _out.inc(); if(!base && !p->hasDataMembers() && !p->isAbstract()) { _out << nl << "pass"; } else { if(p->isAbstract()) { _out << nl << "if __builtin__.type(self) == _M_" << abs << ':'; _out.inc(); _out << nl << "raise RuntimeError('" << abs << " is an abstract class')"; _out.dec(); } if(base) { _out << nl << getSymbol(base) << ".__init__(self"; for(MemberInfoList::iterator q = allMembers.begin(); q != allMembers.end(); ++q) { if(q->inherited) { _out << ", " << q->fixedName; } } _out << ')'; } for(MemberInfoList::iterator q = allMembers.begin(); q != allMembers.end(); ++q) { if(!q->inherited) { _out << nl << "self." << q->fixedName << " = " << q->fixedName;; } } } _out.dec(); if(!p->isLocal()) { // // ice_ids // ClassList allBases = p->allBases(); StringList ids; #if defined(__IBMCPP__) && defined(NDEBUG) // // VisualAge C++ 6.0 does not see that ClassDef is a Contained, // when inlining is on. The code below issues a warning: better // than an error! // transform(allBases.begin(), allBases.end(), back_inserter(ids), IceUtil::constMemFun(&Contained::scoped)); #else transform(allBases.begin(), allBases.end(), back_inserter(ids), IceUtil::constMemFun(&Contained::scoped)); #endif StringList other; other.push_back(scoped); other.push_back("::Ice::Object"); other.sort(); ids.merge(other); ids.unique(); _out << sp << nl << "def ice_ids(self, current=None):"; _out.inc(); _out << nl << "return ("; for(StringList::iterator q = ids.begin(); q != ids.end(); ++q) { if(q != ids.begin()) { _out << ", "; } _out << "'" << *q << "'"; } _out << ')'; _out.dec(); // // ice_id // _out << sp << nl << "def ice_id(self, current=None):"; _out.inc(); _out << nl << "return '" << scoped << "'"; _out.dec(); } if(!ops.empty()) { // // Emit a placeholder for each operation. // _out << sp << nl << "#" << nl << "# Operation signatures." << nl << "#"; for(oli = ops.begin(); oli != ops.end(); ++oli) { string fixedOpName = fixIdent((*oli)->name()); if(!p->isLocal() && (p->hasMetaData("amd") || (*oli)->hasMetaData("amd"))) { _out << nl << "# def " << fixedOpName << "_async(self, _cb"; ParamDeclList params = (*oli)->parameters(); for(ParamDeclList::iterator pli = params.begin(); pli != params.end(); ++pli) { if(!(*pli)->isOutParam()) { _out << ", " << fixIdent((*pli)->name()); } } if(!p->isLocal()) { _out << ", current=None"; } _out << "):"; } else { _out << nl << "# def " << fixedOpName << "(self"; ParamDeclList params = (*oli)->parameters(); for(ParamDeclList::iterator pli = params.begin(); pli != params.end(); ++pli) { if(!(*pli)->isOutParam()) { _out << ", " << fixIdent((*pli)->name()); } } if(!p->isLocal()) { _out << ", current=None"; } _out << "):"; } } } // // __str__ // _out << sp << nl << "def __str__(self):"; _out.inc(); _out << nl << "return IcePy.stringify(self, _M_" << getAbsolute(p, "_t_") << ")"; _out.dec(); _out << sp << nl << "__repr__ = __str__"; _out.dec(); // // Define the proxy class. // if(!p->isLocal()) { _out << sp << nl << "_M_" << abs << "Prx = Ice.createTempClass()"; _out << nl << "class " << name << "Prx("; if(bases.empty()) { _out << "Ice.ObjectPrx"; } else { ClassList::const_iterator q = bases.begin(); while(q != bases.end()) { _out << getSymbol(*q) << "Prx"; if(++q != bases.end()) { _out << ", "; } } } _out << "):"; _out.inc(); for(oli = ops.begin(); oli != ops.end(); ++oli) { string fixedOpName = fixIdent((*oli)->name()); if(fixedOpName == "checkedCast" || fixedOpName == "uncheckedCast") { fixedOpName.insert(0, "_"); } TypePtr ret = (*oli)->returnType(); ParamDeclList paramList = (*oli)->parameters(); string inParams; for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q) { if(!(*q)->isOutParam()) { if(!inParams.empty()) { inParams.append(", "); } inParams.append(fixIdent((*q)->name())); } } _out << sp << nl << "def " << fixedOpName << "(self"; if(!inParams.empty()) { _out << ", " << inParams; } _out << ", _ctx=None):"; _out.inc(); _out << nl << "return _M_" << abs << "._op_" << (*oli)->name() << ".invoke(self, (" << inParams; if(!inParams.empty() && inParams.find(',') == string::npos) { _out << ", "; } _out << "), _ctx)"; _out.dec(); if(p->hasMetaData("ami") || (*oli)->hasMetaData("ami")) { _out << sp << nl << "def " << fixedOpName << "_async(self, _cb"; if(!inParams.empty()) { _out << ", " << inParams; } _out << ", _ctx=None):"; _out.inc(); _out << nl << "return _M_" << abs << "._op_" << (*oli)->name() << ".invokeAsync(self, _cb, (" << inParams; if(!inParams.empty() && inParams.find(',') == string::npos) { _out << ", "; } _out << "), _ctx)"; _out.dec(); } } _out << sp << nl << "def checkedCast(proxy, facetOrCtx=None, _ctx=None):"; _out.inc(); _out << nl << "return _M_" << abs << "Prx.ice_checkedCast(proxy, '" << scoped << "', facetOrCtx, _ctx)"; _out.dec(); _out << nl << "checkedCast = staticmethod(checkedCast)"; _out << sp << nl << "def uncheckedCast(proxy, facet=''):"; _out.inc(); _out << nl << "return _M_" << abs << "Prx.ice_uncheckedCast(proxy, facet)"; _out.dec(); _out << nl << "uncheckedCast = staticmethod(uncheckedCast)"; _out.dec(); _out << sp << nl << "_M_" << type << "Prx = IcePy.defineProxy('" << scoped << "', " << name << "Prx)"; } if(_classHistory.count(scoped) == 0 && p->canBeCyclic()) { // // Emit a forward declaration for the class in case a data member refers to this type. // _out << sp << nl << "_M_" << type << " = IcePy.declareClass('" << scoped << "')"; } DataMemberList members = p->dataMembers(); _out << sp << nl << "_M_" << type << " = IcePy.defineClass('" << scoped << "', " << name << ", "; writeMetaData(p->getMetaData()); _out << ", " << (p->isAbstract() ? "True" : "False") << ", "; if(!base) { _out << "None"; } else { _out << "_M_" << getAbsolute(base, "_t_"); } _out << ", ("; // // Interfaces // int interfaceCount = 0; for(ClassList::const_iterator q = bases.begin(); q != bases.end(); ++q) { if((*q)->isInterface()) { if(interfaceCount > 0) { _out << ", "; } _out << "_M_" << getAbsolute(*q, "_t_"); ++interfaceCount; } } if(interfaceCount == 1) { _out << ','; } // // Members // // Data members are represented as a tuple: // // ('MemberName', MemberMetaData, MemberType) // // where MemberType is either a primitive type constant (T_INT, etc.) or the id of a constructed type. // _out << "), ("; if(members.size() > 1) { _out.inc(); _out << nl; } for(DataMemberList::iterator r = members.begin(); r != members.end(); ++r) { if(r != members.begin()) { _out << ',' << nl; } _out << "('" << fixIdent((*r)->name()) << "', "; writeMetaData((*r)->getMetaData()); _out << ", "; writeType((*r)->type()); _out << ')'; } if(members.size() == 1) { _out << ','; } else if(members.size() > 1) { _out.dec(); _out << nl; } _out << "))"; _out << nl << name << ".ice_type = _M_" << type; // // Define each operation. The arguments to the IcePy.Operation constructor are: // // 'opName', Mode, SendMode, AMD, (MetaData), (InParams), (OutParams), ReturnType, (Exceptions) // // where InParams and OutParams are tuples of type descriptions, and Exceptions // is a tuple of exception type ids. // if(!p->isLocal()) { if(!ops.empty()) { _out << sp; } for(OperationList::iterator s = ops.begin(); s != ops.end(); ++s) { ParamDeclList params = (*s)->parameters(); ParamDeclList::iterator t; int count; _out << nl << name << "._op_" << (*s)->name() << " = IcePy.Operation('" << (*s)->name() << "', " << getOperationMode((*s)->mode()) << ", " << getOperationMode((*s)->sendMode()) << ", " << ((p->hasMetaData("amd") || (*s)->hasMetaData("amd")) ? "True" : "False") << ", "; writeMetaData((*s)->getMetaData()); _out << ", ("; for(t = params.begin(), count = 0; t != params.end(); ++t) { if(!(*t)->isOutParam()) { if(count > 0) { _out << ", "; } _out << '('; writeMetaData((*t)->getMetaData()); _out << ", "; writeType((*t)->type()); _out << ')'; ++count; } } if(count == 1) { _out << ','; } _out << "), ("; for(t = params.begin(), count = 0; t != params.end(); ++t) { if((*t)->isOutParam()) { if(count > 0) { _out << ", "; } _out << '('; writeMetaData((*t)->getMetaData()); _out << ", "; writeType((*t)->type()); _out << ')'; ++count; } } if(count == 1) { _out << ','; } _out << "), "; TypePtr returnType = (*s)->returnType(); if(returnType) { writeType(returnType); } else { _out << "None"; } _out << ", ("; ExceptionList exceptions = (*s)->throws(); for(ExceptionList::iterator u = exceptions.begin(); u != exceptions.end(); ++u) { if(u != exceptions.begin()) { _out << ", "; } _out << "_M_" << getAbsolute(*u, "_t_"); } if(exceptions.size() == 1) { _out << ','; } _out << "))"; string deprecateMetadata; if((*s)->findMetaData("deprecate", deprecateMetadata) || p->findMetaData("deprecate", deprecateMetadata)) { string msg; string::size_type pos = deprecateMetadata.find(':'); if(pos != string::npos && pos < deprecateMetadata.size() - 1) { msg = deprecateMetadata.substr(pos + 1); } _out << nl << name << "._op_" << (*s)->name() << ".deprecate(\"" << msg << "\")"; } } } registerName(name); if(!p->isLocal()) { registerName(name + "Prx"); } _out.dec(); if(_classHistory.count(scoped) == 0) { _classHistory.insert(scoped); // Avoid redundant declarations. } return false; } bool Slice::Python::CodeVisitor::visitExceptionStart(const ExceptionPtr& p) { string scoped = p->scoped(); string abs = getAbsolute(p); string name = fixIdent(p->name()); _out << sp << nl << "if not " << getDictLookup(p) << ':'; _out.inc(); _out << nl << "_M_" << abs << " = Ice.createTempClass()"; _out << nl << "class " << name << '('; ExceptionPtr base = p->base(); string baseName; if(base) { baseName = getSymbol(base); _out << baseName; } else if(p->isLocal()) { _out << "Ice.LocalException"; } else { _out << "Ice.UserException"; } _out << "):"; _out.inc(); DataMemberList members = p->dataMembers(); DataMemberList::iterator dmli; // // __init__ // _out << nl << "def __init__(self"; MemberInfoList allMembers; collectExceptionMembers(p, allMembers, false); if(!allMembers.empty()) { for(MemberInfoList::iterator q = allMembers.begin(); q != allMembers.end(); ++q) { _out << ", " << q->fixedName << '='; writeDefaultValue(q->type); } } _out << "):"; _out.inc(); if(!base && members.empty()) { _out << nl << "pass"; } else { if(base) { _out << nl << baseName << ".__init__(self"; for(MemberInfoList::iterator q = allMembers.begin(); q != allMembers.end(); ++q) { if(q->inherited) { _out << ", " << q->fixedName; } } _out << ')'; } for(MemberInfoList::iterator q = allMembers.begin(); q != allMembers.end(); ++q) { if(!q->inherited) { _out << nl << "self." << q->fixedName << " = " << q->fixedName;; } } } _out.dec(); // // ice_name // _out << sp << nl << "def ice_name(self):"; _out.inc(); _out << nl << "return '" << scoped.substr(2) << "'"; _out.dec(); // // __str__ // _out << sp << nl << "def __str__(self):"; _out.inc(); _out << nl << "return IcePy.stringifyException(self)"; _out.dec(); _out << sp << nl << "__repr__ = __str__"; _out.dec(); // // Emit the type information. // string type = getAbsolute(p, "_t_"); _out << sp << nl << "_M_" << type << " = IcePy.defineException('" << scoped << "', " << name << ", "; writeMetaData(p->getMetaData()); _out << ", "; if(!base) { _out << "None"; } else { _out << "_M_" << getAbsolute(base, "_t_"); } _out << ", ("; if(members.size() > 1) { _out.inc(); _out << nl; } // // Data members are represented as a tuple: // // ('MemberName', MemberMetaData, MemberType) // // where MemberType is either a primitive type constant (T_INT, etc.) or the id of a constructed type. // for(dmli = members.begin(); dmli != members.end(); ++dmli) { if(dmli != members.begin()) { _out << ',' << nl; } _out << "('" << fixIdent((*dmli)->name()) << "', "; writeMetaData((*dmli)->getMetaData()); _out << ", "; writeType((*dmli)->type()); _out << ')'; } if(members.size() == 1) { _out << ','; } else if(members.size() > 1) { _out.dec(); _out << nl; } _out << "))"; _out << nl << name << ".ice_type = _M_" << type; registerName(name); _out.dec(); return false; } bool Slice::Python::CodeVisitor::visitStructStart(const StructPtr& p) { string scoped = p->scoped(); string abs = getAbsolute(p); string name = fixIdent(p->name()); MemberInfoList memberList; MemberInfoList::iterator r; { DataMemberList members = p->dataMembers(); for(DataMemberList::iterator q = members.begin(); q != members.end(); ++q) { memberList.push_back(MemberInfo()); memberList.back().fixedName = fixIdent((*q)->name()); memberList.back().type = (*q)->type(); memberList.back().metaData = (*q)->getMetaData(); } } _out << sp << nl << "if not " << getDictLookup(p) << ':'; _out.inc(); _out << nl << "_M_" << abs << " = Ice.createTempClass()"; _out << nl << "class " << name << "(object):"; _out.inc(); _out << nl << "def __init__(self"; for(r = memberList.begin(); r != memberList.end(); ++r) { _out << ", " << r->fixedName << '='; writeDefaultValue(r->type); } _out << "):"; _out.inc(); for(r = memberList.begin(); r != memberList.end(); ++r) { _out << nl << "self." << r->fixedName << " = " << r->fixedName; } _out.dec(); _out << sp << nl << "def __hash__(self):"; _out.inc(); _out << nl << "_h = 0"; int iter = 0; for(r = memberList.begin(); r != memberList.end(); ++r) { string s = "self." + r->fixedName; writeHash(s, r->type, iter); } _out << nl << "return _h % 0x7fffffff"; _out.dec(); _out << sp << nl << "def __eq__(self, other):"; _out.inc(); for(r = memberList.begin(); r != memberList.end(); ++r) { _out << nl << "if not self." << r->fixedName << " == other." << r->fixedName << ':'; _out.inc(); _out << nl << "return False"; _out.dec(); } _out << nl << "return True"; _out.dec(); // // __str__ // _out << sp << nl << "def __str__(self):"; _out.inc(); _out << nl << "return IcePy.stringify(self, _M_" << getAbsolute(p, "_t_") << ")"; _out.dec(); _out << sp << nl << "__repr__ = __str__"; _out.dec(); // // Emit the type information. // _out << sp << nl << "_M_" << getAbsolute(p, "_t_") << " = IcePy.defineStruct('" << scoped << "', " << name << ", "; writeMetaData(p->getMetaData()); _out << ", ("; // // Data members are represented as a tuple: // // ('MemberName', MemberMetaData, MemberType) // // where MemberType is either a primitive type constant (T_INT, etc.) or the id of a constructed type. // if(memberList.size() > 1) { _out.inc(); _out << nl; } for(r = memberList.begin(); r != memberList.end(); ++r) { if(r != memberList.begin()) { _out << ',' << nl; } _out << "('" << r->fixedName << "', "; writeMetaData(r->metaData); _out << ", "; writeType(r->type); _out << ')'; } if(memberList.size() == 1) { _out << ','; } else if(memberList.size() > 1) { _out.dec(); _out << nl; } _out << "))"; registerName(name); _out.dec(); return false; } void Slice::Python::CodeVisitor::visitSequence(const SequencePtr& p) { // // Emit the type information. // string scoped = p->scoped(); _out << sp << nl << "if not " << getDictLookup(p, "_t_") << ':'; _out.inc(); _out << nl << "_M_" << getAbsolute(p, "_t_") << " = IcePy.defineSequence('" << scoped << "', "; writeMetaData(p->getMetaData()); _out << ", "; writeType(p->type()); _out << ")"; _out.dec(); } void Slice::Python::CodeVisitor::visitDictionary(const DictionaryPtr& p) { // // Emit the type information. // string scoped = p->scoped(); _out << sp << nl << "if not " << getDictLookup(p, "_t_") << ':'; _out.inc(); _out << nl << "_M_" << getAbsolute(p, "_t_") << " = IcePy.defineDictionary('" << scoped << "', "; writeMetaData(p->getMetaData()); _out << ", "; writeType(p->keyType()); _out << ", "; writeType(p->valueType()); _out << ")"; _out.dec(); } void Slice::Python::CodeVisitor::visitEnum(const EnumPtr& p) { string scoped = p->scoped(); string abs = getAbsolute(p); string name = fixIdent(p->name()); EnumeratorList enums = p->getEnumerators(); EnumeratorList::iterator q; int i; _out << sp << nl << "if not " << getDictLookup(p) << ':'; _out.inc(); _out << nl << "_M_" << abs << " = Ice.createTempClass()"; _out << nl << "class " << name << "(object):"; _out.inc(); _out << sp << nl << "def __init__(self, val):"; _out.inc(); { ostringstream assertion; assertion << "assert(val >= 0 and val < " << enums.size() << ')'; _out << nl << assertion.str(); } _out << nl << "self.value = val"; _out.dec(); _out << sp << nl << "def __str__(self):"; _out.inc(); for(q = enums.begin(), i = 0; q != enums.end(); ++q, ++i) { _out << nl; if(q == enums.begin()) { _out << "if"; } else { _out << "elif"; } ostringstream idx; idx << i; _out << " self.value == " << idx.str() << ':'; _out.inc(); _out << nl << "return '" << (*q)->name() << "'"; _out.dec(); } _out << nl << "return None"; _out.dec(); _out << sp << nl << "__repr__ = __str__"; _out << sp << nl << "def __hash__(self):"; _out.inc(); _out << nl << "return self.value"; _out.dec(); _out << sp << nl << "def __cmp__(self, other):"; _out.inc(); _out << nl << "return cmp(self.value, other.value)"; _out.dec(); _out.dec(); _out << sp; for(q = enums.begin(), i = 0; q != enums.end(); ++q, ++i) { string fixedEnum = fixIdent((*q)->name()); ostringstream idx; idx << i; _out << nl << name << '.' << fixedEnum << " = " << name << '(' << idx.str() << ')'; } // // Emit the type information. // _out << sp << nl << "_M_" << getAbsolute(p, "_t_") << " = IcePy.defineEnum('" << scoped << "', " << name << ", "; writeMetaData(p->getMetaData()); _out << ", ("; for(q = enums.begin(); q != enums.end(); ++q) { if(q != enums.begin()) { _out << ", "; } string fixedEnum = fixIdent((*q)->name()); _out << name << '.' << fixedEnum; } if(enums.size() == 1) { _out << ','; } _out << "))"; registerName(name); _out.dec(); } void Slice::Python::CodeVisitor::visitConst(const ConstPtr& p) { Slice::TypePtr type = p->type(); string value = p->value(); string name = fixIdent(p->name()); _out << sp << nl << "_M_" << getAbsolute(p) << " = "; Slice::BuiltinPtr b = Slice::BuiltinPtr::dynamicCast(type); Slice::EnumPtr en = Slice::EnumPtr::dynamicCast(type); if(b) { switch(b->kind()) { case Slice::Builtin::KindBool: { _out << (value == "true" ? "True" : "False"); break; } case Slice::Builtin::KindByte: case Slice::Builtin::KindShort: case Slice::Builtin::KindInt: case Slice::Builtin::KindFloat: case Slice::Builtin::KindDouble: { _out << value; break; } case Slice::Builtin::KindLong: { IceUtil::Int64 l; IceUtil::stringToInt64(value, l); // // The platform's 'long' type may not be 64 bits, so we store 64-bit // values as a string. // if(sizeof(IceUtil::Int64) > sizeof(long) && (l < LONG_MIN || l > LONG_MAX)) { _out << "'" << value << "'"; } else { _out << value; } break; } case Slice::Builtin::KindString: { // // Expand strings into the basic source character set. We can't use isalpha() and the like // here because they are sensitive to the current locale. // static const string basicSourceChars = "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789" "_{}[]#()<>%:;.?*+-/^&|~!=, '"; static const set charSet(basicSourceChars.begin(), basicSourceChars.end()); _out << "\""; // Opening " for(string::const_iterator c = value.begin(); c != value.end(); ++c) { switch(*c) { case '"': { _out << "\\\""; break; } case '\\': { _out << "\\\\"; break; } case '\r': { _out << "\\r"; break; } case '\n': { _out << "\\n"; break; } case '\t': { _out << "\\t"; break; } case '\b': { _out << "\\b"; break; } case '\f': { _out << "\\f"; break; } default: { if(charSet.find(*c) == charSet.end()) { unsigned char uc = *c; // Char may be signed, so make it positive. stringstream s; s << "\\"; // Print as octal if not in basic source character set. s.flags(ios_base::oct); s.width(3); s.fill('0'); s << static_cast(uc); _out << s.str(); } else { _out << *c; // Print normally if in basic source character set. } break; } } } _out << "\""; // Closing " break; } case Slice::Builtin::KindObject: case Slice::Builtin::KindObjectProxy: case Slice::Builtin::KindLocalObject: assert(false); } } else if(en) { string enumName = getSymbol(en); string::size_type colon = value.rfind(':'); string enumerator; if(colon != string::npos) { enumerator = fixIdent(value.substr(colon + 1)); } else { enumerator = fixIdent(value); } _out << enumName << '.' << enumerator; } else { assert(false); // Unknown const type. } } string Slice::Python::CodeVisitor::getSymbol(const ContainedPtr& p) { // // An explicit reference to another type must always be prefixed with "_M_". // return "_M_" + getAbsolute(p); } void Slice::Python::CodeVisitor::registerName(const string& name) { assert(!_moduleStack.empty()); _out << sp << nl << "_M_" << _moduleStack.front() << '.' << name << " = " << name; _out << nl << "del " << name; } void Slice::Python::CodeVisitor::writeType(const TypePtr& p) { BuiltinPtr builtin = BuiltinPtr::dynamicCast(p); if(builtin) { switch(builtin->kind()) { case Builtin::KindBool: { _out << "IcePy._t_bool"; break; } case Builtin::KindByte: { _out << "IcePy._t_byte"; break; } case Builtin::KindShort: { _out << "IcePy._t_short"; break; } case Builtin::KindInt: { _out << "IcePy._t_int"; break; } case Builtin::KindLong: { _out << "IcePy._t_long"; break; } case Builtin::KindFloat: { _out << "IcePy._t_float"; break; } case Builtin::KindDouble: { _out << "IcePy._t_double"; break; } case Builtin::KindString: { _out << "IcePy._t_string"; break; } case Builtin::KindObject: { _out << "IcePy._t_Object"; break; } case Builtin::KindObjectProxy: { _out << "IcePy._t_ObjectPrx"; break; } case Builtin::KindLocalObject: { _out << "IcePy._t_LocalObject"; break; } } return; } ProxyPtr prx = ProxyPtr::dynamicCast(p); if(prx) { _out << "_M_" << getAbsolute(prx->_class(), "_t_") << "Prx"; return; } ContainedPtr cont = ContainedPtr::dynamicCast(p); assert(cont); _out << "_M_" << getAbsolute(cont, "_t_"); } void Slice::Python::CodeVisitor::writeDefaultValue(const TypePtr& p) { BuiltinPtr builtin = BuiltinPtr::dynamicCast(p); if(builtin) { switch(builtin->kind()) { case Builtin::KindBool: { _out << "False"; break; } case Builtin::KindByte: case Builtin::KindShort: case Builtin::KindInt: case Builtin::KindLong: { _out << "0"; break; } case Builtin::KindFloat: case Builtin::KindDouble: { _out << "0.0"; break; } case Builtin::KindString: { _out << "''"; break; } case Builtin::KindObject: case Builtin::KindObjectProxy: case Builtin::KindLocalObject: { _out << "None"; break; } } return; } EnumPtr en = EnumPtr::dynamicCast(p); if(en) { EnumeratorList enums = en->getEnumerators(); _out << getSymbol(en) << "." << fixIdent(enums.front()->name()); return; } StructPtr st = StructPtr::dynamicCast(p); if(st) { _out << getSymbol(st) << "()"; return; } _out << "None"; } void Slice::Python::CodeVisitor::writeHash(const string& name, const TypePtr& p, int& iter) { SequencePtr seq = SequencePtr::dynamicCast(p); if(seq) { _out << nl << "if " << name << ':'; _out.inc(); _out << nl << "for _i" << iter << " in " << name << ':'; _out.inc(); ostringstream elem; elem << "_i" << iter; iter++; writeHash(elem.str(), seq->type(), iter); _out.dec(); _out.dec(); return; } DictionaryPtr dict = DictionaryPtr::dynamicCast(p); if(dict) { _out << nl << "if " << name << ':'; _out.inc(); _out << nl << "for _i" << iter << " in " << name << ':'; _out.inc(); ostringstream key; key << "_i" << iter; ostringstream value; value << name << '[' << key.str() << ']'; iter++; writeHash(key.str(), dict->keyType(), iter); writeHash(value.str(), dict->valueType(), iter); _out.dec(); _out.dec(); return; } _out << nl << "_h = 5 * _h + __builtin__.hash(" << name << ")"; } void Slice::Python::CodeVisitor::writeMetaData(const StringList& meta) { int i = 0; _out << '('; for(StringList::const_iterator p = meta.begin(); p != meta.end(); ++p) { if(p->find("python:") == 0) { if(i > 0) { _out << ", "; } _out << "'" << *p << "'"; ++i; } } if(i == 1) { _out << ','; } _out << ')'; } string Slice::Python::CodeVisitor::getOperationMode(Slice::Operation::Mode mode) { string result; switch(mode) { case Operation::Normal: result = "Ice.OperationMode.Normal"; break; case Operation::Nonmutating: result = "Ice.OperationMode.Nonmutating"; break; case Operation::Idempotent: result = "Ice.OperationMode.Idempotent"; break; } return result; } void Slice::Python::CodeVisitor::collectClassMembers(const ClassDefPtr& p, MemberInfoList& allMembers, bool inherited) { ClassList bases = p->bases(); if(!bases.empty() && !bases.front()->isInterface()) { collectClassMembers(bases.front(), allMembers, true); } DataMemberList members = p->dataMembers(); for(DataMemberList::iterator q = members.begin(); q != members.end(); ++q) { MemberInfo m; m.fixedName = fixIdent((*q)->name()); m.type = (*q)->type(); m.inherited = inherited; m.metaData = (*q)->getMetaData(); allMembers.push_back(m); } } void Slice::Python::CodeVisitor::collectExceptionMembers(const ExceptionPtr& p, MemberInfoList& allMembers, bool inherited) { ExceptionPtr base = p->base(); if(base) { collectExceptionMembers(base, allMembers, true); } DataMemberList members = p->dataMembers(); for(DataMemberList::iterator q = members.begin(); q != members.end(); ++q) { MemberInfo m; m.fixedName = fixIdent((*q)->name()); m.type = (*q)->type(); m.inherited = inherited; m.metaData = (*q)->getMetaData(); allMembers.push_back(m); } } static string normalizePath(const string& path) { string result = path; replace(result.begin(), result.end(), '\\', '/'); string::size_type pos; while((pos = result.find("//")) != string::npos) { result.replace(pos, 2, "/"); } return result; } static string changeInclude(const string& inc, const vector& includePaths) { string orig = normalizePath(inc); string curr = orig; // The current shortest pathname. // // Compare the pathname of the included file against each of the include directories. // If any of the include directories match the leading part of the included file, // then select the include directory whose removal results in the shortest pathname. // for(vector::const_iterator p = includePaths.begin(); p != includePaths.end(); ++p) { string includePath = *p; if(orig.compare(0, p->size(), *p) == 0) { string s = orig.substr(p->size()); if(s.size() < curr.size()) { curr = s; } } } string::size_type pos = curr.rfind('.'); if(pos != string::npos) { curr.erase(pos); } return curr; } void Slice::Python::generate(const UnitPtr& un, bool all, bool checksum, const vector& includePaths, Output& out) { Slice::Python::MetaDataVisitor visitor; un->visit(&visitor, false); out << nl << "import Ice, IcePy, __builtin__"; if(!all) { vector paths = includePaths; for(vector::iterator p = paths.begin(); p != paths.end(); ++p) { if(p->size() && (*p)[p->size() - 1] != '/') { *p += '/'; } *p = normalizePath(*p); } StringList includes = un->includeFiles(); for(StringList::const_iterator q = includes.begin(); q != includes.end(); ++q) { string file = changeInclude(*q, paths); replace(file.begin(), file.end(), '/', '_'); out << nl << "import " << file << "_ice"; } } set moduleHistory; ModuleVisitor moduleVisitor(out, moduleHistory); un->visit(&moduleVisitor, true); CodeVisitor codeVisitor(out, moduleHistory); un->visit(&codeVisitor, false); if(checksum) { ChecksumMap checksums = createChecksums(un); if(!checksums.empty()) { out << sp; for(ChecksumMap::const_iterator p = checksums.begin(); p != checksums.end(); ++p) { out << nl << "Ice.sliceChecksums[\"" << p->first << "\"] = \""; ostringstream str; str.flags(ios_base::hex); str.fill('0'); for(vector::const_iterator q = p->second.begin(); q != p->second.end(); ++q) { str << (int)(*q); } out << str.str() << "\""; } } } out << nl; // Trailing newline. } bool Slice::Python::splitString(const string& str, vector& args, const string& delim) { string::size_type beg; string::size_type end = 0; while(true) { beg = str.find_first_not_of(delim, end); if(beg == string::npos) { break; } // // Check for quoted argument. // char ch = str[beg]; if(ch == '"' || ch == '\'') { beg++; end = str.find(ch, beg); if(end == string::npos) { return false; } args.push_back(str.substr(beg, end - beg)); end++; // Skip end quote. } else { end = str.find_first_of(delim + "'\"", beg); if(end == string::npos) { end = str.length(); } args.push_back(str.substr(beg, end - beg)); } } return true; } string Slice::Python::scopedToName(const string& scoped) { string result = fixIdent(scoped); if(result.find("::") == 0) { result.erase(0, 2); } string::size_type pos; while((pos = result.find("::")) != string::npos) { result.replace(pos, 2, "."); } return result; } string Slice::Python::fixIdent(const string& ident) { if(ident[0] != ':') { return lookupKwd(ident); } vector ids = splitScopedName(ident); transform(ids.begin(), ids.end(), ids.begin(), ptr_fun(lookupKwd)); stringstream result; for(vector::const_iterator i = ids.begin(); i != ids.end(); ++i) { result << "::" + *i; } return result.str(); } string Slice::Python::getPackageMetadata(const ContainedPtr& cont) { string package; DefinitionContextPtr dc = cont->definitionContext(); if(dc) { static const string prefix = "python:package:"; string metadata = dc->findMetaData(prefix); if(!metadata.empty()) { package = metadata.substr(prefix.size()); } } return package; } string Slice::Python::getAbsolute(const ContainedPtr& cont, const string& suffix) { string scope = scopedToName(cont->scope()); string package = getPackageMetadata(cont); if(!package.empty()) { if(!scope.empty()) { scope = package + "." + scope; } else { scope = package + "."; } } if(suffix.empty()) { return scope + fixIdent(cont->name()); } else { return scope + suffix + fixIdent(cont->name()); } } void Slice::Python::printHeader(IceUtil::Output& out) { static const char* header = "# **********************************************************************\n" "#\n" "# Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved.\n" "#\n" "# This copy of Ice is licensed to you under the terms described in the\n" "# ICE_LICENSE file included in this distribution.\n" "#\n" "# **********************************************************************\n" ; out << header; out << "\n# Ice version " << ICE_STRING_VERSION; } bool Slice::Python::MetaDataVisitor::visitModuleStart(const ModulePtr& p) { if(!ModulePtr::dynamicCast(p->container())) { // // We only need to validate global metadata for top-level modules. // validateGlobal(p->definitionContext()); } reject(p); return true; } void Slice::Python::MetaDataVisitor::visitClassDecl(const ClassDeclPtr& p) { reject(p); } bool Slice::Python::MetaDataVisitor::visitClassDefStart(const ClassDefPtr& p) { reject(p); return true; } bool Slice::Python::MetaDataVisitor::visitExceptionStart(const ExceptionPtr& p) { reject(p); return true; } bool Slice::Python::MetaDataVisitor::visitStructStart(const StructPtr& p) { reject(p); return true; } void Slice::Python::MetaDataVisitor::visitOperation(const OperationPtr& p) { DefinitionContextPtr dc = p->definitionContext(); assert(dc); TypePtr ret = p->returnType(); if(ret) { validateSequence(dc, p->line(), ret, p->getMetaData()); } ParamDeclList params = p->parameters(); for(ParamDeclList::iterator q = params.begin(); q != params.end(); ++q) { validateSequence(dc, (*q)->line(), (*q)->type(), (*q)->getMetaData()); } } void Slice::Python::MetaDataVisitor::visitDataMember(const DataMemberPtr& p) { validateSequence(p->definitionContext(), p->line(), p->type(), p->getMetaData()); } void Slice::Python::MetaDataVisitor::visitSequence(const SequencePtr& p) { validateSequence(p->definitionContext(), p->line(), p, p->getMetaData()); } void Slice::Python::MetaDataVisitor::visitDictionary(const DictionaryPtr& p) { reject(p); } void Slice::Python::MetaDataVisitor::visitEnum(const EnumPtr& p) { reject(p); } void Slice::Python::MetaDataVisitor::visitConst(const ConstPtr& p) { reject(p); } void Slice::Python::MetaDataVisitor::validateGlobal(const DefinitionContextPtr& dc) { StringList globalMetaData = dc->getMetaData(); static const string prefix = "python:"; for(StringList::const_iterator p = globalMetaData.begin(); p != globalMetaData.end(); ++p) { string s = *p; if(_history.count(s) == 0) { if(s.find(prefix) == 0) { static const string packagePrefix = "python:package:"; if(s.find(packagePrefix) != 0 || s.size() == packagePrefix.size()) { cout << dc->filename() << ": warning: ignoring invalid global metadata `" << s << "'" << endl; } } _history.insert(s); } } } void Slice::Python::MetaDataVisitor::validateSequence(const DefinitionContextPtr& dc, const string& line, const TypePtr& type, const StringList& meta) { static const string prefix = "python:"; for(StringList::const_iterator p = meta.begin(); p != meta.end(); ++p) { string s = *p; if(s.find(prefix) == 0) { string::size_type pos = s.find(':', prefix.size()); if(pos != string::npos && s.substr(prefix.size(), pos - prefix.size()) == "seq") { static const string seqPrefix = "python:seq:"; string arg = s.substr(seqPrefix.size(), pos - seqPrefix.size()); if(SequencePtr::dynamicCast(type)) { if(arg == "tuple" || arg == "list" || arg == "default") { continue; } } } cout << dc->filename() << ":" << line << ": warning: ignoring metadata `" << s << "'" << endl; } } } void Slice::Python::MetaDataVisitor::reject(const ContainedPtr& cont) { StringList localMetaData = cont->getMetaData(); static const string prefix = "python:"; for(StringList::const_iterator p = localMetaData.begin(); p != localMetaData.end(); ++p) { if(p->find(prefix) == 0) { DefinitionContextPtr dc = cont->definitionContext(); assert(dc); cout << dc->filename() << ":" << cont->line() << ": warning: ignoring metadata `" << *p << "'" << endl; } } } IceE-trans-1.2.0/src/Slice/Grammar.h0000664000076400007640000000707010620635757016422 0ustar dwaynedwayne/* A Bison parser, made by GNU Bison 1.875c. */ /* Skeleton parser for Yacc-like parsing with Bison, Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* As a special exception, when this file is copied by Bison into a Bison output file, you may use that output file without restriction. This special exception was added by the Free Software Foundation in version 1.24 of Bison. */ /* Tokens. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE /* Put the tokens into the symbol table, so that GDB and other debuggers know about them. */ enum yytokentype { ICE_MODULE = 258, ICE_CLASS = 259, ICE_INTERFACE = 260, ICE_EXCEPTION = 261, ICE_STRUCT = 262, ICE_SEQUENCE = 263, ICE_DICTIONARY = 264, ICE_ENUM = 265, ICE_OUT = 266, ICE_EXTENDS = 267, ICE_IMPLEMENTS = 268, ICE_THROWS = 269, ICE_VOID = 270, ICE_BYTE = 271, ICE_BOOL = 272, ICE_SHORT = 273, ICE_INT = 274, ICE_LONG = 275, ICE_FLOAT = 276, ICE_DOUBLE = 277, ICE_STRING = 278, ICE_OBJECT = 279, ICE_LOCAL_OBJECT = 280, ICE_LOCAL = 281, ICE_CONST = 282, ICE_FALSE = 283, ICE_TRUE = 284, ICE_NONMUTATING = 285, ICE_IDEMPOTENT = 286, ICE_SCOPE_DELIMITER = 287, ICE_IDENTIFIER = 288, ICE_STRING_LITERAL = 289, ICE_INTEGER_LITERAL = 290, ICE_FLOATING_POINT_LITERAL = 291, ICE_IDENT_OP = 292, ICE_KEYWORD_OP = 293, ICE_METADATA_OPEN = 294, ICE_METADATA_CLOSE = 295, ICE_GLOBAL_METADATA_OPEN = 296, ICE_GLOBAL_METADATA_CLOSE = 297, BAD_CHAR = 298 }; #endif #define ICE_MODULE 258 #define ICE_CLASS 259 #define ICE_INTERFACE 260 #define ICE_EXCEPTION 261 #define ICE_STRUCT 262 #define ICE_SEQUENCE 263 #define ICE_DICTIONARY 264 #define ICE_ENUM 265 #define ICE_OUT 266 #define ICE_EXTENDS 267 #define ICE_IMPLEMENTS 268 #define ICE_THROWS 269 #define ICE_VOID 270 #define ICE_BYTE 271 #define ICE_BOOL 272 #define ICE_SHORT 273 #define ICE_INT 274 #define ICE_LONG 275 #define ICE_FLOAT 276 #define ICE_DOUBLE 277 #define ICE_STRING 278 #define ICE_OBJECT 279 #define ICE_LOCAL_OBJECT 280 #define ICE_LOCAL 281 #define ICE_CONST 282 #define ICE_FALSE 283 #define ICE_TRUE 284 #define ICE_NONMUTATING 285 #define ICE_IDEMPOTENT 286 #define ICE_SCOPE_DELIMITER 287 #define ICE_IDENTIFIER 288 #define ICE_STRING_LITERAL 289 #define ICE_INTEGER_LITERAL 290 #define ICE_FLOATING_POINT_LITERAL 291 #define ICE_IDENT_OP 292 #define ICE_KEYWORD_OP 293 #define ICE_METADATA_OPEN 294 #define ICE_METADATA_CLOSE 295 #define ICE_GLOBAL_METADATA_OPEN 296 #define ICE_GLOBAL_METADATA_CLOSE 297 #define BAD_CHAR 298 #if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED) typedef int YYSTYPE; # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 # define YYSTYPE_IS_TRIVIAL 1 #endif IceE-trans-1.2.0/src/Slice/dummyinclude/0000775000076400007640000000000010620635756017355 5ustar dwaynedwayneIceE-trans-1.2.0/src/Slice/dummyinclude/unistd.h0000664000076400007640000000015407505664667021047 0ustar dwaynedwayne// // Files generated by flex need unistd.h, which is not available on // Windows. Thus this dummy file. // IceE-trans-1.2.0/src/Slice/Grammar.cpp0000664000076400007640000030517010620635757016757 0ustar dwaynedwayne/* A Bison parser, made by GNU Bison 1.875c. */ /* Skeleton parser for Yacc-like parsing with Bison, Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* As a special exception, when this file is copied by Bison into a Bison output file, you may use that output file without restriction. This special exception was added by the Free Software Foundation in version 1.24 of Bison. */ /* Written by Richard Stallman by simplifying the original so called ``semantic'' parser. */ /* All symbols defined below should begin with yy or YY, to avoid infringing on user name space. This should be done even for local variables, as they might otherwise be expanded by user macros. There are some unavoidable exceptions within include files to define necessary library symbols; they are noted "INFRINGES ON USER NAME SPACE" below. */ /* Identify Bison output. */ #define YYBISON 1 /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" /* Pure parsers. */ #define YYPURE 1 /* Using locations. */ #define YYLSP_NEEDED 0 /* If NAME_PREFIX is specified substitute the variables and functions names. */ #define yyparse slice_parse #define yylex slice_lex #define yyerror slice_error #define yylval slice_lval #define yychar slice_char #define yydebug slice_debug #define yynerrs slice_nerrs /* Tokens. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE /* Put the tokens into the symbol table, so that GDB and other debuggers know about them. */ enum yytokentype { ICE_MODULE = 258, ICE_CLASS = 259, ICE_INTERFACE = 260, ICE_EXCEPTION = 261, ICE_STRUCT = 262, ICE_SEQUENCE = 263, ICE_DICTIONARY = 264, ICE_ENUM = 265, ICE_OUT = 266, ICE_EXTENDS = 267, ICE_IMPLEMENTS = 268, ICE_THROWS = 269, ICE_VOID = 270, ICE_BYTE = 271, ICE_BOOL = 272, ICE_SHORT = 273, ICE_INT = 274, ICE_LONG = 275, ICE_FLOAT = 276, ICE_DOUBLE = 277, ICE_STRING = 278, ICE_OBJECT = 279, ICE_LOCAL_OBJECT = 280, ICE_LOCAL = 281, ICE_CONST = 282, ICE_FALSE = 283, ICE_TRUE = 284, ICE_NONMUTATING = 285, ICE_IDEMPOTENT = 286, ICE_SCOPE_DELIMITER = 287, ICE_IDENTIFIER = 288, ICE_STRING_LITERAL = 289, ICE_INTEGER_LITERAL = 290, ICE_FLOATING_POINT_LITERAL = 291, ICE_IDENT_OP = 292, ICE_KEYWORD_OP = 293, ICE_METADATA_OPEN = 294, ICE_METADATA_CLOSE = 295, ICE_GLOBAL_METADATA_OPEN = 296, ICE_GLOBAL_METADATA_CLOSE = 297, BAD_CHAR = 298 }; #endif #define ICE_MODULE 258 #define ICE_CLASS 259 #define ICE_INTERFACE 260 #define ICE_EXCEPTION 261 #define ICE_STRUCT 262 #define ICE_SEQUENCE 263 #define ICE_DICTIONARY 264 #define ICE_ENUM 265 #define ICE_OUT 266 #define ICE_EXTENDS 267 #define ICE_IMPLEMENTS 268 #define ICE_THROWS 269 #define ICE_VOID 270 #define ICE_BYTE 271 #define ICE_BOOL 272 #define ICE_SHORT 273 #define ICE_INT 274 #define ICE_LONG 275 #define ICE_FLOAT 276 #define ICE_DOUBLE 277 #define ICE_STRING 278 #define ICE_OBJECT 279 #define ICE_LOCAL_OBJECT 280 #define ICE_LOCAL 281 #define ICE_CONST 282 #define ICE_FALSE 283 #define ICE_TRUE 284 #define ICE_NONMUTATING 285 #define ICE_IDEMPOTENT 286 #define ICE_SCOPE_DELIMITER 287 #define ICE_IDENTIFIER 288 #define ICE_STRING_LITERAL 289 #define ICE_INTEGER_LITERAL 290 #define ICE_FLOATING_POINT_LITERAL 291 #define ICE_IDENT_OP 292 #define ICE_KEYWORD_OP 293 #define ICE_METADATA_OPEN 294 #define ICE_METADATA_CLOSE 295 #define ICE_GLOBAL_METADATA_OPEN 296 #define ICE_GLOBAL_METADATA_CLOSE 297 #define BAD_CHAR 298 /* Copy the first part of user declarations. */ #line 1 "Grammar.y" // ********************************************************************** // // Copyright (c) 2003-2007 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 #ifdef _MSC_VER // I get these warnings from some bison versions: // warning C4102: 'yyoverflowlab' : unreferenced label # pragma warning( disable : 4102 ) // warning C4065: switch statement contains 'default' but no 'case' labels # pragma warning( disable : 4065 ) #endif using namespace std; using namespace Slice; void slice_error(const char* s) { // yacc and recent versions of Bison use "syntax error" instead // of "parse error". if (strcmp(s, "parse error") == 0) { unit->error("syntax error"); } else { unit->error(s); } } /* Enabling traces. */ #ifndef YYDEBUG # define YYDEBUG 1 #endif /* Enabling verbose error messages. */ #ifdef YYERROR_VERBOSE # undef YYERROR_VERBOSE # define YYERROR_VERBOSE 1 #else # define YYERROR_VERBOSE 0 #endif #if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED) typedef int YYSTYPE; # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 # define YYSTYPE_IS_TRIVIAL 1 #endif /* Copy the second part of user declarations. */ /* Line 214 of yacc.c. */ #line 225 "Grammar.tab.c" #if ! defined (yyoverflow) || YYERROR_VERBOSE # ifndef YYFREE # define YYFREE free # endif # ifndef YYMALLOC # define YYMALLOC malloc # endif /* The parser invokes alloca or malloc; define the necessary symbols. */ # ifdef YYSTACK_USE_ALLOCA # if YYSTACK_USE_ALLOCA # define YYSTACK_ALLOC alloca # endif # else # if defined (alloca) || defined (_ALLOCA_H) # define YYSTACK_ALLOC alloca # else # ifdef __GNUC__ # define YYSTACK_ALLOC __builtin_alloca # endif # endif # endif # ifdef YYSTACK_ALLOC /* Pacify GCC's `empty if-body' warning. */ # define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) # else # if defined (__STDC__) || defined (__cplusplus) # include /* INFRINGES ON USER NAME SPACE */ # define YYSIZE_T size_t # endif # define YYSTACK_ALLOC YYMALLOC # define YYSTACK_FREE YYFREE # endif #endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */ #if (! defined (yyoverflow) \ && (! defined (__cplusplus) \ || (defined (YYSTYPE_IS_TRIVIAL) && YYSTYPE_IS_TRIVIAL))) /* A type that is properly aligned for any stack member. */ union yyalloc { short yyss; YYSTYPE yyvs; }; /* The size of the maximum gap between one aligned stack and the next. */ # define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) /* The size of an array large to enough to hold all stacks, each with N elements. */ # define YYSTACK_BYTES(N) \ ((N) * (sizeof (short) + sizeof (YYSTYPE)) \ + YYSTACK_GAP_MAXIMUM) /* Copy COUNT objects from FROM to TO. The source and destination do not overlap. */ # ifndef YYCOPY # if defined (__GNUC__) && 1 < __GNUC__ # define YYCOPY(To, From, Count) \ __builtin_memcpy (To, From, (Count) * sizeof (*(From))) # else # define YYCOPY(To, From, Count) \ do \ { \ register YYSIZE_T yyi; \ for (yyi = 0; yyi < (Count); yyi++) \ (To)[yyi] = (From)[yyi]; \ } \ while (0) # endif # endif /* Relocate STACK from its old location to the new one. The local variables YYSIZE and YYSTACKSIZE give the old and new number of elements in the stack, and YYPTR gives the new location of the stack. Advance YYPTR to a properly aligned location for the next stack. */ # define YYSTACK_RELOCATE(Stack) \ do \ { \ YYSIZE_T yynewbytes; \ YYCOPY (&yyptr->Stack, Stack, yysize); \ Stack = &yyptr->Stack; \ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ yyptr += yynewbytes / sizeof (*yyptr); \ } \ while (0) #endif #if defined (__STDC__) || defined (__cplusplus) typedef signed char yysigned_char; #else typedef short yysigned_char; #endif /* YYFINAL -- State number of the termination state. */ #define YYFINAL 13 /* YYLAST -- Last index in YYTABLE. */ #define YYLAST 784 /* YYNTOKENS -- Number of terminals. */ #define YYNTOKENS 53 /* YYNNTS -- Number of nonterminals. */ #define YYNNTS 67 /* YYNRULES -- Number of rules. */ #define YYNRULES 183 /* YYNRULES -- Number of states. */ #define YYNSTATES 266 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 #define YYMAXUTOK 298 #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) /* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ static const unsigned char yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 47, 51, 2, 48, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 44, 49, 52, 50, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 45, 2, 46, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43 }; #if YYDEBUG /* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in YYRHS. */ static const unsigned short yyprhs[] = { 0, 0, 3, 5, 9, 13, 14, 15, 19, 20, 26, 27, 32, 35, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 63, 70, 73, 76, 79, 80, 88, 91, 92, 97, 101, 104, 105, 108, 110, 113, 116, 119, 120, 127, 132, 136, 139, 140, 142, 145, 148, 151, 152, 161, 164, 165, 168, 169, 174, 178, 181, 182, 184, 187, 189, 191, 193, 196, 200, 204, 207, 211, 215, 216, 222, 223, 229, 231, 233, 236, 239, 242, 243, 251, 255, 257, 259, 262, 263, 268, 272, 275, 276, 278, 282, 284, 286, 288, 296, 304, 315, 326, 329, 332, 333, 340, 344, 346, 348, 350, 351, 353, 354, 355, 359, 365, 370, 377, 381, 387, 390, 391, 393, 396, 400, 402, 404, 406, 408, 410, 412, 414, 416, 418, 421, 423, 425, 428, 431, 433, 437, 439, 441, 442, 444, 446, 448, 450, 452, 454, 461, 467, 469, 471, 473, 475, 477, 479, 481, 483, 485, 487, 489, 491, 493, 495, 497, 499, 501, 503, 505, 507, 509, 511, 513, 515, 517, 519, 521, 523 }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ static const yysigned_char yyrhs[] = { 54, 0, -1, 57, -1, 41, 115, 42, -1, 39, 115, 40, -1, -1, -1, 55, 58, 57, -1, -1, 56, 61, 59, 44, 57, -1, -1, 1, 44, 60, 57, -1, 56, 61, -1, -1, 62, -1, 79, -1, 80, -1, 93, -1, 94, -1, 65, -1, 66, -1, 73, -1, 74, -1, 102, -1, 103, -1, 105, -1, 118, -1, -1, 3, 33, 63, 45, 57, 46, -1, 6, 33, -1, 6, 119, -1, 116, 64, -1, -1, 116, 64, 68, 67, 45, 69, 46, -1, 12, 112, -1, -1, 56, 71, 44, 69, -1, 1, 44, 69, -1, 56, 71, -1, -1, 113, 33, -1, 85, -1, 7, 33, -1, 7, 119, -1, 116, 72, -1, -1, 116, 72, 75, 45, 76, 46, -1, 56, 77, 44, 76, -1, 1, 44, 76, -1, 56, 77, -1, -1, 85, -1, 4, 33, -1, 4, 119, -1, 116, 78, -1, -1, 116, 78, 82, 83, 81, 45, 84, 46, -1, 12, 112, -1, -1, 13, 96, -1, -1, 56, 91, 44, 84, -1, 1, 44, 84, -1, 56, 91, -1, -1, 70, -1, 113, 119, -1, 113, -1, 113, -1, 15, -1, 86, 37, -1, 30, 86, 37, -1, 31, 86, 37, -1, 86, 38, -1, 30, 86, 38, -1, 31, 86, 38, -1, -1, 87, 110, 47, 89, 111, -1, -1, 87, 1, 47, 90, 111, -1, 85, -1, 88, -1, 5, 33, -1, 5, 119, -1, 116, 92, -1, -1, 116, 92, 97, 95, 45, 98, 46, -1, 112, 48, 96, -1, 112, -1, 24, -1, 12, 96, -1, -1, 56, 99, 44, 98, -1, 1, 44, 98, -1, 56, 99, -1, -1, 88, -1, 101, 48, 100, -1, 101, -1, 112, -1, 119, -1, 116, 8, 49, 56, 113, 50, 33, -1, 116, 8, 49, 56, 113, 50, 119, -1, 116, 9, 49, 56, 113, 48, 56, 113, 50, 33, -1, 116, 9, 49, 56, 113, 48, 56, 113, 50, 119, -1, 10, 33, -1, 10, 119, -1, -1, 116, 104, 106, 45, 107, 46, -1, 108, 48, 107, -1, 108, -1, 33, -1, 119, -1, -1, 11, -1, -1, -1, 109, 56, 70, -1, 110, 48, 109, 56, 70, -1, 109, 56, 113, 119, -1, 110, 48, 109, 56, 113, 119, -1, 109, 56, 113, -1, 110, 48, 109, 56, 113, -1, 14, 100, -1, -1, 33, -1, 32, 33, -1, 112, 32, 33, -1, 16, -1, 17, -1, 18, -1, 19, -1, 20, -1, 21, -1, 22, -1, 23, -1, 24, -1, 24, 51, -1, 25, -1, 112, -1, 112, 51, -1, 34, 114, -1, 34, -1, 115, 48, 114, -1, 114, -1, 26, -1, -1, 35, -1, 36, -1, 112, -1, 34, -1, 28, -1, 29, -1, 27, 56, 113, 33, 52, 117, -1, 27, 56, 113, 52, 117, -1, 3, -1, 4, -1, 5, -1, 6, -1, 7, -1, 8, -1, 9, -1, 10, -1, 11, -1, 12, -1, 13, -1, 14, -1, 15, -1, 16, -1, 17, -1, 18, -1, 19, -1, 20, -1, 21, -1, 22, -1, 23, -1, 24, -1, 25, -1, 26, -1, 27, -1, 28, -1, 29, -1, 30, -1, 31, -1 }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const unsigned short yyrline[] = { 0, 104, 104, 112, 121, 126, 135, 134, 144, 143, 155, 154, 159, 164, 171, 175, 179, 183, 187, 191, 195, 199, 203, 207, 211, 215, 219, 229, 228, 261, 265, 276, 287, 286, 313, 322, 330, 339, 342, 347, 354, 367, 373, 377, 388, 399, 398, 434, 443, 446, 451, 458, 464, 468, 479, 493, 492, 532, 567, 575, 580, 588, 597, 600, 605, 612, 635, 657, 683, 684, 693, 717, 758, 782, 806, 830, 860, 859, 882, 881, 904, 905, 911, 915, 926, 941, 940, 975, 1010, 1045, 1055, 1060, 1068, 1077, 1080, 1085, 1092, 1098, 1105, 1117, 1129, 1140, 1149, 1164, 1175, 1192, 1196, 1208, 1207, 1235, 1241, 1249, 1261, 1269, 1278, 1285, 1296, 1298, 1316, 1334, 1346, 1358, 1369, 1385, 1390, 1398, 1401, 1407, 1420, 1424, 1428, 1432, 1436, 1440, 1444, 1448, 1452, 1456, 1460, 1464, 1483, 1524, 1530, 1538, 1545, 1557, 1564, 1574, 1584, 1594, 1623, 1631, 1639, 1652, 1660, 1674, 1677, 1680, 1683, 1686, 1689, 1692, 1695, 1698, 1701, 1704, 1707, 1710, 1713, 1716, 1719, 1722, 1725, 1728, 1731, 1734, 1737, 1740, 1743, 1746, 1749, 1752, 1755, 1758 }; #endif #if YYDEBUG || YYERROR_VERBOSE /* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. First, the terminals, then, starting at YYNTOKENS, nonterminals. */ static const char *const yytname[] = { "$end", "error", "$undefined", "ICE_MODULE", "ICE_CLASS", "ICE_INTERFACE", "ICE_EXCEPTION", "ICE_STRUCT", "ICE_SEQUENCE", "ICE_DICTIONARY", "ICE_ENUM", "ICE_OUT", "ICE_EXTENDS", "ICE_IMPLEMENTS", "ICE_THROWS", "ICE_VOID", "ICE_BYTE", "ICE_BOOL", "ICE_SHORT", "ICE_INT", "ICE_LONG", "ICE_FLOAT", "ICE_DOUBLE", "ICE_STRING", "ICE_OBJECT", "ICE_LOCAL_OBJECT", "ICE_LOCAL", "ICE_CONST", "ICE_FALSE", "ICE_TRUE", "ICE_NONMUTATING", "ICE_IDEMPOTENT", "ICE_SCOPE_DELIMITER", "ICE_IDENTIFIER", "ICE_STRING_LITERAL", "ICE_INTEGER_LITERAL", "ICE_FLOATING_POINT_LITERAL", "ICE_IDENT_OP", "ICE_KEYWORD_OP", "ICE_METADATA_OPEN", "ICE_METADATA_CLOSE", "ICE_GLOBAL_METADATA_OPEN", "ICE_GLOBAL_METADATA_CLOSE", "BAD_CHAR", "';'", "'{'", "'}'", "')'", "','", "'<'", "'>'", "'*'", "'='", "$accept", "start", "global_meta_data", "meta_data", "definitions", "@1", "@2", "@3", "definition", "module_def", "@4", "exception_id", "exception_decl", "exception_def", "@5", "exception_extends", "exception_exports", "type_id", "exception_export", "struct_id", "struct_decl", "struct_def", "@6", "struct_exports", "struct_export", "class_id", "class_decl", "class_def", "@7", "class_extends", "implements", "class_exports", "data_member", "return_type", "operation_preamble", "operation", "@8", "@9", "class_export", "interface_id", "interface_decl", "interface_def", "@10", "interface_list", "interface_extends", "interface_exports", "interface_export", "exception_list", "exception", "sequence_def", "dictionary_def", "enum_id", "enum_def", "@11", "enumerator_list", "enumerator", "out_qualifier", "parameters", "throws", "scoped_name", "type", "string_literal", "string_list", "local_qualifier", "const_initializer", "const_def", "keyword", 0 }; #endif # ifdef YYPRINT /* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to token YYLEX-NUM. */ static const unsigned short yytoknum[] = { 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 59, 123, 125, 41, 44, 60, 62, 42, 61 }; # endif /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const unsigned char yyr1[] = { 0, 53, 54, 55, 56, 56, 58, 57, 59, 57, 60, 57, 57, 57, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 63, 62, 64, 64, 65, 67, 66, 68, 68, 69, 69, 69, 69, 70, 71, 72, 72, 73, 75, 74, 76, 76, 76, 76, 77, 78, 78, 79, 81, 80, 82, 82, 83, 83, 84, 84, 84, 84, 85, 85, 85, 86, 86, 87, 87, 87, 87, 87, 87, 89, 88, 90, 88, 91, 91, 92, 92, 93, 95, 94, 96, 96, 96, 97, 97, 98, 98, 98, 98, 99, 100, 100, 101, 101, 102, 102, 103, 103, 104, 104, 106, 105, 107, 107, 108, 108, 108, 109, 109, 110, 110, 110, 110, 110, 110, 110, 111, 111, 112, 112, 112, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 114, 114, 115, 115, 116, 116, 117, 117, 117, 117, 117, 117, 118, 118, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ static const unsigned char yyr2[] = { 0, 2, 1, 3, 3, 0, 0, 3, 0, 5, 0, 4, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 6, 2, 2, 2, 0, 7, 2, 0, 4, 3, 2, 0, 2, 1, 2, 2, 2, 0, 6, 4, 3, 2, 0, 1, 2, 2, 2, 0, 8, 2, 0, 2, 0, 4, 3, 2, 0, 1, 2, 1, 1, 1, 2, 3, 3, 2, 3, 3, 0, 5, 0, 5, 1, 1, 2, 2, 2, 0, 7, 3, 1, 1, 2, 0, 4, 3, 2, 0, 1, 3, 1, 1, 1, 7, 7, 10, 10, 2, 2, 0, 6, 3, 1, 1, 1, 0, 1, 0, 0, 3, 5, 4, 6, 3, 5, 2, 0, 1, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 2, 1, 3, 1, 1, 0, 1, 1, 1, 1, 1, 1, 6, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state STATE-NUM when YYTABLE doesn't specify something else to do. Zero means the default is an error. */ static const unsigned char yydefact[] = { 0, 0, 0, 0, 0, 6, 146, 2, 10, 142, 144, 0, 0, 1, 0, 0, 145, 5, 12, 14, 19, 20, 21, 22, 15, 16, 17, 18, 23, 24, 25, 0, 26, 0, 141, 4, 0, 3, 7, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 44, 54, 84, 107, 11, 143, 0, 128, 129, 130, 131, 132, 133, 134, 135, 136, 138, 0, 125, 139, 0, 0, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 52, 53, 82, 83, 29, 30, 42, 43, 5, 5, 105, 106, 0, 32, 0, 0, 60, 0, 85, 0, 0, 137, 126, 0, 140, 0, 0, 9, 0, 0, 34, 0, 0, 57, 0, 55, 89, 90, 88, 0, 113, 0, 127, 0, 151, 152, 150, 147, 148, 149, 154, 0, 0, 0, 0, 0, 0, 59, 0, 0, 0, 111, 0, 110, 112, 28, 153, 0, 5, 0, 0, 0, 0, 65, 49, 51, 67, 46, 0, 87, 0, 0, 0, 108, 113, 101, 102, 0, 0, 38, 41, 33, 48, 0, 40, 66, 0, 0, 0, 0, 69, 0, 0, 0, 0, 96, 94, 68, 86, 109, 0, 37, 0, 47, 0, 80, 81, 63, 67, 56, 93, 0, 0, 70, 73, 0, 114, 5, 0, 0, 0, 36, 62, 0, 71, 74, 72, 75, 78, 0, 76, 115, 92, 103, 104, 61, 124, 117, 121, 124, 5, 0, 79, 119, 77, 0, 123, 98, 99, 100, 118, 122, 0, 120, 97 }; /* YYDEFGOTO[NTERM-NUM]. */ static const short yydefgoto[] = { -1, 4, 5, 6, 7, 14, 41, 33, 18, 19, 56, 49, 20, 21, 132, 114, 172, 174, 190, 50, 22, 23, 115, 157, 175, 51, 24, 25, 159, 117, 136, 199, 176, 204, 205, 206, 250, 247, 218, 52, 26, 27, 140, 138, 119, 183, 207, 257, 258, 28, 29, 53, 30, 120, 163, 164, 228, 229, 253, 69, 208, 10, 11, 31, 151, 32, 165 }; /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ #define YYPACT_NINF -179 static const short yypact[] = { 341, -22, 2, 2, 61, -179, 7, -179, -179, 2, -179, -21, -18, -179, 76, 34, -179, 60, 29, -179, -179, -179, -179, -179, -179, -179, -179, -179, -179, -179, -179, 119, -179, 76, -179, -179, 2, -179, -179, -179, 751, 77, 447, 478, 509, 540, 55, 58, 571, -8, 75, -10, 9, -179, -179, -179, 85, -179, -179, -179, -179, -179, -179, -179, -179, 82, -179, 101, -179, 36, 37, 76, -179, -179, -179, -179, -179, -179, -179, -179, -179, -179, -179, -179, -179, -179, -179, -179, -179, -179, -179, -179, -179, -179, -179, -179, -179, -179, -179, -179, -179, -179, -179, -179, -179, -179, -179, -179, -179, 60, 60, -179, -179, 32, -179, 90, 32, 123, 39, -179, 93, 330, -179, -179, 106, -179, 89, 62, -179, 751, 751, 110, 98, 168, 110, 39, -179, -179, -179, -19, 100, 602, 103, -179, 62, -179, -179, -179, -179, -179, 110, -179, 96, 102, 286, 107, 751, 108, -179, 112, 39, 220, -179, 109, 105, -179, -179, -179, 633, 60, 114, 751, 115, 168, -179, 116, -179, 664, -179, 253, -179, 121, 714, 117, -179, 602, -179, -179, 751, 286, 122, -179, -179, -179, 168, -179, -179, 124, 714, 125, 220, -179, 733, 733, 63, 27, -179, 126, -179, -179, -179, 128, -179, 286, -179, 253, -179, -179, 129, 380, -179, -179, 72, 74, -179, -179, 120, -179, 60, 66, 220, 695, -179, -179, 253, -179, -179, -179, -179, -179, 751, -179, 164, -179, -179, -179, -179, 162, -179, 664, 162, 60, 416, -179, -179, -179, 751, -179, 131, 110, -179, -179, 664, 416, -179, -179 }; /* YYPGOTO[NTERM-NUM]. */ static const short yypgoto[] = { -179, -179, -179, -17, -13, -179, -179, -179, -179, -179, -179, -179, -179, -179, -179, -179, -172, -178, -179, -179, -179, -179, -179, -155, -179, -179, -179, -179, -179, -179, -179, -146, -156, -84, -179, -3, -179, -179, -179, -179, -179, -179, -179, -103, -179, -175, -179, -83, -179, -179, -179, -179, -179, -179, -4, -179, -45, -179, -51, -104, -24, 17, 199, -179, 59, -179, -37 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule which number is the opposite. If zero, do what YYDEFACT says. If YYTABLE_NINF, syntax error. */ #define YYTABLE_NINF -117 static const short yytable[] = { 40, 38, 116, -58, 113, 102, 104, 106, 108, 131, 15, 112, 134, 124, 139, 191, 70, 212, 193, 35, 54, 118, 8, 150, 37, 221, 34, 36, 226, 160, 36, 139, 158, 16, 17, -58, 9, -35, 227, 214, 150, 232, 216, -115, -115, -115, -115, -115, -115, -115, -115, -115, -115, 55, -91, 243, 139, 180, 128, -115, -115, 13, 248, 137, 67, 68, -115, 39, 124, 233, 126, 67, 68, -8, -116, -116, -13, 1, 261, -5, -5, -5, -5, -5, -5, -5, -5, 125, 246, 127, 145, 146, 129, 130, 67, 68, 147, 148, 149, 2, 224, 225, -5, -5, 109, 152, 153, 110, 142, 235, 236, 237, 238, 241, 242, 2, 156, 3, 222, 223, -45, 71, -13, 42, 43, 44, 45, 46, 47, 48, 121, 187, 177, 122, 123, 133, 135, 171, 141, 143, 196, 144, 124, 154, 182, 161, 168, 177, 259, 166, 169, 173, 188, 185, 178, 184, 156, 179, 189, 259, 194, 192, 198, 209, 211, 200, 213, 239, 215, 155, 230, 220, 171, 234, 219, 227, 252, 156, 231, 263, 265, 210, 196, 182, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, 245, 217, 171, 251, 198, 255, -5, -5, 12, 167, 0, 0, 0, 2, 0, 0, 0, 240, 254, 182, -50, 260, 249, 198, 0, 0, 0, 181, 0, 0, 0, 264, 260, 0, 0, 0, 0, 0, 262, 0, 256, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, 0, 0, 0, 0, -5, -5, -5, -5, 197, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, -95, 0, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, 0, 0, 0, 0, -5, -5, -5, -5, 170, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, -64, 0, 0, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, 0, 0, 0, 0, 0, 0, -5, -5, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, -39, -5, -5, -5, -5, -5, -5, -5, -5, -13, 1, 0, -5, -5, -5, -5, -5, -5, -5, -5, 0, 0, 0, 0, -5, -5, 0, 0, 0, 0, 0, 0, 0, 0, 0, -5, -5, 2, 0, 3, 0, 0, 0, 0, -13, 0, 0, 0, 2, 0, 3, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 0, 195, 0, 0, 0, -68, -68, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 67, 68, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 0, 101, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 0, 103, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 0, 105, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 0, 107, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 0, 111, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 0, 162, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 0, 186, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 0, 195, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 0, 244, 201, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, 202, 203, 67, 68, 201, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, 67, 68, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 0, 0, 0, 0, 0, 0, 67, 68 }; static const short yycheck[] = { 17, 14, 12, 13, 12, 42, 43, 44, 45, 113, 3, 48, 116, 32, 118, 171, 40, 189, 173, 40, 33, 12, 44, 127, 42, 200, 9, 48, 1, 48, 48, 135, 135, 26, 27, 45, 34, 45, 11, 194, 144, 213, 198, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 36, 45, 230, 160, 160, 71, 32, 33, 0, 240, 24, 32, 33, 39, 33, 32, 215, 33, 32, 33, 44, 47, 48, 0, 1, 256, 3, 4, 5, 6, 7, 8, 9, 10, 51, 234, 52, 28, 29, 109, 110, 32, 33, 34, 35, 36, 39, 37, 38, 26, 27, 49, 129, 130, 49, 121, 37, 38, 37, 38, 47, 48, 39, 133, 41, 202, 203, 45, 44, 46, 4, 5, 6, 7, 8, 9, 10, 45, 168, 156, 51, 33, 45, 13, 154, 45, 33, 177, 52, 32, 45, 161, 45, 50, 171, 252, 46, 48, 44, 169, 48, 46, 46, 173, 45, 44, 263, 44, 46, 179, 46, 188, 44, 44, 47, 44, 1, 44, 46, 189, 44, 198, 11, 14, 194, 50, 48, 263, 185, 219, 200, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 231, 198, 213, 242, 215, 250, 32, 33, 3, 144, -1, -1, -1, 39, -1, -1, -1, 228, 249, 230, 46, 252, 240, 234, -1, -1, -1, 1, -1, -1, -1, 262, 263, -1, -1, -1, -1, -1, 256, -1, 251, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 30, 31, 32, 33, 1, -1, -1, -1, -1, 39, -1, -1, -1, -1, -1, -1, 46, -1, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 30, 31, 32, 33, 1, -1, -1, -1, -1, 39, -1, -1, -1, -1, -1, -1, 46, -1, -1, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 32, 33, -1, -1, -1, -1, -1, 39, -1, -1, -1, -1, -1, 1, 46, 3, 4, 5, 6, 7, 8, 9, 10, 0, 1, -1, 3, 4, 5, 6, 7, 8, 9, 10, -1, -1, -1, -1, 26, 27, -1, -1, -1, -1, -1, -1, -1, -1, -1, 26, 27, 39, -1, 41, -1, -1, -1, -1, 46, -1, -1, -1, 39, -1, 41, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, -1, 33, -1, -1, -1, 37, 38, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, -1, 33, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, -1, 33, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, -1, 33, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, -1, 33, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, -1, 33, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, -1, 33, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, -1, 33, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, -1, 33, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, -1, 33, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 30, 31, 32, 33, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 32, 33, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 32, 33 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ static const unsigned char yystos[] = { 0, 1, 39, 41, 54, 55, 56, 57, 44, 34, 114, 115, 115, 0, 58, 3, 26, 27, 61, 62, 65, 66, 73, 74, 79, 80, 93, 94, 102, 103, 105, 116, 118, 60, 114, 40, 48, 42, 57, 33, 56, 59, 4, 5, 6, 7, 8, 9, 10, 64, 72, 78, 92, 104, 57, 114, 63, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 32, 33, 112, 113, 44, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 33, 119, 33, 119, 33, 119, 33, 119, 49, 49, 33, 119, 12, 68, 75, 12, 82, 12, 97, 106, 45, 51, 33, 32, 51, 33, 52, 57, 56, 56, 112, 67, 45, 112, 13, 83, 24, 96, 112, 95, 45, 57, 33, 52, 28, 29, 34, 35, 36, 112, 117, 113, 113, 45, 1, 56, 76, 96, 81, 48, 45, 33, 107, 108, 119, 46, 117, 50, 48, 1, 56, 69, 44, 70, 77, 85, 113, 46, 45, 96, 1, 56, 98, 46, 48, 33, 119, 56, 44, 71, 85, 46, 76, 44, 33, 119, 1, 56, 84, 44, 15, 30, 31, 86, 87, 88, 99, 113, 46, 107, 113, 69, 44, 76, 44, 85, 88, 91, 113, 46, 98, 86, 86, 37, 38, 1, 11, 109, 110, 44, 50, 69, 84, 44, 37, 38, 37, 38, 47, 56, 47, 48, 98, 33, 119, 84, 90, 70, 113, 89, 109, 14, 111, 119, 111, 56, 100, 101, 112, 119, 70, 113, 48, 119, 100 }; #if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__) # define YYSIZE_T __SIZE_TYPE__ #endif #if ! defined (YYSIZE_T) && defined (size_t) # define YYSIZE_T size_t #endif #if ! defined (YYSIZE_T) # if defined (__STDC__) || defined (__cplusplus) # include /* INFRINGES ON USER NAME SPACE */ # define YYSIZE_T size_t # endif #endif #if ! defined (YYSIZE_T) # define YYSIZE_T unsigned int #endif #define yyerrok (yyerrstatus = 0) #define yyclearin (yychar = YYEMPTY) #define YYEMPTY (-2) #define YYEOF 0 #define YYACCEPT goto yyacceptlab #define YYABORT goto yyabortlab #define YYERROR goto yyerrorlab /* Like YYERROR except do call yyerror. This remains here temporarily to ease the transition to the new meaning of YYERROR, for GCC. Once GCC version 2 has supplanted version 1, this can go. */ #define YYFAIL goto yyerrlab #define YYRECOVERING() (!!yyerrstatus) #define YYBACKUP(Token, Value) \ do \ if (yychar == YYEMPTY && yylen == 1) \ { \ yychar = (Token); \ yylval = (Value); \ yytoken = YYTRANSLATE (yychar); \ YYPOPSTACK; \ goto yybackup; \ } \ else \ { \ yyerror ("syntax error: cannot back up");\ YYERROR; \ } \ while (0) #define YYTERROR 1 #define YYERRCODE 256 /* YYLLOC_DEFAULT -- Compute the default location (before the actions are run). */ #ifndef YYLLOC_DEFAULT # define YYLLOC_DEFAULT(Current, Rhs, N) \ ((Current).first_line = (Rhs)[1].first_line, \ (Current).first_column = (Rhs)[1].first_column, \ (Current).last_line = (Rhs)[N].last_line, \ (Current).last_column = (Rhs)[N].last_column) #endif /* YYLEX -- calling `yylex' with the right arguments. */ #ifdef YYLEX_PARAM # define YYLEX yylex (&yylval, YYLEX_PARAM) #else # define YYLEX yylex (&yylval) #endif /* Enable debugging if requested. */ #if YYDEBUG # ifndef YYFPRINTF # include /* INFRINGES ON USER NAME SPACE */ # define YYFPRINTF fprintf # endif # define YYDPRINTF(Args) \ do { \ if (yydebug) \ YYFPRINTF Args; \ } while (0) # define YYDSYMPRINT(Args) \ do { \ if (yydebug) \ yysymprint Args; \ } while (0) # define YYDSYMPRINTF(Title, Token, Value, Location) \ do { \ if (yydebug) \ { \ YYFPRINTF (stderr, "%s ", Title); \ yysymprint (stderr, \ Token, Value); \ YYFPRINTF (stderr, "\n"); \ } \ } while (0) /*------------------------------------------------------------------. | yy_stack_print -- Print the state stack from its BOTTOM up to its | | TOP (included). | `------------------------------------------------------------------*/ #if defined (__STDC__) || defined (__cplusplus) static void yy_stack_print (short *bottom, short *top) #else static void yy_stack_print (bottom, top) short *bottom; short *top; #endif { YYFPRINTF (stderr, "Stack now"); for (/* Nothing. */; bottom <= top; ++bottom) YYFPRINTF (stderr, " %d", *bottom); YYFPRINTF (stderr, "\n"); } # define YY_STACK_PRINT(Bottom, Top) \ do { \ if (yydebug) \ yy_stack_print ((Bottom), (Top)); \ } while (0) /*------------------------------------------------. | Report that the YYRULE is going to be reduced. | `------------------------------------------------*/ #if defined (__STDC__) || defined (__cplusplus) static void yy_reduce_print (int yyrule) #else static void yy_reduce_print (yyrule) int yyrule; #endif { int yyi; unsigned int yylno = yyrline[yyrule]; YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ", yyrule - 1, yylno); /* Print the symbols being reduced, and their result. */ for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++) YYFPRINTF (stderr, "%s ", yytname [yyrhs[yyi]]); YYFPRINTF (stderr, "-> %s\n", yytname [yyr1[yyrule]]); } # define YY_REDUCE_PRINT(Rule) \ do { \ if (yydebug) \ yy_reduce_print (Rule); \ } while (0) /* Nonzero means print parse trace. It is left uninitialized so that multiple parsers can coexist. */ int yydebug; #else /* !YYDEBUG */ # define YYDPRINTF(Args) # define YYDSYMPRINT(Args) # define YYDSYMPRINTF(Title, Token, Value, Location) # define YY_STACK_PRINT(Bottom, Top) # define YY_REDUCE_PRINT(Rule) #endif /* !YYDEBUG */ /* YYINITDEPTH -- initial size of the parser's stacks. */ #ifndef YYINITDEPTH # define YYINITDEPTH 200 #endif /* YYMAXDEPTH -- maximum size the stacks can grow to (effective only if the built-in stack extension method is used). Do not make this value too large; the results are undefined if SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH) evaluated with infinite-precision integer arithmetic. */ #if defined (YYMAXDEPTH) && YYMAXDEPTH == 0 # undef YYMAXDEPTH #endif #ifndef YYMAXDEPTH # define YYMAXDEPTH 10000 #endif #if YYERROR_VERBOSE # ifndef yystrlen # if defined (__GLIBC__) && defined (_STRING_H) # define yystrlen strlen # else /* Return the length of YYSTR. */ static YYSIZE_T # if defined (__STDC__) || defined (__cplusplus) yystrlen (const char *yystr) # else yystrlen (yystr) const char *yystr; # endif { register const char *yys = yystr; while (*yys++ != '\0') continue; return yys - yystr - 1; } # endif # endif # ifndef yystpcpy # if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE) # define yystpcpy stpcpy # else /* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in YYDEST. */ static char * # if defined (__STDC__) || defined (__cplusplus) yystpcpy (char *yydest, const char *yysrc) # else yystpcpy (yydest, yysrc) char *yydest; const char *yysrc; # endif { register char *yyd = yydest; register const char *yys = yysrc; while ((*yyd++ = *yys++) != '\0') continue; return yyd - 1; } # endif # endif #endif /* !YYERROR_VERBOSE */ #if YYDEBUG /*--------------------------------. | Print this symbol on YYOUTPUT. | `--------------------------------*/ #if defined (__STDC__) || defined (__cplusplus) static void yysymprint (FILE *yyoutput, int yytype, YYSTYPE *yyvaluep) #else static void yysymprint (yyoutput, yytype, yyvaluep) FILE *yyoutput; int yytype; YYSTYPE *yyvaluep; #endif { /* Pacify ``unused variable'' warnings. */ (void) yyvaluep; if (yytype < YYNTOKENS) { YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); # ifdef YYPRINT YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); # endif } else YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); switch (yytype) { default: break; } YYFPRINTF (yyoutput, ")"); } #endif /* ! YYDEBUG */ /*-----------------------------------------------. | Release the memory associated to this symbol. | `-----------------------------------------------*/ #if defined (__STDC__) || defined (__cplusplus) static void yydestruct (int yytype, YYSTYPE *yyvaluep) #else static void yydestruct (yytype, yyvaluep) int yytype; YYSTYPE *yyvaluep; #endif { /* Pacify ``unused variable'' warnings. */ (void) yyvaluep; switch (yytype) { default: break; } } /* Prevent warnings from -Wmissing-prototypes. */ #ifdef YYPARSE_PARAM # if defined (__STDC__) || defined (__cplusplus) int yyparse (void *YYPARSE_PARAM); # else int yyparse (); # endif #else /* ! YYPARSE_PARAM */ #if defined (__STDC__) || defined (__cplusplus) int yyparse (void); #else int yyparse (); #endif #endif /* ! YYPARSE_PARAM */ /*----------. | yyparse. | `----------*/ #ifdef YYPARSE_PARAM # if defined (__STDC__) || defined (__cplusplus) int yyparse (void *YYPARSE_PARAM) # else int yyparse (YYPARSE_PARAM) void *YYPARSE_PARAM; # endif #else /* ! YYPARSE_PARAM */ #if defined (__STDC__) || defined (__cplusplus) int yyparse (void) #else int yyparse () #endif #endif { /* The lookahead symbol. */ int yychar; /* The semantic value of the lookahead symbol. */ YYSTYPE yylval; /* Number of syntax errors so far. */ int yynerrs; register int yystate; register int yyn; int yyresult; /* Number of tokens to shift before error messages enabled. */ int yyerrstatus; /* Lookahead token as an internal (translated) token number. */ int yytoken = 0; /* Three stacks and their tools: `yyss': related to states, `yyvs': related to semantic values, `yyls': related to locations. Refer to the stacks thru separate pointers, to allow yyoverflow to reallocate them elsewhere. */ /* The state stack. */ short yyssa[YYINITDEPTH]; short *yyss = yyssa; register short *yyssp; /* The semantic value stack. */ YYSTYPE yyvsa[YYINITDEPTH]; YYSTYPE *yyvs = yyvsa; register YYSTYPE *yyvsp; #define YYPOPSTACK (yyvsp--, yyssp--) YYSIZE_T yystacksize = YYINITDEPTH; /* The variables used to return semantic value and location from the action routines. */ YYSTYPE yyval; /* When reducing, the number of symbols on the RHS of the reduced rule. */ int yylen; YYDPRINTF ((stderr, "Starting parse\n")); yystate = 0; yyerrstatus = 0; yynerrs = 0; yychar = YYEMPTY; /* Cause a token to be read. */ /* Initialize stack pointers. Waste one element of value and location stack so that they stay on the same level as the state stack. The wasted elements are never initialized. */ yyssp = yyss; yyvsp = yyvs; goto yysetstate; /*------------------------------------------------------------. | yynewstate -- Push a new state, which is found in yystate. | `------------------------------------------------------------*/ yynewstate: /* In all cases, when you get here, the value and location stacks have just been pushed. so pushing a state here evens the stacks. */ yyssp++; yysetstate: *yyssp = yystate; if (yyss + yystacksize - 1 <= yyssp) { /* Get the current used size of the three stacks, in elements. */ YYSIZE_T yysize = yyssp - yyss + 1; #ifdef yyoverflow { /* Give user a chance to reallocate the stack. Use copies of these so that the &'s don't force the real ones into memory. */ YYSTYPE *yyvs1 = yyvs; short *yyss1 = yyss; /* Each stack pointer address is followed by the size of the data in use in that stack, in bytes. This used to be a conditional around just the two extra args, but that might be undefined if yyoverflow is a macro. */ yyoverflow ("parser stack overflow", &yyss1, yysize * sizeof (*yyssp), &yyvs1, yysize * sizeof (*yyvsp), &yystacksize); yyss = yyss1; yyvs = yyvs1; } #else /* no yyoverflow */ # ifndef YYSTACK_RELOCATE goto yyoverflowlab; # else /* Extend the stack our own way. */ if (YYMAXDEPTH <= yystacksize) goto yyoverflowlab; yystacksize *= 2; if (YYMAXDEPTH < yystacksize) yystacksize = YYMAXDEPTH; { short *yyss1 = yyss; union yyalloc *yyptr = (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); if (! yyptr) goto yyoverflowlab; YYSTACK_RELOCATE (yyss); YYSTACK_RELOCATE (yyvs); # undef YYSTACK_RELOCATE if (yyss1 != yyssa) YYSTACK_FREE (yyss1); } # endif #endif /* no yyoverflow */ yyssp = yyss + yysize - 1; yyvsp = yyvs + yysize - 1; YYDPRINTF ((stderr, "Stack size increased to %lu\n", (unsigned long int) yystacksize)); if (yyss + yystacksize - 1 <= yyssp) YYABORT; } YYDPRINTF ((stderr, "Entering state %d\n", yystate)); goto yybackup; /*-----------. | yybackup. | `-----------*/ yybackup: /* Do appropriate processing given the current state. */ /* Read a lookahead token if we need one and don't already have one. */ /* yyresume: */ /* First try to decide what to do without reference to lookahead token. */ yyn = yypact[yystate]; if (yyn == YYPACT_NINF) goto yydefault; /* Not known => get a lookahead token if don't already have one. */ /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ if (yychar == YYEMPTY) { YYDPRINTF ((stderr, "Reading a token: ")); yychar = YYLEX; } if (yychar <= YYEOF) { yychar = yytoken = YYEOF; YYDPRINTF ((stderr, "Now at end of input.\n")); } else { yytoken = YYTRANSLATE (yychar); YYDSYMPRINTF ("Next token is", yytoken, &yylval, &yylloc); } /* If the proper action on seeing token YYTOKEN is to reduce or to detect an error, take that action. */ yyn += yytoken; if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) goto yydefault; yyn = yytable[yyn]; if (yyn <= 0) { if (yyn == 0 || yyn == YYTABLE_NINF) goto yyerrlab; yyn = -yyn; goto yyreduce; } if (yyn == YYFINAL) YYACCEPT; /* Shift the lookahead token. */ YYDPRINTF ((stderr, "Shifting token %s, ", yytname[yytoken])); /* Discard the token being shifted unless it is eof. */ if (yychar != YYEOF) yychar = YYEMPTY; *++yyvsp = yylval; /* Count tokens shifted since error; after three, turn off error status. */ if (yyerrstatus) yyerrstatus--; yystate = yyn; goto yynewstate; /*-----------------------------------------------------------. | yydefault -- do the default action for the current state. | `-----------------------------------------------------------*/ yydefault: yyn = yydefact[yystate]; if (yyn == 0) goto yyerrlab; goto yyreduce; /*-----------------------------. | yyreduce -- Do a reduction. | `-----------------------------*/ yyreduce: /* yyn is the number of a rule to reduce with. */ yylen = yyr2[yyn]; /* If YYLEN is nonzero, implement the default value of the action: `$$ = $1'. Otherwise, the following line sets YYVAL to garbage. This behavior is undocumented and Bison users should not rely upon it. Assigning to YYVAL unconditionally makes the parser a bit smaller, and it avoids a GCC warning that YYVAL may be used uninitialized. */ yyval = yyvsp[1-yylen]; YY_REDUCE_PRINT (yyn); switch (yyn) { case 2: #line 105 "Grammar.y" { ;} break; case 3: #line 113 "Grammar.y" { yyval = yyvsp[-1]; ;} break; case 4: #line 122 "Grammar.y" { yyval = yyvsp[-1]; ;} break; case 5: #line 126 "Grammar.y" { yyval = new StringListTok; ;} break; case 6: #line 135 "Grammar.y" { StringListTokPtr metaData = StringListTokPtr::dynamicCast(yyvsp[0]); if(!metaData->v.empty()) { unit->addGlobalMetaData(metaData->v); } ;} break; case 8: #line 144 "Grammar.y" { StringListTokPtr metaData = StringListTokPtr::dynamicCast(yyvsp[-1]); ContainedPtr contained = ContainedPtr::dynamicCast(yyvsp[0]); if(contained && !metaData->v.empty()) { contained->setMetaData(metaData->v); } unit->setSeenDefinition(); ;} break; case 10: #line 155 "Grammar.y" { yyerrok; ;} break; case 12: #line 160 "Grammar.y" { unit->error("`;' missing after definition"); ;} break; case 13: #line 164 "Grammar.y" { ;} break; case 14: #line 172 "Grammar.y" { assert(yyvsp[0] == 0 || ModulePtr::dynamicCast(yyvsp[0])); ;} break; case 15: #line 176 "Grammar.y" { assert(yyvsp[0] == 0 || ClassDeclPtr::dynamicCast(yyvsp[0])); ;} break; case 16: #line 180 "Grammar.y" { assert(yyvsp[0] == 0 || ClassDefPtr::dynamicCast(yyvsp[0])); ;} break; case 17: #line 184 "Grammar.y" { assert(yyvsp[0] == 0 || ClassDeclPtr::dynamicCast(yyvsp[0])); ;} break; case 18: #line 188 "Grammar.y" { assert(yyvsp[0] == 0 || ClassDefPtr::dynamicCast(yyvsp[0])); ;} break; case 19: #line 192 "Grammar.y" { assert(yyvsp[0] == 0); ;} break; case 20: #line 196 "Grammar.y" { assert(yyvsp[0] == 0 || ExceptionPtr::dynamicCast(yyvsp[0])); ;} break; case 21: #line 200 "Grammar.y" { assert(yyvsp[0] == 0); ;} break; case 22: #line 204 "Grammar.y" { assert(yyvsp[0] == 0 || StructPtr::dynamicCast(yyvsp[0])); ;} break; case 23: #line 208 "Grammar.y" { assert(yyvsp[0] == 0 || SequencePtr::dynamicCast(yyvsp[0])); ;} break; case 24: #line 212 "Grammar.y" { assert(yyvsp[0] == 0 || DictionaryPtr::dynamicCast(yyvsp[0])); ;} break; case 25: #line 216 "Grammar.y" { assert(yyvsp[0] == 0 || EnumPtr::dynamicCast(yyvsp[0])); ;} break; case 26: #line 220 "Grammar.y" { assert(yyvsp[0] == 0 || ConstPtr::dynamicCast(yyvsp[0])); ;} break; case 27: #line 229 "Grammar.y" { StringTokPtr ident = StringTokPtr::dynamicCast(yyvsp[0]); ContainerPtr cont = unit->currentContainer(); ModulePtr module = cont->createModule(ident->v); if(module) { cont->checkIntroduced(ident->v, module); unit->pushContainer(module); yyval = module; } else { yyval = 0; } ;} break; case 28: #line 245 "Grammar.y" { if(yyvsp[-3]) { unit->popContainer(); yyval = yyvsp[-3]; } else { yyval = 0; } ;} break; case 29: #line 262 "Grammar.y" { yyval = yyvsp[0]; ;} break; case 30: #line 266 "Grammar.y" { StringTokPtr ident = StringTokPtr::dynamicCast(yyvsp[0]); unit->error("keyword `" + ident->v + "' cannot be used as exception name"); yyval = yyvsp[0]; ;} break; case 31: #line 277 "Grammar.y" { unit->error("exceptions cannot be forward declared"); yyval = 0; ;} break; case 32: #line 287 "Grammar.y" { BoolTokPtr local = BoolTokPtr::dynamicCast(yyvsp[-2]); StringTokPtr ident = StringTokPtr::dynamicCast(yyvsp[-1]); ExceptionPtr base = ExceptionPtr::dynamicCast(yyvsp[0]); ContainerPtr cont = unit->currentContainer(); ExceptionPtr ex = cont->createException(ident->v, base, local->v); if(ex) { cont->checkIntroduced(ident->v, ex); unit->pushContainer(ex); } yyval = ex; ;} break; case 33: #line 301 "Grammar.y" { if(yyvsp[-3]) { unit->popContainer(); } yyval = yyvsp[-3]; ;} break; case 34: #line 314 "Grammar.y" { StringTokPtr scoped = StringTokPtr::dynamicCast(yyvsp[0]); ContainerPtr cont = unit->currentContainer(); ContainedPtr contained = cont->lookupException(scoped->v); cont->checkIntroduced(scoped->v); yyval = contained; ;} break; case 35: #line 322 "Grammar.y" { yyval = 0; ;} break; case 36: #line 331 "Grammar.y" { StringListTokPtr metaData = StringListTokPtr::dynamicCast(yyvsp[-3]); ContainedPtr contained = ContainedPtr::dynamicCast(yyvsp[-2]); if(contained && !metaData->v.empty()) { contained->setMetaData(metaData->v); } ;} break; case 37: #line 340 "Grammar.y" { ;} break; case 38: #line 343 "Grammar.y" { unit->error("`;' missing after definition"); ;} break; case 39: #line 347 "Grammar.y" { ;} break; case 40: #line 355 "Grammar.y" { TypePtr type = TypePtr::dynamicCast(yyvsp[-1]); StringTokPtr ident = StringTokPtr::dynamicCast(yyvsp[0]); TypeStringTokPtr typestring = new TypeStringTok; typestring->v = make_pair(type, ident->v); yyval = typestring; ;} break; case 42: #line 374 "Grammar.y" { yyval = yyvsp[0]; ;} break; case 43: #line 378 "Grammar.y" { StringTokPtr ident = StringTokPtr::dynamicCast(yyvsp[0]); unit->error("keyword `" + ident->v + "' cannot be used as struct name"); yyval = yyvsp[0]; ;} break; case 44: #line 389 "Grammar.y" { unit->error("structs cannot be forward declared"); yyval = 0; ;} break; case 45: #line 399 "Grammar.y" { BoolTokPtr local = BoolTokPtr::dynamicCast(yyvsp[-1]); StringTokPtr ident = StringTokPtr::dynamicCast(yyvsp[0]); ContainerPtr cont = unit->currentContainer(); StructPtr st = cont->createStruct(ident->v, local->v); if(st) { cont->checkIntroduced(ident->v, st); unit->pushContainer(st); } yyval = st; ;} break; case 46: #line 412 "Grammar.y" { if(yyvsp[-3]) { unit->popContainer(); } yyval = yyvsp[-3]; // // Empty structures are not allowed // StructPtr st = StructPtr::dynamicCast(yyval); assert(st); if(st->dataMembers().empty()) { unit->error("struct `" + st->name() + "' must have at least one member"); } ;} break; case 47: #line 435 "Grammar.y" { StringListTokPtr metaData = StringListTokPtr::dynamicCast(yyvsp[-3]); ContainedPtr contained = ContainedPtr::dynamicCast(yyvsp[-2]); if(contained && !metaData->v.empty()) { contained->setMetaData(metaData->v); } ;} break; case 48: #line 444 "Grammar.y" { ;} break; case 49: #line 447 "Grammar.y" { unit->error("`;' missing after definition"); ;} break; case 50: #line 451 "Grammar.y" { ;} break; case 52: #line 465 "Grammar.y" { yyval = yyvsp[0]; ;} break; case 53: #line 469 "Grammar.y" { StringTokPtr ident = StringTokPtr::dynamicCast(yyvsp[0]); unit->error("keyword `" + ident->v + "' cannot be used as class name"); yyval = yyvsp[0]; ;} break; case 54: #line 480 "Grammar.y" { BoolTokPtr local = BoolTokPtr::dynamicCast(yyvsp[-1]); StringTokPtr ident = StringTokPtr::dynamicCast(yyvsp[0]); ContainerPtr cont = unit->currentContainer(); ClassDeclPtr cl = cont->createClassDecl(ident->v, false, local->v); yyval = cl; ;} break; case 55: #line 493 "Grammar.y" { BoolTokPtr local = BoolTokPtr::dynamicCast(yyvsp[-3]); StringTokPtr ident = StringTokPtr::dynamicCast(yyvsp[-2]); ContainerPtr cont = unit->currentContainer(); ClassDefPtr base = ClassDefPtr::dynamicCast(yyvsp[-1]); ClassListTokPtr bases = ClassListTokPtr::dynamicCast(yyvsp[0]); if(base) { bases->v.push_front(base); } ClassDefPtr cl = cont->createClassDef(ident->v, false, bases->v, local->v); if(cl) { cont->checkIntroduced(ident->v, cl); unit->pushContainer(cl); yyval = cl; } else { yyval = 0; } ;} break; case 56: #line 516 "Grammar.y" { if(yyvsp[-3]) { unit->popContainer(); yyval = yyvsp[-3]; } else { yyval = 0; } ;} break; case 57: #line 533 "Grammar.y" { StringTokPtr scoped = StringTokPtr::dynamicCast(yyvsp[0]); ContainerPtr cont = unit->currentContainer(); TypeList types = cont->lookupType(scoped->v); yyval = 0; if(!types.empty()) { ClassDeclPtr cl = ClassDeclPtr::dynamicCast(types.front()); if(!cl) { string msg = "`"; msg += scoped->v; msg += "' is not a class"; unit->error(msg); } else { ClassDefPtr def = cl->definition(); if(!def) { string msg = "`"; msg += scoped->v; msg += "' has been declared but not defined"; unit->error(msg); } else { cont->checkIntroduced(scoped->v); yyval = def; } } } ;} break; case 58: #line 567 "Grammar.y" { yyval = 0; ;} break; case 59: #line 576 "Grammar.y" { yyval = yyvsp[0]; ;} break; case 60: #line 580 "Grammar.y" { yyval = new ClassListTok; ;} break; case 61: #line 589 "Grammar.y" { StringListTokPtr metaData = StringListTokPtr::dynamicCast(yyvsp[-3]); ContainedPtr contained = ContainedPtr::dynamicCast(yyvsp[-2]); if(contained && !metaData->v.empty()) { contained->setMetaData(metaData->v); } ;} break; case 62: #line 598 "Grammar.y" { ;} break; case 63: #line 601 "Grammar.y" { unit->error("`;' missing after definition"); ;} break; case 64: #line 605 "Grammar.y" { ;} break; case 65: #line 613 "Grammar.y" { TypePtr type = TypeStringTokPtr::dynamicCast(yyvsp[0])->v.first; string name = TypeStringTokPtr::dynamicCast(yyvsp[0])->v.second; ClassDefPtr cl = ClassDefPtr::dynamicCast(unit->currentContainer()); DataMemberPtr dm; if(cl) { dm = cl->createDataMember(name, type); } StructPtr st = StructPtr::dynamicCast(unit->currentContainer()); if(st) { dm = st->createDataMember(name, type); } ExceptionPtr ex = ExceptionPtr::dynamicCast(unit->currentContainer()); if(ex) { dm = ex->createDataMember(name, type); } unit->currentContainer()->checkIntroduced(name, dm); yyval = dm; ;} break; case 66: #line 636 "Grammar.y" { TypePtr type = TypePtr::dynamicCast(yyvsp[-1]); string name = StringTokPtr::dynamicCast(yyvsp[0])->v; ClassDefPtr cl = ClassDefPtr::dynamicCast(unit->currentContainer()); if(cl) { yyval = cl->createDataMember(name, type); } StructPtr st = StructPtr::dynamicCast(unit->currentContainer()); if(st) { yyval = st->createDataMember(name, type); } ExceptionPtr ex = ExceptionPtr::dynamicCast(unit->currentContainer()); if(ex) { yyval = ex->createDataMember(name, type); } assert(yyval); unit->error("keyword `" + name + "' cannot be used as data member name"); ;} break; case 67: #line 658 "Grammar.y" { TypePtr type = TypePtr::dynamicCast(yyvsp[0]); ClassDefPtr cl = ClassDefPtr::dynamicCast(unit->currentContainer()); if(cl) { yyval = cl->createDataMember(IceUtil::generateUUID(), type); } StructPtr st = StructPtr::dynamicCast(unit->currentContainer()); if(st) { yyval = st->createDataMember(IceUtil::generateUUID(), type); } ExceptionPtr ex = ExceptionPtr::dynamicCast(unit->currentContainer()); if(ex) { yyval = ex->createDataMember(IceUtil::generateUUID(), type); } assert(yyval); unit->error("missing data member name"); ;} break; case 69: #line 685 "Grammar.y" { yyval = 0; ;} break; case 70: #line 694 "Grammar.y" { TypePtr returnType = TypePtr::dynamicCast(yyvsp[-1]); string name = StringTokPtr::dynamicCast(yyvsp[0])->v; ClassDefPtr cl = ClassDefPtr::dynamicCast(unit->currentContainer()); if(cl) { OperationPtr op = cl->createOperation(name, returnType); if(op) { cl->checkIntroduced(name, op); unit->pushContainer(op); yyval = op; } else { yyval = 0; } } else { yyval = 0; } ;} break; case 71: #line 718 "Grammar.y" { TypePtr returnType = TypePtr::dynamicCast(yyvsp[-1]); string name = StringTokPtr::dynamicCast(yyvsp[0])->v; ClassDefPtr cl = ClassDefPtr::dynamicCast(unit->currentContainer()); if(cl) { OperationPtr op = cl->createOperation(name, returnType, Operation::Nonmutating); if(op) { cl->checkIntroduced(name, op); unit->pushContainer(op); static bool firstWarning = true; string msg = "the keyword 'nonmutating' is deprecated"; if(firstWarning) { msg += ";\n"; msg += "You should use instead 'idempotent' plus:\n"; msg += " - Freeze metadata ([\"freeze:read\"], [\"freeze:write\"]) if you implement your objects with a Freeze evictor\n"; msg += " - [\"nonmutating\"], if you need to maintain compatibility with operations that expect "; msg += "'Nonmutating' as operation-mode. With this metadata, the generated code sends "; msg += "'Nonmutating' instead of 'Idempotent'\n"; msg += " - [\"cpp:const\"], to get a const member function on the generated C++ servant base class"; firstWarning = false; } unit->warning(msg); yyval = op; } else { yyval = 0; } } else { yyval = 0; } ;} break; case 72: #line 759 "Grammar.y" { TypePtr returnType = TypePtr::dynamicCast(yyvsp[-1]); string name = StringTokPtr::dynamicCast(yyvsp[0])->v; ClassDefPtr cl = ClassDefPtr::dynamicCast(unit->currentContainer()); if(cl) { OperationPtr op = cl->createOperation(name, returnType, Operation::Idempotent); if(op) { cl->checkIntroduced(name, op); unit->pushContainer(op); yyval = op; } else { yyval = 0; } } else { yyval = 0; } ;} break; case 73: #line 783 "Grammar.y" { TypePtr returnType = TypePtr::dynamicCast(yyvsp[-1]); string name = StringTokPtr::dynamicCast(yyvsp[0])->v; ClassDefPtr cl = ClassDefPtr::dynamicCast(unit->currentContainer()); if(cl) { OperationPtr op = cl->createOperation(name, returnType); if(op) { unit->pushContainer(op); unit->error("keyword `" + name + "' cannot be used as operation name"); yyval = op; } else { yyval = 0; } } else { yyval = 0; } ;} break; case 74: #line 807 "Grammar.y" { TypePtr returnType = TypePtr::dynamicCast(yyvsp[-1]); string name = StringTokPtr::dynamicCast(yyvsp[0])->v; ClassDefPtr cl = ClassDefPtr::dynamicCast(unit->currentContainer()); if(cl) { OperationPtr op = cl->createOperation(name, returnType, Operation::Nonmutating); if(op) { unit->pushContainer(op); unit->error("keyword `" + name + "' cannot be used as operation name"); yyval = op; } else { yyval = 0; } } else { yyval = 0; } ;} break; case 75: #line 831 "Grammar.y" { TypePtr returnType = TypePtr::dynamicCast(yyvsp[-1]); string name = StringTokPtr::dynamicCast(yyvsp[0])->v; ClassDefPtr cl = ClassDefPtr::dynamicCast(unit->currentContainer()); if(cl) { OperationPtr op = cl->createOperation(name, returnType, Operation::Idempotent); if(op) { unit->pushContainer(op); unit->error("keyword `" + name + "' cannot be used as operation name"); yyval = op; } else { return 0; } } else { yyval = 0; } ;} break; case 76: #line 860 "Grammar.y" { if(yyvsp[-2]) { unit->popContainer(); yyval = yyvsp[-2]; } else { yyval = 0; } ;} break; case 77: #line 872 "Grammar.y" { OperationPtr op = OperationPtr::dynamicCast(yyvsp[-1]); ExceptionListTokPtr el = ExceptionListTokPtr::dynamicCast(yyvsp[0]); assert(el); if(op) { op->setExceptionList(el->v); } ;} break; case 78: #line 882 "Grammar.y" { if(yyvsp[-2]) { unit->popContainer(); } yyerrok; ;} break; case 79: #line 890 "Grammar.y" { OperationPtr op = OperationPtr::dynamicCast(yyvsp[-1]); ExceptionListTokPtr el = ExceptionListTokPtr::dynamicCast(yyvsp[0]); assert(el); if(op) { op->setExceptionList(el->v); } ;} break; case 82: #line 912 "Grammar.y" { yyval = yyvsp[0]; ;} break; case 83: #line 916 "Grammar.y" { StringTokPtr ident = StringTokPtr::dynamicCast(yyvsp[0]); unit->error("keyword `" + ident->v + "' cannot be used as interface name"); yyval = yyvsp[0]; ;} break; case 84: #line 927 "Grammar.y" { BoolTokPtr local = BoolTokPtr::dynamicCast(yyvsp[-1]); StringTokPtr ident = StringTokPtr::dynamicCast(yyvsp[0]); ContainerPtr cont = unit->currentContainer(); ClassDeclPtr cl = cont->createClassDecl(ident->v, true, local->v); cont->checkIntroduced(ident->v, cl); yyval = cl; ;} break; case 85: #line 941 "Grammar.y" { BoolTokPtr local = BoolTokPtr::dynamicCast(yyvsp[-2]); StringTokPtr ident = StringTokPtr::dynamicCast(yyvsp[-1]); ContainerPtr cont = unit->currentContainer(); ClassListTokPtr bases = ClassListTokPtr::dynamicCast(yyvsp[0]); ClassDefPtr cl = cont->createClassDef(ident->v, true, bases->v, local->v); if(cl) { cont->checkIntroduced(ident->v, cl); unit->pushContainer(cl); yyval = cl; } else { yyval = 0; } ;} break; case 86: #line 959 "Grammar.y" { if(yyvsp[-3]) { unit->popContainer(); yyval = yyvsp[-3]; } else { yyval = 0; } ;} break; case 87: #line 976 "Grammar.y" { ClassListTokPtr intfs = ClassListTokPtr::dynamicCast(yyvsp[0]); StringTokPtr scoped = StringTokPtr::dynamicCast(yyvsp[-2]); ContainerPtr cont = unit->currentContainer(); TypeList types = cont->lookupType(scoped->v); if(!types.empty()) { ClassDeclPtr cl = ClassDeclPtr::dynamicCast(types.front()); if(!cl || !cl->isInterface()) { string msg = "`"; msg += scoped->v; msg += "' is not an interface"; unit->error(msg); } else { ClassDefPtr def = cl->definition(); if(!def) { string msg = "`"; msg += scoped->v; msg += "' has been declared but not defined"; unit->error(msg); } else { cont->checkIntroduced(scoped->v); intfs->v.push_front(def); } } } yyval = intfs; ;} break; case 88: #line 1011 "Grammar.y" { ClassListTokPtr intfs = new ClassListTok; StringTokPtr scoped = StringTokPtr::dynamicCast(yyvsp[0]); ContainerPtr cont = unit->currentContainer(); TypeList types = cont->lookupType(scoped->v); if(!types.empty()) { ClassDeclPtr cl = ClassDeclPtr::dynamicCast(types.front()); if(!cl || !cl->isInterface()) { string msg = "`"; msg += scoped->v; msg += "' is not an interface"; unit->error(msg); } else { ClassDefPtr def = cl->definition(); if(!def) { string msg = "`"; msg += scoped->v; msg += "' has been declared but not defined"; unit->error(msg); } else { cont->checkIntroduced(scoped->v); intfs->v.push_front(def); } } } yyval = intfs; ;} break; case 89: #line 1046 "Grammar.y" { unit->error("illegal inheritance from type Object"); yyval = new ClassListTok; ;} break; case 90: #line 1056 "Grammar.y" { yyval = yyvsp[0]; ;} break; case 91: #line 1060 "Grammar.y" { yyval = new ClassListTok; ;} break; case 92: #line 1069 "Grammar.y" { StringListTokPtr metaData = StringListTokPtr::dynamicCast(yyvsp[-3]); ContainedPtr contained = ContainedPtr::dynamicCast(yyvsp[-2]); if(contained && !metaData->v.empty()) { contained->setMetaData(metaData->v); } ;} break; case 93: #line 1078 "Grammar.y" { ;} break; case 94: #line 1081 "Grammar.y" { unit->error("`;' missing after definition"); ;} break; case 95: #line 1085 "Grammar.y" { ;} break; case 97: #line 1099 "Grammar.y" { ExceptionPtr exception = ExceptionPtr::dynamicCast(yyvsp[-2]); ExceptionListTokPtr exceptionList = ExceptionListTokPtr::dynamicCast(yyvsp[0]); exceptionList->v.push_front(exception); yyval = exceptionList; ;} break; case 98: #line 1106 "Grammar.y" { ExceptionPtr exception = ExceptionPtr::dynamicCast(yyvsp[0]); ExceptionListTokPtr exceptionList = new ExceptionListTok; exceptionList->v.push_front(exception); yyval = exceptionList; ;} break; case 99: #line 1118 "Grammar.y" { StringTokPtr scoped = StringTokPtr::dynamicCast(yyvsp[0]); ContainerPtr cont = unit->currentContainer(); ExceptionPtr exception = cont->lookupException(scoped->v); if(!exception) { exception = cont->createException(IceUtil::generateUUID(), 0, false); } cont->checkIntroduced(scoped->v, exception); yyval = exception; ;} break; case 100: #line 1130 "Grammar.y" { StringTokPtr ident = StringTokPtr::dynamicCast(yyvsp[0]); unit->error("keyword `" + ident->v + "' cannot be used as exception name"); yyval = unit->currentContainer()->createException(IceUtil::generateUUID(), 0, false); ;} break; case 101: #line 1141 "Grammar.y" { BoolTokPtr local = BoolTokPtr::dynamicCast(yyvsp[-6]); StringTokPtr ident = StringTokPtr::dynamicCast(yyvsp[0]); StringListTokPtr metaData = StringListTokPtr::dynamicCast(yyvsp[-3]); TypePtr type = TypePtr::dynamicCast(yyvsp[-2]); ContainerPtr cont = unit->currentContainer(); yyval = cont->createSequence(ident->v, type, metaData->v, local->v); ;} break; case 102: #line 1150 "Grammar.y" { BoolTokPtr local = BoolTokPtr::dynamicCast(yyvsp[-6]); StringTokPtr ident = StringTokPtr::dynamicCast(yyvsp[0]); StringListTokPtr metaData = StringListTokPtr::dynamicCast(yyvsp[-3]); TypePtr type = TypePtr::dynamicCast(yyvsp[-2]); ContainerPtr cont = unit->currentContainer(); yyval = cont->createSequence(ident->v, type, metaData->v, local->v); unit->error("keyword `" + ident->v + "' cannot be used as sequence name"); ;} break; case 103: #line 1165 "Grammar.y" { BoolTokPtr local = BoolTokPtr::dynamicCast(yyvsp[-9]); StringTokPtr ident = StringTokPtr::dynamicCast(yyvsp[0]); StringListTokPtr keyMetaData = StringListTokPtr::dynamicCast(yyvsp[-6]); TypePtr keyType = TypePtr::dynamicCast(yyvsp[-5]); StringListTokPtr valueMetaData = StringListTokPtr::dynamicCast(yyvsp[-3]); TypePtr valueType = TypePtr::dynamicCast(yyvsp[-2]); ContainerPtr cont = unit->currentContainer(); yyval = cont->createDictionary(ident->v, keyType, keyMetaData->v, valueType, valueMetaData->v, local->v); ;} break; case 104: #line 1176 "Grammar.y" { BoolTokPtr local = BoolTokPtr::dynamicCast(yyvsp[-9]); StringTokPtr ident = StringTokPtr::dynamicCast(yyvsp[0]); StringListTokPtr keyMetaData = StringListTokPtr::dynamicCast(yyvsp[-6]); TypePtr keyType = TypePtr::dynamicCast(yyvsp[-5]); StringListTokPtr valueMetaData = StringListTokPtr::dynamicCast(yyvsp[-3]); TypePtr valueType = TypePtr::dynamicCast(yyvsp[-2]); ContainerPtr cont = unit->currentContainer(); yyval = cont->createDictionary(ident->v, keyType, keyMetaData->v, valueType, valueMetaData->v, local->v); unit->error("keyword `" + ident->v + "' cannot be used as dictionary name"); ;} break; case 105: #line 1193 "Grammar.y" { yyval = yyvsp[0]; ;} break; case 106: #line 1197 "Grammar.y" { StringTokPtr ident = StringTokPtr::dynamicCast(yyvsp[0]); unit->error("keyword `" + ident->v + "' cannot be used as enumeration name"); yyval = yyvsp[0]; ;} break; case 107: #line 1208 "Grammar.y" { BoolTokPtr local = BoolTokPtr::dynamicCast(yyvsp[-1]); StringTokPtr ident = StringTokPtr::dynamicCast(yyvsp[0]); ContainerPtr cont = unit->currentContainer(); EnumPtr en = cont->createEnum(ident->v, local->v); cont->checkIntroduced(ident->v, en); yyval = en; ;} break; case 108: #line 1217 "Grammar.y" { EnumPtr en = EnumPtr::dynamicCast(yyvsp[-3]); if(en) { EnumeratorListTokPtr enumerators = EnumeratorListTokPtr::dynamicCast(yyvsp[-1]); if(enumerators->v.empty()) { unit->error("enum `" + en->name() + "' must have at least one enumerator"); } en->setEnumerators(enumerators->v); } yyval = yyvsp[-3]; ;} break; case 109: #line 1236 "Grammar.y" { EnumeratorListTokPtr ens = EnumeratorListTokPtr::dynamicCast(yyvsp[-2]); ens->v.splice(ens->v.end(), EnumeratorListTokPtr::dynamicCast(yyvsp[0])->v); yyval = ens; ;} break; case 110: #line 1242 "Grammar.y" { ;} break; case 111: #line 1250 "Grammar.y" { StringTokPtr ident = StringTokPtr::dynamicCast(yyvsp[0]); EnumeratorListTokPtr ens = new EnumeratorListTok; ContainerPtr cont = unit->currentContainer(); EnumeratorPtr en = cont->createEnumerator(ident->v); if(en) { ens->v.push_front(en); } yyval = ens; ;} break; case 112: #line 1262 "Grammar.y" { StringTokPtr ident = StringTokPtr::dynamicCast(yyvsp[0]); unit->error("keyword `" + ident->v + "' cannot be used as enumerator"); EnumeratorListTokPtr ens = new EnumeratorListTok; yyval = ens; ;} break; case 113: #line 1269 "Grammar.y" { EnumeratorListTokPtr ens = new EnumeratorListTok; yyval = ens; ;} break; case 114: #line 1279 "Grammar.y" { BoolTokPtr out = new BoolTok; out->v = true; yyval = out; ;} break; case 115: #line 1285 "Grammar.y" { BoolTokPtr out = new BoolTok; out->v = false; yyval = out; ;} break; case 116: #line 1296 "Grammar.y" { ;} break; case 117: #line 1299 "Grammar.y" { BoolTokPtr isOutParam = BoolTokPtr::dynamicCast(yyvsp[-2]); TypeStringTokPtr tsp = TypeStringTokPtr::dynamicCast(yyvsp[0]); TypePtr type = tsp->v.first; string ident = tsp->v.second; OperationPtr op = OperationPtr::dynamicCast(unit->currentContainer()); if(op) { ParamDeclPtr pd = op->createParamDecl(ident, type, isOutParam->v); unit->currentContainer()->checkIntroduced(ident, pd); StringListTokPtr metaData = StringListTokPtr::dynamicCast(yyvsp[-1]); if(!metaData->v.empty()) { pd->setMetaData(metaData->v); } } ;} break; case 118: #line 1317 "Grammar.y" { BoolTokPtr isOutParam = BoolTokPtr::dynamicCast(yyvsp[-2]); TypeStringTokPtr tsp = TypeStringTokPtr::dynamicCast(yyvsp[0]); TypePtr type = tsp->v.first; string ident = tsp->v.second; OperationPtr op = OperationPtr::dynamicCast(unit->currentContainer()); if(op) { ParamDeclPtr pd = op->createParamDecl(ident, type, isOutParam->v); unit->currentContainer()->checkIntroduced(ident, pd); StringListTokPtr metaData = StringListTokPtr::dynamicCast(yyvsp[-1]); if(!metaData->v.empty()) { pd->setMetaData(metaData->v); } } ;} break; case 119: #line 1335 "Grammar.y" { BoolTokPtr isOutParam = BoolTokPtr::dynamicCast(yyvsp[-3]); TypePtr type = TypePtr::dynamicCast(yyvsp[-1]); StringTokPtr ident = StringTokPtr::dynamicCast(yyvsp[0]); OperationPtr op = OperationPtr::dynamicCast(unit->currentContainer()); if(op) { op->createParamDecl(ident->v, type, isOutParam->v); unit->error("keyword `" + ident->v + "' cannot be used as parameter name"); } ;} break; case 120: #line 1347 "Grammar.y" { BoolTokPtr isOutParam = BoolTokPtr::dynamicCast(yyvsp[-3]); TypePtr type = TypePtr::dynamicCast(yyvsp[-1]); StringTokPtr ident = StringTokPtr::dynamicCast(yyvsp[0]); OperationPtr op = OperationPtr::dynamicCast(unit->currentContainer()); if(op) { op->createParamDecl(ident->v, type, isOutParam->v); unit->error("keyword `" + ident->v + "' cannot be used as parameter name"); } ;} break; case 121: #line 1359 "Grammar.y" { BoolTokPtr isOutParam = BoolTokPtr::dynamicCast(yyvsp[-2]); TypePtr type = TypePtr::dynamicCast(yyvsp[0]); OperationPtr op = OperationPtr::dynamicCast(unit->currentContainer()); if(op) { op->createParamDecl(IceUtil::generateUUID(), type, isOutParam->v); unit->error("missing parameter name"); } ;} break; case 122: #line 1370 "Grammar.y" { BoolTokPtr isOutParam = BoolTokPtr::dynamicCast(yyvsp[-2]); TypePtr type = TypePtr::dynamicCast(yyvsp[0]); OperationPtr op = OperationPtr::dynamicCast(unit->currentContainer()); if(op) { op->createParamDecl(IceUtil::generateUUID(), type, isOutParam->v); unit->error("missing parameter name"); } ;} break; case 123: #line 1386 "Grammar.y" { yyval = yyvsp[0]; ;} break; case 124: #line 1390 "Grammar.y" { yyval = new ExceptionListTok; ;} break; case 125: #line 1399 "Grammar.y" { ;} break; case 126: #line 1402 "Grammar.y" { StringTokPtr ident = StringTokPtr::dynamicCast(yyvsp[0]); ident->v = "::" + ident->v; yyval = ident; ;} break; case 127: #line 1408 "Grammar.y" { StringTokPtr scoped = StringTokPtr::dynamicCast(yyvsp[-2]); StringTokPtr ident = StringTokPtr::dynamicCast(yyvsp[0]); scoped->v += "::"; scoped->v += ident->v; yyval = scoped; ;} break; case 128: #line 1421 "Grammar.y" { yyval = unit->builtin(Builtin::KindByte); ;} break; case 129: #line 1425 "Grammar.y" { yyval = unit->builtin(Builtin::KindBool); ;} break; case 130: #line 1429 "Grammar.y" { yyval = unit->builtin(Builtin::KindShort); ;} break; case 131: #line 1433 "Grammar.y" { yyval = unit->builtin(Builtin::KindInt); ;} break; case 132: #line 1437 "Grammar.y" { yyval = unit->builtin(Builtin::KindLong); ;} break; case 133: #line 1441 "Grammar.y" { yyval = unit->builtin(Builtin::KindFloat); ;} break; case 134: #line 1445 "Grammar.y" { yyval = unit->builtin(Builtin::KindDouble); ;} break; case 135: #line 1449 "Grammar.y" { yyval = unit->builtin(Builtin::KindString); ;} break; case 136: #line 1453 "Grammar.y" { yyval = unit->builtin(Builtin::KindObject); ;} break; case 137: #line 1457 "Grammar.y" { yyval = unit->builtin(Builtin::KindObjectProxy); ;} break; case 138: #line 1461 "Grammar.y" { yyval = unit->builtin(Builtin::KindLocalObject); ;} break; case 139: #line 1465 "Grammar.y" { StringTokPtr scoped = StringTokPtr::dynamicCast(yyvsp[0]); ContainerPtr cont = unit->currentContainer(); if(cont) { TypeList types = cont->lookupType(scoped->v); if(types.empty()) { YYERROR; // Can't continue, jump to next yyerrok } cont->checkIntroduced(scoped->v); yyval = types.front(); } else { yyval = 0; } ;} break; case 140: #line 1484 "Grammar.y" { StringTokPtr scoped = StringTokPtr::dynamicCast(yyvsp[-1]); ContainerPtr cont = unit->currentContainer(); if(cont) { TypeList types = cont->lookupType(scoped->v); if(types.empty()) { YYERROR; // Can't continue, jump to next yyerrok } for(TypeList::iterator p = types.begin(); p != types.end(); ++p) { ClassDeclPtr cl = ClassDeclPtr::dynamicCast(*p); if(!cl) { string msg = "`"; msg += scoped->v; msg += "' must be class or interface"; unit->error(msg); YYERROR; // Can't continue, jump to next yyerrok } cont->checkIntroduced(scoped->v); if(cl->isLocal()) { unit->error("cannot create proxy for " + cl->kindOf() + " `" + cl->name() + "'"); } *p = new Proxy(cl); } yyval = types.front(); } else { yyval = 0; } ;} break; case 141: #line 1525 "Grammar.y" { StringTokPtr str1 = StringTokPtr::dynamicCast(yyvsp[-1]); StringTokPtr str2 = StringTokPtr::dynamicCast(yyvsp[0]); str1->v += str2->v; ;} break; case 142: #line 1531 "Grammar.y" { ;} break; case 143: #line 1539 "Grammar.y" { StringTokPtr str = StringTokPtr::dynamicCast(yyvsp[0]); StringListTokPtr stringList = StringListTokPtr::dynamicCast(yyvsp[-2]); stringList->v.push_back(str->v); yyval = stringList; ;} break; case 144: #line 1546 "Grammar.y" { StringTokPtr str = StringTokPtr::dynamicCast(yyvsp[0]); StringListTokPtr stringList = new StringListTok; stringList->v.push_back(str->v); yyval = stringList; ;} break; case 145: #line 1558 "Grammar.y" { BoolTokPtr local = new BoolTok; local->v = true; yyval = local; ;} break; case 146: #line 1564 "Grammar.y" { BoolTokPtr local = new BoolTok; local->v = false; yyval = local; ;} break; case 147: #line 1575 "Grammar.y" { BuiltinPtr type = unit->builtin(Builtin::KindLong); IntegerTokPtr intVal = IntegerTokPtr::dynamicCast(yyvsp[0]); ostringstream sstr; sstr << intVal->v; SyntaxTreeBaseStringTokPtr basestring = new SyntaxTreeBaseStringTok; basestring->v = pair(type, sstr.str()); yyval = basestring; ;} break; case 148: #line 1585 "Grammar.y" { BuiltinPtr type = unit->builtin(Builtin::KindDouble); FloatingTokPtr floatVal = FloatingTokPtr::dynamicCast(yyvsp[0]); ostringstream sstr; sstr << floatVal->v; SyntaxTreeBaseStringTokPtr basestring = new SyntaxTreeBaseStringTok; basestring->v = pair(type, sstr.str()); yyval = basestring; ;} break; case 149: #line 1595 "Grammar.y" { StringTokPtr scoped = StringTokPtr::dynamicCast(yyvsp[0]); SyntaxTreeBaseStringTokPtr basestring = new SyntaxTreeBaseStringTok; ContainedList cl = unit->currentContainer()->lookupContained(scoped->v); if(cl.empty()) { basestring->v = pair(TypePtr(0), scoped->v); } else { EnumeratorPtr enumerator = EnumeratorPtr::dynamicCast(cl.front()); if(!enumerator) { string msg = "illegal initializer: `" + scoped->v + "' is a"; static const string vowels = "aeiou"; string kindOf = cl.front()->kindOf(); if(vowels.find_first_of(kindOf[0]) != string::npos) { msg += "n"; } msg += " " + kindOf; unit->error(msg); } unit->currentContainer()->checkIntroduced(scoped->v, enumerator); basestring->v = pair(enumerator, scoped->v); } yyval = basestring; ;} break; case 150: #line 1624 "Grammar.y" { BuiltinPtr type = unit->builtin(Builtin::KindString); StringTokPtr literal = StringTokPtr::dynamicCast(yyvsp[0]); SyntaxTreeBaseStringTokPtr basestring = new SyntaxTreeBaseStringTok; basestring->v = pair(type, literal->v); yyval = basestring; ;} break; case 151: #line 1632 "Grammar.y" { BuiltinPtr type = unit->builtin(Builtin::KindBool); StringTokPtr literal = StringTokPtr::dynamicCast(yyvsp[0]); SyntaxTreeBaseStringTokPtr basestring = new SyntaxTreeBaseStringTok; basestring->v = pair(type, literal->v); yyval = basestring; ;} break; case 152: #line 1640 "Grammar.y" { BuiltinPtr type = unit->builtin(Builtin::KindBool); StringTokPtr literal = StringTokPtr::dynamicCast(yyvsp[0]); SyntaxTreeBaseStringTokPtr basestring = new SyntaxTreeBaseStringTok; basestring->v = pair(type, literal->v); yyval = basestring; ;} break; case 153: #line 1653 "Grammar.y" { StringListTokPtr metaData = StringListTokPtr::dynamicCast(yyvsp[-4]); TypePtr const_type = TypePtr::dynamicCast(yyvsp[-3]); StringTokPtr ident = StringTokPtr::dynamicCast(yyvsp[-2]); SyntaxTreeBaseStringTokPtr value = SyntaxTreeBaseStringTokPtr::dynamicCast(yyvsp[0]); yyval = unit->currentContainer()->createConst(ident->v, const_type, metaData->v, value->v.first, value->v.second); ;} break; case 154: #line 1661 "Grammar.y" { StringListTokPtr metaData = StringListTokPtr::dynamicCast(yyvsp[-3]); TypePtr const_type = TypePtr::dynamicCast(yyvsp[-2]); SyntaxTreeBaseStringTokPtr value = SyntaxTreeBaseStringTokPtr::dynamicCast(yyvsp[0]); unit->error("missing constant name"); yyval = unit->currentContainer()->createConst(IceUtil::generateUUID(), const_type, metaData->v, value->v.first, value->v.second); ;} break; case 155: #line 1675 "Grammar.y" { ;} break; case 156: #line 1678 "Grammar.y" { ;} break; case 157: #line 1681 "Grammar.y" { ;} break; case 158: #line 1684 "Grammar.y" { ;} break; case 159: #line 1687 "Grammar.y" { ;} break; case 160: #line 1690 "Grammar.y" { ;} break; case 161: #line 1693 "Grammar.y" { ;} break; case 162: #line 1696 "Grammar.y" { ;} break; case 163: #line 1699 "Grammar.y" { ;} break; case 164: #line 1702 "Grammar.y" { ;} break; case 165: #line 1705 "Grammar.y" { ;} break; case 166: #line 1708 "Grammar.y" { ;} break; case 167: #line 1711 "Grammar.y" { ;} break; case 168: #line 1714 "Grammar.y" { ;} break; case 169: #line 1717 "Grammar.y" { ;} break; case 170: #line 1720 "Grammar.y" { ;} break; case 171: #line 1723 "Grammar.y" { ;} break; case 172: #line 1726 "Grammar.y" { ;} break; case 173: #line 1729 "Grammar.y" { ;} break; case 174: #line 1732 "Grammar.y" { ;} break; case 175: #line 1735 "Grammar.y" { ;} break; case 176: #line 1738 "Grammar.y" { ;} break; case 177: #line 1741 "Grammar.y" { ;} break; case 178: #line 1744 "Grammar.y" { ;} break; case 179: #line 1747 "Grammar.y" { ;} break; case 180: #line 1750 "Grammar.y" { ;} break; case 181: #line 1753 "Grammar.y" { ;} break; case 182: #line 1756 "Grammar.y" { ;} break; case 183: #line 1759 "Grammar.y" { ;} break; } /* Line 1000 of yacc.c. */ #line 3393 "Grammar.tab.c" yyvsp -= yylen; yyssp -= yylen; YY_STACK_PRINT (yyss, yyssp); *++yyvsp = yyval; /* Now `shift' the result of the reduction. Determine what state that goes to, based on the state we popped back to and the rule number reduced by. */ yyn = yyr1[yyn]; yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) yystate = yytable[yystate]; else yystate = yydefgoto[yyn - YYNTOKENS]; goto yynewstate; /*------------------------------------. | yyerrlab -- here on detecting error | `------------------------------------*/ yyerrlab: /* If not already recovering from an error, report this error. */ if (!yyerrstatus) { ++yynerrs; #if YYERROR_VERBOSE yyn = yypact[yystate]; if (YYPACT_NINF < yyn && yyn < YYLAST) { YYSIZE_T yysize = 0; int yytype = YYTRANSLATE (yychar); const char* yyprefix; char *yymsg; int yyx; /* Start YYX at -YYN if negative to avoid negative indexes in YYCHECK. */ int yyxbegin = yyn < 0 ? -yyn : 0; /* Stay within bounds of both yycheck and yytname. */ int yychecklim = YYLAST - yyn; int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; int yycount = 0; yyprefix = ", expecting "; for (yyx = yyxbegin; yyx < yyxend; ++yyx) if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) { yysize += yystrlen (yyprefix) + yystrlen (yytname [yyx]); yycount += 1; if (yycount == 5) { yysize = 0; break; } } yysize += (sizeof ("syntax error, unexpected ") + yystrlen (yytname[yytype])); yymsg = (char *) YYSTACK_ALLOC (yysize); if (yymsg != 0) { char *yyp = yystpcpy (yymsg, "syntax error, unexpected "); yyp = yystpcpy (yyp, yytname[yytype]); if (yycount < 5) { yyprefix = ", expecting "; for (yyx = yyxbegin; yyx < yyxend; ++yyx) if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) { yyp = yystpcpy (yyp, yyprefix); yyp = yystpcpy (yyp, yytname[yyx]); yyprefix = " or "; } } yyerror (yymsg); YYSTACK_FREE (yymsg); } else yyerror ("syntax error; also virtual memory exhausted"); } else #endif /* YYERROR_VERBOSE */ yyerror ("syntax error"); } if (yyerrstatus == 3) { /* If just tried and failed to reuse lookahead token after an error, discard it. */ if (yychar <= YYEOF) { /* If at end of input, pop the error token, then the rest of the stack, then return failure. */ if (yychar == YYEOF) for (;;) { YYPOPSTACK; if (yyssp == yyss) YYABORT; YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp); yydestruct (yystos[*yyssp], yyvsp); } } else { YYDSYMPRINTF ("Error: discarding", yytoken, &yylval, &yylloc); yydestruct (yytoken, &yylval); yychar = YYEMPTY; } } /* Else will try to reuse lookahead token after shifting the error token. */ goto yyerrlab1; /*---------------------------------------------------. | yyerrorlab -- error raised explicitly by YYERROR. | `---------------------------------------------------*/ yyerrorlab: #ifdef __GNUC__ /* Pacify GCC when the user code never invokes YYERROR and the label yyerrorlab therefore never appears in user code. */ if (0) goto yyerrorlab; #endif yyvsp -= yylen; yyssp -= yylen; yystate = *yyssp; goto yyerrlab1; /*-------------------------------------------------------------. | yyerrlab1 -- common code for both syntax error and YYERROR. | `-------------------------------------------------------------*/ yyerrlab1: yyerrstatus = 3; /* Each real token shifted decrements this. */ for (;;) { yyn = yypact[yystate]; if (yyn != YYPACT_NINF) { yyn += YYTERROR; if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) { yyn = yytable[yyn]; if (0 < yyn) break; } } /* Pop the current state because it cannot handle the error token. */ if (yyssp == yyss) YYABORT; YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp); yydestruct (yystos[yystate], yyvsp); YYPOPSTACK; yystate = *yyssp; YY_STACK_PRINT (yyss, yyssp); } if (yyn == YYFINAL) YYACCEPT; YYDPRINTF ((stderr, "Shifting error token, ")); *++yyvsp = yylval; yystate = yyn; goto yynewstate; /*-------------------------------------. | yyacceptlab -- YYACCEPT comes here. | `-------------------------------------*/ yyacceptlab: yyresult = 0; goto yyreturn; /*-----------------------------------. | yyabortlab -- YYABORT comes here. | `-----------------------------------*/ yyabortlab: yyresult = 1; goto yyreturn; #ifndef yyoverflow /*----------------------------------------------. | yyoverflowlab -- parser overflow comes here. | `----------------------------------------------*/ yyoverflowlab: yyerror ("parser stack overflow"); yyresult = 2; /* Fall through. */ #endif yyreturn: #ifndef yyoverflow if (yyss != yyssa) YYSTACK_FREE (yyss); #endif return yyresult; } #line 1763 "Grammar.y" IceE-trans-1.2.0/src/Slice/Grammar.y0000664000076400007640000012422110550516551016431 0ustar dwaynedwayne%{ // ********************************************************************** // // Copyright (c) 2003-2007 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 #ifdef _MSC_VER // I get these warnings from some bison versions: // warning C4102: 'yyoverflowlab' : unreferenced label # pragma warning( disable : 4102 ) // warning C4065: switch statement contains 'default' but no 'case' labels # pragma warning( disable : 4065 ) #endif using namespace std; using namespace Slice; void slice_error(const char* s) { // yacc and recent versions of Bison use "syntax error" instead // of "parse error". if (strcmp(s, "parse error") == 0) { unit->error("syntax error"); } else { unit->error(s); } } %} %pure_parser // // All keyword tokens. Make sure to modify the "keyword" rule in this // file if the list of keywords is changed. Also make sure to add the // keyword to the keyword table in Scanner.l. // %token ICE_MODULE %token ICE_CLASS %token ICE_INTERFACE %token ICE_EXCEPTION %token ICE_STRUCT %token ICE_SEQUENCE %token ICE_DICTIONARY %token ICE_ENUM %token ICE_OUT %token ICE_EXTENDS %token ICE_IMPLEMENTS %token ICE_THROWS %token ICE_VOID %token ICE_BYTE %token ICE_BOOL %token ICE_SHORT %token ICE_INT %token ICE_LONG %token ICE_FLOAT %token ICE_DOUBLE %token ICE_STRING %token ICE_OBJECT %token ICE_LOCAL_OBJECT %token ICE_LOCAL %token ICE_CONST %token ICE_FALSE %token ICE_TRUE %token ICE_NONMUTATING %token ICE_IDEMPOTENT // // Other tokens. // %token ICE_SCOPE_DELIMITER %token ICE_IDENTIFIER %token ICE_STRING_LITERAL %token ICE_INTEGER_LITERAL %token ICE_FLOATING_POINT_LITERAL %token ICE_IDENT_OP %token ICE_KEYWORD_OP %token ICE_METADATA_OPEN %token ICE_METADATA_CLOSE %token ICE_GLOBAL_METADATA_OPEN %token ICE_GLOBAL_METADATA_CLOSE %token BAD_CHAR %% // ---------------------------------------------------------------------- start // ---------------------------------------------------------------------- : definitions { } ; // ---------------------------------------------------------------------- global_meta_data // ---------------------------------------------------------------------- : ICE_GLOBAL_METADATA_OPEN string_list ICE_GLOBAL_METADATA_CLOSE { $$ = $2; } ; // ---------------------------------------------------------------------- meta_data // ---------------------------------------------------------------------- : ICE_METADATA_OPEN string_list ICE_METADATA_CLOSE { $$ = $2; } | { $$ = new StringListTok; } ; // ---------------------------------------------------------------------- definitions // ---------------------------------------------------------------------- : global_meta_data { StringListTokPtr metaData = StringListTokPtr::dynamicCast($1); if(!metaData->v.empty()) { unit->addGlobalMetaData(metaData->v); } } definitions | meta_data definition { StringListTokPtr metaData = StringListTokPtr::dynamicCast($1); ContainedPtr contained = ContainedPtr::dynamicCast($2); if(contained && !metaData->v.empty()) { contained->setMetaData(metaData->v); } unit->setSeenDefinition(); } ';' definitions | error ';' { yyerrok; } definitions | meta_data definition { unit->error("`;' missing after definition"); } | { } ; // ---------------------------------------------------------------------- definition // ---------------------------------------------------------------------- : module_def { assert($1 == 0 || ModulePtr::dynamicCast($1)); } | class_decl { assert($1 == 0 || ClassDeclPtr::dynamicCast($1)); } | class_def { assert($1 == 0 || ClassDefPtr::dynamicCast($1)); } | interface_decl { assert($1 == 0 || ClassDeclPtr::dynamicCast($1)); } | interface_def { assert($1 == 0 || ClassDefPtr::dynamicCast($1)); } | exception_decl { assert($1 == 0); } | exception_def { assert($1 == 0 || ExceptionPtr::dynamicCast($1)); } | struct_decl { assert($1 == 0); } | struct_def { assert($1 == 0 || StructPtr::dynamicCast($1)); } | sequence_def { assert($1 == 0 || SequencePtr::dynamicCast($1)); } | dictionary_def { assert($1 == 0 || DictionaryPtr::dynamicCast($1)); } | enum_def { assert($1 == 0 || EnumPtr::dynamicCast($1)); } | const_def { assert($1 == 0 || ConstPtr::dynamicCast($1)); } ; // ---------------------------------------------------------------------- module_def // ---------------------------------------------------------------------- : ICE_MODULE ICE_IDENTIFIER { StringTokPtr ident = StringTokPtr::dynamicCast($2); ContainerPtr cont = unit->currentContainer(); ModulePtr module = cont->createModule(ident->v); if(module) { cont->checkIntroduced(ident->v, module); unit->pushContainer(module); $$ = module; } else { $$ = 0; } } '{' definitions '}' { if($3) { unit->popContainer(); $$ = $3; } else { $$ = 0; } } ; // ---------------------------------------------------------------------- exception_id // ---------------------------------------------------------------------- : ICE_EXCEPTION ICE_IDENTIFIER { $$ = $2; } | ICE_EXCEPTION keyword { StringTokPtr ident = StringTokPtr::dynamicCast($2); unit->error("keyword `" + ident->v + "' cannot be used as exception name"); $$ = $2; } ; // ---------------------------------------------------------------------- exception_decl // ---------------------------------------------------------------------- : local_qualifier exception_id { unit->error("exceptions cannot be forward declared"); $$ = 0; } ; // ---------------------------------------------------------------------- exception_def // ---------------------------------------------------------------------- : local_qualifier exception_id exception_extends { BoolTokPtr local = BoolTokPtr::dynamicCast($1); StringTokPtr ident = StringTokPtr::dynamicCast($2); ExceptionPtr base = ExceptionPtr::dynamicCast($3); ContainerPtr cont = unit->currentContainer(); ExceptionPtr ex = cont->createException(ident->v, base, local->v); if(ex) { cont->checkIntroduced(ident->v, ex); unit->pushContainer(ex); } $$ = ex; } '{' exception_exports '}' { if($4) { unit->popContainer(); } $$ = $4; } ; // ---------------------------------------------------------------------- exception_extends // ---------------------------------------------------------------------- : ICE_EXTENDS scoped_name { StringTokPtr scoped = StringTokPtr::dynamicCast($2); ContainerPtr cont = unit->currentContainer(); ContainedPtr contained = cont->lookupException(scoped->v); cont->checkIntroduced(scoped->v); $$ = contained; } | { $$ = 0; } ; // ---------------------------------------------------------------------- exception_exports // ---------------------------------------------------------------------- : meta_data exception_export ';' exception_exports { StringListTokPtr metaData = StringListTokPtr::dynamicCast($1); ContainedPtr contained = ContainedPtr::dynamicCast($2); if(contained && !metaData->v.empty()) { contained->setMetaData(metaData->v); } } | error ';' exception_exports { } | meta_data exception_export { unit->error("`;' missing after definition"); } | { } ; // ---------------------------------------------------------------------- type_id // ---------------------------------------------------------------------- : type ICE_IDENTIFIER { TypePtr type = TypePtr::dynamicCast($1); StringTokPtr ident = StringTokPtr::dynamicCast($2); TypeStringTokPtr typestring = new TypeStringTok; typestring->v = make_pair(type, ident->v); $$ = typestring; } ; // ---------------------------------------------------------------------- exception_export // ---------------------------------------------------------------------- : data_member ; // ---------------------------------------------------------------------- struct_id // ---------------------------------------------------------------------- : ICE_STRUCT ICE_IDENTIFIER { $$ = $2; } | ICE_STRUCT keyword { StringTokPtr ident = StringTokPtr::dynamicCast($2); unit->error("keyword `" + ident->v + "' cannot be used as struct name"); $$ = $2; } ; // ---------------------------------------------------------------------- struct_decl // ---------------------------------------------------------------------- : local_qualifier struct_id { unit->error("structs cannot be forward declared"); $$ = 0; } ; // ---------------------------------------------------------------------- struct_def // ---------------------------------------------------------------------- : local_qualifier struct_id { BoolTokPtr local = BoolTokPtr::dynamicCast($1); StringTokPtr ident = StringTokPtr::dynamicCast($2); ContainerPtr cont = unit->currentContainer(); StructPtr st = cont->createStruct(ident->v, local->v); if(st) { cont->checkIntroduced(ident->v, st); unit->pushContainer(st); } $$ = st; } '{' struct_exports '}' { if($3) { unit->popContainer(); } $$ = $3; // // Empty structures are not allowed // StructPtr st = StructPtr::dynamicCast($$); assert(st); if(st->dataMembers().empty()) { unit->error("struct `" + st->name() + "' must have at least one member"); } } ; // ---------------------------------------------------------------------- struct_exports // ---------------------------------------------------------------------- : meta_data struct_export ';' struct_exports { StringListTokPtr metaData = StringListTokPtr::dynamicCast($1); ContainedPtr contained = ContainedPtr::dynamicCast($2); if(contained && !metaData->v.empty()) { contained->setMetaData(metaData->v); } } | error ';' struct_exports { } | meta_data struct_export { unit->error("`;' missing after definition"); } | { } ; // ---------------------------------------------------------------------- struct_export // ---------------------------------------------------------------------- : data_member ; // ---------------------------------------------------------------------- class_id // ---------------------------------------------------------------------- : ICE_CLASS ICE_IDENTIFIER { $$ = $2; } | ICE_CLASS keyword { StringTokPtr ident = StringTokPtr::dynamicCast($2); unit->error("keyword `" + ident->v + "' cannot be used as class name"); $$ = $2; } ; // ---------------------------------------------------------------------- class_decl // ---------------------------------------------------------------------- : local_qualifier class_id { BoolTokPtr local = BoolTokPtr::dynamicCast($1); StringTokPtr ident = StringTokPtr::dynamicCast($2); ContainerPtr cont = unit->currentContainer(); ClassDeclPtr cl = cont->createClassDecl(ident->v, false, local->v); $$ = cl; } ; // ---------------------------------------------------------------------- class_def // ---------------------------------------------------------------------- : local_qualifier class_id class_extends implements { BoolTokPtr local = BoolTokPtr::dynamicCast($1); StringTokPtr ident = StringTokPtr::dynamicCast($2); ContainerPtr cont = unit->currentContainer(); ClassDefPtr base = ClassDefPtr::dynamicCast($3); ClassListTokPtr bases = ClassListTokPtr::dynamicCast($4); if(base) { bases->v.push_front(base); } ClassDefPtr cl = cont->createClassDef(ident->v, false, bases->v, local->v); if(cl) { cont->checkIntroduced(ident->v, cl); unit->pushContainer(cl); $$ = cl; } else { $$ = 0; } } '{' class_exports '}' { if($5) { unit->popContainer(); $$ = $5; } else { $$ = 0; } } ; // ---------------------------------------------------------------------- class_extends // ---------------------------------------------------------------------- : ICE_EXTENDS scoped_name { StringTokPtr scoped = StringTokPtr::dynamicCast($2); ContainerPtr cont = unit->currentContainer(); TypeList types = cont->lookupType(scoped->v); $$ = 0; if(!types.empty()) { ClassDeclPtr cl = ClassDeclPtr::dynamicCast(types.front()); if(!cl) { string msg = "`"; msg += scoped->v; msg += "' is not a class"; unit->error(msg); } else { ClassDefPtr def = cl->definition(); if(!def) { string msg = "`"; msg += scoped->v; msg += "' has been declared but not defined"; unit->error(msg); } else { cont->checkIntroduced(scoped->v); $$ = def; } } } } | { $$ = 0; } ; // ---------------------------------------------------------------------- implements // ---------------------------------------------------------------------- : ICE_IMPLEMENTS interface_list { $$ = $2; } | { $$ = new ClassListTok; } ; // ---------------------------------------------------------------------- class_exports // ---------------------------------------------------------------------- : meta_data class_export ';' class_exports { StringListTokPtr metaData = StringListTokPtr::dynamicCast($1); ContainedPtr contained = ContainedPtr::dynamicCast($2); if(contained && !metaData->v.empty()) { contained->setMetaData(metaData->v); } } | error ';' class_exports { } | meta_data class_export { unit->error("`;' missing after definition"); } | { } ; // ---------------------------------------------------------------------- data_member // ---------------------------------------------------------------------- : type_id { TypePtr type = TypeStringTokPtr::dynamicCast($1)->v.first; string name = TypeStringTokPtr::dynamicCast($1)->v.second; ClassDefPtr cl = ClassDefPtr::dynamicCast(unit->currentContainer()); DataMemberPtr dm; if(cl) { dm = cl->createDataMember(name, type); } StructPtr st = StructPtr::dynamicCast(unit->currentContainer()); if(st) { dm = st->createDataMember(name, type); } ExceptionPtr ex = ExceptionPtr::dynamicCast(unit->currentContainer()); if(ex) { dm = ex->createDataMember(name, type); } unit->currentContainer()->checkIntroduced(name, dm); $$ = dm; } | type keyword { TypePtr type = TypePtr::dynamicCast($1); string name = StringTokPtr::dynamicCast($2)->v; ClassDefPtr cl = ClassDefPtr::dynamicCast(unit->currentContainer()); if(cl) { $$ = cl->createDataMember(name, type); } StructPtr st = StructPtr::dynamicCast(unit->currentContainer()); if(st) { $$ = st->createDataMember(name, type); } ExceptionPtr ex = ExceptionPtr::dynamicCast(unit->currentContainer()); if(ex) { $$ = ex->createDataMember(name, type); } assert($$); unit->error("keyword `" + name + "' cannot be used as data member name"); } | type { TypePtr type = TypePtr::dynamicCast($1); ClassDefPtr cl = ClassDefPtr::dynamicCast(unit->currentContainer()); if(cl) { $$ = cl->createDataMember(IceUtil::generateUUID(), type); } StructPtr st = StructPtr::dynamicCast(unit->currentContainer()); if(st) { $$ = st->createDataMember(IceUtil::generateUUID(), type); } ExceptionPtr ex = ExceptionPtr::dynamicCast(unit->currentContainer()); if(ex) { $$ = ex->createDataMember(IceUtil::generateUUID(), type); } assert($$); unit->error("missing data member name"); } ; // ---------------------------------------------------------------------- return_type // ---------------------------------------------------------------------- : type | ICE_VOID { $$ = 0; } ; // ---------------------------------------------------------------------- operation_preamble // ---------------------------------------------------------------------- : return_type ICE_IDENT_OP { TypePtr returnType = TypePtr::dynamicCast($1); string name = StringTokPtr::dynamicCast($2)->v; ClassDefPtr cl = ClassDefPtr::dynamicCast(unit->currentContainer()); if(cl) { OperationPtr op = cl->createOperation(name, returnType); if(op) { cl->checkIntroduced(name, op); unit->pushContainer(op); $$ = op; } else { $$ = 0; } } else { $$ = 0; } } | ICE_NONMUTATING return_type ICE_IDENT_OP { TypePtr returnType = TypePtr::dynamicCast($2); string name = StringTokPtr::dynamicCast($3)->v; ClassDefPtr cl = ClassDefPtr::dynamicCast(unit->currentContainer()); if(cl) { OperationPtr op = cl->createOperation(name, returnType, Operation::Nonmutating); if(op) { cl->checkIntroduced(name, op); unit->pushContainer(op); static bool firstWarning = true; string msg = "the keyword 'nonmutating' is deprecated"; if(firstWarning) { msg += ";\n"; msg += "You should use instead 'idempotent' plus:\n"; msg += " - Freeze metadata ([\"freeze:read\"], [\"freeze:write\"]) if you implement your objects with a Freeze evictor\n"; msg += " - [\"nonmutating\"], if you need to maintain compatibility with operations that expect "; msg += "'Nonmutating' as operation-mode. With this metadata, the generated code sends "; msg += "'Nonmutating' instead of 'Idempotent'\n"; msg += " - [\"cpp:const\"], to get a const member function on the generated C++ servant base class"; firstWarning = false; } unit->warning(msg); $$ = op; } else { $$ = 0; } } else { $$ = 0; } } | ICE_IDEMPOTENT return_type ICE_IDENT_OP { TypePtr returnType = TypePtr::dynamicCast($2); string name = StringTokPtr::dynamicCast($3)->v; ClassDefPtr cl = ClassDefPtr::dynamicCast(unit->currentContainer()); if(cl) { OperationPtr op = cl->createOperation(name, returnType, Operation::Idempotent); if(op) { cl->checkIntroduced(name, op); unit->pushContainer(op); $$ = op; } else { $$ = 0; } } else { $$ = 0; } } | return_type ICE_KEYWORD_OP { TypePtr returnType = TypePtr::dynamicCast($1); string name = StringTokPtr::dynamicCast($2)->v; ClassDefPtr cl = ClassDefPtr::dynamicCast(unit->currentContainer()); if(cl) { OperationPtr op = cl->createOperation(name, returnType); if(op) { unit->pushContainer(op); unit->error("keyword `" + name + "' cannot be used as operation name"); $$ = op; } else { $$ = 0; } } else { $$ = 0; } } | ICE_NONMUTATING return_type ICE_KEYWORD_OP { TypePtr returnType = TypePtr::dynamicCast($2); string name = StringTokPtr::dynamicCast($3)->v; ClassDefPtr cl = ClassDefPtr::dynamicCast(unit->currentContainer()); if(cl) { OperationPtr op = cl->createOperation(name, returnType, Operation::Nonmutating); if(op) { unit->pushContainer(op); unit->error("keyword `" + name + "' cannot be used as operation name"); $$ = op; } else { $$ = 0; } } else { $$ = 0; } } | ICE_IDEMPOTENT return_type ICE_KEYWORD_OP { TypePtr returnType = TypePtr::dynamicCast($2); string name = StringTokPtr::dynamicCast($3)->v; ClassDefPtr cl = ClassDefPtr::dynamicCast(unit->currentContainer()); if(cl) { OperationPtr op = cl->createOperation(name, returnType, Operation::Idempotent); if(op) { unit->pushContainer(op); unit->error("keyword `" + name + "' cannot be used as operation name"); $$ = op; } else { return 0; } } else { $$ = 0; } } ; // ---------------------------------------------------------------------- operation // ---------------------------------------------------------------------- : operation_preamble parameters ')' { if($1) { unit->popContainer(); $$ = $1; } else { $$ = 0; } } throws { OperationPtr op = OperationPtr::dynamicCast($4); ExceptionListTokPtr el = ExceptionListTokPtr::dynamicCast($5); assert(el); if(op) { op->setExceptionList(el->v); } } | operation_preamble error ')' { if($1) { unit->popContainer(); } yyerrok; } throws { OperationPtr op = OperationPtr::dynamicCast($4); ExceptionListTokPtr el = ExceptionListTokPtr::dynamicCast($5); assert(el); if(op) { op->setExceptionList(el->v); } } ; // ---------------------------------------------------------------------- class_export // ---------------------------------------------------------------------- : data_member | operation ; // ---------------------------------------------------------------------- interface_id // ---------------------------------------------------------------------- : ICE_INTERFACE ICE_IDENTIFIER { $$ = $2; } | ICE_INTERFACE keyword { StringTokPtr ident = StringTokPtr::dynamicCast($2); unit->error("keyword `" + ident->v + "' cannot be used as interface name"); $$ = $2; } ; // ---------------------------------------------------------------------- interface_decl // ---------------------------------------------------------------------- : local_qualifier interface_id { BoolTokPtr local = BoolTokPtr::dynamicCast($1); StringTokPtr ident = StringTokPtr::dynamicCast($2); ContainerPtr cont = unit->currentContainer(); ClassDeclPtr cl = cont->createClassDecl(ident->v, true, local->v); cont->checkIntroduced(ident->v, cl); $$ = cl; } ; // ---------------------------------------------------------------------- interface_def // ---------------------------------------------------------------------- : local_qualifier interface_id interface_extends { BoolTokPtr local = BoolTokPtr::dynamicCast($1); StringTokPtr ident = StringTokPtr::dynamicCast($2); ContainerPtr cont = unit->currentContainer(); ClassListTokPtr bases = ClassListTokPtr::dynamicCast($3); ClassDefPtr cl = cont->createClassDef(ident->v, true, bases->v, local->v); if(cl) { cont->checkIntroduced(ident->v, cl); unit->pushContainer(cl); $$ = cl; } else { $$ = 0; } } '{' interface_exports '}' { if($4) { unit->popContainer(); $$ = $4; } else { $$ = 0; } } ; // ---------------------------------------------------------------------- interface_list // ---------------------------------------------------------------------- : scoped_name ',' interface_list { ClassListTokPtr intfs = ClassListTokPtr::dynamicCast($3); StringTokPtr scoped = StringTokPtr::dynamicCast($1); ContainerPtr cont = unit->currentContainer(); TypeList types = cont->lookupType(scoped->v); if(!types.empty()) { ClassDeclPtr cl = ClassDeclPtr::dynamicCast(types.front()); if(!cl || !cl->isInterface()) { string msg = "`"; msg += scoped->v; msg += "' is not an interface"; unit->error(msg); } else { ClassDefPtr def = cl->definition(); if(!def) { string msg = "`"; msg += scoped->v; msg += "' has been declared but not defined"; unit->error(msg); } else { cont->checkIntroduced(scoped->v); intfs->v.push_front(def); } } } $$ = intfs; } | scoped_name { ClassListTokPtr intfs = new ClassListTok; StringTokPtr scoped = StringTokPtr::dynamicCast($1); ContainerPtr cont = unit->currentContainer(); TypeList types = cont->lookupType(scoped->v); if(!types.empty()) { ClassDeclPtr cl = ClassDeclPtr::dynamicCast(types.front()); if(!cl || !cl->isInterface()) { string msg = "`"; msg += scoped->v; msg += "' is not an interface"; unit->error(msg); } else { ClassDefPtr def = cl->definition(); if(!def) { string msg = "`"; msg += scoped->v; msg += "' has been declared but not defined"; unit->error(msg); } else { cont->checkIntroduced(scoped->v); intfs->v.push_front(def); } } } $$ = intfs; } | ICE_OBJECT { unit->error("illegal inheritance from type Object"); $$ = new ClassListTok; } ; // ---------------------------------------------------------------------- interface_extends // ---------------------------------------------------------------------- : ICE_EXTENDS interface_list { $$ = $2; } | { $$ = new ClassListTok; } ; // ---------------------------------------------------------------------- interface_exports // ---------------------------------------------------------------------- : meta_data interface_export ';' interface_exports { StringListTokPtr metaData = StringListTokPtr::dynamicCast($1); ContainedPtr contained = ContainedPtr::dynamicCast($2); if(contained && !metaData->v.empty()) { contained->setMetaData(metaData->v); } } | error ';' interface_exports { } | meta_data interface_export { unit->error("`;' missing after definition"); } | { } ; // ---------------------------------------------------------------------- interface_export // ---------------------------------------------------------------------- : operation ; // ---------------------------------------------------------------------- exception_list // ---------------------------------------------------------------------- : exception ',' exception_list { ExceptionPtr exception = ExceptionPtr::dynamicCast($1); ExceptionListTokPtr exceptionList = ExceptionListTokPtr::dynamicCast($3); exceptionList->v.push_front(exception); $$ = exceptionList; } | exception { ExceptionPtr exception = ExceptionPtr::dynamicCast($1); ExceptionListTokPtr exceptionList = new ExceptionListTok; exceptionList->v.push_front(exception); $$ = exceptionList; } ; // ---------------------------------------------------------------------- exception // ---------------------------------------------------------------------- : scoped_name { StringTokPtr scoped = StringTokPtr::dynamicCast($1); ContainerPtr cont = unit->currentContainer(); ExceptionPtr exception = cont->lookupException(scoped->v); if(!exception) { exception = cont->createException(IceUtil::generateUUID(), 0, false); } cont->checkIntroduced(scoped->v, exception); $$ = exception; } | keyword { StringTokPtr ident = StringTokPtr::dynamicCast($1); unit->error("keyword `" + ident->v + "' cannot be used as exception name"); $$ = unit->currentContainer()->createException(IceUtil::generateUUID(), 0, false); } ; // ---------------------------------------------------------------------- sequence_def // ---------------------------------------------------------------------- : local_qualifier ICE_SEQUENCE '<' meta_data type '>' ICE_IDENTIFIER { BoolTokPtr local = BoolTokPtr::dynamicCast($1); StringTokPtr ident = StringTokPtr::dynamicCast($7); StringListTokPtr metaData = StringListTokPtr::dynamicCast($4); TypePtr type = TypePtr::dynamicCast($5); ContainerPtr cont = unit->currentContainer(); $$ = cont->createSequence(ident->v, type, metaData->v, local->v); } | local_qualifier ICE_SEQUENCE '<' meta_data type '>' keyword { BoolTokPtr local = BoolTokPtr::dynamicCast($1); StringTokPtr ident = StringTokPtr::dynamicCast($7); StringListTokPtr metaData = StringListTokPtr::dynamicCast($4); TypePtr type = TypePtr::dynamicCast($5); ContainerPtr cont = unit->currentContainer(); $$ = cont->createSequence(ident->v, type, metaData->v, local->v); unit->error("keyword `" + ident->v + "' cannot be used as sequence name"); } ; // ---------------------------------------------------------------------- dictionary_def // ---------------------------------------------------------------------- : local_qualifier ICE_DICTIONARY '<' meta_data type ',' meta_data type '>' ICE_IDENTIFIER { BoolTokPtr local = BoolTokPtr::dynamicCast($1); StringTokPtr ident = StringTokPtr::dynamicCast($10); StringListTokPtr keyMetaData = StringListTokPtr::dynamicCast($4); TypePtr keyType = TypePtr::dynamicCast($5); StringListTokPtr valueMetaData = StringListTokPtr::dynamicCast($7); TypePtr valueType = TypePtr::dynamicCast($8); ContainerPtr cont = unit->currentContainer(); $$ = cont->createDictionary(ident->v, keyType, keyMetaData->v, valueType, valueMetaData->v, local->v); } | local_qualifier ICE_DICTIONARY '<' meta_data type ',' meta_data type '>' keyword { BoolTokPtr local = BoolTokPtr::dynamicCast($1); StringTokPtr ident = StringTokPtr::dynamicCast($10); StringListTokPtr keyMetaData = StringListTokPtr::dynamicCast($4); TypePtr keyType = TypePtr::dynamicCast($5); StringListTokPtr valueMetaData = StringListTokPtr::dynamicCast($7); TypePtr valueType = TypePtr::dynamicCast($8); ContainerPtr cont = unit->currentContainer(); $$ = cont->createDictionary(ident->v, keyType, keyMetaData->v, valueType, valueMetaData->v, local->v); unit->error("keyword `" + ident->v + "' cannot be used as dictionary name"); } ; // ---------------------------------------------------------------------- enum_id // ---------------------------------------------------------------------- : ICE_ENUM ICE_IDENTIFIER { $$ = $2; } | ICE_ENUM keyword { StringTokPtr ident = StringTokPtr::dynamicCast($2); unit->error("keyword `" + ident->v + "' cannot be used as enumeration name"); $$ = $2; } ; // ---------------------------------------------------------------------- enum_def // ---------------------------------------------------------------------- : local_qualifier enum_id { BoolTokPtr local = BoolTokPtr::dynamicCast($1); StringTokPtr ident = StringTokPtr::dynamicCast($2); ContainerPtr cont = unit->currentContainer(); EnumPtr en = cont->createEnum(ident->v, local->v); cont->checkIntroduced(ident->v, en); $$ = en; } '{' enumerator_list '}' { EnumPtr en = EnumPtr::dynamicCast($3); if(en) { EnumeratorListTokPtr enumerators = EnumeratorListTokPtr::dynamicCast($5); if(enumerators->v.empty()) { unit->error("enum `" + en->name() + "' must have at least one enumerator"); } en->setEnumerators(enumerators->v); } $$ = $3; } ; // ---------------------------------------------------------------------- enumerator_list // ---------------------------------------------------------------------- : enumerator ',' enumerator_list { EnumeratorListTokPtr ens = EnumeratorListTokPtr::dynamicCast($1); ens->v.splice(ens->v.end(), EnumeratorListTokPtr::dynamicCast($3)->v); $$ = ens; } | enumerator { } ; // ---------------------------------------------------------------------- enumerator // ---------------------------------------------------------------------- : ICE_IDENTIFIER { StringTokPtr ident = StringTokPtr::dynamicCast($1); EnumeratorListTokPtr ens = new EnumeratorListTok; ContainerPtr cont = unit->currentContainer(); EnumeratorPtr en = cont->createEnumerator(ident->v); if(en) { ens->v.push_front(en); } $$ = ens; } | keyword { StringTokPtr ident = StringTokPtr::dynamicCast($1); unit->error("keyword `" + ident->v + "' cannot be used as enumerator"); EnumeratorListTokPtr ens = new EnumeratorListTok; $$ = ens; } | { EnumeratorListTokPtr ens = new EnumeratorListTok; $$ = ens; } ; // ---------------------------------------------------------------------- out_qualifier // ---------------------------------------------------------------------- : ICE_OUT { BoolTokPtr out = new BoolTok; out->v = true; $$ = out; } | { BoolTokPtr out = new BoolTok; out->v = false; $$ = out; } ; // ---------------------------------------------------------------------- parameters // ---------------------------------------------------------------------- : // empty { } | out_qualifier meta_data type_id { BoolTokPtr isOutParam = BoolTokPtr::dynamicCast($1); TypeStringTokPtr tsp = TypeStringTokPtr::dynamicCast($3); TypePtr type = tsp->v.first; string ident = tsp->v.second; OperationPtr op = OperationPtr::dynamicCast(unit->currentContainer()); if(op) { ParamDeclPtr pd = op->createParamDecl(ident, type, isOutParam->v); unit->currentContainer()->checkIntroduced(ident, pd); StringListTokPtr metaData = StringListTokPtr::dynamicCast($2); if(!metaData->v.empty()) { pd->setMetaData(metaData->v); } } } | parameters ',' out_qualifier meta_data type_id { BoolTokPtr isOutParam = BoolTokPtr::dynamicCast($3); TypeStringTokPtr tsp = TypeStringTokPtr::dynamicCast($5); TypePtr type = tsp->v.first; string ident = tsp->v.second; OperationPtr op = OperationPtr::dynamicCast(unit->currentContainer()); if(op) { ParamDeclPtr pd = op->createParamDecl(ident, type, isOutParam->v); unit->currentContainer()->checkIntroduced(ident, pd); StringListTokPtr metaData = StringListTokPtr::dynamicCast($4); if(!metaData->v.empty()) { pd->setMetaData(metaData->v); } } } | out_qualifier meta_data type keyword { BoolTokPtr isOutParam = BoolTokPtr::dynamicCast($1); TypePtr type = TypePtr::dynamicCast($3); StringTokPtr ident = StringTokPtr::dynamicCast($4); OperationPtr op = OperationPtr::dynamicCast(unit->currentContainer()); if(op) { op->createParamDecl(ident->v, type, isOutParam->v); unit->error("keyword `" + ident->v + "' cannot be used as parameter name"); } } | parameters ',' out_qualifier meta_data type keyword { BoolTokPtr isOutParam = BoolTokPtr::dynamicCast($3); TypePtr type = TypePtr::dynamicCast($5); StringTokPtr ident = StringTokPtr::dynamicCast($6); OperationPtr op = OperationPtr::dynamicCast(unit->currentContainer()); if(op) { op->createParamDecl(ident->v, type, isOutParam->v); unit->error("keyword `" + ident->v + "' cannot be used as parameter name"); } } | out_qualifier meta_data type { BoolTokPtr isOutParam = BoolTokPtr::dynamicCast($1); TypePtr type = TypePtr::dynamicCast($3); OperationPtr op = OperationPtr::dynamicCast(unit->currentContainer()); if(op) { op->createParamDecl(IceUtil::generateUUID(), type, isOutParam->v); unit->error("missing parameter name"); } } | parameters ',' out_qualifier meta_data type { BoolTokPtr isOutParam = BoolTokPtr::dynamicCast($3); TypePtr type = TypePtr::dynamicCast($5); OperationPtr op = OperationPtr::dynamicCast(unit->currentContainer()); if(op) { op->createParamDecl(IceUtil::generateUUID(), type, isOutParam->v); unit->error("missing parameter name"); } } ; // ---------------------------------------------------------------------- throws // ---------------------------------------------------------------------- : ICE_THROWS exception_list { $$ = $2; } | { $$ = new ExceptionListTok; } ; // ---------------------------------------------------------------------- scoped_name // ---------------------------------------------------------------------- : ICE_IDENTIFIER { } | ICE_SCOPE_DELIMITER ICE_IDENTIFIER { StringTokPtr ident = StringTokPtr::dynamicCast($2); ident->v = "::" + ident->v; $$ = ident; } | scoped_name ICE_SCOPE_DELIMITER ICE_IDENTIFIER { StringTokPtr scoped = StringTokPtr::dynamicCast($1); StringTokPtr ident = StringTokPtr::dynamicCast($3); scoped->v += "::"; scoped->v += ident->v; $$ = scoped; } ; // ---------------------------------------------------------------------- type // ---------------------------------------------------------------------- : ICE_BYTE { $$ = unit->builtin(Builtin::KindByte); } | ICE_BOOL { $$ = unit->builtin(Builtin::KindBool); } | ICE_SHORT { $$ = unit->builtin(Builtin::KindShort); } | ICE_INT { $$ = unit->builtin(Builtin::KindInt); } | ICE_LONG { $$ = unit->builtin(Builtin::KindLong); } | ICE_FLOAT { $$ = unit->builtin(Builtin::KindFloat); } | ICE_DOUBLE { $$ = unit->builtin(Builtin::KindDouble); } | ICE_STRING { $$ = unit->builtin(Builtin::KindString); } | ICE_OBJECT { $$ = unit->builtin(Builtin::KindObject); } | ICE_OBJECT '*' { $$ = unit->builtin(Builtin::KindObjectProxy); } | ICE_LOCAL_OBJECT { $$ = unit->builtin(Builtin::KindLocalObject); } | scoped_name { StringTokPtr scoped = StringTokPtr::dynamicCast($1); ContainerPtr cont = unit->currentContainer(); if(cont) { TypeList types = cont->lookupType(scoped->v); if(types.empty()) { YYERROR; // Can't continue, jump to next yyerrok } cont->checkIntroduced(scoped->v); $$ = types.front(); } else { $$ = 0; } } | scoped_name '*' { StringTokPtr scoped = StringTokPtr::dynamicCast($1); ContainerPtr cont = unit->currentContainer(); if(cont) { TypeList types = cont->lookupType(scoped->v); if(types.empty()) { YYERROR; // Can't continue, jump to next yyerrok } for(TypeList::iterator p = types.begin(); p != types.end(); ++p) { ClassDeclPtr cl = ClassDeclPtr::dynamicCast(*p); if(!cl) { string msg = "`"; msg += scoped->v; msg += "' must be class or interface"; unit->error(msg); YYERROR; // Can't continue, jump to next yyerrok } cont->checkIntroduced(scoped->v); if(cl->isLocal()) { unit->error("cannot create proxy for " + cl->kindOf() + " `" + cl->name() + "'"); } *p = new Proxy(cl); } $$ = types.front(); } else { $$ = 0; } } ; // ---------------------------------------------------------------------- string_literal // ---------------------------------------------------------------------- : ICE_STRING_LITERAL string_literal // Adjacent string literals are concatenated { StringTokPtr str1 = StringTokPtr::dynamicCast($1); StringTokPtr str2 = StringTokPtr::dynamicCast($2); str1->v += str2->v; } | ICE_STRING_LITERAL { } ; // ---------------------------------------------------------------------- string_list // ---------------------------------------------------------------------- : string_list ',' string_literal { StringTokPtr str = StringTokPtr::dynamicCast($3); StringListTokPtr stringList = StringListTokPtr::dynamicCast($1); stringList->v.push_back(str->v); $$ = stringList; } | string_literal { StringTokPtr str = StringTokPtr::dynamicCast($1); StringListTokPtr stringList = new StringListTok; stringList->v.push_back(str->v); $$ = stringList; } ; // ---------------------------------------------------------------------- local_qualifier // ---------------------------------------------------------------------- : ICE_LOCAL { BoolTokPtr local = new BoolTok; local->v = true; $$ = local; } | { BoolTokPtr local = new BoolTok; local->v = false; $$ = local; } ; // ---------------------------------------------------------------------- const_initializer // ---------------------------------------------------------------------- : ICE_INTEGER_LITERAL { BuiltinPtr type = unit->builtin(Builtin::KindLong); IntegerTokPtr intVal = IntegerTokPtr::dynamicCast($1); ostringstream sstr; sstr << intVal->v; SyntaxTreeBaseStringTokPtr basestring = new SyntaxTreeBaseStringTok; basestring->v = pair(type, sstr.str()); $$ = basestring; } | ICE_FLOATING_POINT_LITERAL { BuiltinPtr type = unit->builtin(Builtin::KindDouble); FloatingTokPtr floatVal = FloatingTokPtr::dynamicCast($1); ostringstream sstr; sstr << floatVal->v; SyntaxTreeBaseStringTokPtr basestring = new SyntaxTreeBaseStringTok; basestring->v = pair(type, sstr.str()); $$ = basestring; } | scoped_name { StringTokPtr scoped = StringTokPtr::dynamicCast($1); SyntaxTreeBaseStringTokPtr basestring = new SyntaxTreeBaseStringTok; ContainedList cl = unit->currentContainer()->lookupContained(scoped->v); if(cl.empty()) { basestring->v = pair(TypePtr(0), scoped->v); } else { EnumeratorPtr enumerator = EnumeratorPtr::dynamicCast(cl.front()); if(!enumerator) { string msg = "illegal initializer: `" + scoped->v + "' is a"; static const string vowels = "aeiou"; string kindOf = cl.front()->kindOf(); if(vowels.find_first_of(kindOf[0]) != string::npos) { msg += "n"; } msg += " " + kindOf; unit->error(msg); } unit->currentContainer()->checkIntroduced(scoped->v, enumerator); basestring->v = pair(enumerator, scoped->v); } $$ = basestring; } | ICE_STRING_LITERAL { BuiltinPtr type = unit->builtin(Builtin::KindString); StringTokPtr literal = StringTokPtr::dynamicCast($1); SyntaxTreeBaseStringTokPtr basestring = new SyntaxTreeBaseStringTok; basestring->v = pair(type, literal->v); $$ = basestring; } | ICE_FALSE { BuiltinPtr type = unit->builtin(Builtin::KindBool); StringTokPtr literal = StringTokPtr::dynamicCast($1); SyntaxTreeBaseStringTokPtr basestring = new SyntaxTreeBaseStringTok; basestring->v = pair(type, literal->v); $$ = basestring; } | ICE_TRUE { BuiltinPtr type = unit->builtin(Builtin::KindBool); StringTokPtr literal = StringTokPtr::dynamicCast($1); SyntaxTreeBaseStringTokPtr basestring = new SyntaxTreeBaseStringTok; basestring->v = pair(type, literal->v); $$ = basestring; } ; // ---------------------------------------------------------------------- const_def // ---------------------------------------------------------------------- : ICE_CONST meta_data type ICE_IDENTIFIER '=' const_initializer { StringListTokPtr metaData = StringListTokPtr::dynamicCast($2); TypePtr const_type = TypePtr::dynamicCast($3); StringTokPtr ident = StringTokPtr::dynamicCast($4); SyntaxTreeBaseStringTokPtr value = SyntaxTreeBaseStringTokPtr::dynamicCast($6); $$ = unit->currentContainer()->createConst(ident->v, const_type, metaData->v, value->v.first, value->v.second); } | ICE_CONST meta_data type '=' const_initializer { StringListTokPtr metaData = StringListTokPtr::dynamicCast($2); TypePtr const_type = TypePtr::dynamicCast($3); SyntaxTreeBaseStringTokPtr value = SyntaxTreeBaseStringTokPtr::dynamicCast($5); unit->error("missing constant name"); $$ = unit->currentContainer()->createConst(IceUtil::generateUUID(), const_type, metaData->v, value->v.first, value->v.second); } ; // ---------------------------------------------------------------------- keyword // ---------------------------------------------------------------------- : ICE_MODULE { } | ICE_CLASS { } | ICE_INTERFACE { } | ICE_EXCEPTION { } | ICE_STRUCT { } | ICE_SEQUENCE { } | ICE_DICTIONARY { } | ICE_ENUM { } | ICE_OUT { } | ICE_EXTENDS { } | ICE_IMPLEMENTS { } | ICE_THROWS { } | ICE_VOID { } | ICE_BYTE { } | ICE_BOOL { } | ICE_SHORT { } | ICE_INT { } | ICE_LONG { } | ICE_FLOAT { } | ICE_DOUBLE { } | ICE_STRING { } | ICE_OBJECT { } | ICE_LOCAL_OBJECT { } | ICE_LOCAL { } | ICE_CONST { } | ICE_FALSE { } | ICE_TRUE { } | ICE_NONMUTATING { } | ICE_IDEMPOTENT { } ; %% IceE-trans-1.2.0/src/Slice/JavaUtil.cpp0000664000076400007640000036340010602627307017100 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 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 #ifdef _WIN32 #include #endif #ifndef _WIN32 #include #endif using namespace std; using namespace Slice; using namespace IceUtil; Slice::JavaOutput::JavaOutput() { } Slice::JavaOutput::JavaOutput(ostream& os) : Output(os) { } Slice::JavaOutput::JavaOutput(const char* s) : Output(s) { } bool Slice::JavaOutput::openClass(const string& cls, const string& prefix) { string package; string file; string path = prefix; string::size_type pos = cls.rfind('.'); if(pos != string::npos) { package = cls.substr(0, pos); file = cls.substr(pos + 1); string dir = package; // // Create package directories if necessary. // pos = 0; string::size_type start = 0; do { if(!path.empty()) { path += "/"; } pos = dir.find('.', start); if(pos != string::npos) { path += dir.substr(start, pos - start); start = pos + 1; } else { path += dir.substr(start); } struct stat st; int result; result = stat(path.c_str(), &st); if(result == 0) { continue; } #ifdef _WIN32 result = _mkdir(path.c_str()); #else result = mkdir(path.c_str(), S_IRWXU | S_IRWXG | S_IRWXO); #endif if(result != 0) { return false; } } while(pos != string::npos); } else { file = cls; } file += ".java"; // // Open class file. // if(!path.empty()) { path += "/"; } path += file; open(path.c_str()); if(isOpen()) { printHeader(); if(!package.empty()) { separator(); separator(); print("package "); print(package.c_str()); print(";"); } return true; } return false; } void Slice::JavaOutput::printHeader() { static const char* header = "// **********************************************************************\n" "//\n" "// Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved.\n" "//\n" "// This copy of Ice is licensed to you under the terms described in the\n" "// ICE_LICENSE file included in this distribution.\n" "//\n" "// **********************************************************************\n" ; print(header); print("\n// Ice version "); print(ICE_STRING_VERSION); } const string Slice::JavaGenerator::_getSetMetaData = "java:getset"; const string Slice::JavaGenerator::_java2MetaData = "java:java2"; const string Slice::JavaGenerator::_java5MetaData = "java:java5"; Slice::JavaGenerator::JavaGenerator(const string& dir) : _featureProfile(Slice::Ice), _dir(dir), _out(0) { } Slice::JavaGenerator::JavaGenerator(const string& dir, Slice::FeatureProfile profile) : _featureProfile(profile), _dir(dir), _out(0) { } Slice::JavaGenerator::~JavaGenerator() { assert(_out == 0); } bool Slice::JavaGenerator::open(const string& absolute) { assert(_out == 0); JavaOutput* out = createOutput(); if(out->openClass(absolute, _dir)) { _out = out; } else { delete out; } return _out != 0; } void Slice::JavaGenerator::close() { assert(_out != 0); *_out << nl; delete _out; _out = 0; } Output& Slice::JavaGenerator::output() const { assert(_out != 0); return *_out; } static string lookupKwd(const string& name) { // // Keyword list. *Must* be kept in alphabetical order. Note that checkedCast and uncheckedCast // are not Java keywords, but are in this list to prevent illegal code being generated if // someone defines Slice operations with that name. // // NOTE: Any changes made to this list must also be made in BasicStream.java. // static const string keywordList[] = { "abstract", "assert", "boolean", "break", "byte", "case", "catch", "char", "checkedCast", "class", "clone", "const", "continue", "default", "do", "double", "else", "enum", "equals", "extends", "false", "final", "finalize", "finally", "float", "for", "getClass", "goto", "hashCode", "if", "implements", "import", "instanceof", "int", "interface", "long", "native", "new", "notify", "notifyAll", "null", "package", "private", "protected", "public", "return", "short", "static", "strictfp", "super", "switch", "synchronized", "this", "throw", "throws", "toString", "transient", "true", "try", "uncheckedCast", "void", "volatile", "wait", "while" }; bool found = binary_search(&keywordList[0], &keywordList[sizeof(keywordList) / sizeof(*keywordList)], name); return found ? "_" + name : name; } // // Split a scoped name into its components and return the components as a list of (unscoped) identifiers. // static StringList splitScopedName(const string& scoped) { assert(scoped[0] == ':'); StringList ids; string::size_type next = 0; string::size_type pos; while((pos = scoped.find("::", next)) != string::npos) { pos += 2; if(pos != scoped.size()) { string::size_type endpos = scoped.find("::", pos); if(endpos != string::npos) { ids.push_back(scoped.substr(pos, endpos - pos)); } } next = pos; } if(next != scoped.size()) { ids.push_back(scoped.substr(next)); } else { ids.push_back(""); } return ids; } // // If the passed name is a scoped name, return the identical scoped name, // but with all components that are Java keywords replaced by // their "_"-prefixed version; otherwise, if the passed name is // not scoped, but a Java keyword, return the "_"-prefixed name; // otherwise, return the name unchanged. // string Slice::JavaGenerator::fixKwd(const string& name) const { if(name.empty()) { return name; } if(name[0] != ':') { return lookupKwd(name); } StringList ids = splitScopedName(name); transform(ids.begin(), ids.end(), ids.begin(), ptr_fun(lookupKwd)); stringstream result; for(StringList::const_iterator i = ids.begin(); i != ids.end(); ++i) { result << "::" + *i; } return result.str(); } string Slice::JavaGenerator::convertScopedName(const string& scoped, const string& prefix, const string& suffix) const { string result; string::size_type start = 0; string fscoped = fixKwd(scoped); // // Skip leading "::" // if(fscoped[start] == ':') { assert(fscoped[start + 1] == ':'); start += 2; } // // Convert all occurrences of "::" to "." // string::size_type pos; do { pos = fscoped.find(':', start); string fix; if(pos == string::npos) { string s = fscoped.substr(start); if(!s.empty()) { fix = prefix + fixKwd(s) + suffix; } } else { assert(fscoped[pos + 1] == ':'); fix = fixKwd(fscoped.substr(start, pos - start)); start = pos + 2; } if(!result.empty() && !fix.empty()) { result += "."; } result += fix; } while(pos != string::npos); return result; } string Slice::JavaGenerator::getPackage(const ContainedPtr& cont) const { string scope = convertScopedName(cont->scope()); DefinitionContextPtr dc = cont->definitionContext(); if(dc) { static const string prefix = "java:package:"; string package = dc->findMetaData(prefix); if(!package.empty()) { if(!scope.empty()) { return package.substr(prefix.size()) + "." + scope; } else { return package.substr(prefix.size()); } } } return scope; } string Slice::JavaGenerator::getAbsolute(const ContainedPtr& cont, const string& package, const string& prefix, const string& suffix) const { string name = cont->name(); if(prefix == "" && suffix == "") { name = fixKwd(name); } string contPkg = getPackage(cont); if(contPkg == package) { return prefix + name + suffix; } else if(!contPkg.empty()) { return contPkg + "." + prefix + name + suffix; } else { return prefix + name + suffix; } } string Slice::JavaGenerator::typeToString(const TypePtr& type, TypeMode mode, const string& package, const StringList& metaData, bool abstract) const { static const char* builtinTable[] = { "byte", "boolean", "short", "int", "long", "float", "double", "String", "Ice.Object", "Ice.ObjectPrx", "Ice.LocalObject" }; static const char* builtinHolderTable[] = { "Ice.ByteHolder", "Ice.BooleanHolder", "Ice.ShortHolder", "Ice.IntHolder", "Ice.LongHolder", "Ice.FloatHolder", "Ice.DoubleHolder", "Ice.StringHolder", "Ice.ObjectHolder", "Ice.ObjectPrxHolder", "Ice.LocalObjectHolder" }; if(!type) { assert(mode == TypeModeReturn); return "void"; } BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); if(builtin) { if(mode == TypeModeOut) { return builtinHolderTable[builtin->kind()]; } else { return builtinTable[builtin->kind()]; } } ClassDeclPtr cl = ClassDeclPtr::dynamicCast(type); if(cl) { return getAbsolute(cl, package, "", mode == TypeModeOut ? "Holder" : ""); } ProxyPtr proxy = ProxyPtr::dynamicCast(type); if(proxy) { return getAbsolute(proxy->_class(), package, "", mode == TypeModeOut ? "PrxHolder" : "Prx"); } DictionaryPtr dict = DictionaryPtr::dynamicCast(type); if(dict) { if(mode == TypeModeOut) { if(_featureProfile == Slice::IceE) { return getAbsolute(dict, package, "", "Holder"); } else { // // Only use the type's generated holder if the concrete and // abstract types match. // string concreteType, abstractType; getDictionaryTypes(dict, "", metaData, concreteType, abstractType); string origConcreteType, origAbstractType; getDictionaryTypes(dict, "", StringList(), origConcreteType, origAbstractType); if(abstractType == origAbstractType && concreteType == origConcreteType) { return getAbsolute(dict, package, "", "Holder"); } bool java2 = dict->definitionContext()->findMetaData(_java2MetaData) == _java2MetaData; // // The custom type may or may not be compatible with the type used // in the generated holder. For Java5, we can use a generic holder // that holds a value of the abstract custom type. Otherwise, we // use MapHolder. // if(java2) { return "Ice.MapHolder"; } else { return string("Ice.Holder<") + abstractType + " >"; } } } else { string concreteType, abstractType; getDictionaryTypes(dict, package, metaData, concreteType, abstractType); return abstract ? abstractType : concreteType; } } SequencePtr seq = SequencePtr::dynamicCast(type); if(seq) { if(mode == TypeModeOut) { if(_featureProfile == Slice::IceE) { return getAbsolute(seq, package, "", "Holder"); } else { // // Only use the type's generated holder if the concrete and // abstract types match. // string concreteType, abstractType; getSequenceTypes(seq, "", metaData, concreteType, abstractType); string origConcreteType, origAbstractType; getSequenceTypes(seq, "", StringList(), origConcreteType, origAbstractType); if(abstractType == origAbstractType && concreteType == origConcreteType) { return getAbsolute(seq, package, "", "Holder"); } bool java2 = seq->definitionContext()->findMetaData(_java2MetaData) == _java2MetaData; // // The custom type may or may not be compatible with the type used // in the generated holder. For Java5, we can use a generic holder // that holds a value of the abstract custom type. Otherwise, we // choose a predefined holder class. // if(java2) { if(abstractType == "java.util.ArrayList") { return "Ice.ArrayListHolder"; } else if(abstractType == "java.util.LinkedList") { return "Ice.LinkedListHolder"; } else { return "Ice.ListHolder"; } } else { return string("Ice.Holder<") + abstractType + " >"; } } } else { string concreteType, abstractType; getSequenceTypes(seq, package, metaData, concreteType, abstractType); return abstract ? abstractType : concreteType; } } ContainedPtr contained = ContainedPtr::dynamicCast(type); if(contained) { if(mode == TypeModeOut) { return getAbsolute(contained, package, "", "Holder"); } else { return getAbsolute(contained, package); } } return "???"; } string Slice::JavaGenerator::typeToObjectString(const TypePtr& type, TypeMode mode, const string& package, const StringList& metaData, bool abstract) const { 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 builtin = BuiltinPtr::dynamicCast(type); if(builtin && mode != TypeModeOut) { return builtinTable[builtin->kind()]; } return typeToString(type, mode, package, metaData, abstract); } void Slice::JavaGenerator::writeMarshalUnmarshalCode(Output& out, const string& package, const TypePtr& type, const string& param, bool marshal, int& iter, bool holder, const StringList& metaData, const string& patchParams) { string stream = marshal ? "__os" : "__is"; string v; if(holder) { v = param + ".value"; } else { v = param; } BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); if(builtin) { switch(builtin->kind()) { case Builtin::KindByte: { if(marshal) { out << nl << stream << ".writeByte(" << v << ");"; } else { out << nl << v << " = " << stream << ".readByte();"; } break; } case Builtin::KindBool: { if(marshal) { out << nl << stream << ".writeBool(" << v << ");"; } else { out << nl << v << " = " << stream << ".readBool();"; } break; } case Builtin::KindShort: { if(marshal) { out << nl << stream << ".writeShort(" << v << ");"; } else { out << nl << v << " = " << stream << ".readShort();"; } break; } case Builtin::KindInt: { if(marshal) { out << nl << stream << ".writeInt(" << v << ");"; } else { out << nl << v << " = " << stream << ".readInt();"; } break; } case Builtin::KindLong: { if(marshal) { out << nl << stream << ".writeLong(" << v << ");"; } else { out << nl << v << " = " << stream << ".readLong();"; } break; } case Builtin::KindFloat: { if(marshal) { out << nl << stream << ".writeFloat(" << v << ");"; } else { out << nl << v << " = " << stream << ".readFloat();"; } break; } case Builtin::KindDouble: { if(marshal) { out << nl << stream << ".writeDouble(" << v << ");"; } else { out << nl << v << " = " << stream << ".readDouble();"; } break; } case Builtin::KindString: { if(marshal) { out << nl << stream << ".writeString(" << v << ");"; } else { out << nl << v << " = " << stream << ".readString();"; } break; } case Builtin::KindObject: { if(_featureProfile != Slice::IceE) { if(marshal) { out << nl << stream << ".writeObject(" << v << ");"; } else { if(holder) { out << nl << stream << ".readObject(" << param << ".getPatcher());"; } else { if(patchParams.empty()) { out << nl << stream << ".readObject(new Patcher());"; } else { out << nl << stream << ".readObject(" << patchParams << ");"; } } } } break; } case Builtin::KindObjectProxy: { if(marshal) { out << nl << stream << ".writeProxy(" << v << ");"; } else { out << nl << v << " = " << stream << ".readProxy();"; } break; } case Builtin::KindLocalObject: { assert(false); break; } } return; } ProxyPtr prx = ProxyPtr::dynamicCast(type); if(prx) { string typeS = typeToString(type, TypeModeIn, package); if(marshal) { out << nl << typeS << "Helper.__write(" << stream << ", " << v << ");"; } else { out << nl << v << " = " << typeS << "Helper.__read(" << stream << ");"; } return; } ClassDeclPtr cl = ClassDeclPtr::dynamicCast(type); if(cl) { if(_featureProfile != Slice::IceE) { if(marshal) { out << nl << stream << ".writeObject(" << v << ");"; } else { string typeS = typeToString(type, TypeModeIn, package); if(holder) { out << nl << stream << ".readObject(" << param << ".getPatcher());"; } else { if(patchParams.empty()) { out << nl << stream << ".readObject(new Patcher());"; } else { out << nl << stream << ".readObject(" << patchParams << ");"; } } } } return; } StructPtr st = StructPtr::dynamicCast(type); if(st) { if(marshal) { out << nl << v << ".__write(" << stream << ");"; } else { string typeS = typeToString(type, TypeModeIn, package); out << nl << v << " = new " << typeS << "();"; out << nl << v << ".__read(" << stream << ");"; } return; } EnumPtr en = EnumPtr::dynamicCast(type); if(en) { if(marshal) { out << nl << v << ".__write(" << stream << ");"; } else { string typeS = typeToString(type, TypeModeIn, package); out << nl << v << " = " << typeS << ".__read(" << stream << ");"; } return; } DictionaryPtr dict = DictionaryPtr::dynamicCast(type); if(dict) { writeDictionaryMarshalUnmarshalCode(out, package, dict, v, marshal, iter, true, metaData); return; } SequencePtr seq = SequencePtr::dynamicCast(type); if(seq) { writeSequenceMarshalUnmarshalCode(out, package, seq, v, marshal, iter, true, metaData); return; } ConstructedPtr constructed = ConstructedPtr::dynamicCast(type); assert(constructed); string typeS = getAbsolute(constructed, package); if(marshal) { out << nl << typeS << "Helper.write(" << stream << ", " << v << ");"; } else { out << nl << v << " = " << typeS << "Helper.read(" << stream << ");"; } } void Slice::JavaGenerator::writeDictionaryMarshalUnmarshalCode(Output& out, const string& package, const DictionaryPtr& dict, const string& param, bool marshal, int& iter, bool useHelper, const StringList& metaData) { string stream = marshal ? "__os" : "__is"; string v = param; bool java2 = false; string concreteType; if(_featureProfile != Slice::IceE) { java2 = dict->definitionContext()->findMetaData(_java2MetaData) == _java2MetaData; // // We have to determine whether it's possible to use the // type's generated helper class for this marshal/unmarshal // task. Since the user may have specified a custom type in // metadata, it's possible that the helper class is not // compatible and therefore we'll need to generate the code // in-line instead. // // Specifically, there may be "local" metadata (i.e., from // a data member or parameter definition) that overrides the // original type. We'll compare the mapped types with and // without local metadata to determine whether we can use // the helper. // string abstractType; getDictionaryTypes(dict, "", metaData, concreteType, abstractType); string origConcreteType, origAbstractType; getDictionaryTypes(dict, "", StringList(), origConcreteType, origAbstractType); if((abstractType != origAbstractType) || (!marshal && concreteType != origConcreteType)) { useHelper = false; } } // // If we can use the helper, it's easy. // if(useHelper) { string typeS = getAbsolute(dict, package); if(marshal) { out << nl << typeS << "Helper.write(" << stream << ", " << v << ");"; } else { out << nl << v << " = " << typeS << "Helper.read(" << stream << ");"; } return; } TypePtr key = dict->keyType(); TypePtr value = dict->valueType(); string keyS = typeToString(key, TypeModeIn, package); string valueS = typeToString(value, TypeModeIn, package); int i; ostringstream o; o << iter; string iterS = o.str(); iter++; if(marshal) { out << nl << "if(" << v << " == null)"; out << sb; out << nl << "__os.writeSize(0);"; out << eb; out << nl << "else"; out << sb; out << nl << "__os.writeSize(" << v << ".size());"; if(java2) { out << nl << "java.util.Iterator __i" << iterS << " = " << v << ".entrySet().iterator();"; out << nl << "while(__i" << iterS << ".hasNext())"; out << sb; out << nl << "java.util.Map.Entry __e = (java.util.Map.Entry)" << "__i" << iterS << ".next();"; } else { string keyObjectS = typeToObjectString(key, TypeModeIn, package); string valueObjectS = typeToObjectString(value, TypeModeIn, package); out << nl << "for(java.util.Map.Entry<" << keyObjectS << ", " << valueObjectS << "> __e : " << v << ".entrySet())"; out << sb; } for(i = 0; i < 2; i++) { string val; string arg; TypePtr type; if(i == 0) { arg = "__e.getKey()"; type = key; } else { arg = "__e.getValue()"; type = value; } // // We have to downcast unless we're using Java5. // if(java2) { BuiltinPtr b = BuiltinPtr::dynamicCast(type); if(b) { switch(b->kind()) { case Builtin::KindByte: { val = "((java.lang.Byte)" + arg + ").byteValue()"; break; } case Builtin::KindBool: { val = "((java.lang.Boolean)" + arg + ").booleanValue()"; break; } case Builtin::KindShort: { val = "((java.lang.Short)" + arg + ").shortValue()"; break; } case Builtin::KindInt: { val = "((java.lang.Integer)" + arg + ").intValue()"; break; } case Builtin::KindLong: { val = "((java.lang.Long)" + arg + ").longValue()"; break; } case Builtin::KindFloat: { val = "((java.lang.Float)" + arg + ").floatValue()"; break; } case Builtin::KindDouble: { val = "((java.lang.Double)" + arg + ").doubleValue()"; break; } case Builtin::KindString: case Builtin::KindObject: case Builtin::KindObjectProxy: { break; } case Builtin::KindLocalObject: { assert(false); break; } } } if(val.empty()) { val = "((" + typeToString(type, TypeModeIn, package) + ')' + arg + ')'; } } else { val = arg; } writeMarshalUnmarshalCode(out, package, type, val, true, iter, false); } out << eb; out << eb; } else { out << nl << v << " = new " << concreteType << "();"; out << nl << "int __sz" << iterS << " = __is.readSize();"; out << nl << "for(int __i" << iterS << " = 0; __i" << iterS << " < __sz" << iterS << "; __i" << iterS << "++)"; out << sb; for(i = 0; i < 2; i++) { string arg; TypePtr type; string typeS; if(i == 0) { arg = "__key"; type = key; typeS = keyS; } else { arg = "__value"; type = value; typeS = valueS; } BuiltinPtr b = BuiltinPtr::dynamicCast(type); if(b && java2) { switch(b->kind()) { case Builtin::KindByte: { out << nl << "java.lang.Byte " << arg << " = new java.lang.Byte(__is.readByte());"; break; } case Builtin::KindBool: { out << nl << "java.lang.Boolean " << arg << " = new java.lang.Boolean(__is.readBool());"; break; } case Builtin::KindShort: { out << nl << "java.lang.Short " << arg << " = new java.lang.Short(__is.readShort());"; break; } case Builtin::KindInt: { out << nl << "java.lang.Integer " << arg << " = new java.lang.Integer(__is.readInt());"; break; } case Builtin::KindLong: { out << nl << "java.lang.Long " << arg << " = new java.lang.Long(__is.readLong());"; break; } case Builtin::KindFloat: { out << nl << "java.lang.Float " << arg << " = new java.lang.Float(__is.readFloat());"; break; } case Builtin::KindDouble: { out << nl << "java.lang.Double " << arg << " = new java.lang.Double(__is.readDouble());"; break; } case Builtin::KindString: { out << nl << "java.lang.String " << arg << " = __is.readString();"; break; } case Builtin::KindObject: { assert(i == 1); // Must be the element value, since an object cannot be a key. out << nl << "__is.readObject(new IceInternal.DictionaryPatcher(" << v << ", " << valueS << ".class, \"" << value->typeId() << "\", __key));"; break; } case Builtin::KindObjectProxy: { out << nl << "Ice.ObjectPrx " << arg << " = __is.readProxy();"; break; } case Builtin::KindLocalObject: { assert(false); break; } } } else { if(ClassDeclPtr::dynamicCast(type) || (b && b->kind() == Builtin::KindObject)) { writeMarshalUnmarshalCode(out, package, type, arg, false, iter, false, StringList(), "new IceInternal.DictionaryPatcher(" + v + ", " + typeS + ".class, \"" + type->typeId() + "\", __key)"); } else { out << nl << typeS << ' ' << arg << ';'; writeMarshalUnmarshalCode(out, package, type, arg, false, iter, false); } } } BuiltinPtr builtin = BuiltinPtr::dynamicCast(value); if(!(builtin && builtin->kind() == Builtin::KindObject) && !ClassDeclPtr::dynamicCast(value)) { out << nl << "" << v << ".put(__key, __value);"; } out << eb; } } void Slice::JavaGenerator::writeSequenceMarshalUnmarshalCode(Output& out, const string& package, const SequencePtr& seq, const string& param, bool marshal, int& iter, bool useHelper, const StringList& metaData) { string stream = marshal ? "__os" : "__is"; string v = param; bool java2 = false; bool customType = false; string concreteType; if(_featureProfile != Slice::IceE) { java2 = seq->definitionContext()->findMetaData(_java2MetaData) == _java2MetaData; // // We have to determine whether it's possible to use the // type's generated helper class for this marshal/unmarshal // task. Since the user may have specified a custom type in // metadata, it's possible that the helper class is not // compatible and therefore we'll need to generate the code // in-line instead. // // Specifically, there may be "local" metadata (i.e., from // a data member or parameter definition) that overrides the // original type. We'll compare the mapped types with and // without local metadata to determine whether we can use // the helper. // string abstractType; customType = getSequenceTypes(seq, "", metaData, concreteType, abstractType); string origConcreteType, origAbstractType; getSequenceTypes(seq, "", StringList(), origConcreteType, origAbstractType); if((abstractType != origAbstractType) || (!marshal && concreteType != origConcreteType)) { useHelper = false; } } // // If we can use the helper, it's easy. // if(useHelper) { string typeS = getAbsolute(seq, package); if(marshal) { out << nl << typeS << "Helper.write(" << stream << ", " << v << ");"; } else { out << nl << v << " = " << typeS << "Helper.read(" << stream << ");"; } return; } // // Determine sequence depth. // int depth = 0; TypePtr origContent = seq->type(); SequencePtr s = SequencePtr::dynamicCast(origContent); while(s) { // // Stop if the inner sequence type has a custom type. // if(hasTypeMetaData(s) && _featureProfile != Slice::IceE) { break; } depth++; origContent = s->type(); s = SequencePtr::dynamicCast(origContent); } string origContentS = typeToString(origContent, TypeModeIn, package); TypePtr type = seq->type(); if(customType) { // // Marshal/unmarshal a custom sequence type. // BuiltinPtr b = BuiltinPtr::dynamicCast(type); if(b && b->kind() != Builtin::KindObject && b->kind() != Builtin::KindObjectProxy && java2) { if(marshal) { out << nl << "if(" << v << " == null)"; out << sb; out << nl << stream << ".writeSize(0);"; out << eb; out << nl << "else"; out << sb; out << nl << stream << ".writeSize(" << v << ".size());"; ostringstream o; o << "__i" << iter; string it = o.str(); iter++; out << nl << "java.util.Iterator " << it << " = " << v << ".iterator();"; out << nl << "while(" << it << ".hasNext())"; out << sb; switch(b->kind()) { case Builtin::KindByte: { out << nl << "java.lang.Byte __elem = (java.lang.Byte)" << it << ".next();"; out << nl << stream << ".writeByte(__elem.byteValue());"; break; } case Builtin::KindBool: { out << nl << "java.lang.Boolean __elem = (java.lang.Boolean)" << it << ".next();"; out << nl << stream << ".writeBool(__elem.booleanValue());"; break; } case Builtin::KindShort: { out << nl << "java.lang.Short __elem = (java.lang.Short)" << it << ".next();"; out << nl << stream << ".writeShort(__elem.shortValue());"; break; } case Builtin::KindInt: { out << nl << "java.lang.Integer __elem = (java.lang.Integer)" << it << ".next();"; out << nl << stream << ".writeInt(__elem.intValue());"; break; } case Builtin::KindLong: { out << nl << "java.lang.Long __elem = (java.lang.Long)" << it << ".next();"; out << nl << stream << ".writeLong(__elem.longValue());"; break; } case Builtin::KindFloat: { out << nl << "java.lang.Float __elem = (java.lang.Float)" << it << ".next();"; out << nl << stream << ".writeFloat(__elem.floatValue());"; break; } case Builtin::KindDouble: { out << nl << "java.lang.Double __elem = (java.lang.Double)" << it << ".next();"; out << nl << stream << ".writeDouble(__elem.doubleValue());"; break; } case Builtin::KindString: { out << nl << "java.lang.String __elem = (java.lang.String)" << it << ".next();"; out << nl << stream << ".writeString(__elem);"; break; } case Builtin::KindObject: case Builtin::KindObjectProxy: case Builtin::KindLocalObject: { assert(false); break; } } out << eb; // while out << eb; } else { out << nl << v << " = new " << concreteType << "();"; ostringstream o; o << origContentS << "[]"; int d = depth; while(d--) { o << "[]"; } switch(b->kind()) { case Builtin::KindByte: { out << nl << o.str() << " __seq" << iter << " = " << stream << ".readByteSeq();"; out << nl << "for(int __i" << iter << " = 0; __i" << iter << " < __seq" << iter << ".length; __i" << iter << "++)"; out << sb; out << nl << v << ".add(new java.lang.Byte(__seq" << iter << "[__i" << iter << "]));"; out << eb; iter++; break; } case Builtin::KindBool: { out << nl << o.str() << " __seq" << iter << " = " << stream << ".readBoolSeq();"; out << nl << "for(int __i" << iter << " = 0; __i" << iter << " < __seq" << iter << ".length; __i" << iter << "++)"; out << sb; out << nl << v << ".add(__seq" << iter << "[__i" << iter << "] ? java.lang.Boolean.TRUE : java.lang.Boolean.FALSE);"; out << eb; iter++; break; } case Builtin::KindShort: { out << nl << o.str() << " __seq" << iter << " = " << stream << ".readShortSeq();"; out << nl << "for(int __i" << iter << " = 0; __i" << iter << " < __seq" << iter << ".length; __i" << iter << "++)"; out << sb; out << nl << v << ".add(new java.lang.Short(__seq" << iter << "[__i" << iter << "]));"; out << eb; iter++; break; } case Builtin::KindInt: { out << nl << o.str() << " __seq" << iter << " = " << stream << ".readIntSeq();"; out << nl << "for(int __i" << iter << " = 0; __i" << iter << " < __seq" << iter << ".length; __i" << iter << "++)"; out << sb; out << nl << v << ".add(new java.lang.Integer(__seq" << iter << "[__i" << iter << "]));"; out << eb; iter++; break; } case Builtin::KindLong: { out << nl << o.str() << " __seq" << iter << " = " << stream << ".readLongSeq();"; out << nl << "for(int __i" << iter << " = 0; __i" << iter << " < __seq" << iter << ".length; __i" << iter << "++)"; out << sb; out << nl << v << ".add(new java.lang.Long(__seq" << iter << "[__i" << iter << "]));"; out << eb; iter++; break; } case Builtin::KindFloat: { out << nl << o.str() << " __seq" << iter << " = " << stream << ".readFloatSeq();"; out << nl << "for(int __i" << iter << " = 0; __i" << iter << " < __seq" << iter << ".length; __i" << iter << "++)"; out << sb; out << nl << v << ".add(new java.lang.Float(__seq" << iter << "[__i" << iter << "]));"; out << eb; iter++; break; } case Builtin::KindDouble: { out << nl << o.str() << " __seq" << iter << " = " << stream << ".readDoubleSeq();"; out << nl << "for(int __i" << iter << " = 0; __i" << iter << " < __seq" << iter << ".length; __i" << iter << "++)"; out << sb; out << nl << v << ".add(new java.lang.Double(__seq" << iter << "[__i" << iter << "]));"; out << eb; iter++; break; } case Builtin::KindString: { out << nl << o.str() << " __seq" << iter << " = " << stream << ".readStringSeq();"; out << nl << "for(int __i" << iter << " = 0; __i" << iter << " < __seq" << iter << ".length; __i" << iter << "++)"; out << sb; out << nl << v << ".add(__seq" << iter << "[__i" << iter << "]);"; out << eb; iter++; break; } case Builtin::KindObject: case Builtin::KindObjectProxy: case Builtin::KindLocalObject: { assert(false); break; } } } } else { string typeS = getAbsolute(seq, package); ostringstream o; o << origContentS; int d = depth; while(d--) { o << "[]"; } string cont = o.str(); if(marshal) { out << nl << "if(" << v << " == null)"; out << sb; out << nl << stream << ".writeSize(0);"; out << eb; out << nl << "else"; out << sb; out << nl << stream << ".writeSize(" << v << ".size());"; if(java2) { ostringstream oit; oit << "__i" << iter; iter++; string it = oit.str(); out << nl << "java.util.Iterator " << it << " = " << v << ".iterator();"; out << nl << "while(" << it << ".hasNext())"; out << sb; out << nl << cont << " __elem = (" << cont << ")" << it << ".next();"; writeMarshalUnmarshalCode(out, package, type, "__elem", true, iter, false); out << eb; } else { string typeS = typeToString(type, TypeModeIn, package); out << nl << "for(" << typeS << " __elem : " << v << ')'; out << sb; writeMarshalUnmarshalCode(out, package, type, "__elem", true, iter, false); out << eb; } out << eb; // else } else { bool isObject = false; ClassDeclPtr cl = ClassDeclPtr::dynamicCast(type); if((b && b->kind() == Builtin::KindObject) || cl) { isObject = true; } out << nl << v << " = new " << concreteType << "();"; out << nl << "final int __len" << iter << " = " << stream << ".readSize();"; if(type->isVariableLength()) { out << nl << stream << ".startSeq(__len" << iter << ", " << type->minWireSize() << ");"; } else { out << nl << stream << ".checkFixedSeq(__len" << iter << ", " << type->minWireSize() << ");"; } if(isObject) { if(b) { out << nl << "final String __type" << iter << " = Ice.ObjectImpl.ice_staticId();"; } else { assert(cl); if(cl->isInterface()) { out << nl << "final String __type" << iter << " = " << getAbsolute(cl, package, "_", "Disp") << ".ice_staticId();"; } else { out << nl << "final String __type" << iter << " = " << origContentS << ".ice_staticId();"; } } } out << nl << "for(int __i" << iter << " = 0; __i" << iter << " < __len" << iter << "; __i" << iter << "++)"; out << sb; if(isObject) { // // Add a null value to the list as a placeholder for the element. // out << nl << v << ".add(null);"; ostringstream patchParams; patchParams << "new IceInternal.ListPatcher(" << v << ", " << origContentS << ".class, __type" << iter << ", __i" << iter << ')'; writeMarshalUnmarshalCode(out, package, type, "__elem", false, iter, false, StringList(), patchParams.str()); } else { out << nl << cont << " __elem;"; writeMarshalUnmarshalCode(out, package, type, "__elem", false, iter, false); } if(!isObject) { out << nl << v << ".add(__elem);"; } // // After unmarshaling each element, check that there are still enough bytes left in the stream // to unmarshal the remainder of the sequence, and decrement the count of elements // yet to be unmarshaled for sequences with variable-length element type (that is, for sequences // of classes, structs, dictionaries, sequences, strings, or proxies). This allows us to // abort unmarshaling for bogus sequence sizes at the earliest possible moment. // (For fixed-length sequences, we don't need to do this because the prediction of how many // bytes will be taken up by the sequence is accurate.) // if(type->isVariableLength()) { if(!SequencePtr::dynamicCast(type)) { // // No need to check for directly nested sequences because, at the at start of each // sequence, we check anyway. // out << nl << stream << ".checkSeq();"; } out << nl << stream << ".endElement();"; } out << eb; if(type->isVariableLength()) { out << nl << stream << ".endSeq(__len" << iter << ");"; } iter++; } } } else { BuiltinPtr b = BuiltinPtr::dynamicCast(type); if(b && b->kind() != Builtin::KindObject && b->kind() != Builtin::KindObjectProxy) { switch(b->kind()) { case Builtin::KindByte: { if(marshal) { out << nl << stream << ".writeByteSeq(" << v << ");"; } else { out << nl << v << " = " << stream << ".readByteSeq();"; } break; } case Builtin::KindBool: { if(marshal) { out << nl << stream << ".writeBoolSeq(" << v << ");"; } else { out << nl << v << " = " << stream << ".readBoolSeq();"; } break; } case Builtin::KindShort: { if(marshal) { out << nl << stream << ".writeShortSeq(" << v << ");"; } else { out << nl << v << " = " << stream << ".readShortSeq();"; } break; } case Builtin::KindInt: { if(marshal) { out << nl << stream << ".writeIntSeq(" << v << ");"; } else { out << nl << v << " = " << stream << ".readIntSeq();"; } break; } case Builtin::KindLong: { if(marshal) { out << nl << stream << ".writeLongSeq(" << v << ");"; } else { out << nl << v << " = " << stream << ".readLongSeq();"; } break; } case Builtin::KindFloat: { if(marshal) { out << nl << stream << ".writeFloatSeq(" << v << ");"; } else { out << nl << v << " = " << stream << ".readFloatSeq();"; } break; } case Builtin::KindDouble: { if(marshal) { out << nl << stream << ".writeDoubleSeq(" << v << ");"; } else { out << nl << v << " = " << stream << ".readDoubleSeq();"; } break; } case Builtin::KindString: { if(marshal) { out << nl << stream << ".writeStringSeq(" << v << ");"; } else { out << nl << v << " = " << stream << ".readStringSeq();"; } break; } case Builtin::KindObject: case Builtin::KindObjectProxy: case Builtin::KindLocalObject: { assert(false); break; } } } else { if(marshal) { out << nl << "if(" << v << " == null)"; out << sb; out << nl << stream << ".writeSize(0);"; out << eb; out << nl << "else"; out << sb; out << nl << stream << ".writeSize(" << v << ".length);"; out << nl << "for(int __i" << iter << " = 0; __i" << iter << " < " << v << ".length; __i" << iter << "++)"; out << sb; ostringstream o; o << v << "[__i" << iter << "]"; iter++; writeMarshalUnmarshalCode(out, package, type, o.str(), true, iter, false); out << eb; out << eb; } else { bool isObject = false; ClassDeclPtr cl = ClassDeclPtr::dynamicCast(origContent); if((b && b->kind() == Builtin::KindObject) || cl) { isObject = true; } out << nl << "final int __len" << iter << " = " << stream << ".readSize();"; if(type->isVariableLength()) { out << nl << stream << ".startSeq(__len" << iter << ", " << type->minWireSize() << ");"; } else { out << nl << stream << ".checkFixedSeq(__len" << iter << ", " << type->minWireSize() << ");"; } if(isObject) { if(b) { out << nl << "final String __type" << iter << " = Ice.ObjectImpl.ice_staticId();"; } else { assert(cl); if(cl->isInterface()) { out << nl << "final String __type" << iter << " = " << getAbsolute(cl, package, "_", "Disp") << ".ice_staticId();"; } else { out << nl << "final String __type" << iter << " = " << origContentS << ".ice_staticId();"; } } } // // In Java5, we cannot allocate an array of a generic type, such as // // arr = new Map[sz]; // // Attempting to compile this code results in a "generic array creation" error // message. This problem can occur when the sequence's element type is a // dictionary, or when the element type is a nested sequence that uses a custom // mapping. // // The solution is to rewrite the code as follows: // // arr = (Map[])new Map[sz]; // // Unfortunately, this produces an unchecked warning during compilation. // // A simple test is to look for a "<" character in the content type, which // indicates the use of a generic type. // string::size_type pos = origContentS.find('<'); if(pos != string::npos) { string nonGenericType = origContentS.substr(0, pos); out << nl << v << " = (" << origContentS << "[]"; int d = depth; while(d--) { out << "[]"; } out << ")new " << nonGenericType << "[__len" << iter << "]"; } else { out << nl << v << " = new " << origContentS << "[__len" << iter << "]"; } int d = depth; while(d--) { out << "[]"; } out << ';'; out << nl << "for(int __i" << iter << " = 0; __i" << iter << " < __len" << iter << "; __i" << iter << "++)"; out << sb; ostringstream o; o << v << "[__i" << iter << "]"; ostringstream patchParams; if(isObject) { patchParams << "new IceInternal.SequencePatcher(" << v << ", " << origContentS << ".class, __type" << iter << ", __i" << iter << ')'; writeMarshalUnmarshalCode(out, package, type, o.str(), false, iter, false, StringList(), patchParams.str()); } else { writeMarshalUnmarshalCode(out, package, type, o.str(), false, iter, false); } // // After unmarshaling each element, check that there are still enough bytes left in the stream // to unmarshal the remainder of the sequence, and decrement the count of elements // yet to be unmarshaled for sequences with variable-length element type (that is, for sequences // of classes, structs, dictionaries, sequences, strings, or proxies). This allows us to // abort unmarshaling for bogus sequence sizes at the earliest possible moment. // (For fixed-length sequences, we don't need to do this because the prediction of how many // bytes will be taken up by the sequence is accurate.) // if(type->isVariableLength()) { if(!SequencePtr::dynamicCast(type)) { // // No need to check for directly nested sequences because, at the at start of each // sequence, we check anyway. // out << nl << stream << ".checkSeq();"; } out << nl << stream << ".endElement();"; } out << eb; if(type->isVariableLength()) { out << nl << stream << ".endSeq(__len" << iter << ");"; } iter++; } } } } void Slice::JavaGenerator::writeStreamMarshalUnmarshalCode(Output& out, const string& package, const TypePtr& type, const string& param, bool marshal, int& iter, bool holder, const StringList& metaData, const string& patchParams) { string stream = marshal ? "__outS" : "__inS"; string v; if(holder) { v = param + ".value"; } else { v = param; } BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); if(builtin) { switch(builtin->kind()) { case Builtin::KindByte: { if(marshal) { out << nl << stream << ".writeByte(" << v << ");"; } else { out << nl << v << " = " << stream << ".readByte();"; } break; } case Builtin::KindBool: { if(marshal) { out << nl << stream << ".writeBool(" << v << ");"; } else { out << nl << v << " = " << stream << ".readBool();"; } break; } case Builtin::KindShort: { if(marshal) { out << nl << stream << ".writeShort(" << v << ");"; } else { out << nl << v << " = " << stream << ".readShort();"; } break; } case Builtin::KindInt: { if(marshal) { out << nl << stream << ".writeInt(" << v << ");"; } else { out << nl << v << " = " << stream << ".readInt();"; } break; } case Builtin::KindLong: { if(marshal) { out << nl << stream << ".writeLong(" << v << ");"; } else { out << nl << v << " = " << stream << ".readLong();"; } break; } case Builtin::KindFloat: { if(marshal) { out << nl << stream << ".writeFloat(" << v << ");"; } else { out << nl << v << " = " << stream << ".readFloat();"; } break; } case Builtin::KindDouble: { if(marshal) { out << nl << stream << ".writeDouble(" << v << ");"; } else { out << nl << v << " = " << stream << ".readDouble();"; } break; } case Builtin::KindString: { if(marshal) { out << nl << stream << ".writeString(" << v << ");"; } else { out << nl << v << " = " << stream << ".readString();"; } break; } case Builtin::KindObject: { if(_featureProfile != Slice::IceE) { if(marshal) { out << nl << stream << ".writeObject(" << v << ");"; } else { if(holder) { out << nl << stream << ".readObject((Ice.ReadObjectCallback)" << param << ".getPatcher());"; } else { if(patchParams.empty()) { out << nl << stream << ".readObject(new Patcher());"; } else { out << nl << stream << ".readObject(" << patchParams << ");"; } } } } break; } case Builtin::KindObjectProxy: { if(marshal) { out << nl << stream << ".writeProxy(" << v << ");"; } else { out << nl << v << " = " << stream << ".readProxy();"; } break; } case Builtin::KindLocalObject: { assert(false); break; } } return; } ProxyPtr prx = ProxyPtr::dynamicCast(type); if(prx) { string typeS = typeToString(type, TypeModeIn, package); if(marshal) { out << nl << typeS << "Helper.write(" << stream << ", " << v << ");"; } else { out << nl << v << " = " << typeS << "Helper.read(" << stream << ");"; } return; } ClassDeclPtr cl = ClassDeclPtr::dynamicCast(type); if(cl) { if(_featureProfile != Slice::IceE) { if(marshal) { out << nl << stream << ".writeObject(" << v << ");"; } else { string typeS = typeToString(type, TypeModeIn, package); if(holder) { out << nl << stream << ".readObject(" << param << ".getPatcher());"; } else { if(patchParams.empty()) { out << nl << stream << ".readObject(new Patcher());"; } else { out << nl << stream << ".readObject(" << patchParams << ");"; } } } } return; } StructPtr st = StructPtr::dynamicCast(type); if(st) { if(marshal) { out << nl << v << ".ice_write(" << stream << ");"; } else { string typeS = typeToString(type, TypeModeIn, package); out << nl << v << " = new " << typeS << "();"; out << nl << v << ".ice_read(" << stream << ");"; } return; } EnumPtr en = EnumPtr::dynamicCast(type); if(en) { if(marshal) { out << nl << v << ".ice_write(" << stream << ");"; } else { string typeS = typeToString(type, TypeModeIn, package); out << nl << v << " = " << typeS << ".ice_read(" << stream << ");"; } return; } DictionaryPtr dict = DictionaryPtr::dynamicCast(type); if(dict) { writeStreamDictionaryMarshalUnmarshalCode(out, package, dict, v, marshal, iter, true, metaData); return; } SequencePtr seq = SequencePtr::dynamicCast(type); if(seq) { writeStreamSequenceMarshalUnmarshalCode(out, package, seq, v, marshal, iter, true, metaData); return; } ConstructedPtr constructed = ConstructedPtr::dynamicCast(type); assert(constructed); string typeS = getAbsolute(constructed, package); if(marshal) { out << nl << typeS << "Helper.write(" << stream << ", " << v << ");"; } else { out << nl << v << " = " << typeS << "Helper.read(" << stream << ");"; } } void Slice::JavaGenerator::writeStreamDictionaryMarshalUnmarshalCode(Output& out, const string& package, const DictionaryPtr& dict, const string& param, bool marshal, int& iter, bool useHelper, const StringList& metaData) { string stream = marshal ? "__outS" : "__inS"; string v = param; bool java2 = dict->definitionContext()->findMetaData(_java2MetaData) == _java2MetaData; // // We have to determine whether it's possible to use the // type's generated helper class for this marshal/unmarshal // task. Since the user may have specified a custom type in // metadata, it's possible that the helper class is not // compatible and therefore we'll need to generate the code // in-line instead. // // Specifically, there may be "local" metadata (i.e., from // a data member or parameter definition) that overrides the // original type. We'll compare the mapped types with and // without local metadata to determine whether we can use // the helper. // string concreteType, abstractType; getDictionaryTypes(dict, "", metaData, concreteType, abstractType); string origConcreteType, origAbstractType; getDictionaryTypes(dict, "", StringList(), origConcreteType, origAbstractType); if((abstractType != origAbstractType) || (!marshal && concreteType != origConcreteType)) { useHelper = false; } // // If we can use the helper, it's easy. // if(useHelper) { string typeS = getAbsolute(dict, package); if(marshal) { out << nl << typeS << "Helper.write(" << stream << ", " << v << ");"; } else { out << nl << v << " = " << typeS << "Helper.read(" << stream << ");"; } return; } TypePtr key = dict->keyType(); TypePtr value = dict->valueType(); string keyS = typeToString(key, TypeModeIn, package); string valueS = typeToString(value, TypeModeIn, package); int i; ostringstream o; o << iter; string iterS = o.str(); iter++; if(marshal) { out << nl << "if(" << v << " == null)"; out << sb; out << nl << "__outS.writeSize(0);"; out << eb; out << nl << "else"; out << sb; out << nl << "__outS.writeSize(" << v << ".size());"; if(java2) { out << nl << "java.util.Iterator __i" << iterS << " = " << v << ".entrySet().iterator();"; out << nl << "while(__i" << iterS << ".hasNext())"; out << sb; out << nl << "java.util.Map.Entry __e = (java.util.Map.Entry)" << "__i" << iterS << ".next();"; } else { string keyObjectS = typeToObjectString(key, TypeModeIn, package); string valueObjectS = typeToObjectString(value, TypeModeIn, package); out << nl << "for(java.util.Map.Entry<" << keyObjectS << ", " << valueObjectS << "> __e : " << v << ".entrySet())"; out << sb; } for(i = 0; i < 2; i++) { string val; string arg; TypePtr type; if(i == 0) { arg = "__e.getKey()"; type = key; } else { arg = "__e.getValue()"; type = value; } // // We have to downcast unless we're using Java5. // if(java2) { BuiltinPtr b = BuiltinPtr::dynamicCast(type); if(b) { switch(b->kind()) { case Builtin::KindByte: { val = "((java.lang.Byte)" + arg + ").byteValue()"; break; } case Builtin::KindBool: { val = "((java.lang.Boolean)" + arg + ").booleanValue()"; break; } case Builtin::KindShort: { val = "((java.lang.Short)" + arg + ").shortValue()"; break; } case Builtin::KindInt: { val = "((java.lang.Integer)" + arg + ").intValue()"; break; } case Builtin::KindLong: { val = "((java.lang.Long)" + arg + ").longValue()"; break; } case Builtin::KindFloat: { val = "((java.lang.Float)" + arg + ").floatValue()"; break; } case Builtin::KindDouble: { val = "((java.lang.Double)" + arg + ").doubleValue()"; break; } case Builtin::KindString: case Builtin::KindObject: case Builtin::KindObjectProxy: { break; } case Builtin::KindLocalObject: { assert(false); break; } } } if(val.empty()) { val = "((" + typeToString(type, TypeModeIn, package) + ')' + arg + ')'; } } else { val = arg; } writeStreamMarshalUnmarshalCode(out, package, type, val, true, iter, false); } out << eb; out << eb; } else { out << nl << v << " = new " << concreteType << "();"; out << nl << "int __sz" << iterS << " = __inS.readSize();"; out << nl << "for(int __i" << iterS << " = 0; __i" << iterS << " < __sz" << iterS << "; __i" << iterS << "++)"; out << sb; for(i = 0; i < 2; i++) { string arg; TypePtr type; string typeS; if(i == 0) { arg = "__key"; type = key; typeS = keyS; } else { arg = "__value"; type = value; typeS = valueS; } BuiltinPtr b = BuiltinPtr::dynamicCast(type); if(b && java2) { switch(b->kind()) { case Builtin::KindByte: { out << nl << "java.lang.Byte " << arg << " = new java.lang.Byte(__inS.readByte());"; break; } case Builtin::KindBool: { out << nl << "java.lang.Boolean " << arg << " = new java.lang.Boolean(__inS.readBool());"; break; } case Builtin::KindShort: { out << nl << "java.lang.Short " << arg << " = new java.lang.Short(__inS.readShort());"; break; } case Builtin::KindInt: { out << nl << "java.lang.Integer " << arg << " = new java.lang.Integer(__inS.readInt());"; break; } case Builtin::KindLong: { out << nl << "java.lang.Long " << arg << " = new java.lang.Long(__inS.readLong());"; break; } case Builtin::KindFloat: { out << nl << "java.lang.Float " << arg << " = new java.lang.Float(__inS.readFloat());"; break; } case Builtin::KindDouble: { out << nl << "java.lang.Double " << arg << " = new java.lang.Double(__inS.readDouble());"; break; } case Builtin::KindString: { out << nl << "java.lang.String " << arg << " = __inS.readString();"; break; } case Builtin::KindObject: { out << nl << "__inS.readObject(new IceInternal.DictionaryPatcher(" << v << ", " << valueS << ".class, \"" << value->typeId() << "\", __key));"; break; } case Builtin::KindObjectProxy: { out << nl << "Ice.ObjectPrx " << arg << " = __inS.readProxy();"; break; } case Builtin::KindLocalObject: { assert(false); break; } } } else { string s = typeToString(type, TypeModeIn, package); if(ClassDeclPtr::dynamicCast(type) || (b && b->kind() == Builtin::KindObject)) { writeStreamMarshalUnmarshalCode(out, package, type, arg, false, iter, false, StringList(), "new IceInternal.DictionaryPatcher(" + v + ", " + s + ".class, \"" + type->typeId() + "\", __key)"); } else { out << nl << s << ' ' << arg << ';'; writeStreamMarshalUnmarshalCode(out, package, type, arg, false, iter, false); } } } BuiltinPtr builtin = BuiltinPtr::dynamicCast(value); if(!(builtin && builtin->kind() == Builtin::KindObject) && !ClassDeclPtr::dynamicCast(value)) { out << nl << "" << v << ".put(__key, __value);"; } out << eb; } } void Slice::JavaGenerator::writeStreamSequenceMarshalUnmarshalCode(Output& out, const string& package, const SequencePtr& seq, const string& param, bool marshal, int& iter, bool useHelper, const StringList& metaData) { string stream = marshal ? "__outS" : "__inS"; string v = param; bool java2 = seq->definitionContext()->findMetaData(_java2MetaData) == _java2MetaData; // // We have to determine whether it's possible to use the // type's generated helper class for this marshal/unmarshal // task. Since the user may have specified a custom type in // metadata, it's possible that the helper class is not // compatible and therefore we'll need to generate the code // in-line instead. // // Specifically, there may be "local" metadata (i.e., from // a data member or parameter definition) that overrides the // original type. We'll compare the mapped types with and // without local metadata to determine whether we can use // the helper. // string concreteType, abstractType; bool customType = getSequenceTypes(seq, "", metaData, concreteType, abstractType); string origConcreteType, origAbstractType; getSequenceTypes(seq, "", StringList(), origConcreteType, origAbstractType); if((abstractType != origAbstractType) || (!marshal && concreteType != origConcreteType)) { useHelper = false; } // // If we can use the helper, it's easy. // if(useHelper) { string typeS = getAbsolute(seq, package); if(marshal) { out << nl << typeS << "Helper.write(" << stream << ", " << v << ");"; } else { out << nl << v << " = " << typeS << "Helper.read(" << stream << ");"; } return; } // // Determine sequence depth // int depth = 0; TypePtr origContent = seq->type(); SequencePtr s = SequencePtr::dynamicCast(origContent); while(s) { // // Stop if the inner sequence type has a custom type. // if(hasTypeMetaData(s)) { break; } depth++; origContent = s->type(); s = SequencePtr::dynamicCast(origContent); } string origContentS = typeToString(origContent, TypeModeIn, package); TypePtr type = seq->type(); if(customType) { // // Marshal/unmarshal a custom sequence type. // BuiltinPtr b = BuiltinPtr::dynamicCast(type); if(b && b->kind() != Builtin::KindObject && b->kind() != Builtin::KindObjectProxy && java2) { if(marshal) { out << nl << "if(" << v << " == null)"; out << sb; out << nl << stream << ".writeSize(0);"; out << eb; out << nl << "else"; out << sb; out << nl << stream << ".writeSize(" << v << ".size());"; ostringstream o; o << "__i" << iter; string it = o.str(); iter++; out << nl << "java.util.Iterator " << it << " = " << v << ".iterator();"; out << nl << "while(" << it << ".hasNext())"; out << sb; switch(b->kind()) { case Builtin::KindByte: { out << nl << "java.lang.Byte __elem = (java.lang.Byte)" << it << ".next();"; out << nl << stream << ".writeByte(__elem.byteValue());"; break; } case Builtin::KindBool: { out << nl << "java.lang.Boolean __elem = (java.lang.Boolean)" << it << ".next();"; out << nl << stream << ".writeBool(__elem.booleanValue());"; break; } case Builtin::KindShort: { out << nl << "java.lang.Short __elem = (java.lang.Short)" << it << ".next();"; out << nl << stream << ".writeShort(__elem.shortValue());"; break; } case Builtin::KindInt: { out << nl << "java.lang.Integer __elem = (java.lang.Integer)" << it << ".next();"; out << nl << stream << ".writeInt(__elem.intValue());"; break; } case Builtin::KindLong: { out << nl << "java.lang.Long __elem = (java.lang.Long)" << it << ".next();"; out << nl << stream << ".writeLong(__elem.longValue());"; break; } case Builtin::KindFloat: { out << nl << "java.lang.Float __elem = (java.lang.Float)" << it << ".next();"; out << nl << stream << ".writeFloat(__elem.floatValue());"; break; } case Builtin::KindDouble: { out << nl << "java.lang.Double __elem = (java.lang.Double)" << it << ".next();"; out << nl << stream << ".writeDouble(__elem.doubleValue());"; break; } case Builtin::KindString: { out << nl << "java.lang.String __elem = (java.lang.String)" << it << ".next();"; out << nl << stream << ".writeString(__elem);"; break; } case Builtin::KindObject: case Builtin::KindObjectProxy: case Builtin::KindLocalObject: { assert(false); break; } } out << eb; // while out << eb; } else { out << nl << v << " = new " << concreteType << "();"; ostringstream o; o << origContentS << "[]"; int d = depth; while(d--) { o << "[]"; } switch(b->kind()) { case Builtin::KindByte: { out << nl << o.str() << " __seq" << iter << " = " << stream << ".readByteSeq();"; out << nl << "for(int __i" << iter << " = 0; __i" << iter << " < __seq" << iter << ".length; __i" << iter << "++)"; out << sb; out << nl << v << ".add(new java.lang.Byte(__seq" << iter << "[__i" << iter << "]));"; out << eb; iter++; break; } case Builtin::KindBool: { out << nl << o.str() << " __seq" << iter << " = " << stream << ".readBoolSeq();"; out << nl << "for(int __i" << iter << " = 0; __i" << iter << " < __seq" << iter << ".length; __i" << iter << "++)"; out << sb; out << nl << v << ".add(__seq" << iter << "[__i" << iter << "] ? java.lang.Boolean.TRUE : java.lang.Boolean.FALSE);"; out << eb; iter++; break; } case Builtin::KindShort: { out << nl << o.str() << " __seq" << iter << " = " << stream << ".readShortSeq();"; out << nl << "for(int __i" << iter << " = 0; __i" << iter << " < __seq" << iter << ".length; __i" << iter << "++)"; out << sb; out << nl << v << ".add(new java.lang.Short(__seq" << iter << "[__i" << iter << "]));"; out << eb; iter++; break; } case Builtin::KindInt: { out << nl << o.str() << " __seq" << iter << " = " << stream << ".readIntSeq();"; out << nl << "for(int __i" << iter << " = 0; __i" << iter << " < __seq" << iter << ".length; __i" << iter << "++)"; out << sb; out << nl << v << ".add(new java.lang.Integer(__seq" << iter << "[__i" << iter << "]));"; out << eb; iter++; break; } case Builtin::KindLong: { out << nl << o.str() << " __seq" << iter << " = " << stream << ".readLongSeq();"; out << nl << "for(int __i" << iter << " = 0; __i" << iter << " < __seq" << iter << ".length; __i" << iter << "++)"; out << sb; out << nl << v << ".add(new java.lang.Long(__seq" << iter << "[__i" << iter << "]));"; out << eb; iter++; break; } case Builtin::KindFloat: { out << nl << o.str() << " __seq" << iter << " = " << stream << ".readFloatSeq();"; out << nl << "for(int __i" << iter << " = 0; __i" << iter << " < __seq" << iter << ".length; __i" << iter << "++)"; out << sb; out << nl << v << ".add(new java.lang.Float(__seq" << iter << "[__i" << iter << "]));"; out << eb; iter++; break; } case Builtin::KindDouble: { out << nl << o.str() << " __seq" << iter << " = " << stream << ".readDoubleSeq();"; out << nl << "for(int __i" << iter << " = 0; __i" << iter << " < __seq" << iter << ".length; __i" << iter << "++)"; out << sb; out << nl << v << ".add(new java.lang.Double(__seq" << iter << "[__i" << iter << "]));"; out << eb; iter++; break; } case Builtin::KindString: { out << nl << o.str() << " __seq" << iter << " = " << stream << ".readStringSeq();"; out << nl << "for(int __i" << iter << " = 0; __i" << iter << " < __seq" << iter << ".length; __i" << iter << "++)"; out << sb; out << nl << v << ".add(__seq" << iter << "[__i" << iter << "]);"; out << eb; iter++; break; } case Builtin::KindObject: case Builtin::KindObjectProxy: case Builtin::KindLocalObject: { assert(false); break; } } } } else { string typeS = getAbsolute(seq, package); ostringstream o; o << origContentS; int d = depth; while(d--) { o << "[]"; } string cont = o.str(); if(marshal) { out << nl << "if(" << v << " == null)"; out << sb; out << nl << stream << ".writeSize(0);"; out << eb; out << nl << "else"; out << sb; out << nl << stream << ".writeSize(" << v << ".size());"; if(java2) { ostringstream oit; oit << "__i" << iter; iter++; string it = oit.str(); out << nl << "java.util.Iterator " << it << " = " << v << ".iterator();"; out << nl << "while(" << it << ".hasNext())"; out << sb; out << nl << cont << " __elem = (" << cont << ")" << it << ".next();"; writeStreamMarshalUnmarshalCode(out, package, type, "__elem", true, iter, false); out << eb; } else { string typeS = typeToString(type, TypeModeIn, package); out << nl << "for(" << typeS << " __elem : " << v << ')'; out << sb; writeStreamMarshalUnmarshalCode(out, package, type, "__elem", true, iter, false); out << eb; } out << eb; // else } else { bool isObject = false; ClassDeclPtr cl = ClassDeclPtr::dynamicCast(type); if((b && b->kind() == Builtin::KindObject) || cl) { isObject = true; } out << nl << v << " = new " << concreteType << "();"; out << nl << "final int __len" << iter << " = " << stream << ".readSize();"; if(isObject) { if(b) { out << nl << "final String __type" << iter << " = Ice.ObjectImpl.ice_staticId();"; } else { assert(cl); if(cl->isInterface()) { out << nl << "final String __type" << iter << " = " << getAbsolute(cl, package, "_", "Disp") << ".ice_staticId();"; } else { out << nl << "final String __type" << iter << " = " << origContentS << ".ice_staticId();"; } } } out << nl << "for(int __i" << iter << " = 0; __i" << iter << " < __len" << iter << "; __i" << iter << "++)"; out << sb; if(isObject) { // // Add a null value to the list as a placeholder for the element. // out << nl << v << ".add(null);"; ostringstream patchParams; patchParams << "new IceInternal.ListPatcher(" << v << ", " << origContentS << ".class, __type" << iter << ", __i" << iter << ')'; writeStreamMarshalUnmarshalCode(out, package, type, "__elem", false, iter, false, StringList(), patchParams.str()); } else { out << nl << cont << " __elem;"; writeStreamMarshalUnmarshalCode(out, package, type, "__elem", false, iter, false); } if(!isObject) { out << nl << v << ".add(__elem);"; } out << eb; iter++; } } } else { BuiltinPtr b = BuiltinPtr::dynamicCast(type); if(b && b->kind() != Builtin::KindObject && b->kind() != Builtin::KindObjectProxy) { switch(b->kind()) { case Builtin::KindByte: { if(marshal) { out << nl << stream << ".writeByteSeq(" << v << ");"; } else { out << nl << v << " = " << stream << ".readByteSeq();"; } break; } case Builtin::KindBool: { if(marshal) { out << nl << stream << ".writeBoolSeq(" << v << ");"; } else { out << nl << v << " = " << stream << ".readBoolSeq();"; } break; } case Builtin::KindShort: { if(marshal) { out << nl << stream << ".writeShortSeq(" << v << ");"; } else { out << nl << v << " = " << stream << ".readShortSeq();"; } break; } case Builtin::KindInt: { if(marshal) { out << nl << stream << ".writeIntSeq(" << v << ");"; } else { out << nl << v << " = " << stream << ".readIntSeq();"; } break; } case Builtin::KindLong: { if(marshal) { out << nl << stream << ".writeLongSeq(" << v << ");"; } else { out << nl << v << " = " << stream << ".readLongSeq();"; } break; } case Builtin::KindFloat: { if(marshal) { out << nl << stream << ".writeFloatSeq(" << v << ");"; } else { out << nl << v << " = " << stream << ".readFloatSeq();"; } break; } case Builtin::KindDouble: { if(marshal) { out << nl << stream << ".writeDoubleSeq(" << v << ");"; } else { out << nl << v << " = " << stream << ".readDoubleSeq();"; } break; } case Builtin::KindString: { if(marshal) { out << nl << stream << ".writeStringSeq(" << v << ");"; } else { out << nl << v << " = " << stream << ".readStringSeq();"; } break; } case Builtin::KindObject: case Builtin::KindObjectProxy: case Builtin::KindLocalObject: { assert(false); break; } } } else { if(marshal) { out << nl << "if(" << v << " == null)"; out << sb; out << nl << stream << ".writeSize(0);"; out << eb; out << nl << "else"; out << sb; out << nl << stream << ".writeSize(" << v << ".length);"; out << nl << "for(int __i" << iter << " = 0; __i" << iter << " < " << v << ".length; __i" << iter << "++)"; out << sb; ostringstream o; o << v << "[__i" << iter << "]"; iter++; writeStreamMarshalUnmarshalCode(out, package, type, o.str(), true, iter, false); out << eb; out << eb; } else { bool isObject = false; ClassDeclPtr cl = ClassDeclPtr::dynamicCast(origContent); if((b && b->kind() == Builtin::KindObject) || cl) { isObject = true; } out << nl << "final int __len" << iter << " = " << stream << ".readSize();"; if(isObject) { if(b) { out << nl << "final String __type" << iter << " = Ice.ObjectImpl.ice_staticId();"; } else { assert(cl); if(cl->isInterface()) { out << nl << "final String __type" << iter << " = " << getAbsolute(cl, package, "_", "Disp") << ".ice_staticId();"; } else { out << nl << "final String __type" << iter << " = " << origContentS << ".ice_staticId();"; } } } // // In Java5, we cannot allocate an array of a generic type, such as // // arr = new Map[sz]; // // Attempting to compile this code results in a "generic array creation" error // message. This problem can occur when the sequence's element type is a // dictionary, or when the element type is a nested sequence that uses a custom // mapping. // // The solution is to rewrite the code as follows: // // arr = (Map[])new Map[sz]; // // Unfortunately, this produces an unchecked warning during compilation. // // A simple test is to look for a "<" character in the content type, which // indicates the use of a generic type. // string::size_type pos = origContentS.find('<'); if(pos != string::npos) { string nonGenericType = origContentS.substr(0, pos); out << nl << v << " = (" << origContentS << "[]"; int d = depth; while(d--) { out << "[]"; } out << ")new " << nonGenericType << "[__len" << iter << "]"; } else { out << nl << v << " = new " << origContentS << "[__len" << iter << "]"; } int d = depth; while(d--) { out << "[]"; } out << ';'; out << nl << "for(int __i" << iter << " = 0; __i" << iter << " < __len" << iter << "; __i" << iter << "++)"; out << sb; ostringstream o; o << v << "[__i" << iter << "]"; ostringstream patchParams; if(isObject) { patchParams << "new IceInternal.SequencePatcher(" << v << ", " << origContentS << ".class, __type" << iter << ", __i" << iter << ')'; writeStreamMarshalUnmarshalCode(out, package, type, o.str(), false, iter, false, StringList(), patchParams.str()); } else { writeStreamMarshalUnmarshalCode(out, package, type, o.str(), false, iter, false); } out << eb; iter++; } } } } bool Slice::JavaGenerator::getTypeMetaData(const StringList& metaData, string& concreteType, string& abstractType) { // // Extract the concrete type and an optional abstract type. // The correct syntax is "java:type:concrete-type[:abstract-type]". // static const string prefix = "java:type:"; for(StringList::const_iterator q = metaData.begin(); q != metaData.end(); ++q) { string str = *q; if(str.find(prefix) == 0) { string::size_type pos = str.find(':', prefix.size()); if(pos != string::npos) { concreteType = str.substr(prefix.size(), pos - prefix.size()); abstractType = str.substr(pos + 1); } else { concreteType = str.substr(prefix.size()); abstractType.clear(); } return true; } } return false; } bool Slice::JavaGenerator::hasTypeMetaData(const TypePtr& type, const StringList& localMetaData) { ContainedPtr cont = ContainedPtr::dynamicCast(type); if(cont) { static const string prefix = "java:type:"; StringList::const_iterator q; for(q = localMetaData.begin(); q != localMetaData.end(); ++q) { string str = *q; if(str.find(prefix) == 0) { return true; } } StringList metaData = cont->getMetaData(); for(q = metaData.begin(); q != metaData.end(); ++q) { string str = *q; if(str.find(prefix) == 0) { return true; } } } return false; } bool Slice::JavaGenerator::getDictionaryTypes(const DictionaryPtr& dict, const string& package, const StringList& metaData, string& concreteType, string& abstractType) const { bool customType = false; if(_featureProfile == Slice::IceE) { concreteType = abstractType = "java.util.Hashtable"; return customType; } bool java2 = dict->definitionContext()->findMetaData(_java2MetaData) == _java2MetaData; // // Collect metadata for a custom type. // string ct, at; customType = getTypeMetaData(metaData, ct, at); if(!customType) { customType = getTypeMetaData(dict->getMetaData(), ct, at); } // // Get the types of the key and value. // string keyTypeStr; string valueTypeStr; if(!java2) { keyTypeStr = typeToObjectString(dict->keyType(), TypeModeIn, package); valueTypeStr = typeToObjectString(dict->valueType(), TypeModeIn, package); } // // Handle a custom type. // if(customType) { assert(!ct.empty()); // // Check for portable syntax. Convert {type} to type for Java5. // if(ct[0] == '{') { string::size_type pos = ct.find('}'); if(pos != string::npos) { concreteType = ct.substr(1, pos - 1); if(!java2) { concreteType += "<" + keyTypeStr + ", " + valueTypeStr + ">"; } } } else { concreteType = ct; } if(!at.empty()) { if(at[0] == '{') { string::size_type pos = at.find('}'); if(pos != string::npos) { abstractType = at.substr(1, pos - 1); if(!java2) { abstractType += "<" + keyTypeStr + ", " + valueTypeStr + ">"; } } } else { abstractType = at; } } } // // Return a default type for the platform. // if(concreteType.empty()) { concreteType = "java.util.HashMap"; if(!java2) { concreteType += "<" + keyTypeStr + ", " + valueTypeStr + ">"; } } // // If an abstract type is not defined, we use the concrete type as the default. // If instead we chose a default abstract type, such as Map, then we // might inadvertently generate uncompilable code. The Java5 compiler does not // allow polymorphic assignment between generic types if it can weaken the // compile-time type safety rules. // if(abstractType.empty()) { abstractType = "java.util.Map"; if(!java2) { abstractType += "<" + keyTypeStr + ", " + valueTypeStr + ">"; } } return customType; } bool Slice::JavaGenerator::getSequenceTypes(const SequencePtr& seq, const string& package, const StringList& metaData, string& concreteType, string& abstractType) const { bool customType = false; if(_featureProfile == Slice::IceE) { concreteType = abstractType = typeToString(seq->type(), TypeModeIn, package) + "[]"; return customType; } bool java2 = seq->definitionContext()->findMetaData(_java2MetaData) == _java2MetaData; // // Collect metadata for a custom type. // string ct, at; customType = getTypeMetaData(metaData, ct, at); if(!customType) { customType = getTypeMetaData(seq->getMetaData(), ct, at); } // // Get the inner type. // string typeStr; if(!java2) { typeStr = typeToObjectString(seq->type(), TypeModeIn, package); } // // Handle a custom type. // if(customType) { assert(!ct.empty()); // // Check for portable syntax. Convert {type} to type for Java5. // if(ct[0] == '{') { string::size_type pos = ct.find('}'); if(pos != string::npos) { concreteType = ct.substr(1, pos - 1); if(!java2) { concreteType += "<" + typeStr + ">"; } } } else { concreteType = ct; } if(!at.empty()) { if(at[0] == '{') { string::size_type pos = at.find('}'); if(pos != string::npos) { abstractType = at.substr(1, pos - 1); if(!java2) { abstractType += "<" + typeStr + ">"; } } } else { abstractType = at; } } else { // // If an abstract type is not defined, we use the concrete type as the default. // If instead we chose a default abstract type, such as List, then we // might inadvertently generate uncompilable code. The Java5 compiler does not // allow polymorphic assignment between generic types if it can weaken the // compile-time type safety rules. // abstractType = "java.util.List"; if(!java2) { abstractType += "<" + typeStr + ">"; } } } // // The default mapping is a native array. // if(concreteType.empty()) { concreteType = abstractType = typeToString(seq->type(), TypeModeIn, package) + "[]"; } return customType; } JavaOutput* Slice::JavaGenerator::createOutput() { return new JavaOutput; } void Slice::JavaGenerator::validateMetaData(const UnitPtr& u) { MetaDataVisitor visitor; u->visit(&visitor, true); } bool Slice::JavaGenerator::MetaDataVisitor::visitModuleStart(const ModulePtr& p) { // // Validate global metadata. // DefinitionContextPtr dc = p->definitionContext(); assert(dc); StringList globalMetaData = dc->getMetaData(); string file = dc->filename(); static const string prefix = "java:"; for(StringList::const_iterator q = globalMetaData.begin(); q != globalMetaData.end(); ++q) { string s = *q; if(_history.count(s) == 0) { if(s.find(prefix) == 0) { bool ok = false; static const string packagePrefix = "java:package:"; if(s.find(packagePrefix) == 0 && s.size() > packagePrefix.size()) { ok = true; } else if(s == _java2MetaData) { ok = true; } else if(s == _java5MetaData) { ok = true; } if(!ok) { cout << file << ": warning: ignoring invalid global metadata `" << s << "'" << endl; } } _history.insert(s); } } StringList metaData = getMetaData(p); validateType(p, metaData, p->definitionContext()->filename(), p->line()); validateGetSet(p, metaData, p->definitionContext()->filename(), p->line()); return true; } void Slice::JavaGenerator::MetaDataVisitor::visitClassDecl(const ClassDeclPtr& p) { StringList metaData = getMetaData(p); validateType(p, metaData, p->definitionContext()->filename(), p->line()); validateGetSet(p, metaData, p->definitionContext()->filename(), p->line()); } bool Slice::JavaGenerator::MetaDataVisitor::visitClassDefStart(const ClassDefPtr& p) { StringList metaData = getMetaData(p); validateType(p, metaData, p->definitionContext()->filename(), p->line()); validateGetSet(p, metaData, p->definitionContext()->filename(), p->line()); return true; } bool Slice::JavaGenerator::MetaDataVisitor::visitExceptionStart(const ExceptionPtr& p) { StringList metaData = getMetaData(p); validateType(p, metaData, p->definitionContext()->filename(), p->line()); validateGetSet(p, metaData, p->definitionContext()->filename(), p->line()); return true; } bool Slice::JavaGenerator::MetaDataVisitor::visitStructStart(const StructPtr& p) { StringList metaData = getMetaData(p); validateType(p, metaData, p->definitionContext()->filename(), p->line()); validateGetSet(p, metaData, p->definitionContext()->filename(), p->line()); return true; } void Slice::JavaGenerator::MetaDataVisitor::visitOperation(const OperationPtr& p) { StringList metaData = getMetaData(p); TypePtr returnType = p->returnType(); if(!metaData.empty()) { if(!returnType) { for(StringList::const_iterator q = metaData.begin(); q != metaData.end(); ++q) { if(q->find("java:type:", 0) == 0) { cout << p->definitionContext()->filename() << ":" << p->line() << ": warning: invalid metadata for operation" << endl; break; } } } else { validateType(returnType, metaData, p->definitionContext()->filename(), p->line()); } } ParamDeclList params = p->parameters(); for(ParamDeclList::iterator q = params.begin(); q != params.end(); ++q) { metaData = getMetaData(*q); validateType((*q)->type(), metaData, p->definitionContext()->filename(), (*q)->line()); } validateGetSet(p, metaData, p->definitionContext()->filename(), p->line()); } void Slice::JavaGenerator::MetaDataVisitor::visitDataMember(const DataMemberPtr& p) { StringList metaData = getMetaData(p); validateType(p->type(), metaData, p->definitionContext()->filename(), p->line()); validateGetSet(p, metaData, p->definitionContext()->filename(), p->line()); } void Slice::JavaGenerator::MetaDataVisitor::visitSequence(const SequencePtr& p) { StringList metaData = getMetaData(p); validateType(p, metaData, p->definitionContext()->filename(), p->line()); validateGetSet(p, metaData, p->definitionContext()->filename(), p->line()); } void Slice::JavaGenerator::MetaDataVisitor::visitDictionary(const DictionaryPtr& p) { StringList metaData = getMetaData(p); validateType(p, metaData, p->definitionContext()->filename(), p->line()); validateGetSet(p, metaData, p->definitionContext()->filename(), p->line()); } void Slice::JavaGenerator::MetaDataVisitor::visitEnum(const EnumPtr& p) { StringList metaData = getMetaData(p); validateType(p, metaData, p->definitionContext()->filename(), p->line()); validateGetSet(p, metaData, p->definitionContext()->filename(), p->line()); } void Slice::JavaGenerator::MetaDataVisitor::visitConst(const ConstPtr& p) { StringList metaData = getMetaData(p); validateType(p, metaData, p->definitionContext()->filename(), p->line()); validateGetSet(p, metaData, p->definitionContext()->filename(), p->line()); } StringList Slice::JavaGenerator::MetaDataVisitor::getMetaData(const ContainedPtr& cont) { StringList metaData = cont->getMetaData(); DefinitionContextPtr dc = cont->definitionContext(); assert(dc); string file = dc->filename(); StringList result; static const string prefix = "java:"; for(StringList::const_iterator p = metaData.begin(); p != metaData.end(); ++p) { string s = *p; if(_history.count(s) == 0) // Don't complain about the same metadata more than once. { if(s.find(prefix) == 0) { string::size_type pos = s.find(':', prefix.size()); if(pos == string::npos) { if(s.size() > prefix.size()) { string rest = s.substr(prefix.size()); if(rest == "getset") { result.push_back(s); } continue; } } else if(s.substr(prefix.size(), pos - prefix.size()) == "type") { result.push_back(s); continue; } cout << file << ":" << cont->line() << ": warning: ignoring invalid metadata `" << s << "'" << endl; } _history.insert(s); } } return result; } void Slice::JavaGenerator::MetaDataVisitor::validateType(const SyntaxTreeBasePtr& p, const StringList& metaData, const string& file, const string& line) { for(StringList::const_iterator i = metaData.begin(); i != metaData.end(); ++i) { // // Type metadata ("java:type:Foo") is only supported by sequences and dictionaries. // if(i->find("java:type:", 0) == 0 && (!SequencePtr::dynamicCast(p) && !DictionaryPtr::dynamicCast(p))) { string str; ContainedPtr cont = ContainedPtr::dynamicCast(p); if(cont) { str = cont->kindOf(); } else { BuiltinPtr b = BuiltinPtr::dynamicCast(p); assert(b); str = b->typeId(); } cout << file << ":" << line << ": warning: invalid metadata for " << str << endl; } } } void Slice::JavaGenerator::MetaDataVisitor::validateGetSet(const SyntaxTreeBasePtr& p, const StringList& metaData, const string& file, const string& line) { for(StringList::const_iterator i = metaData.begin(); i != metaData.end(); ++i) { // // The "getset" metadata can only be specified on a class, struct, exception or data member. // if((*i) == "java:getset" && (!ClassDefPtr::dynamicCast(p) && !StructPtr::dynamicCast(p) && !ExceptionPtr::dynamicCast(p) && !DataMemberPtr::dynamicCast(p))) { string str; ContainedPtr cont = ContainedPtr::dynamicCast(p); if(cont) { str = cont->kindOf(); } else { BuiltinPtr b = BuiltinPtr::dynamicCast(p); assert(b); str = b->typeId(); } cout << file << ":" << line << ": warning: invalid metadata for " << str << endl; } } } IceE-trans-1.2.0/src/slice2cppe/0000775000076400007640000000000010620635756015650 5ustar dwaynedwayneIceE-trans-1.2.0/src/slice2cppe/Gen.h0000664000076400007640000002164610576520443016537 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** #ifndef GEN_H #define GEN_H #include #include // // The Ice-E version. // #define ICEE_STRING_VERSION "1.2.0" // "A.B.C", with A=major, B=minor, C=patch #define ICEE_INT_VERSION 10200 // AABBCC, with AA=major, BB=minor, CC=patch namespace Slice { class Gen : private ::IceUtil::noncopyable { public: Gen(const std::string&, const std::string&, const std::string&, const std::string&, const std::vector&, const std::string&, const std::vector&, const std::string&, const std::string&, bool, bool); ~Gen(); bool operator!() const; // Returns true if there was a constructor error void generate(const UnitPtr&); static bool setUseWstring(ContainedPtr, std::list&, bool); static bool resetUseWstring(std::list&); private: void writeExtraHeaders(::IceUtil::Output&); ::IceUtil::Output H; ::IceUtil::Output C; ::IceUtil::Output implH; ::IceUtil::Output implC; std::string _base; std::string _headerExtension; std::string _sourceExtension; std::vector _extraHeaders; std::string _include; std::vector _includePaths; std::string _dllExport; bool _impl; bool _ice; class GlobalIncludeVisitor : private ::IceUtil::noncopyable, public ParserVisitor { public: GlobalIncludeVisitor(::IceUtil::Output&); virtual bool visitModuleStart(const ModulePtr&); private: ::IceUtil::Output& H; bool _finished; }; class TypesVisitor : private ::IceUtil::noncopyable, public ParserVisitor { public: TypesVisitor(::IceUtil::Output&, ::IceUtil::Output&, const std::string&); virtual bool visitModuleStart(const ModulePtr&); virtual void visitModuleEnd(const ModulePtr&); virtual bool visitClassDefStart(const ClassDefPtr&); virtual bool visitExceptionStart(const ExceptionPtr&); virtual void visitExceptionEnd(const ExceptionPtr&); virtual bool visitStructStart(const StructPtr&); virtual void visitStructEnd(const StructPtr&); virtual void visitSequence(const SequencePtr&); virtual void visitDictionary(const DictionaryPtr&); virtual void visitEnum(const EnumPtr&); virtual void visitConst(const ConstPtr&); virtual void visitDataMember(const DataMemberPtr&); private: void emitUpcall(const ExceptionPtr&, const std::string&, bool = false); ::IceUtil::Output& H; ::IceUtil::Output& C; std::string _dllExport; bool _doneStaticSymbol; bool _useWstring; std::list _useWstringHist; }; class ProxyDeclVisitor : private ::IceUtil::noncopyable, public ParserVisitor { public: ProxyDeclVisitor(::IceUtil::Output&, ::IceUtil::Output&, const std::string&); virtual bool visitUnitStart(const UnitPtr&); virtual void visitUnitEnd(const UnitPtr&); virtual bool visitModuleStart(const ModulePtr&); virtual void visitModuleEnd(const ModulePtr&); virtual void visitClassDecl(const ClassDeclPtr&); private: ::IceUtil::Output& H; ::IceUtil::Output& C; std::string _dllExport; }; class ProxyVisitor : private ::IceUtil::noncopyable, public ParserVisitor { public: ProxyVisitor(::IceUtil::Output&, ::IceUtil::Output&, const std::string&); virtual bool visitUnitStart(const UnitPtr&); virtual void visitUnitEnd(const UnitPtr&); virtual bool visitModuleStart(const ModulePtr&); virtual void visitModuleEnd(const ModulePtr&); virtual bool visitClassDefStart(const ClassDefPtr&); virtual void visitClassDefEnd(const ClassDefPtr&); virtual void visitOperation(const OperationPtr&); private: ::IceUtil::Output& H; ::IceUtil::Output& C; std::string _dllExport; bool _useWstring; std::list _useWstringHist; }; class ObjectDeclVisitor : private ::IceUtil::noncopyable, public ParserVisitor { public: ObjectDeclVisitor(::IceUtil::Output&, ::IceUtil::Output&, const std::string&); virtual bool visitModuleStart(const ModulePtr&); virtual void visitModuleEnd(const ModulePtr&); virtual void visitClassDecl(const ClassDeclPtr&); private: ::IceUtil::Output& H; ::IceUtil::Output& C; std::string _dllExport; }; class ObjectVisitor : private ::IceUtil::noncopyable, public ParserVisitor { public: ObjectVisitor(::IceUtil::Output&, ::IceUtil::Output&, const std::string&); virtual bool visitModuleStart(const ModulePtr&); virtual void visitModuleEnd(const ModulePtr&); virtual bool visitClassDefStart(const ClassDefPtr&); virtual void visitClassDefEnd(const ClassDefPtr&); virtual bool visitExceptionStart(const ExceptionPtr&); virtual bool visitStructStart(const StructPtr&); virtual void visitOperation(const OperationPtr&); virtual void visitDataMember(const DataMemberPtr&); private: bool emitVirtualBaseInitializers(const ClassDefPtr&); void emitOneShotConstructor(const ClassDefPtr&); void emitUpcall(const ClassDefPtr&, const std::string&); ::IceUtil::Output& H; ::IceUtil::Output& C; std::string _dllExport; bool _useWstring; std::list _useWstringHist; }; class IceInternalVisitor : private ::IceUtil::noncopyable, public ParserVisitor { public: IceInternalVisitor(::IceUtil::Output&, ::IceUtil::Output&, const std::string&); virtual bool visitUnitStart(const UnitPtr&); virtual void visitUnitEnd(const UnitPtr&); virtual void visitClassDecl(const ClassDeclPtr&); virtual bool visitClassDefStart(const ClassDefPtr&); private: ::IceUtil::Output& H; ::IceUtil::Output& C; std::string _dllExport; }; class HandleVisitor : private ::IceUtil::noncopyable, public ParserVisitor { public: HandleVisitor(::IceUtil::Output&, ::IceUtil::Output&, const std::string&); virtual bool visitModuleStart(const ModulePtr&); virtual void visitModuleEnd(const ModulePtr&); virtual void visitClassDecl(const ClassDeclPtr&); virtual bool visitClassDefStart(const ClassDefPtr&); private: ::IceUtil::Output& H; ::IceUtil::Output& C; std::string _dllExport; }; class ImplVisitor : private ::IceUtil::noncopyable, public ParserVisitor { public: ImplVisitor(::IceUtil::Output&, ::IceUtil::Output&, const std::string&); virtual bool visitModuleStart(const ModulePtr&); virtual void visitModuleEnd(const ModulePtr&); virtual bool visitClassDefStart(const ClassDefPtr&); private: ::IceUtil::Output& H; ::IceUtil::Output& C; std::string _dllExport; bool _useWstring; std::list _useWstringHist; // // Generate code to return a dummy value // void writeReturn(::IceUtil::Output&, const TypePtr&, const StringList&); }; class MetaDataVisitor : public ParserVisitor { public: virtual bool visitModuleStart(const ModulePtr&); virtual void visitModuleEnd(const ModulePtr&); virtual void visitClassDecl(const ClassDeclPtr&); virtual bool visitClassDefStart(const ClassDefPtr&); virtual void visitClassDefEnd(const ClassDefPtr&); virtual bool visitExceptionStart(const ExceptionPtr&); virtual void visitExceptionEnd(const ExceptionPtr&); virtual bool visitStructStart(const StructPtr&); virtual void visitStructEnd(const StructPtr&); virtual void visitOperation(const OperationPtr&); virtual void visitParamDecl(const ParamDeclPtr&); virtual void visitDataMember(const DataMemberPtr&); virtual void visitSequence(const SequencePtr&); virtual void visitDictionary(const DictionaryPtr&); virtual void visitEnum(const EnumPtr&); virtual void visitConst(const ConstPtr&); private: void validate(const SyntaxTreeBasePtr&, const StringList&, const std::string&, const std::string&, bool = false); StringSet _history; }; static void validateMetaData(const UnitPtr&); static void printHeader(IceUtil::Output&); static void printVersionCheck(IceUtil::Output&); static void printDllExportStuff(IceUtil::Output&, const std::string&); }; } #endif IceE-trans-1.2.0/src/slice2cppe/.depend0000664000076400007640000000141510562516517017107 0ustar dwaynedwayneGen$(OBJEXT): Gen.cpp Gen.h ../../include/Slice/Parser.h ../../include/IceUtil/Shared.h ../../include/IceUtil/Config.h ../../include/IceUtil/Handle.h ../../include/IceUtil/Exception.h ../../include/IceUtil/InputUtil.h ../../include/IceUtil/OutputUtil.h ../../include/Slice/CPlusPlusUtil.h ../../include/IceUtil/Functional.h ../../include/IceUtil/Iterator.h Main$(OBJEXT): Main.cpp ../../include/IceUtil/Options.h ../../include/IceUtil/Config.h ../../include/IceUtil/RecMutex.h ../../include/IceUtil/Lock.h ../../include/IceUtil/ThreadException.h ../../include/IceUtil/Exception.h ../../include/IceUtil/Shared.h ../../include/IceUtil/Handle.h ../../include/Slice/Preprocessor.h Gen.h ../../include/Slice/Parser.h ../../include/IceUtil/InputUtil.h ../../include/IceUtil/OutputUtil.h IceE-trans-1.2.0/src/slice2cppe/Makefile0000664000076400007640000000126410616353534017307 0ustar dwaynedwayne# ********************************************************************** # # Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. # # This copy of Ice is licensed to you under the terms described in the # ICE_LICENSE file included in this distribution. # # ********************************************************************** top_srcdir = ../.. NAME = $(top_srcdir)/bin/slice2cppe TARGETS = $(NAME) OBJS = Gen.o \ Main.o SRCS = $(OBJS:.o=.cpp) include $(top_srcdir)/config/Make.rules CPPFLAGS := -I. $(CPPFLAGS) $(NAME): $(OBJS) rm -f $@ $(CXX) $(LDFLAGS) -o $@ $(OBJS) -lSlice $(BASELIBS) install:: all $(INSTALL_PROGRAM) $(NAME) $(install_bindir) include .depend IceE-trans-1.2.0/src/slice2cppe/Makefile.mak0000664000076400007640000000235510616353534020060 0ustar dwaynedwayne# ********************************************************************** # # Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. # # This copy of Ice is licensed to you under the terms described in the # ICE_LICENSE file included in this distribution. # # ********************************************************************** top_srcdir = ..\.. NAME = $(top_srcdir)\bin\slice2cppe.exe TARGETS = $(NAME) OBJS = Gen.obj \ Main.obj SRCS = $(OBJS:.obj=.cpp) !include $(top_srcdir)/config/Make.rules.mak CPPFLAGS = -I. $(CPPFLAGS) -DWIN32_LEAN_AND_MEAN !if "$(CPP_COMPILER)" != "BCC2006" & "$(OPTIMIZE)" != "yes" PDBFLAGS = /pdb:$(NAME:.exe=.pdb) !endif $(NAME): $(OBJS) $(LINK) $(LD_EXEFLAGS) $(PDBFLAGS) $(OBJS) $(SETARGV) $(PREOUT)$@ $(PRELIBS)slice$(LIBSUFFIX).lib $(BASELIBS) @if exist $@.manifest echo ^ ^ ^ Embedding manifest using $(MT) && \ $(MT) -nologo -manifest $@.manifest -outputresource:$@;#1 && del /q $@.manifest clean:: del /q $(NAME:.exe=.*) install:: all copy $(NAME) $(install_bindir) !if "$(OPTIMIZE)" != "yes" !if "$(CPP_COMPILER)" == "BCC2006" install:: all copy $(NAME:.exe=.tds) $(install_bindir) !else install:: all copy $(NAME:.exe=.pdb) $(install_bindir) !endif !endif !include .depend IceE-trans-1.2.0/src/slice2cppe/Main.cpp0000664000076400007640000001465710561612334017244 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 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 using namespace std; using namespace Slice; void usage(const char* n) { cerr << "Usage: " << n << " [options] slice-files...\n"; cerr << "Options:\n" "-h, --help Show this message.\n" "-v, --version Display the Ice version.\n" "--header-ext EXT Use EXT instead of the default `h' extension.\n" "--source-ext EXT Use EXT instead of the default `cpp' extension.\n" "--add-header HDR[,GUARD] 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" "--output-dir DIR Create files in the directory DIR.\n" "--dll-export SYMBOL Use SYMBOL for DLL exports.\n" "--impl Generate sample implementations.\n" "--depend Generate Makefile dependencies.\n" "-d, --debug Print debug messages.\n" "--ice Permit `Ice' prefix (for building Ice source code only)\n" ; // Note: --case-sensitive is intentionally not shown here! } int main(int argc, char* argv[]) { IceUtil::Options opts; opts.addOpt("h", "help"); opts.addOpt("v", "version"); opts.addOpt("", "header-ext", IceUtil::Options::NeedArg, "h"); opts.addOpt("", "source-ext", IceUtil::Options::NeedArg, "cpp"); opts.addOpt("", "add-header", IceUtil::Options::NeedArg, "", IceUtil::Options::Repeat); opts.addOpt("D", "", IceUtil::Options::NeedArg, "", IceUtil::Options::Repeat); opts.addOpt("U", "", IceUtil::Options::NeedArg, "", IceUtil::Options::Repeat); opts.addOpt("I", "", IceUtil::Options::NeedArg, "", IceUtil::Options::Repeat); opts.addOpt("E"); opts.addOpt("", "include-dir", IceUtil::Options::NeedArg); opts.addOpt("", "output-dir", IceUtil::Options::NeedArg); opts.addOpt("", "dll-export", IceUtil::Options::NeedArg); opts.addOpt("", "impl"); opts.addOpt("", "depend"); opts.addOpt("d", "debug"); opts.addOpt("", "ice"); opts.addOpt("", "case-sensitive"); vector args; try { args = opts.parse(argc, (const char**)argv); } catch(const IceUtil::BadOptException& e) { cerr << argv[0] << ": " << e.reason << endl; usage(argv[0]); return EXIT_FAILURE; } if(opts.isSet("help")) { usage(argv[0]); return EXIT_SUCCESS; } if(opts.isSet("version")) { cout << ICEE_STRING_VERSION << endl; return EXIT_SUCCESS; } string headerExtension = opts.optArg("header-ext"); string sourceExtension = opts.optArg("source-ext"); vectorextraHeaders = opts.argVec("add-header"); string cppArgs; vector optargs = opts.argVec("D"); vector::const_iterator i; for(i = optargs.begin(); i != optargs.end(); ++i) { cppArgs += " -D" + Preprocessor::addQuotes(*i); } optargs = opts.argVec("U"); for(i = optargs.begin(); i != optargs.end(); ++i) { cppArgs += " -U" + Preprocessor::addQuotes(*i); } vector includePaths = opts.argVec("I"); for(i = includePaths.begin(); i != includePaths.end(); ++i) { cppArgs += " -I" + Preprocessor::normalizeIncludePath(*i); } bool preprocess = opts.isSet("E"); string include = opts.optArg("include-dir"); string output = opts.optArg("output-dir"); string dllExport = opts.optArg("dll-export"); bool impl = opts.isSet("impl"); bool depend = opts.isSet("depend"); bool debug = opts.isSet("debug"); bool ice = opts.isSet("ice"); bool caseSensitive = opts.isSet("case-sensitive"); if(args.empty()) { cerr << argv[0] << ": no input file" << endl; usage(argv[0]); return EXIT_FAILURE; } int status = EXIT_SUCCESS; for(i = args.begin(); i != args.end(); ++i) { if(depend) { Preprocessor icecpp(argv[0], *i, cppArgs); icecpp.printMakefileDependencies(Preprocessor::CPlusPlus); } else { Preprocessor icecpp(argv[0], *i, cppArgs); FILE* cppHandle = icecpp.preprocess(false); if(cppHandle == 0) { return EXIT_FAILURE; } if(preprocess) { char buf[4096]; while(fgets(buf, static_cast(sizeof(buf)), cppHandle) != NULL) { if(fputs(buf, stdout) == EOF) { return EXIT_FAILURE; } } if(!icecpp.close()) { return EXIT_FAILURE; } } else { UnitPtr u = Unit::createUnit(false, false, ice, caseSensitive); int parseStatus = u->parse(cppHandle, debug, Slice::IceE); if(!icecpp.close()) { u->destroy(); return EXIT_FAILURE; } if(parseStatus == EXIT_FAILURE) { status = EXIT_FAILURE; } else { Gen gen(argv[0], icecpp.getBaseName(), headerExtension, sourceExtension, extraHeaders, include, includePaths, dllExport, output, impl, ice); if(!gen) { u->destroy(); return EXIT_FAILURE; } gen.generate(u); } u->destroy(); } } } return status; } IceE-trans-1.2.0/src/slice2cppe/Gen.cpp0000664000076400007640000025521110616353534017067 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 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 using namespace std; using namespace Slice; using namespace IceUtil; static void getIds(const ClassDefPtr& p, StringList& ids) { ClassList allBases = p->allBases(); #if defined(__IBMCPP__) && defined(NDEBUG) // // VisualAge C++ 6.0 does not see that ClassDef is a Contained, // when inlining is on. The code below issues a warning: better // than an error! // transform(allBases.begin(), allBases.end(), back_inserter(ids), ::IceUtil::constMemFun(&Contained::scoped)); #else transform(allBases.begin(), allBases.end(), back_inserter(ids), ::IceUtil::constMemFun(&Contained::scoped)); #endif StringList other; other.push_back(p->scoped()); other.push_back("::Ice::Object"); other.sort(); ids.merge(other); ids.unique(); } static string getDeprecateSymbol(const ContainedPtr& p1, const ContainedPtr& p2) { string deprecateMetadata, deprecateSymbol; if(p1->findMetaData("deprecate", deprecateMetadata) || (p2 != 0 && p2->findMetaData("deprecate", deprecateMetadata))) { deprecateSymbol = "ICE_DEPRECATED_API "; } return deprecateSymbol; } Slice::Gen::Gen(const string& name, const string& base, const string& headerExtension, const string& sourceExtension, const vector& extraHeaders, const string& include, const vector& includePaths, const string& dllExport, const string& dir, bool imp, bool ice) : _base(base), _headerExtension(headerExtension), _sourceExtension(sourceExtension), _extraHeaders(extraHeaders), _include(include), _includePaths(includePaths), _dllExport(dllExport), _impl(imp), _ice(ice) { Slice::featureProfile = Slice::IceE; for(vector::iterator p = _includePaths.begin(); p != _includePaths.end(); ++p) { if(p->length() && (*p)[p->length() - 1] != '/') { *p += '/'; } } string::size_type pos = _base.find_last_of("/\\"); if(pos != string::npos) { _base.erase(0, pos + 1); } if(_impl) { string fileImplH = _base + "I." + _headerExtension; string fileImplC = _base + "I." + _sourceExtension; if(!dir.empty()) { fileImplH = dir + '/' + fileImplH; fileImplC = dir + '/' + fileImplC; } struct stat st; if(stat(fileImplH.c_str(), &st) == 0) { cerr << name << ": `" << fileImplH << "' already exists - will not overwrite" << endl; return; } if(stat(fileImplC.c_str(), &st) == 0) { cerr << name << ": `" << fileImplC << "' already exists - will not overwrite" << endl; return; } implH.open(fileImplH.c_str()); if(!implH) { cerr << name << ": can't open `" << fileImplH << "' for writing" << endl; return; } implC.open(fileImplC.c_str()); if(!implC) { cerr << name << ": can't open `" << fileImplC << "' for writing" << endl; return; } string s = fileImplH; if(_include.size()) { s = _include + '/' + s; } transform(s.begin(), s.end(), s.begin(), ToIfdef()); implH << "#ifndef __" << s << "__"; implH << "\n#define __" << s << "__"; implH << '\n'; } string fileH = _base + "." + _headerExtension; string fileC = _base + "." + _sourceExtension; if(!dir.empty()) { fileH = dir + '/' + fileH; fileC = dir + '/' + fileC; } H.open(fileH.c_str()); if(!H) { cerr << name << ": can't open `" << fileH << "' for writing" << endl; return; } C.open(fileC.c_str()); if(!C) { cerr << name << ": can't open `" << fileC << "' for writing" << endl; return; } printHeader(H); printHeader(C); H << "\n// Generated from file `" << changeInclude(_base, _includePaths) << ".ice'\n"; C << "\n// Generated from file `" << changeInclude(_base, _includePaths) << ".ice'\n"; string s = fileH; if(_include.size()) { s = _include + '/' + s; } transform(s.begin(), s.end(), s.begin(), ToIfdef()); H << "\n#ifndef __" << s << "__"; H << "\n#define __" << s << "__"; H << '\n'; } Slice::Gen::~Gen() { H << "\n\n#endif\n"; C << '\n'; if(_impl) { implH << "\n\n#endif\n"; implC << '\n'; } } bool Slice::Gen::operator!() const { if(!H || !C) { return true; } if(_impl && (!implH || !implC)) { return true; } return false; } void Slice::Gen::generate(const UnitPtr& p) { validateMetaData(p); writeExtraHeaders(C); C << "\n#include <"; if(_include.size()) { C << _include << '/'; } C << _base << "." << _headerExtension << ">"; H << "\n#include "; H << "\n#ifndef ICEE_PURE_CLIENT"; H << "\n# include "; H << "\n#endif"; H << "\n#include "; H << "\n#include "; if(p->usesProxies()) { H << "\n#include "; } if(p->hasNonLocalClassDefs()) { H << "\n#ifndef ICEE_PURE_CLIENT"; H << "\n# include "; H << "\n# include "; H << "\n#endif"; H << "\n#include "; C << "\n#include "; C << "\n#include "; } else if(p->hasNonLocalClassDecls()) { H << "\n#ifndef ICEE_PURE_CLIENT"; H << "\n# include "; H << "\n#endif"; } if(p->hasNonLocalExceptions()) { H << "\n#include "; } if(p->hasDataOnlyClasses() || p->hasNonLocalExceptions()) { H << "\n#include "; } if(p->usesNonLocals()) { C << "\n#include "; if(!p->hasNonLocalClassDefs() && !p->hasNonLocalClassDecls()) { C << "\n#ifndef ICEE_PURE_CLIENT"; C << "\n# include "; C << "\n#endif"; } } if(p->hasNonLocalExceptions()) { C << "\n#include "; } C << "\n#include "; StringList includes = p->includeFiles(); for(StringList::const_iterator q = includes.begin(); q != includes.end(); ++q) { H << "\n#include <" << changeInclude(*q, _includePaths) << "." << _headerExtension << ">"; } H << "\n#include "; if(_ice) { C << "\n#include "; } GlobalIncludeVisitor globalIncludeVisitor(H); p->visit(&globalIncludeVisitor, false); printVersionCheck(H); printVersionCheck(C); printDllExportStuff(H, _dllExport); if(_dllExport.size()) { _dllExport += " "; } ProxyDeclVisitor proxyDeclVisitor(H, C, _dllExport); p->visit(&proxyDeclVisitor, false); ObjectDeclVisitor objectDeclVisitor(H, C, _dllExport); p->visit(&objectDeclVisitor, false); IceInternalVisitor iceInternalVisitor(H, C, _dllExport); p->visit(&iceInternalVisitor, false); HandleVisitor handleVisitor(H, C, _dllExport); p->visit(&handleVisitor, false); TypesVisitor typesVisitor(H, C, _dllExport); p->visit(&typesVisitor, false); ObjectVisitor objectVisitor(H, C, _dllExport); p->visit(&objectVisitor, false); ProxyVisitor proxyVisitor(H, C, _dllExport); p->visit(&proxyVisitor, false); if(_impl) { implH << "\n#include <"; if(_include.size()) { implH << _include << '/'; } implH << _base << ".h>"; writeExtraHeaders(implC); implC << "\n#include <"; if(_include.size()) { implC << _include << '/'; } implC << _base << "I.h>"; ImplVisitor implVisitor(implH, implC, _dllExport); p->visit(&implVisitor, false); } } void Slice::Gen::writeExtraHeaders(Output& out) { 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()) { out << "\n#ifndef " << guard; out << "\n#define " << guard; } out << "\n#include <"; if(!_include.empty()) { out << _include << '/'; } out << hdr << '>'; if(!guard.empty()) { out << "\n#endif"; } } } Slice::Gen::GlobalIncludeVisitor::GlobalIncludeVisitor(Output& h) : H(h), _finished(false) { } bool Slice::Gen::GlobalIncludeVisitor::visitModuleStart(const ModulePtr& p) { if(!_finished) { DefinitionContextPtr dc = p->definitionContext(); assert(dc); StringList globalMetaData = dc->getMetaData(); static const string includePrefix = "cpp:include:"; for(StringList::const_iterator q = globalMetaData.begin(); q != globalMetaData.end(); ++q) { string s = *q; if(s.find(includePrefix) == 0) { H << nl << "#include <" << s.substr(includePrefix.size()) << ">"; } } _finished = true; } return false; } Slice::Gen::TypesVisitor::TypesVisitor(Output& h, Output& c, const string& dllExport) : H(h), C(c), _dllExport(dllExport), _doneStaticSymbol(false), _useWstring(false) { } bool Slice::Gen::TypesVisitor::visitModuleStart(const ModulePtr& p) { _useWstring = setUseWstring(p, _useWstringHist, _useWstring); string name = fixKwd(p->name()); H << sp << nl << "namespace " << name << nl << '{'; return true; } void Slice::Gen::TypesVisitor::visitModuleEnd(const ModulePtr& p) { H << sp << nl << '}'; _useWstring = resetUseWstring(_useWstringHist); } bool Slice::Gen::TypesVisitor::visitClassDefStart(const ClassDefPtr&) { return false; } bool Slice::Gen::TypesVisitor::visitExceptionStart(const ExceptionPtr& p) { _useWstring = setUseWstring(p, _useWstringHist, _useWstring); string name = fixKwd(p->name()); string scoped = fixKwd(p->scoped()); ExceptionPtr base = p->base(); DataMemberList dataMembers = p->dataMembers(); DataMemberList allDataMembers = p->allDataMembers(); DataMemberList::const_iterator q; vector params; vector allTypes; vector allParamDecls; vector baseParams; vector::const_iterator pi; for(q = dataMembers.begin(); q != dataMembers.end(); ++q) { params.push_back(fixKwd((*q)->name())); } for(q = allDataMembers.begin(); q != allDataMembers.end(); ++q) { string typeName = inputTypeToString((*q)->type(), _useWstring, (*q)->getMetaData()); allTypes.push_back(typeName); allParamDecls.push_back(typeName + " __ice_" + (*q)->name()); } if(base) { DataMemberList baseDataMembers = base->allDataMembers(); for(q = baseDataMembers.begin(); q != baseDataMembers.end(); ++q) { baseParams.push_back("__ice_" + (*q)->name()); } } H << sp << nl << "class " << _dllExport << name << " : "; H.useCurrentPosAsIndent(); H << "public "; if(!base) { H << (p->isLocal() ? "::Ice::LocalException" : "::Ice::UserException"); } else { H << fixKwd(base->scoped()); } H.restoreIndent(); H << sb; H.dec(); H << nl << "public:"; H.inc(); H << sp << nl << name << spar; if(p->isLocal()) { H << "const char*" << "int"; } H << epar; if(!p->isLocal()) { H << " {}"; } else { H << ';'; } if(!allTypes.empty()) { H << nl; if(!p->isLocal() && allTypes.size() == 1) { H << "explicit "; } H << name << spar; if(p->isLocal()) { H << "const char*" << "int"; } H << allTypes << epar << ';'; } H << nl << "virtual ~" << name << "() throw();"; H << sp; if(p->isLocal()) { C << sp << nl << scoped.substr(2) << "::" << name << spar << "const char* __file" << "int __line" << epar << " :"; C.inc(); emitUpcall(base, "(__file, __line)", true); C.dec(); C << sb; C << eb; } if(!allTypes.empty()) { C << sp << nl; C << scoped.substr(2) << "::" << name << spar; if(p->isLocal()) { C << "const char* __file" << "int __line"; } C << allParamDecls << epar; if(p->isLocal() || !baseParams.empty() || !params.empty()) { C << " :"; C.inc(); string upcall; if(!allParamDecls.empty()) { upcall = "("; if(p->isLocal()) { upcall += "__file, __line"; } for(pi = baseParams.begin(); pi != baseParams.end(); ++pi) { if(p->isLocal() || pi != baseParams.begin()) { upcall += ", "; } upcall += *pi; } upcall += ")"; } if(!params.empty()) { upcall += ","; } emitUpcall(base, upcall, p->isLocal()); } for(pi = params.begin(); pi != params.end(); ++pi) { if(pi != params.begin()) { C << ","; } C << nl << *pi << "(__ice_" << *pi << ')'; } if(p->isLocal() || !baseParams.empty() || !params.empty()) { C.dec(); } C << sb; C << eb; } C << sp << nl; C << scoped.substr(2) << "::~" << name << "() throw()"; C << sb; C << eb; H << nl << "virtual ::std::string ice_name() const;"; string flatName = p->flattenedScope() + p->name() + "_name"; C << sp << nl << "static const char* " << flatName << " = \"" << p->scoped().substr(2) << "\";"; C << sp << nl << "::std::string" << nl << scoped.substr(2) << "::ice_name() const"; C << sb; C << nl << "return " << flatName << ';'; C << eb; if(p->isLocal()) { H << nl << "virtual ::std::string toString() const;"; } H << nl << "virtual ::Ice::Exception* ice_clone() const;"; C << sp << nl << "::Ice::Exception*" << nl << scoped.substr(2) << "::ice_clone() const"; C << sb; C << nl << "return new " << name << "(*this);"; C << eb; H << nl << "virtual void ice_throw() const;"; C << sp << nl << "void" << nl << scoped.substr(2) << "::ice_throw() const"; C << sb; C << nl << "throw *this;"; C << eb; if(!p->isLocal()) { H << sp << nl << "static const ::IceInternal::UserExceptionFactoryPtr& ice_factory();"; } if(!dataMembers.empty()) { H << sp; } return true; } void Slice::Gen::TypesVisitor::visitExceptionEnd(const ExceptionPtr& p) { string name = fixKwd(p->name()); string scope = fixKwd(p->scope()); string scoped = fixKwd(p->scoped()); DataMemberList dataMembers = p->dataMembers(); DataMemberList::const_iterator q; string factoryName; if(!p->isLocal()) { ExceptionPtr base = p->base(); H << sp << nl << "virtual void __write(::IceInternal::BasicStream*) const;"; H << nl << "virtual void __read(::IceInternal::BasicStream*, bool);"; C << sp << nl << "void" << nl << scoped.substr(2) << "::__write(::IceInternal::BasicStream* __os) const"; C << sb; C << nl << "__os->write(::std::string(\"" << p->scoped() << "\"), false);"; C << nl << "__os->startWriteSlice();"; for(q = dataMembers.begin(); q != dataMembers.end(); ++q) { writeMarshalUnmarshalCode(C, (*q)->type(), fixKwd((*q)->name()), true, "", true, (*q)->getMetaData()); } C << nl << "__os->endWriteSlice();"; if(base) { emitUpcall(base, "::__write(__os);"); } C << eb; C << sp << nl << "void" << nl << scoped.substr(2) << "::__read(::IceInternal::BasicStream* __is, bool __rid)"; C << sb; C << nl << "if(__rid)"; C << sb; C << nl << "::std::string myId;"; C << nl << "__is->read(myId, false);"; C << eb; C << nl << "__is->startReadSlice();"; for(q = dataMembers.begin(); q != dataMembers.end(); ++q) { writeMarshalUnmarshalCode(C, (*q)->type(), fixKwd((*q)->name()), false, "", true, (*q)->getMetaData()); } C << nl << "__is->endReadSlice();"; if(base) { emitUpcall(base, "::__read(__is, true);"); } C << eb; factoryName = "__F" + p->flattenedScope() + p->name(); C << sp << nl << "struct " << factoryName << " : public ::IceInternal::UserExceptionFactory"; C << sb; C << sp << nl << "virtual void"; C << nl << "createAndThrow()"; C << sb; C << nl << "throw " << scoped << "();"; C << eb; C << eb << ';'; C << sp << nl << "static ::IceInternal::UserExceptionFactoryPtr " << factoryName << "__Ptr = new " << factoryName << ';'; C << sp << nl << "const ::IceInternal::UserExceptionFactoryPtr&"; C << nl << scoped.substr(2) << "::ice_factory()"; C << sb; C << nl << "return " << factoryName << "__Ptr;"; C << eb; C << sp << nl << "class " << factoryName << "__Init"; C << sb; C.dec(); C << nl << "public:"; C.inc(); C << sp << nl << factoryName << "__Init()"; C << sb; C << nl << "::IceInternal::factoryTable->addExceptionFactory(\"" << p->scoped() << "\", " << scoped << "::ice_factory());"; C << eb; C << sp << nl << "~" << factoryName << "__Init()"; C << sb; C << nl << "::IceInternal::factoryTable->removeExceptionFactory(\"" << p->scoped() << "\");"; C << eb; C << eb << ';'; C << sp << nl << "static " << factoryName << "__Init "<< factoryName << "__i;"; C << sp << nl << "#ifdef __APPLE__"; string initfuncname = "__F" + p->flattenedScope() + p->name() + "__initializer"; C << nl << "extern \"C\" { void " << initfuncname << "() {} }"; C << nl << "#endif"; } H << eb << ';'; if(!p->isLocal()) { // // We need an instance here to trigger initialization if the implementation is in a shared libarry. // But we do this only once per source file, because a single instance is sufficient to initialize // all of the globals in a shared library. // if(!_doneStaticSymbol) { _doneStaticSymbol = true; H << sp << nl << "static " << name << " __" << p->name() << "_init;"; } } _useWstring = resetUseWstring(_useWstringHist); } bool Slice::Gen::TypesVisitor::visitStructStart(const StructPtr& p) { _useWstring = setUseWstring(p, _useWstringHist, _useWstring); string name = fixKwd(p->name()); H << sp << nl << "struct " << name; H << sb; return true; } void Slice::Gen::TypesVisitor::visitStructEnd(const StructPtr& p) { string name = fixKwd(p->name()); string scoped = fixKwd(p->scoped()); string scope = fixKwd(p->scope()); DataMemberList dataMembers = p->dataMembers(); DataMemberList::const_iterator q; vector params; vector::const_iterator pi; for(q = dataMembers.begin(); q != dataMembers.end(); ++q) { params.push_back(fixKwd((*q)->name())); } H << sp; H << nl << _dllExport << "bool operator==(const " << name << "&) const;"; H << nl << _dllExport << "bool operator<(const " << name << "&) const;"; H << nl << "bool operator!=(const " << name << "& __rhs) const"; H << sb; H << nl << "return !operator==(__rhs);"; H << eb; H << nl << "bool operator<=(const " << name << "& __rhs) const"; H << sb; H << nl << "return operator<(__rhs) || operator==(__rhs);"; H << eb; H << nl << "bool operator>(const " << name << "& __rhs) const"; H << sb; H << nl << "return !operator<(__rhs) && !operator==(__rhs);"; H << eb; H << nl << "bool operator>=(const " << name << "& __rhs) const"; H << sb; H << nl << "return !operator<(__rhs);"; H << eb; C << sp << nl << "bool" << nl << scoped.substr(2) << "::operator==(const " << name << "& __rhs) const"; C << sb; C << nl << "if(this == &__rhs)"; C << sb; C << nl << "return true;"; C << eb; for(pi = params.begin(); pi != params.end(); ++pi) { C << nl << "if(" << *pi << " != __rhs." << *pi << ')'; C << sb; C << nl << "return false;"; C << eb; } C << nl << "return true;"; C << eb; C << sp << nl << "bool" << nl << scoped.substr(2) << "::operator<(const " << name << "& __rhs) const"; C << sb; C << nl << "if(this == &__rhs)"; C << sb; C << nl << "return false;"; C << eb; for(pi = params.begin(); pi != params.end(); ++pi) { C << nl << "if(" << *pi << " < __rhs." << *pi << ')'; C << sb; C << nl << "return true;"; C << eb; C << nl << "else if(__rhs." << *pi << " < " << *pi << ')'; C << sb; C << nl << "return false;"; C << eb; } C << nl << "return false;"; C << eb; // // None of these member functions is virtual! // H << sp << nl << _dllExport << "void __write(::IceInternal::BasicStream*) const;"; H << nl << _dllExport << "void __read(::IceInternal::BasicStream*);"; C << sp << nl << "void" << nl << scoped.substr(2) << "::__write(::IceInternal::BasicStream* __os) const"; C << sb; for(q = dataMembers.begin(); q != dataMembers.end(); ++q) { writeMarshalUnmarshalCode(C, (*q)->type(), fixKwd((*q)->name()), true, "", true, (*q)->getMetaData()); } C << eb; C << sp << nl << "void" << nl << scoped.substr(2) << "::__read(::IceInternal::BasicStream* __is)"; C << sb; for(q = dataMembers.begin(); q != dataMembers.end(); ++q) { writeMarshalUnmarshalCode(C, (*q)->type(), fixKwd((*q)->name()), false, "", true, (*q)->getMetaData()); } C << eb; H << eb << ';'; _useWstring = resetUseWstring(_useWstringHist); } void Slice::Gen::TypesVisitor::visitDataMember(const DataMemberPtr& p) { string name = fixKwd(p->name()); string s = typeToString(p->type(), _useWstring, p->getMetaData()); H << nl << s << ' ' << name << ';'; } void Slice::Gen::TypesVisitor::visitSequence(const SequencePtr& p) { string name = fixKwd(p->name()); TypePtr type = p->type(); string s = typeToString(type, _useWstring, p->typeMetaData()); StringList metaData = p->getMetaData(); string seqType = findMetaData(metaData, true); if(!seqType.empty() && seqType != "array" && seqType.find("range") != 0) { H << sp << nl << "typedef " << seqType << ' ' << name << ';'; } else { H << sp << nl << "typedef ::std::vector<" << (s[0] == ':' ? " " : "") << s << "> " << name << ';'; } BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); if(!p->isLocal()) { string scoped = fixKwd(p->scoped()); string scope = fixKwd(p->scope()); if(!seqType.empty()) { H << nl << _dllExport << "void __write" << name << "(::IceInternal::BasicStream*, const " << name << "&);"; H << nl << _dllExport << "void __read" << name << "(::IceInternal::BasicStream*, " << name << "&);"; C << sp << nl << "void" << nl << scope.substr(2) << "__write" << name << "(::IceInternal::BasicStream* __os, const " << scoped << "& v)"; C << sb; C << nl << "::Ice::Int size = static_cast< ::Ice::Int>(v.size());"; C << nl << "__os->writeSize(size);"; C << nl << "for(" << name << "::const_iterator p = v.begin(); p != v.end(); ++p)"; C << sb; writeMarshalUnmarshalCode(C, type, "(*p)", true); C << eb; C << eb; C << sp << nl << "void" << nl << scope.substr(2) << "__read" << name << "(::IceInternal::BasicStream* __is, " << scoped << "& v)"; C << sb; C << nl << "::Ice::Int sz;"; C << nl << "__is->readSize(sz);"; C << nl << name << "(sz).swap(v);"; if(type->isVariableLength()) { // Protect against bogus sequence sizes. C << nl << "__is->startSeq(sz, " << type->minWireSize() << ");"; } else { C << nl << "__is->checkFixedSeq(sz, " << type->minWireSize() << ");"; } C << nl << "for(" << name << "::iterator p = v.begin(); p != v.end(); ++p)"; C << sb; writeMarshalUnmarshalCode(C, type, "(*p)", false); // // After unmarshaling each element, check that there are still enough bytes left in the stream // to unmarshal the remainder of the sequence, and decrement the count of elements // yet to be unmarshaled for sequences with variable-length element type (that is, for sequences // of classes, structs, dictionaries, sequences, strings, or proxies). This allows us to // abort unmarshaling for bogus sequence sizes at the earliest possible moment. // (For fixed-length sequences, we don't need to do this because the prediction of how many // bytes will be taken up by the sequence is accurate.) // if(type->isVariableLength()) { if(!SequencePtr::dynamicCast(type)) { // // No need to check for directly nested sequences because, at the start of each // sequence, we check anyway. // C << nl << "__is->checkSeq();"; } C << nl << "__is->endElement();"; } C << eb; if(type->isVariableLength()) { C << nl << "__is->endSeq(sz);"; } C << eb; } else if(!builtin || builtin->kind() == Builtin::KindObject || builtin->kind() == Builtin::KindObjectProxy) { H << nl << _dllExport << "void __write" << name << "(::IceInternal::BasicStream*, const " << s << "*, const " << s << "*);"; H << nl << _dllExport << "void __read" << name << "(::IceInternal::BasicStream*, " << name << "&);"; C << sp << nl << "void" << nl << scope.substr(2) << "__write" << name << "(::IceInternal::BasicStream* __os, const " << s << "* begin, const " << s << "* end)"; C << sb; C << nl << "::Ice::Int size = static_cast< ::Ice::Int>(end - begin);"; C << nl << "__os->writeSize(size);"; C << nl << "for(int i = 0; i < size; ++i)"; C << sb; writeMarshalUnmarshalCode(C, type, "begin[i]", true); C << eb; C << eb; C << sp << nl << "void" << nl << scope.substr(2) << "__read" << name << "(::IceInternal::BasicStream* __is, " << scoped << "& v)"; C << sb; C << nl << "::Ice::Int sz;"; C << nl << "__is->readSize(sz);"; if(type->isVariableLength()) { // Protect against bogus sequence sizes. C << nl << "__is->startSeq(sz, " << type->minWireSize() << ");"; } else { C << nl << "__is->checkFixedSeq(sz, " << type->minWireSize() << ");"; } C << nl << "v.resize(sz);"; C << nl << "for(int i = 0; i < sz; ++i)"; C << sb; writeMarshalUnmarshalCode(C, type, "v[i]", false); // // After unmarshaling each element, check that there are still enough bytes left in the stream // to unmarshal the remainder of the sequence, and decrement the count of elements // yet to be unmarshaled for sequences with variable-length element type (that is, for sequences // of classes, structs, dictionaries, sequences, strings, or proxies). This allows us to // abort unmarshaling for bogus sequence sizes at the earliest possible moment. // (For fixed-length sequences, we don't need to do this because the prediction of how many // bytes will be taken up by the sequence is accurate.) // if(type->isVariableLength()) { if(!SequencePtr::dynamicCast(type)) { // // No need to check for directly nested sequences because, at the start of each // sequence, we check anyway. // C << nl << "__is->checkSeq();"; } C << nl << "__is->endElement();"; } C << eb; if(type->isVariableLength()) { C << nl << "__is->endSeq(sz);"; } C << eb; } } } void Slice::Gen::TypesVisitor::visitDictionary(const DictionaryPtr& p) { string name = fixKwd(p->name()); TypePtr keyType = p->keyType(); TypePtr valueType = p->valueType(); string ks = typeToString(keyType, _useWstring, p->keyMetaData()); if(ks[0] == ':') { ks.insert(0, " "); } string vs = typeToString(valueType, _useWstring, p->valueMetaData()); H << sp << nl << "typedef ::std::map<" << ks << ", " << vs << "> " << name << ';'; if(!p->isLocal()) { string scoped = fixKwd(p->scoped()); string scope = fixKwd(p->scope()); H << nl << _dllExport << "void __write" << name << "(::IceInternal::BasicStream*, const " << name << "&);"; H << nl << _dllExport << "void __read" << name << "(::IceInternal::BasicStream*, " << name << "&);"; C << sp << nl << "void" << nl << scope.substr(2) << "__write" << name << "(::IceInternal::BasicStream* __os, const " << scoped << "& v)"; C << sb; C << nl << "__os->writeSize(::Ice::Int(v.size()));"; C << nl << scoped << "::const_iterator p;"; C << nl << "for(p = v.begin(); p != v.end(); ++p)"; C << sb; writeMarshalUnmarshalCode(C, keyType, "p->first", true); writeMarshalUnmarshalCode(C, valueType, "p->second", true); C << eb; C << eb; C << sp << nl << "void" << nl << scope.substr(2) << "__read" << name << "(::IceInternal::BasicStream* __is, " << scoped << "& v)"; C << sb; C << nl << "::Ice::Int sz;"; C << nl << "__is->readSize(sz);"; C << nl << "while(sz--)"; C << sb; C << nl << "::std::pair pair;"; string pf = string("const_cast<") + ks + "&>(pair.first)"; writeMarshalUnmarshalCode(C, keyType, pf, false); C << nl << scoped << "::iterator __i = v.insert(v.end(), pair);"; writeMarshalUnmarshalCode(C, valueType, "__i->second", false); C << eb; C << eb; } } void Slice::Gen::TypesVisitor::visitEnum(const EnumPtr& p) { string name = fixKwd(p->name()); EnumeratorList enumerators = p->getEnumerators(); H << sp << nl << "enum " << name; H << sb; EnumeratorList::const_iterator en = enumerators.begin(); while(en != enumerators.end()) { H << nl << fixKwd((*en)->name()); if(++en != enumerators.end()) { H << ','; } } H << eb << ';'; if(!p->isLocal()) { string scoped = fixKwd(p->scoped()); string scope = fixKwd(p->scope()); size_t sz = enumerators.size(); assert(sz <= 0x7fffffff); // 64-bit enums are not supported H << sp << nl << _dllExport << "void __write(::IceInternal::BasicStream*, " << name << ");"; H << nl << _dllExport << "void __read(::IceInternal::BasicStream*, " << name << "&);"; C << sp << nl << "void" << nl << scope.substr(2) << "__write(::IceInternal::BasicStream* __os, " << scoped << " v)"; C << sb; if(sz <= 0x7f) { C << nl << "__os->write(static_cast< ::Ice::Byte>(v));"; } else if(sz <= 0x7fff) { C << nl << "__os->write(static_cast< ::Ice::Short>(v));"; } else { C << nl << "__os->write(static_cast< ::Ice::Int>(v));"; } C << eb; C << sp << nl << "void" << nl << scope.substr(2) << "__read(::IceInternal::BasicStream* __is, " << scoped << "& v)"; C << sb; if(sz <= 0x7f) { C << nl << "::Ice::Byte val;"; C << nl << "__is->read(val);"; C << nl << "v = static_cast< " << scoped << ">(val);"; } else if(sz <= 0x7fff) { C << nl << "::Ice::Short val;"; C << nl << "__is->read(val);"; C << nl << "v = static_cast< " << scoped << ">(val);"; } else { C << nl << "::Ice::Int val;"; C << nl << "__is->read(val);"; C << nl << "v = static_cast< " << scoped << ">(val);"; } C << eb; } } void Slice::Gen::TypesVisitor::visitConst(const ConstPtr& p) { H << sp; H << nl << "const " << typeToString(p->type(), _useWstring, p->typeMetaData()) << " " << fixKwd(p->name()) << " = "; BuiltinPtr bp = BuiltinPtr::dynamicCast(p->type()); if(bp && bp->kind() == Builtin::KindString) { // // Expand strings into the basic source character set. We can't use isalpha() and the like // here because they are sensitive to the current locale. // static const string basicSourceChars = "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789" "_{}[]#()<>%:;.?*+-/^&|~!=,\\\"' "; static const set charSet(basicSourceChars.begin(), basicSourceChars.end()); ostringstream initString; initString << "\""; // Opening " const string val = p->value(); for(string::const_iterator c = val.begin(); c != val.end(); ++c) { if(charSet.find(*c) == charSet.end()) { unsigned char uc = *c; // char may be signed, so make it positive ostringstream s; s << "\\"; // Print as octal if not in basic source character set s.flags(ios_base::oct); s.width(3); s.fill('0'); s << static_cast(uc); initString << s.str(); } else { initString << *c; // Print normally if in basic source character set } } initString << "\""; // Closing " bool isWstring = _useWstring || findMetaData(p->typeMetaData(), true) == "wstring"; if(isWstring) { H.zeroIndent(); H << "#ifdef ICEE_HAS_WSTRING"; H.restoreIndent(); H << 'L' << initString.str();; H.zeroIndent(); H << "#else"; H.restoreIndent(); } H << initString.str(); if(isWstring) { H.zeroIndent(); H << "#endif"; H.restoreIndent(); } } else if(bp && bp->kind() == Builtin::KindLong) { H << "ICE_INT64(" << p->value() << ")"; } else { EnumPtr ep = EnumPtr::dynamicCast(p->type()); if(ep) { H << fixKwd(p->value()); } else { H << p->value(); } } H << ';'; } void Slice::Gen::TypesVisitor::emitUpcall(const ExceptionPtr& base, const string& call, bool isLocal) { C.zeroIndent(); C << nl << "#if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug"; // COMPILERBUG C.restoreIndent(); C << nl << (base ? fixKwd(base->name()) : string(isLocal ? "LocalException" : "UserException")) << call; C.zeroIndent(); C << nl << "#else"; C.restoreIndent(); C << nl << (base ? fixKwd(base->scoped()) : string(isLocal ? "::Ice::LocalException" : "::Ice::UserException")) << call; C.zeroIndent(); C << nl << "#endif"; C.restoreIndent(); } Slice::Gen::ProxyDeclVisitor::ProxyDeclVisitor(Output& h, Output& c, const string& dllExport) : H(h), C(c), _dllExport(dllExport) { } bool Slice::Gen::ProxyDeclVisitor::visitUnitStart(const UnitPtr& p) { if(!p->hasNonLocalClassDecls()) { return false; } H << sp << nl << "namespace IceProxy" << nl << '{'; return true; } void Slice::Gen::ProxyDeclVisitor::visitUnitEnd(const UnitPtr& p) { H << sp << nl << '}'; } bool Slice::Gen::ProxyDeclVisitor::visitModuleStart(const ModulePtr& p) { if(!p->hasNonLocalClassDecls()) { return false; } string name = fixKwd(p->name()); H << sp << nl << "namespace " << name << nl << '{'; return true; } void Slice::Gen::ProxyDeclVisitor::visitModuleEnd(const ModulePtr& p) { H << sp << nl << '}'; } void Slice::Gen::ProxyDeclVisitor::visitClassDecl(const ClassDeclPtr& p) { string name = fixKwd(p->name()); H << sp << nl << "class " << name << ';'; } Slice::Gen::ProxyVisitor::ProxyVisitor(Output& h, Output& c, const string& dllExport) : H(h), C(c), _dllExport(dllExport), _useWstring(false) { } bool Slice::Gen::ProxyVisitor::visitUnitStart(const UnitPtr& p) { if(!p->hasNonLocalClassDefs()) { return false; } H << sp << nl << "namespace IceProxy" << nl << '{'; return true; } void Slice::Gen::ProxyVisitor::visitUnitEnd(const UnitPtr& p) { H << sp << nl << '}'; } bool Slice::Gen::ProxyVisitor::visitModuleStart(const ModulePtr& p) { if(!p->hasNonLocalClassDefs()) { return false; } _useWstring = setUseWstring(p, _useWstringHist, _useWstring); string name = fixKwd(p->name()); H << sp << nl << "namespace " << name << nl << '{'; return true; } void Slice::Gen::ProxyVisitor::visitModuleEnd(const ModulePtr& p) { H << sp << nl << '}'; _useWstring = resetUseWstring(_useWstringHist); } bool Slice::Gen::ProxyVisitor::visitClassDefStart(const ClassDefPtr& p) { _useWstring = setUseWstring(p, _useWstringHist, _useWstring); string name = fixKwd(p->name()); string scoped = fixKwd(p->scoped()); ClassList bases = p->bases(); H << sp << nl << "class " << name << " : "; if(bases.empty()) { H << "virtual public ::IceProxy::Ice::Object"; } else { H.useCurrentPosAsIndent(); ClassList::const_iterator q = bases.begin(); while(q != bases.end()) { H << "virtual public ::IceProxy" << fixKwd((*q)->scoped()); if(++q != bases.end()) { H << ',' << nl; } } H.restoreIndent(); } H << sb; H.dec(); H << nl << "public:"; H.inc(); return true; } void Slice::Gen::ProxyVisitor::visitClassDefEnd(const ClassDefPtr& p) { string scoped = fixKwd(p->scoped()); string scope = fixKwd(p->scope()); H << nl << nl << _dllExport << "static const ::std::string& ice_staticId();"; H << eb << ';'; string flatName = p->flattenedScope() + p->name() + "_ids"; StringList ids; getIds(p, ids); StringList::const_iterator firstIter = ids.begin(); StringList::const_iterator scopedIter = find(ids.begin(), ids.end(), p->scoped()); assert(scopedIter != ids.end()); StringList::difference_type scopedPos = ice_distance(firstIter, scopedIter); C << sp; C << nl << "const ::std::string&" << nl << "IceProxy" << scoped << "::ice_staticId()"; C << sb; C << nl << "return " << flatName << '[' << scopedPos << "];"; C << eb; _useWstring = resetUseWstring(_useWstringHist); } void Slice::Gen::ProxyVisitor::visitOperation(const OperationPtr& p) { string name = p->name(); string scoped = fixKwd(p->scoped()); string scope = fixKwd(p->scope()); TypePtr ret = p->returnType(); string retS = returnTypeToString(ret, _useWstring, p->getMetaData()); vector params; vector paramsDecl; vector paramsName; vector args; ParamDeclList inParams; ParamDeclList outParams; ParamDeclList paramList = p->parameters(); for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q) { string paramName = fixKwd((*q)->name()); StringList metaData = (*q)->getMetaData(); string typeString; if((*q)->isOutParam()) { outParams.push_back(*q); typeString = outputTypeToString((*q)->type(), _useWstring, metaData); } else { inParams.push_back(*q); typeString = inputTypeToString((*q)->type(), _useWstring, metaData); } params.push_back(typeString); paramsDecl.push_back(typeString + ' ' + paramName); paramsName.push_back(paramName); args.push_back(paramName); } paramsName.push_back("__outS"); string thisPointer = fixKwd(scope.substr(0, scope.size() - 2)) + "*"; ContainerPtr container = p->container(); ClassDefPtr cl = ClassDefPtr::dynamicCast(container); string deprecateSymbol = getDeprecateSymbol(p, cl); H << sp << nl << deprecateSymbol << retS << ' ' << fixKwd(name) << spar << paramsDecl << epar; H << sb; H << nl; if(ret) { H << "return "; } H << fixKwd(name) << spar << args << "0" << epar << ';'; H << eb; H << nl << deprecateSymbol << retS << ' ' << fixKwd(name) << spar << paramsDecl << "const ::Ice::Context& __ctx" << epar; H << sb; H << nl; if(ret) { H << "return "; } H << fixKwd(name) << spar << args << "&__ctx" << epar << ';'; H << eb; H << nl; H.dec(); H << nl << "private:"; H.inc(); H << sp << nl << _dllExport << retS << ' ' << fixKwd(name) << spar << params << "const ::Ice::Context*" << epar << ';'; H << nl; H.dec(); H << nl << "public:"; H.inc(); C << sp << nl << retS << nl << "IceProxy" << scoped << spar << paramsDecl << "const ::Ice::Context* __ctx" << epar; C << sb; C << nl << "int __cnt = 0;"; C << nl << "while(true)"; C << sb; C << nl << "::Ice::ConnectionPtr __connection;"; C << nl << "try"; C << sb; if(p->returnsData()) { C << nl << "__checkTwowayOnly(\"" << name << "\");"; } C << nl << "static const ::std::string __operation(\"" << p->name() << "\");"; C << nl << "__connection = ice_getConnection();"; C << nl << "::IceInternal::Outgoing __outS(__connection.get(), _reference.get(), __operation, " << operationModeToString(p->sendMode()) << ", __ctx);"; if(!inParams.empty()) { C << nl << "try"; C << sb; C << nl << "::IceInternal::BasicStream* __os = __outS.stream();"; writeMarshalCode(C, inParams, 0, StringList(), true); C << eb; C << nl << "catch(const ::Ice::LocalException& __ex)"; C << sb; C << nl << "__outS.abort(__ex);"; C << eb; } C << nl << "bool __ok = __outS.invoke();"; C << nl << "try"; C << sb; C << nl << "::IceInternal::BasicStream* __is = __outS.stream();"; C << nl << "if(!__ok)"; C << sb; C << nl << "try"; C << sb; C << nl << "__is->throwException();"; C << eb; // // Generate a catch block for each legal user exception. This is necessary // to prevent an "impossible" user exception to be thrown if client and // and server use different exception specifications for an operation. For // example: // // Client compiled with: // exception A {}; // exception B {}; // interface I { // void op() throws A; // }; // // Server compiled with: // exception A {}; // exception B {}; // interface I { // void op() throws B; // Differs from client // }; // // We need the catch blocks so, if the server throws B from op(), the // client receives UnknownUserException instead of B. // ExceptionList throws = p->throws(); throws.sort(); throws.unique(); #if defined(__SUNPRO_CC) throws.sort(derivedToBaseCompare); #else throws.sort(Slice::DerivedToBaseCompare()); #endif for(ExceptionList::const_iterator i = throws.begin(); i != throws.end(); ++i) { C << nl << "catch(const " << fixKwd((*i)->scoped()) << "&)"; C << sb; C << nl << "throw;"; C << eb; } C << nl << "catch(const ::Ice::UserException& __ex)"; C << sb; C << nl << "::Ice::UnknownUserException __uex(__FILE__, __LINE__);"; C << nl << "__uex.unknown = __ex.ice_name();"; C << nl << "throw __uex;"; C << eb; C << eb; writeAllocateCode(C, ParamDeclList(), ret, p->getMetaData(), _useWstring); writeUnmarshalCode(C, outParams, ret, p->getMetaData()); if(ret) { C << nl << "return __ret;"; } C << eb; C << nl << "catch(const ::Ice::LocalException& __ex)"; C << sb; C << nl << "throw ::IceInternal::LocalExceptionWrapper(__ex, false);"; C << eb; C.zeroIndent(); C << nl << "#if defined(_MSC_VER) && defined(_M_ARM) // ARM bug."; // COMPILERBUG C.restoreIndent(); C << nl << "catch(...)"; C << sb; C << nl << "throw;"; C << eb; C.zeroIndent(); C << nl << "#endif"; C.restoreIndent(); if(!ret) { C << nl << "return;"; } C << eb; C << nl << "catch(const ::IceInternal::LocalExceptionWrapper& __ex)"; C << sb; if(p->mode() == Operation::Idempotent || p->mode() == Operation::Nonmutating) { C << nl << "__handleExceptionWrapperRelaxed(__connection, __ex, __cnt);"; } else { C << nl << "__handleExceptionWrapper(__connection, __ex);"; } C << eb; C << nl << "catch(const ::Ice::LocalException& __ex)"; C << sb; C << nl << "__handleException(__connection, __ex, __cnt);"; C << eb; C.zeroIndent(); C << nl << "#if defined(_MSC_VER) && defined(_M_ARM) // ARM bug."; // COMPILERBUG C.restoreIndent(); C << nl << "catch(...)"; C << sb; C << nl << "throw;"; C << eb; C.zeroIndent(); C << nl << "#endif"; C.restoreIndent(); C << eb; C << eb; } Slice::Gen::ObjectDeclVisitor::ObjectDeclVisitor(Output& h, Output& c, const string& dllExport) : H(h), C(c), _dllExport(dllExport) { } bool Slice::Gen::ObjectDeclVisitor::visitModuleStart(const ModulePtr& p) { if(!p->hasClassDecls()) { return false; } string name = fixKwd(p->name()); H << sp << nl << "namespace " << name << nl << '{'; return true; } void Slice::Gen::ObjectDeclVisitor::visitModuleEnd(const ModulePtr& p) { H << sp << nl << '}'; } void Slice::Gen::ObjectDeclVisitor::visitClassDecl(const ClassDeclPtr& p) { string name = fixKwd(p->name()); H << sp << nl << "#ifndef ICEE_PURE_CLIENT"; H << sp << nl << "class " << name << ';'; H << nl << _dllExport << "bool operator==(const " << name << "&, const " << name << "&);"; H << nl << _dllExport << "bool operator<(const " << name << "&, const " << name << "&);"; H << sp << nl << "#endif // ICEE_PURE_CLIENT"; } Slice::Gen::ObjectVisitor::ObjectVisitor(Output& h, Output& c, const string& dllExport) : H(h), C(c), _dllExport(dllExport), _useWstring(false) { } bool Slice::Gen::ObjectVisitor::visitModuleStart(const ModulePtr& p) { if(!p->hasClassDefs()) { return false; } _useWstring = setUseWstring(p, _useWstringHist, _useWstring); string name = fixKwd(p->name()); H << sp << nl << "namespace " << name << nl << '{'; return true; } void Slice::Gen::ObjectVisitor::visitModuleEnd(const ModulePtr& p) { H << sp; H << nl << '}'; _useWstring = resetUseWstring(_useWstringHist); } bool Slice::Gen::ObjectVisitor::visitClassDefStart(const ClassDefPtr& p) { _useWstring = setUseWstring(p, _useWstringHist, _useWstring); string name = fixKwd(p->name()); string scoped = fixKwd(p->scoped()); ClassList bases = p->bases(); ClassDefPtr base; if(!bases.empty() && !bases.front()->isInterface()) { base = bases.front(); } DataMemberList dataMembers = p->dataMembers(); DataMemberList allDataMembers = p->allDataMembers(); H << sp << nl << "#ifndef ICEE_PURE_CLIENT"; H << sp << nl << "class " << _dllExport << name << " : "; H.useCurrentPosAsIndent(); if(bases.empty()) { H << "virtual public ::Ice::Object"; } else { ClassList::const_iterator q = bases.begin(); while(q != bases.end()) { H << "virtual public " << fixKwd((*q)->scoped()); if(++q != bases.end()) { H << ',' << nl; } } } H.restoreIndent(); H << sb; H.dec(); H << nl << "public:" << sp; H.inc(); H << nl << "typedef " << name << "Prx ProxyType;"; H << nl << "typedef " << name << "Ptr PointerType;"; H << nl; vector params; vector allTypes; vector allParamDecls; DataMemberList::const_iterator q; for(q = dataMembers.begin(); q != dataMembers.end(); ++q) { params.push_back(fixKwd((*q)->name())); } for(q = allDataMembers.begin(); q != allDataMembers.end(); ++q) { string typeName = inputTypeToString((*q)->type(), _useWstring, (*q)->getMetaData()); allTypes.push_back(typeName); allParamDecls.push_back(typeName + " __ice_" + (*q)->name()); } if(!p->isInterface()) { H << nl << name << "() {}"; if(!allParamDecls.empty()) { H << nl; if(allParamDecls.size() == 1) { H << "explicit "; } H << name << spar << allTypes << epar << ';'; } /* * Strong guarantee: commented-out code marked "Strong guarantee" generates * a copy-assignment operator that provides the strong exception guarantee. * For now, this is commented out, and we use the compiler-generated * copy-assignment operator. However, that one does not provide the strong * guarantee. H << ';'; if(!p->isAbstract()) { H << nl << name << "& operator=(const " << name << "&)"; if(allDataMembers.empty()) { H << " { return *this; }"; } H << ';'; } // // __swap() is static because classes may be abstract, so we // can't use a non-static member function when we do an upcall // from a non-abstract derived __swap to the __swap in an abstract base. // H << sp << nl << "static void __swap(" << name << "&, " << name << "&) throw()"; if(allDataMembers.empty()) { H << " {}"; } H << ';'; H << nl << "void swap(" << name << "& rhs) throw()"; H << sb; if(!allDataMembers.empty()) { H << nl << "__swap(*this, rhs);"; } H << eb; * Strong guarantee */ emitOneShotConstructor(p); /* * Strong guarantee if(!allDataMembers.empty()) { C << sp << nl << "void"; C << nl << scoped.substr(2) << "::__swap(" << name << "& __lhs, " << name << "& __rhs) throw()"; C << sb; if(base) { emitUpcall(base, "::__swap(__lhs, __rhs);"); } // // We use a map to remember for which types we have already declared // a temporary variable and reuse that variable if a class has // more than one member of the same type. That way, we don't use more // temporaries than necessary. (::std::swap() instantiates a new temporary // each time it is used.) // map tmpMap; map::iterator pos; int tmpCount = 0; for(q = dataMembers.begin(); q != dataMembers.end(); ++q) { string memberName = fixKwd((*q)->name()); TypePtr type = (*q)->type(); BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); if(builtin && builtin->kind() != Builtin::KindString || EnumPtr::dynamicCast(type) || ProxyPtr::dynamicCast(type) || ClassDeclPtr::dynamicCast(type) || StructPtr::dynamicCast(type)) { // // For built-in types (except string), enums, proxies, structs, and classes, // do the swap via a temporary variable. // string typeName = typeToString(type); pos = tmpMap.find(typeName); if(pos == tmpMap.end()) { pos = tmpMap.insert(pos, make_pair(typeName, tmpCount)); C << nl << typeName << " __tmp" << tmpCount << ';'; tmpCount++; } C << nl << "__tmp" << pos->second << " = __rhs." << memberName << ';'; C << nl << "__rhs." << memberName << " = __lhs." << memberName << ';'; C << nl << "__lhs." << memberName << " = __tmp" << pos->second << ';'; } else { // // For dictionaries, vectors, and maps, use the standard container's // swap() (which is usually optimized). // C << nl << "__lhs." << memberName << ".swap(__rhs." << memberName << ");"; } } C << eb; if(!p->isAbstract()) { C << sp << nl << scoped << "&"; C << nl << scoped.substr(2) << "::operator=(const " << name << "& __rhs)"; C << sb; C << nl << name << " __tmp(__rhs);"; C << nl << "__swap(*this, __tmp);"; C << nl << "return *this;"; C << eb; } } * Strong guarantee */ } StringList ids; getIds(p, ids); StringList::const_iterator firstIter = ids.begin(); StringList::const_iterator scopedIter = find(ids.begin(), ids.end(), p->scoped()); assert(scopedIter != ids.end()); StringList::difference_type scopedPos = ice_distance(firstIter, scopedIter); StringList::const_iterator q1; H << sp; H << nl << "virtual bool ice_isA" << "(const ::std::string&, const ::Ice::Current& = ::Ice::Current()) const;"; H << nl << "virtual ::std::vector< ::std::string> ice_ids" << "(const ::Ice::Current& = ::Ice::Current()) const;"; H << nl << "virtual const ::std::string& ice_id(const ::Ice::Current& = ::Ice::Current()) const;"; H << nl << "static const ::std::string& ice_staticId();"; if(!dataMembers.empty()) { H << sp; } string flatName = p->flattenedScope() + p->name() + "_ids"; C << sp; C << nl << "static const ::std::string " << flatName << '[' << ids.size() << "] ="; C << sb; q1 = ids.begin(); while(q1 != ids.end()) { C << nl << '"' << *q1 << '"'; if(++q1 != ids.end()) { C << ','; } } C << eb << ';'; C << sp << nl << "#ifndef ICEE_PURE_CLIENT"; C << sp; C << nl << "bool" << nl << fixKwd(p->scoped()).substr(2) << "::ice_isA(const ::std::string& _s, const ::Ice::Current&) const"; C << sb; C << nl << "return ::std::binary_search(" << flatName << ", " << flatName << " + " << ids.size() << ", _s);"; C << eb; C << sp; C << nl << "::std::vector< ::std::string>" << nl << fixKwd(p->scoped()).substr(2) << "::ice_ids(const ::Ice::Current&) const"; C << sb; C << nl << "return ::std::vector< ::std::string>(&" << flatName << "[0], &" << flatName << '[' << ids.size() << "]);"; C << eb; C << sp; C << nl << "const ::std::string&" << nl << fixKwd(p->scoped()).substr(2) << "::ice_id(const ::Ice::Current&) const"; C << sb; C << nl << "return " << flatName << '[' << scopedPos << "];"; C << eb; C << sp; C << nl << "const ::std::string&" << nl << fixKwd(p->scoped()).substr(2) << "::ice_staticId()"; C << sb; C << nl << "return " << flatName << '[' << scopedPos << "];"; C << eb; return true; } void Slice::Gen::ObjectVisitor::visitClassDefEnd(const ClassDefPtr& p) { string scoped = fixKwd(p->scoped()); string scope = fixKwd(p->scope()); ClassList bases = p->bases(); ClassDefPtr base; if(!bases.empty() && !bases.front()->isInterface()) { base = bases.front(); } OperationList allOps = p->allOperations(); if(!allOps.empty()) { StringList allOpNames; #if defined(__IBMCPP__) && defined(NDEBUG) // // See comment for transform above // transform(allOps.begin(), allOps.end(), back_inserter(allOpNames), ::IceUtil::constMemFun(&Contained::name)); #else transform(allOps.begin(), allOps.end(), back_inserter(allOpNames), ::IceUtil::constMemFun(&Contained::name)); #endif allOpNames.push_back("ice_id"); allOpNames.push_back("ice_ids"); allOpNames.push_back("ice_isA"); allOpNames.push_back("ice_ping"); allOpNames.sort(); allOpNames.unique(); StringList::const_iterator q; H << sp; H << nl << "virtual ::IceInternal::DispatchStatus __dispatch(::IceInternal::Incoming&, const ::Ice::Current&);"; string flatName = p->flattenedScope() + p->name() + "_all"; C << sp; C << nl << "static ::std::string " << flatName << "[] ="; C << sb; q = allOpNames.begin(); while(q != allOpNames.end()) { C << nl << '"' << *q << '"'; if(++q != allOpNames.end()) { C << ','; } } C << eb << ';'; C << sp; C << nl << "::IceInternal::DispatchStatus" << nl << scoped.substr(2) << "::__dispatch(::IceInternal::Incoming& in, const ::Ice::Current& current)"; C << sb; C << nl << "::std::pair< ::std::string*, ::std::string*> r = " << "::std::equal_range(" << flatName << ", " << flatName << " + " << allOpNames.size() << ", current.operation);"; C << nl << "if(r.first == r.second)"; C << sb; C << nl << "return ::IceInternal::DispatchOperationNotExist;"; C << eb; C << sp; C << nl << "switch(r.first - " << flatName << ')'; C << sb; int i = 0; for(q = allOpNames.begin(); q != allOpNames.end(); ++q) { C << nl << "case " << i++ << ':'; C << sb; C << nl << "return ___" << *q << "(in, current);"; C << eb; } C << eb; C << sp; C << nl << "assert(false);"; C << nl << "return ::IceInternal::DispatchOperationNotExist;"; C << eb; } // // We add a protected destructor to force heap instantiation of the class. // if(!p->isAbstract()) { H.dec(); H << sp << nl << "protected:"; H.inc(); H << sp << nl << "virtual ~" << fixKwd(p->name()) << "() {}"; } H << eb << ';'; H << sp << nl << "#endif // ICEE_PURE_CLIENT"; string name = p->name(); C << sp; C << nl << "bool" << nl << scope.substr(2) << "operator==(const " << scoped << "& l, const " << scoped << "& r)"; C << sb; C << nl << "return static_cast(l) == static_cast(r);"; C << eb; C << sp; C << nl << "bool" << nl << scope.substr(2) << "operator<(const " << scoped << "& l, const " << scoped << "& r)"; C << sb; C << nl << "return static_cast(l) < static_cast(r);"; C << eb; C << sp << nl << "#endif // ICEE_PURE_CLIENT"; _useWstring = resetUseWstring(_useWstringHist); } bool Slice::Gen::ObjectVisitor::visitExceptionStart(const ExceptionPtr&) { return false; } bool Slice::Gen::ObjectVisitor::visitStructStart(const StructPtr&) { return false; } void Slice::Gen::ObjectVisitor::visitOperation(const OperationPtr& p) { string name = p->name(); string scoped = fixKwd(p->scoped()); string scope = fixKwd(p->scope()); TypePtr ret = p->returnType(); string retS = returnTypeToString(ret, _useWstring, p->getMetaData()); string params = "("; string paramsDecl = "("; string args = "("; ContainerPtr container = p->container(); ClassDefPtr cl = ClassDefPtr::dynamicCast(container); ParamDeclList inParams; ParamDeclList outParams; ParamDeclList paramList = p->parameters(); for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q) { string paramName = fixKwd((*q)->name()); TypePtr type = (*q)->type(); bool isOutParam = (*q)->isOutParam(); StringList metaData = (*q)->getMetaData(); string typeString; if(isOutParam) { outParams.push_back(*q); typeString = outputTypeToString(type, _useWstring, metaData); } else { inParams.push_back(*q); typeString = inputTypeToString(type, _useWstring, metaData); } if(q != paramList.begin()) { params += ", "; paramsDecl += ", "; args += ", "; } params += typeString; paramsDecl += typeString; paramsDecl += ' '; paramsDecl += paramName; args += paramName; } if(!paramList.empty()) { params += ", "; paramsDecl += ", "; args += ", "; } params += "const ::Ice::Current& = ::Ice::Current())"; paramsDecl += "const ::Ice::Current& __current)"; args += "__current)"; bool isConst = (p->mode() == Operation::Nonmutating) || p->hasMetaData("cpp:const"); string deprecateSymbol = getDeprecateSymbol(p, cl); H << sp; H << nl << deprecateSymbol << "virtual " << retS << ' ' << fixKwd(name) << params << (isConst ? " const" : "") << " = 0;"; H << nl << "::IceInternal::DispatchStatus ___" << name << "(::IceInternal::Incoming&, const ::Ice::Current&)" << (isConst ? " const" : "") << ';'; C << sp; C << nl << "::IceInternal::DispatchStatus" << nl << scope.substr(2) << "___" << name << "(::IceInternal::Incoming& __inS, const ::Ice::Current& __current)" << (isConst ? " const" : ""); C << sb; ExceptionList throws = p->throws(); throws.sort(); throws.unique(); // // Arrange exceptions into most-derived to least-derived order. If we don't // do this, a base exception handler can appear before a derived exception // handler, causing compiler warnings and resulting in the base exception // being marshaled instead of the derived exception. // #if defined(__SUNPRO_CC) throws.sort(derivedToBaseCompare); #else throws.sort(Slice::DerivedToBaseCompare()); #endif C << nl << "__checkMode(" << operationModeToString(p->mode()) << ", __current.mode);"; if(!inParams.empty()) { C << nl << "::IceInternal::BasicStream* __is = __inS.is();"; } if(ret || !outParams.empty() || !throws.empty()) { C << nl << "::IceInternal::BasicStream* __os = __inS.os();"; } writeAllocateCode(C, inParams, 0, StringList(), _useWstring, true); writeUnmarshalCode(C, inParams, 0, StringList(), true); writeAllocateCode(C, outParams, 0, StringList(), _useWstring); if(!throws.empty()) { C << nl << "try"; C << sb; } C << nl; if(ret) { C << retS << " __ret = "; } C << fixKwd(name) << args << ';'; writeMarshalCode(C, outParams, ret, p->getMetaData()); if(!throws.empty()) { C << eb; ExceptionList::const_iterator r; for(r = throws.begin(); r != throws.end(); ++r) { C << nl << "catch(const " << fixKwd((*r)->scoped()) << "& __ex)"; C << sb; C << nl << "__os->write(__ex);"; C << nl << "return ::IceInternal::DispatchUserException;"; C << eb; } } C << nl << "return ::IceInternal::DispatchOK;"; C << eb; } void Slice::Gen::ObjectVisitor::visitDataMember(const DataMemberPtr& p) { string name = fixKwd(p->name()); string s = typeToString(p->type(), _useWstring, p->getMetaData()); H << nl << s << ' ' << name << ';'; } bool Slice::Gen::ObjectVisitor::emitVirtualBaseInitializers(const ClassDefPtr& p) { DataMemberList allDataMembers = p->allDataMembers(); if(allDataMembers.empty()) { return false; } ClassList bases = p->bases(); if(!bases.empty() && !bases.front()->isInterface()) { if(emitVirtualBaseInitializers(bases.front())) { C << ','; } } string upcall = "("; DataMemberList::const_iterator q; for(q = allDataMembers.begin(); q != allDataMembers.end(); ++q) { if(q != allDataMembers.begin()) { upcall += ", "; } upcall += "__ice_" + (*q)->name(); } upcall += ")"; C.zeroIndent(); C << nl << "#if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug"; C.restoreIndent(); C << nl << fixKwd(p->name()) << upcall; C.zeroIndent(); C << nl << "#else"; C.restoreIndent(); C << nl << fixKwd(p->scoped()) << upcall; C.zeroIndent(); C << nl << "#endif"; C << nl; C.restoreIndent(); return true; } void Slice::Gen::ObjectVisitor::emitOneShotConstructor(const ClassDefPtr& p) { DataMemberList allDataMembers = p->allDataMembers(); DataMemberList::const_iterator q; vector allParamDecls; for(q = allDataMembers.begin(); q != allDataMembers.end(); ++q) { string typeName = inputTypeToString((*q)->type(), _useWstring); allParamDecls.push_back(typeName + " __ice_" + (*q)->name()); } if(!allDataMembers.empty()) { C << sp << nl << p->scoped().substr(2) << "::" << fixKwd(p->name()) << spar << allParamDecls << epar << " :"; C.inc(); DataMemberList dataMembers = p->dataMembers(); ClassList bases = p->bases(); ClassDefPtr base; if(!bases.empty() && !bases.front()->isInterface()) { if(emitVirtualBaseInitializers(bases.front())) { if(!dataMembers.empty()) { C << ','; } } } if(!dataMembers.empty()) { C << nl; } for(q = dataMembers.begin(); q != dataMembers.end(); ++q) { if(q != dataMembers.begin()) { C << ',' << nl; } string memberName = fixKwd((*q)->name()); C << memberName << '(' << "__ice_" << (*q)->name() << ')'; } C.dec(); C << sb; C << eb; } } void Slice::Gen::ObjectVisitor::emitUpcall(const ClassDefPtr& base, const string& call) { C.zeroIndent(); C << nl << "#if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug"; // COMPILERBUG C.restoreIndent(); C << nl << (base ? fixKwd(base->name()) : string("Object")) << call; C.zeroIndent(); C << nl << "#else"; C.restoreIndent(); C << nl << (base ? fixKwd(base->scoped()) : string("::Ice::Object")) << call; C.zeroIndent(); C << nl << "#endif"; C.restoreIndent(); } Slice::Gen::IceInternalVisitor::IceInternalVisitor(Output& h, Output& c, const string& dllExport) : H(h), C(c), _dllExport(dllExport) { } bool Slice::Gen::IceInternalVisitor::visitUnitStart(const UnitPtr& p) { if(!p->hasClassDecls()) { return false; } H << sp; H << nl << "namespace IceInternal" << nl << '{'; return true; } void Slice::Gen::IceInternalVisitor::visitUnitEnd(const UnitPtr& p) { H << sp; H << nl << '}'; } void Slice::Gen::IceInternalVisitor::visitClassDecl(const ClassDeclPtr& p) { string scoped = fixKwd(p->scoped()); H << sp; H << nl << "#ifndef ICEE_PURE_CLIENT"; H << nl << _dllExport << "::Ice::Object* upCast(" << scoped << "*);"; H << nl << "#endif // ICEE_PURE_CLIENT"; H << nl << _dllExport << "::IceProxy::Ice::Object* upCast(::IceProxy" << scoped << "*);"; } bool Slice::Gen::IceInternalVisitor::visitClassDefStart(const ClassDefPtr& p) { string scoped = fixKwd(p->scoped()); C << sp; C << nl << "#ifndef ICEE_PURE_CLIENT"; C << nl << "::Ice::Object* IceInternal::upCast(" << scoped << "* p) { return p; }"; C << nl << "#endif // ICEE_PURE_CLIENT"; C << nl << "::IceProxy::Ice::Object* IceInternal::upCast(::IceProxy" << scoped << "* p) { return p; }"; return true; } Slice::Gen::HandleVisitor::HandleVisitor(Output& h, Output& c, const string& dllExport) : H(h), C(c), _dllExport(dllExport) { } bool Slice::Gen::HandleVisitor::visitModuleStart(const ModulePtr& p) { if(!p->hasClassDecls()) { return false; } string name = fixKwd(p->name()); H << sp; H << nl << "namespace " << name << nl << '{'; return true; } void Slice::Gen::HandleVisitor::visitModuleEnd(const ModulePtr& p) { H << sp; H << nl << '}'; } void Slice::Gen::HandleVisitor::visitClassDecl(const ClassDeclPtr& p) { string name = p->name(); string scoped = fixKwd(p->scoped()); H << sp << nl << "#ifndef ICEE_PURE_CLIENT"; H << sp; H << nl << "typedef ::IceInternal::Handle< " << scoped << "> " << name << "Ptr;"; H << sp << nl << "#endif // ICEE_PURE_CLIENT" << sp; H << nl << "typedef ::IceInternal::ProxyHandle< ::IceProxy" << scoped << "> " << name << "Prx;"; H << sp; H << nl << _dllExport << "void __read(::IceInternal::BasicStream*, " << name << "Prx&);"; } bool Slice::Gen::HandleVisitor::visitClassDefStart(const ClassDefPtr& p) { string name = p->name(); string scoped = fixKwd(p->scoped()); string scope = fixKwd(p->scope()); string factory; string type; if(!p->isAbstract()) { type = scoped + "::ice_staticId()"; factory = scoped + "::ice_factory()"; } else { type = "\"\""; factory = "0"; } C << sp; C << nl << "void" << nl << scope.substr(2) << "__read(::IceInternal::BasicStream* __is, " << scope << name << "Prx& v)"; C << sb; C << nl << "::Ice::ObjectPrx proxy;"; C << nl << "__is->read(proxy);"; C << nl << "if(!proxy)"; C << sb; C << nl << "v = 0;"; C << eb; C << nl << "else"; C << sb; C << nl << "v = new ::IceProxy" << scoped << ';'; C << nl << "v->__copyFrom(proxy);"; C << eb; C << eb; return true; } Slice::Gen::ImplVisitor::ImplVisitor(Output& h, Output& c, const string& dllExport) : H(h), C(c), _dllExport(dllExport), _useWstring(false) { } void Slice::Gen::ImplVisitor::writeReturn(Output& out, const TypePtr& type, const StringList& metaData) { BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); if(builtin) { switch(builtin->kind()) { case Builtin::KindBool: { out << nl << "return false;"; break; } case Builtin::KindByte: case Builtin::KindShort: case Builtin::KindInt: case Builtin::KindLong: { out << nl << "return 0;"; break; } case Builtin::KindFloat: case Builtin::KindDouble: { out << nl << "return 0.0;"; break; } case Builtin::KindString: { out << nl << "return ::std::string();"; break; } case Builtin::KindObject: case Builtin::KindObjectProxy: case Builtin::KindLocalObject: { out << nl << "return 0;"; break; } } } else { ProxyPtr prx = ProxyPtr::dynamicCast(type); if(prx) { out << nl << "return 0;"; } else { ClassDeclPtr cl = ClassDeclPtr::dynamicCast(type); if(cl) { out << nl << "return 0;"; } else { StructPtr st = StructPtr::dynamicCast(type); if(st) { out << nl << "return " << fixKwd(st->scoped()) << "();"; } else { EnumPtr en = EnumPtr::dynamicCast(type); if(en) { EnumeratorList enumerators = en->getEnumerators(); out << nl << "return " << fixKwd(en->scope()) << fixKwd(enumerators.front()->name()) << ';'; } else { SequencePtr seq = SequencePtr::dynamicCast(type); if(seq) { out << nl << "return " << typeToString(seq, _useWstring, metaData) << "();"; } else { DictionaryPtr dict = DictionaryPtr::dynamicCast(type); assert(dict); out << nl << "return " << fixKwd(dict->scoped()) << "();"; } } } } } } } bool Slice::Gen::ImplVisitor::visitModuleStart(const ModulePtr& p) { if(!p->hasClassDefs()) { return false; } _useWstring = setUseWstring(p, _useWstringHist, _useWstring); string name = fixKwd(p->name()); H << sp << nl << "namespace " << name << nl << '{'; return true; } void Slice::Gen::ImplVisitor::visitModuleEnd(const ModulePtr& p) { H << sp; H << nl << '}'; _useWstring = resetUseWstring(_useWstringHist); } bool Slice::Gen::ImplVisitor::visitClassDefStart(const ClassDefPtr& p) { if(!p->isAbstract()) { return false; } _useWstring = setUseWstring(p, _useWstringHist, _useWstring); string name = p->name(); string scope = fixKwd(p->scope()); string cls = scope.substr(2) + name + "I"; ClassList bases = p->bases(); ClassDefPtr base; if(!bases.empty() && !bases.front()->isInterface()) { base = bases.front(); } H << sp; H << nl << "class " << name << "I : "; H.useCurrentPosAsIndent(); H << "virtual public " << fixKwd(name); for(ClassList::const_iterator q = bases.begin(); q != bases.end(); ++q) { H << ',' << nl << "virtual public " << fixKwd((*q)->scope()); if((*q)->isAbstract()) { H << (*q)->name() << "I"; } else { H << fixKwd((*q)->name()); } } H.restoreIndent(); H << sb; H.dec(); H << nl << "public:"; H.inc(); OperationList ops = p->operations(); OperationList::const_iterator r; for(r = ops.begin(); r != ops.end(); ++r) { OperationPtr op = (*r); string opName = op->name(); TypePtr ret = op->returnType(); string retS = returnTypeToString(ret, _useWstring, op->getMetaData()); H << sp << nl << "virtual " << retS << ' ' << fixKwd(opName) << '('; H.useCurrentPosAsIndent(); ParamDeclList paramList = op->parameters(); ParamDeclList::const_iterator q; for(q = paramList.begin(); q != paramList.end(); ++q) { if(q != paramList.begin()) { H << ',' << nl; } StringList metaData = (*q)->getMetaData(); #if defined(__SUNPRO_CC) && (__SUNPRO_CC==0x550) // // Work around for Sun CC 5.5 bug #4853566 // string typeString; if((*q)->isOutParam()) { typeString = outputTypeToString((*q)->type(), _useWstring, metaData); } else { typeString = inputTypeToString((*q)->type(), _useWstring, metaData); } #else string typeString = (*q)->isOutParam() ? outputTypeToString((*q)->type(), _useWstring, metaData) : inputTypeToString((*q)->type(), _useWstring, metaData); #endif H << typeString; } if(!paramList.empty()) { H << ',' << nl; } H << "const Ice::Current&"; H.restoreIndent(); bool isConst = (op->mode() == Operation::Nonmutating) || op->hasMetaData("cpp:const"); H << ")" << (isConst ? " const" : "") << ';'; C << sp << nl << retS << nl; C << scope.substr(2) << name << "I::" << fixKwd(opName) << '('; C.useCurrentPosAsIndent(); for(q = paramList.begin(); q != paramList.end(); ++q) { if(q != paramList.begin()) { C << ',' << nl; } StringList metaData = (*q)->getMetaData(); #if defined(__SUNPRO_CC) && (__SUNPRO_CC==0x550) // // Work around for Sun CC 5.5 bug #4853566 // string typeString; if((*q)->isOutParam()) { typeString = outputTypeToString((*q)->type(), _useWstring, metaData); } else { typeString = inputTypeToString((*q)->type(), _useWstring, metaData); } #else string typeString = (*q)->isOutParam() ? outputTypeToString((*q)->type(), _useWstring, metaData) : inputTypeToString((*q)->type(), _useWstring, metaData); #endif C << typeString << ' ' << fixKwd((*q)->name()); } if(!paramList.empty()) { C << ',' << nl; } C << "const Ice::Current& current"; C.restoreIndent(); C << ')'; C << (isConst ? " const" : ""); C << sb; if(ret) { writeReturn(C, ret, op->getMetaData()); } C << eb; } H << eb << ';'; return true; } bool Slice::Gen::MetaDataVisitor::visitModuleStart(const ModulePtr& p) { // // Validate global metadata. // DefinitionContextPtr dc = p->definitionContext(); assert(dc); StringList globalMetaData = dc->getMetaData(); string file = dc->filename(); static const string prefix = "cpp:"; for(StringList::const_iterator q = globalMetaData.begin(); q != globalMetaData.end(); ++q) { string s = *q; if(_history.count(s) == 0) { if(s.find(prefix) == 0) { string ss = s.substr(prefix.size()); if(ss.find("include:") == 0) { continue; } cout << file << ": warning: ignoring invalid global metadata `" << s << "'" << endl; } _history.insert(s); } } validate(p, p->getMetaData(), p->definitionContext()->filename(), p->line()); return true; } void Slice::Gen::MetaDataVisitor::visitModuleEnd(const ModulePtr&) { } void Slice::Gen::MetaDataVisitor::visitClassDecl(const ClassDeclPtr& p) { validate(p, p->getMetaData(), p->definitionContext()->filename(), p->line()); } bool Slice::Gen::MetaDataVisitor::visitClassDefStart(const ClassDefPtr& p) { validate(p, p->getMetaData(), p->definitionContext()->filename(), p->line()); return true; } void Slice::Gen::MetaDataVisitor::visitClassDefEnd(const ClassDefPtr&) { } bool Slice::Gen::MetaDataVisitor::visitExceptionStart(const ExceptionPtr& p) { validate(p, p->getMetaData(), p->definitionContext()->filename(), p->line()); return true; } void Slice::Gen::MetaDataVisitor::visitExceptionEnd(const ExceptionPtr&) { } bool Slice::Gen::MetaDataVisitor::visitStructStart(const StructPtr& p) { validate(p, p->getMetaData(), p->definitionContext()->filename(), p->line()); return true; } void Slice::Gen::MetaDataVisitor::visitStructEnd(const StructPtr&) { } void Slice::Gen::MetaDataVisitor::visitOperation(const OperationPtr& p) { StringList metaData = p->getMetaData(); metaData.remove("cpp:const"); TypePtr returnType = p->returnType(); if(!metaData.empty()) { if(!returnType) { for(StringList::const_iterator q = metaData.begin(); q != metaData.end(); ++q) { if(q->find("cpp:type:", 0) == 0 || q->find("cpp:array", 0) == 0 || q->find("cpp:range", 0) == 0) { cout << p->definitionContext()->filename() << ":" << p->line() << ": warning: invalid metadata for operation" << endl; break; } } } else { validate(returnType, metaData, p->definitionContext()->filename(), p->line(), false); } } ParamDeclList params = p->parameters(); for(ParamDeclList::iterator q = params.begin(); q != params.end(); ++q) { validate((*q)->type(), (*q)->getMetaData(), p->definitionContext()->filename(), (*q)->line(), !(*q)->isOutParam()); } } void Slice::Gen::MetaDataVisitor::visitParamDecl(const ParamDeclPtr& p) { validate(p, p->getMetaData(), p->definitionContext()->filename(), p->line()); } void Slice::Gen::MetaDataVisitor::visitDataMember(const DataMemberPtr& p) { validate(p->type(), p->getMetaData(), p->definitionContext()->filename(), p->line()); } void Slice::Gen::MetaDataVisitor::visitSequence(const SequencePtr& p) { validate(p, p->getMetaData(), p->definitionContext()->filename(), p->line()); } void Slice::Gen::MetaDataVisitor::visitDictionary(const DictionaryPtr& p) { validate(p, p->getMetaData(), p->definitionContext()->filename(), p->line()); } void Slice::Gen::MetaDataVisitor::visitEnum(const EnumPtr& p) { validate(p, p->getMetaData(), p->definitionContext()->filename(), p->line()); } void Slice::Gen::MetaDataVisitor::visitConst(const ConstPtr& p) { validate(p, p->getMetaData(), p->definitionContext()->filename(), p->line()); } void Slice::Gen::MetaDataVisitor::validate(const SyntaxTreeBasePtr& cont, const StringList& metaData, const string& file, const string& line, bool inParam) { static const string prefix = "cpp:"; for(StringList::const_iterator p = metaData.begin(); p != metaData.end(); ++p) { string s = *p; if(_history.count(s) == 0) { if(s.find(prefix) == 0) { string ss = s.substr(prefix.size()); if(ss.find("type:string") == 0 || ss.find("type:wstring") == 0) { BuiltinPtr builtin = BuiltinPtr::dynamicCast(cont); ModulePtr module = ModulePtr::dynamicCast(cont); ClassDefPtr clss = ClassDefPtr::dynamicCast(cont); StructPtr strct = StructPtr::dynamicCast(cont); ExceptionPtr exception = ExceptionPtr::dynamicCast(cont); if((builtin && builtin->kind() == Builtin::KindString) || module || clss || strct || exception) { continue; } } if(SequencePtr::dynamicCast(cont)) { if(ss.find("type:") == 0 || (inParam && (ss == "array" || ss.find("range") == 0))) { continue; } } cout << file << ":" << line << ": warning: ignoring invalid metadata `" << s << "'" << endl; } _history.insert(s); } } } void Slice::Gen::validateMetaData(const UnitPtr& u) { MetaDataVisitor visitor; u->visit(&visitor, false); } bool Slice::Gen::setUseWstring(ContainedPtr p, list& hist, bool use) { hist.push_back(use); StringList metaData = p->getMetaData(); if(find(metaData.begin(), metaData.end(), "cpp:type:wstring") != metaData.end()) { use = true; } else if(find(metaData.begin(), metaData.end(), "cpp:type:string") != metaData.end()) { use = false; } return use; } bool Slice::Gen::resetUseWstring(list& hist) { bool use = hist.back(); hist.pop_back(); return use; } void Slice::Gen::printHeader(Output& out) { static const char* header = "// **********************************************************************\n" "//\n" "// Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved.\n" "//\n" "// This copy of Ice-E is licensed to you under the terms described in the\n" "// ICEE_LICENSE file included in this distribution.\n" "//\n" "// **********************************************************************\n" ; out << header; out << "\n// Ice-E version " << ICEE_STRING_VERSION; } void Slice::Gen::printVersionCheck(Output& out) { out << "\n"; out << "\n#ifndef ICEE_IGNORE_VERSION"; out << "\n# if ICEE_INT_VERSION / 100 != " << ICEE_INT_VERSION / 100; out << "\n# error IceE version mismatch!"; out << "\n# endif"; out << "\n# if ICEE_INT_VERSION % 100 < " << ICEE_INT_VERSION % 100; out << "\n# error IceE patch level mismatch!"; out << "\n# endif"; out << "\n#endif"; } void Slice::Gen::printDllExportStuff(Output& out, const string& dllExport) { if(dllExport.size()) { out << sp; out << "\n#ifndef " << dllExport; out << "\n# ifdef " << dllExport << "_EXPORTS"; out << "\n# define " << dllExport << " ICE_DECLSPEC_EXPORT"; out << "\n# else"; out << "\n# define " << dllExport << " ICE_DECLSPEC_IMPORT"; out << "\n# endif"; out << "\n#endif"; } } IceE-trans-1.2.0/src/icecpp/0000775000076400007640000000000010620635757015063 5ustar dwaynedwayneIceE-trans-1.2.0/src/icecpp/COPYING0000664000076400007640000004313510524133611016105 0ustar dwaynedwayne GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. IceE-trans-1.2.0/src/icecpp/config.h0000664000076400007640000000443310550516551016475 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 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. // // ********************************************************************** // // This configuration file is based on the one generated by the // configure script from the gcc-2.8.1 distribution. // #if defined(__linux) || defined(__FreeBSD__) \ || defined(__sun) || defined(__hpux) || defined(__APPLE__) \ || defined(_AIX) || defined(__osf1__) # define TIME_WITH_SYS_TIME 1 # define HAVE_BCMP 1 # define HAVE_BCOPY 1 # define HAVE_BZERO 1 # define HAVE_GETRLIMIT 1 # define HAVE_INDEX 1 # define HAVE_RINDEX 1 # define HAVE_UNISTD_H 1 #elif defined(_WIN32) # include # include # ifdef _MSC_VER # pragma warning( disable : 4018 ) # pragma warning( disable : 4244 ) // // Move deprecated warning on VC8 to level 4 // # if _MSC_VER==1400 # pragma warning( 4 : 4996 ) # pragma warning( 4 : 4267 ) # endif # endif # ifdef _MSC_VER # define alloca _alloca # endif #endif #if defined(__linux) || defined(__FreeBSD__) || defined(__sun) || \ defined(__hpux) || defined(__APPLE__) || defined(_AIX) # define HAVE_INTTYPES_H 1 #endif #if defined(__hpux) || defined(_AIX) # include #endif #if defined(__sun) || defined(__osf1__) # include # include # include #endif #define HAVE_SETRLIMIT 1 #define HAVE_STRERROR 1 #define HAVE_VPRINTF 1 #define HAVE_FCNTL_H 1 #define HAVE_LIMITS_H 1 #define HAVE_STDDEF_H 1 #define HAVE_STDLIB_H 1 #define HAVE_STRING_H 1 #define HAVE_STRINGS_H 1 #define CHAR_TYPE_SIZE 8 #define INT_TYPE_SIZE 32 // // Should be sizeof(long) * 8; but 32 works well. // #define LONG_TYPE_SIZE 32 #define TARGET_BELL 007 #define TARGET_BS 010 #define TARGET_TAB 011 #define TARGET_NEWLINE 012 #define TARGET_VT 013 #define TARGET_FF 014 #define TARGET_CR 015 static char *version_string = "2.8.1"; #define INCLUDE_DEFAULTS { { 0, 0, 0 } } #define GCC_INCLUDE_DIR "" #define FATAL_EXIT_CODE 33 #define SUCCESS_EXIT_CODE 0 #define PREFIX "" #define OBJECT_SUFFIX ".cpp" // For -M option. IceE-trans-1.2.0/src/icecpp/prefix.c0000664000076400007640000001667110560413774016533 0ustar dwaynedwayne/* Utility to update paths from internal to external forms. Copyright (C) 1997, 1998 Free Software Foundation, Inc. This file is part of GNU CC. GNU CC is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. GCC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with GCC; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /* This file contains routines to update a path, both to canonicalize the directory format and to handle any prefix translation. This file must be compiled with -DPREFIX= to specify the "prefix" value used by configure. If a filename does not begin with this prefix, it will not be affected other than by directory canonicalization. Each caller of 'update_path' may specify both a filename and a translation prefix and consist of the name of the package that contains the file ("@GCC", "@BINUTIL", "@GNU", etc). If the prefix is not specified, the filename will only undergo directory canonicalization. If it is specified, the string given by PREFIX will be replaced by the specified prefix (with a '@' in front unless the prefix begins with a '$') and further translation will be done as follows until none of the two conditions below are met: 1) If the filename begins with '@', the string between the '@' and the end of the name or the first '/' or directory separator will be considered a "key" and looked up as follows: -- If this is a Win32 OS, then the Registry will be examined for an entry of "key" in HKEY_LOCAL_MACHINE\SOFTWARE\Free Software Foundation\ if found, that value will be used. -- If not found (or not a Win32 OS), the environment variable key_ROOT (the value of "key" concatenated with the constant "_ROOT") is tried. If that fails, then PREFIX (see above) is used. 2) If the filename begins with a '$', the rest of the string up to the end or the first '/' or directory separator will be used as an environment variable, whose value will be returned. Once all this is done, any '/' will be converted to DIR_SEPARATOR, if they are different. NOTE: using resolve_keyed_path under Win32 requires linking with advapi32.dll. */ #include "config.h" #include "gansidecl.h" #ifdef __STDC__ #include #else #include #endif #include #include #ifdef _WIN32 #include #endif static char *get_key_value PROTO((char *)); static char *translate_name PROTO((char *)); static char *concat PVPROTO((char *, ...)); static char *save_string PROTO((char *, int)); #ifdef _WIN32 static char *lookup_key PROTO((char *)); static HKEY reg_key = (HKEY) INVALID_HANDLE_VALUE; #endif #ifndef _WIN32 extern char *getenv (); #endif /* Given KEY, as above, return its value. */ static char * get_key_value (key) char *key; { char *prefix = 0; #ifdef _WIN32 prefix = lookup_key (key); #endif if (prefix == 0) prefix = getenv (concat (key, "_ROOT", NULL_PTR)); return prefix; } /* Concatenate a sequence of strings, returning the result. This function is based on the one in libiberty. */ static char * concat VPROTO((char *first, ...)) { register int length; register char *newstr; register char *end; register char *arg; va_list args; #ifndef __STDC__ char *first; #endif /* First compute the size of the result and get sufficient memory. */ VA_START (args, first); #ifndef __STDC__ first = va_arg (args, char *); #endif arg = first; length = 0; while (arg != 0) { length += (int) strlen (arg); arg = va_arg (args, char *); } newstr = (char *) malloc (length + 1); va_end (args); /* Now copy the individual pieces to the result string. */ VA_START (args, first); #ifndef __STDC__ first = va_arg (args, char *); #endif end = newstr; arg = first; while (arg != 0) { while (*arg) *end++ = *arg++; arg = va_arg (args, char *); } *end = '\000'; va_end (args); return (newstr); } /* Return a copy of a string that has been placed in the heap. */ static char * save_string (s, len) char *s; int len; { register char *result = (char *) malloc (len + 1); bcopy (s, result, len); result[len] = 0; return result; } #ifdef _WIN32 /* Look up "key" in the registry, as above. */ static char * lookup_key (key) char *key; { char *dst; DWORD size; DWORD type; LONG res; if (reg_key == (HKEY) INVALID_HANDLE_VALUE) { res = RegOpenKeyExA (HKEY_LOCAL_MACHINE, "SOFTWARE", 0, KEY_READ, ®_key); if (res == ERROR_SUCCESS) res = RegOpenKeyExA (reg_key, "Free Software Foundation", 0, KEY_READ, ®_key); if (res != ERROR_SUCCESS) { reg_key = (HKEY) INVALID_HANDLE_VALUE; return 0; } } size = 32; dst = (char *) malloc (size); res = RegQueryValueExA (reg_key, key, 0, &type, dst, &size); if (res == ERROR_MORE_DATA && type == REG_SZ) { dst = (char *) realloc (dst, size); res = RegQueryValueExA (reg_key, key, 0, &type, dst, &size); } if (type != REG_SZ || res != ERROR_SUCCESS) { free (dst); dst = 0; } return dst; } #endif /* If NAME starts with a '@' or '$', apply the translation rules above and return a new name. Otherwise, return the given name. */ static char * translate_name (name) char *name; { char code = name[0]; char *key, *prefix = 0; int keylen; if (code != '@' && code != '$') return name; for (keylen = 0; (name[keylen + 1] != 0 && name[keylen + 1] != '/' #ifdef DIR_SEPARATOR && name[keylen + 1] != DIR_SEPARATOR #endif ); keylen++) ; key = alloca (keylen + 1); strncpy (key, &name[1], keylen); key[keylen] = 0; name = &name[keylen + 1]; if (code == '@') prefix = get_key_value (key); else prefix = getenv (key); if (prefix == 0) prefix = PREFIX; /* Remove any trailing directory separator from what we got. */ if (prefix[strlen (prefix) - 1] == '/' #ifdef DIR_SEPARATOR || prefix[strlen (prefix) - 1] == DIR_SEPARATOR #endif ) { prefix = save_string (prefix, (int)strlen (prefix)); prefix[strlen (prefix) - 1] = 0; } return concat (prefix, name, NULL_PTR); } /* Update PATH using KEY if PATH starts with PREFIX. */ char * update_path (path, key) char *path; char *key; { if (! strncmp (path, PREFIX, strlen (PREFIX)) && key != 0) { if (key[0] != '$') key = concat ("@", key, NULL_PTR); path = concat (key, &path[strlen (PREFIX)], NULL_PTR); while (path[0] == '@' || path[0] == '$') path = translate_name (path); } #ifdef DIR_SEPARATOR if (DIR_SEPARATOR != '/') { int i; int len = strlen (path); path = save_string (path, len); for (i = 0; i < len; i++) if (path[i] == '/') path[i] = DIR_SEPARATOR; } #endif return path; } IceE-trans-1.2.0/src/icecpp/gansidecl.h0000664000076400007640000000467510560413774017175 0ustar dwaynedwayne/* ANSI and traditional C compatibility macros. Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. This file is part of GNU CC. GNU CC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU CC; see the file COPYING. If not, write to the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /* This file mimics some of the support provided by include/ansidecl.h in binutils and gdb releases. ??? Over time the two should be merged into one. */ #ifndef ANSIDECL_H #define ANSIDECL_H /* Add prototype support. */ #ifndef PROTO #if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__) #define PROTO(ARGS) ARGS #else #define PROTO(ARGS) () #endif #endif #ifndef VPROTO #ifdef __STDC__ #define PVPROTO(ARGS) ARGS #define VPROTO(ARGS) ARGS #define VA_START(va_list,var) va_start(va_list,var) #else #define PVPROTO(ARGS) () #define VPROTO(ARGS) (va_alist) va_dcl #define VA_START(va_list,var) va_start(va_list) #endif #endif /* Define a generic NULL if one hasn't already been defined. */ #ifndef NULL #define NULL 0 #endif #ifndef GENERIC_PTR #if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__) #define GENERIC_PTR void * #else #define GENERIC_PTR char * #endif #endif #ifndef NULL_PTR #define NULL_PTR ((GENERIC_PTR) 0) #endif #ifdef __STDC__ #define PTR void * #else #define PTR char * #ifndef const #define const #endif #endif /* ! __STDC__ */ /* We don't have autoconf for libgcc2.c since it's a target, so don't define these functions, which aren't used there anyway. */ #ifndef IN_LIBGCC2 #ifndef HAVE_BCOPY #define bcopy(src,dst,len) memcpy ((dst),(src),(len)) #endif #ifndef HAVE_BZERO #define bzero(dst,len) memset ((dst),0,(len)) #endif #ifndef HAVE_BCMP #define bcmp(left,right,len) memcmp ((left),(right),(len)) #endif #ifndef HAVE_RINDEX #define rindex strrchr #endif #ifndef HAVE_INDEX #define index strchr #endif #endif /* IN_LIBGCC2 */ #endif /* ANSIDECL_H */ IceE-trans-1.2.0/src/icecpp/cexp.c0000664000076400007640000020636110620635757016176 0ustar dwaynedwayne/* A Bison parser, made by GNU Bison 1.875c. */ /* Skeleton parser for Yacc-like parsing with Bison, Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* As a special exception, when this file is copied by Bison into a Bison output file, you may use that output file without restriction. This special exception was added by the Free Software Foundation in version 1.24 of Bison. */ /* Written by Richard Stallman by simplifying the original so called ``semantic'' parser. */ /* All symbols defined below should begin with yy or YY, to avoid infringing on user name space. This should be done even for local variables, as they might otherwise be expanded by user macros. There are some unavoidable exceptions within include files to define necessary library symbols; they are noted "INFRINGES ON USER NAME SPACE" below. */ /* Identify Bison output. */ #define YYBISON 1 /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" /* Pure parsers. */ #define YYPURE 0 /* Using locations. */ #define YYLSP_NEEDED 0 /* Tokens. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE /* Put the tokens into the symbol table, so that GDB and other debuggers know about them. */ enum yytokentype { INT = 258, CHAR = 259, NAME = 260, ERROR = 261, OR = 262, AND = 263, NOTEQUAL = 264, EQUAL = 265, GEQ = 266, LEQ = 267, RSH = 268, LSH = 269, UNARY = 270 }; #endif #define INT 258 #define CHAR 259 #define NAME 260 #define ERROR 261 #define OR 262 #define AND 263 #define NOTEQUAL 264 #define EQUAL 265 #define GEQ 266 #define LEQ 267 #define RSH 268 #define LSH 269 #define UNARY 270 /* Copy the first part of user declarations. */ #line 26 "cexp.y" #include "config.h" #include /* #define YYDEBUG 1 */ #ifdef HAVE_STRING_H # include #endif #ifdef HAVE_STDLIB_H # include #endif #ifdef HAVE_LIMITS_H # include #endif #ifdef MULTIBYTE_CHARS #include #endif #include typedef unsigned char U_CHAR; /* This is used for communicating lists of keywords with cccp.c. */ struct arglist { struct arglist *next; U_CHAR *name; int length; int argno; }; /* Define a generic NULL if one hasn't already been defined. */ #ifndef NULL #define NULL 0 #endif #ifndef GENERIC_PTR #if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__) #define GENERIC_PTR void * #else #define GENERIC_PTR char * #endif #endif #ifndef NULL_PTR #define NULL_PTR ((GENERIC_PTR) 0) #endif /* Find the largest host integer type and set its size and type. Watch out: on some crazy hosts `long' is shorter than `int'. */ #ifndef HOST_WIDE_INT # if HAVE_INTTYPES_H # include # define HOST_WIDE_INT intmax_t # define unsigned_HOST_WIDE_INT uintmax_t # else # if (HOST_BITS_PER_LONG <= HOST_BITS_PER_INT && HOST_BITS_PER_LONGLONG <= HOST_BITS_PER_INT) # define HOST_WIDE_INT int # else # if (HOST_BITS_PER_LONGLONG <= HOST_BITS_PER_LONG || ! (defined LONG_LONG_MAX || defined LLONG_MAX)) # define HOST_WIDE_INT long # else # define HOST_WIDE_INT long long # endif # endif # endif #endif #ifndef unsigned_HOST_WIDE_INT #define unsigned_HOST_WIDE_INT unsigned HOST_WIDE_INT #endif #ifndef CHAR_BIT #define CHAR_BIT 8 #endif #ifndef HOST_BITS_PER_WIDE_INT #define HOST_BITS_PER_WIDE_INT (CHAR_BIT * sizeof (HOST_WIDE_INT)) #endif #ifdef _MSC_VER // I get these warnings from some bison versions: // warning C4102: 'yyoverflowlab' : unreferenced label # pragma warning( disable : 4102 ) #endif #if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7) # define __attribute__(x) #endif #ifndef PROTO # if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__) # define PROTO(ARGS) ARGS # else # define PROTO(ARGS) () # endif #endif #if defined (__STDC__) && defined (HAVE_VPRINTF) # include # define VA_START(va_list, var) va_start (va_list, var) # define PRINTF_ALIST(msg) char *msg, ... # define PRINTF_DCL(msg) # define PRINTF_PROTO(ARGS, m, n) PROTO (ARGS) __attribute__ ((format (__printf__, m, n))) #else # include # define VA_START(va_list, var) va_start (va_list) # define PRINTF_ALIST(msg) msg, va_alist # define PRINTF_DCL(msg) char *msg; va_dcl # define PRINTF_PROTO(ARGS, m, n) () __attribute__ ((format (__printf__, m, n))) # define vfprintf(file, msg, args) \ { \ char *a0 = va_arg(args, char *); \ char *a1 = va_arg(args, char *); \ char *a2 = va_arg(args, char *); \ char *a3 = va_arg(args, char *); \ fprintf (file, msg, a0, a1, a2, a3); \ } #endif #define PRINTF_PROTO_1(ARGS) PRINTF_PROTO(ARGS, 1, 2) HOST_WIDE_INT parse_c_expression PROTO((char *, int)); static int yylex PROTO((void)); static void yyerror PROTO((char *)) __attribute__ ((noreturn)); static HOST_WIDE_INT expression_value; #ifdef TEST_EXP_READER static int expression_signedp; #endif static jmp_buf parse_return_error; /* Nonzero means count most punctuation as part of a name. */ static int keyword_parsing = 0; /* Nonzero means do not evaluate this expression. This is a count, since unevaluated expressions can nest. */ static int skip_evaluation; /* Nonzero means warn if undefined identifiers are evaluated. */ static int warn_undef; /* some external tables of character types */ extern unsigned char is_idstart[], is_idchar[], is_space[]; /* Flag for -pedantic. */ extern int pedantic; /* Flag for -traditional. */ extern int traditional; /* Flag for -lang-c89. */ extern int c89; #ifndef CHAR_TYPE_SIZE #define CHAR_TYPE_SIZE BITS_PER_UNIT #endif #ifndef INT_TYPE_SIZE #define INT_TYPE_SIZE BITS_PER_WORD #endif #ifndef LONG_TYPE_SIZE #define LONG_TYPE_SIZE BITS_PER_WORD #endif #ifndef MAX_CHAR_TYPE_SIZE #define MAX_CHAR_TYPE_SIZE CHAR_TYPE_SIZE #endif #ifndef MAX_INT_TYPE_SIZE #define MAX_INT_TYPE_SIZE INT_TYPE_SIZE #endif #ifndef MAX_LONG_TYPE_SIZE #define MAX_LONG_TYPE_SIZE LONG_TYPE_SIZE #endif #define MAX_CHAR_TYPE_MASK (MAX_CHAR_TYPE_SIZE < HOST_BITS_PER_WIDE_INT \ ? (~ (~ (HOST_WIDE_INT) 0 << MAX_CHAR_TYPE_SIZE)) \ : ~ (HOST_WIDE_INT) 0) /* Suppose A1 + B1 = SUM1, using 2's complement arithmetic ignoring overflow. Suppose A, B and SUM have the same respective signs as A1, B1, and SUM1. Suppose SIGNEDP is negative if the result is signed, zero if unsigned. Then this yields nonzero if overflow occurred during the addition. Overflow occurs if A and B have the same sign, but A and SUM differ in sign, and SIGNEDP is negative. Use `^' to test whether signs differ, and `< 0' to isolate the sign. */ #define overflow_sum_sign(a, b, sum, signedp) \ ((~((a) ^ (b)) & ((a) ^ (sum)) & (signedp)) < 0) struct constant; GENERIC_PTR xmalloc PROTO((size_t)); HOST_WIDE_INT parse_escape PROTO((char **, HOST_WIDE_INT)); int check_assertion PROTO((U_CHAR *, int, int, struct arglist *)); struct hashnode *lookup PROTO((U_CHAR *, int, int)); void error PRINTF_PROTO_1((char *, ...)); void pedwarn PRINTF_PROTO_1((char *, ...)); void warning PRINTF_PROTO_1((char *, ...)); static int parse_number PROTO((int)); static HOST_WIDE_INT left_shift PROTO((struct constant *, unsigned_HOST_WIDE_INT)); static HOST_WIDE_INT right_shift PROTO((struct constant *, unsigned_HOST_WIDE_INT)); static void integer_overflow PROTO((void)); /* `signedp' values */ #define SIGNED (~0) #define UNSIGNED 0 // // Required to allow the code to compile with VC 8 with bison 2.1. // #if defined(_MSC_VER) && _MSC_VER == 1400 # define __STDC__ # define YYMALLOC # define YYFREE #endif // // Required to allow the code to compile with VC 6 and VC 71 with // bison 2.3. // #if defined(_MSC_VER) && _MSC_VER < 1400 # define YYMALLOC malloc # define YYFREE free #endif /* Enabling traces. */ #ifndef YYDEBUG # define YYDEBUG 0 #endif /* Enabling verbose error messages. */ #ifdef YYERROR_VERBOSE # undef YYERROR_VERBOSE # define YYERROR_VERBOSE 1 #else # define YYERROR_VERBOSE 0 #endif #if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED) #line 265 "cexp.y" typedef union YYSTYPE { struct constant {HOST_WIDE_INT value; int signedp;} integer; struct name {U_CHAR *address; int length;} name; struct arglist *keywords; } YYSTYPE; /* Line 191 of yacc.c. */ #line 351 "cexp.c" # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 # define YYSTYPE_IS_TRIVIAL 1 #endif /* Copy the second part of user declarations. */ /* Line 214 of yacc.c. */ #line 363 "cexp.c" #if ! defined (yyoverflow) || YYERROR_VERBOSE # ifndef YYFREE # define YYFREE free # endif # ifndef YYMALLOC # define YYMALLOC malloc # endif /* The parser invokes alloca or malloc; define the necessary symbols. */ # ifdef YYSTACK_USE_ALLOCA # if YYSTACK_USE_ALLOCA # define YYSTACK_ALLOC alloca # endif # else # if defined (alloca) || defined (_ALLOCA_H) # define YYSTACK_ALLOC alloca # else # ifdef __GNUC__ # define YYSTACK_ALLOC __builtin_alloca # endif # endif # endif # ifdef YYSTACK_ALLOC /* Pacify GCC's `empty if-body' warning. */ # define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) # else # if defined (__STDC__) || defined (__cplusplus) # include /* INFRINGES ON USER NAME SPACE */ # define YYSIZE_T size_t # endif # define YYSTACK_ALLOC YYMALLOC # define YYSTACK_FREE YYFREE # endif #endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */ #if (! defined (yyoverflow) \ && (! defined (__cplusplus) \ || (defined (YYSTYPE_IS_TRIVIAL) && YYSTYPE_IS_TRIVIAL))) /* A type that is properly aligned for any stack member. */ union yyalloc { short yyss; YYSTYPE yyvs; }; /* The size of the maximum gap between one aligned stack and the next. */ # define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) /* The size of an array large to enough to hold all stacks, each with N elements. */ # define YYSTACK_BYTES(N) \ ((N) * (sizeof (short) + sizeof (YYSTYPE)) \ + YYSTACK_GAP_MAXIMUM) /* Copy COUNT objects from FROM to TO. The source and destination do not overlap. */ # ifndef YYCOPY # if defined (__GNUC__) && 1 < __GNUC__ # define YYCOPY(To, From, Count) \ __builtin_memcpy (To, From, (Count) * sizeof (*(From))) # else # define YYCOPY(To, From, Count) \ do \ { \ register YYSIZE_T yyi; \ for (yyi = 0; yyi < (Count); yyi++) \ (To)[yyi] = (From)[yyi]; \ } \ while (0) # endif # endif /* Relocate STACK from its old location to the new one. The local variables YYSIZE and YYSTACKSIZE give the old and new number of elements in the stack, and YYPTR gives the new location of the stack. Advance YYPTR to a properly aligned location for the next stack. */ # define YYSTACK_RELOCATE(Stack) \ do \ { \ YYSIZE_T yynewbytes; \ YYCOPY (&yyptr->Stack, Stack, yysize); \ Stack = &yyptr->Stack; \ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ yyptr += yynewbytes / sizeof (*yyptr); \ } \ while (0) #endif #if defined (__STDC__) || defined (__cplusplus) typedef signed char yysigned_char; #else typedef short yysigned_char; #endif /* YYFINAL -- State number of the termination state. */ #define YYFINAL 19 /* YYLAST -- Last index in YYTABLE. */ #define YYLAST 190 /* YYNTOKENS -- Number of terminals. */ #define YYNTOKENS 34 /* YYNNTS -- Number of nonterminals. */ #define YYNNTS 10 /* YYNRULES -- Number of rules. */ #define YYNRULES 41 /* YYNRULES -- Number of states. */ #define YYNSTATES 77 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 #define YYMAXUTOK 270 #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) /* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ static const unsigned char yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 29, 2, 31, 2, 27, 14, 2, 32, 33, 25, 23, 9, 24, 2, 26, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 8, 2, 17, 2, 18, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 13, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 12, 2, 30, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, 6, 10, 11, 15, 16, 19, 20, 21, 22, 28 }; #if YYDEBUG /* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in YYRHS. */ static const unsigned char yyprhs[] = { 0, 0, 3, 5, 7, 11, 14, 17, 20, 23, 26, 27, 34, 38, 42, 46, 50, 54, 58, 62, 66, 70, 74, 78, 82, 86, 90, 94, 98, 102, 103, 108, 109, 114, 115, 116, 124, 126, 128, 130, 131, 136 }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ static const yysigned_char yyrhs[] = { 35, 0, -1, 36, -1, 37, -1, 36, 9, 37, -1, 24, 37, -1, 29, 37, -1, 23, 37, -1, 30, 37, -1, 31, 5, -1, -1, 31, 5, 38, 32, 43, 33, -1, 32, 36, 33, -1, 37, 25, 37, -1, 37, 26, 37, -1, 37, 27, 37, -1, 37, 23, 37, -1, 37, 24, 37, -1, 37, 22, 37, -1, 37, 21, 37, -1, 37, 16, 37, -1, 37, 15, 37, -1, 37, 20, 37, -1, 37, 19, 37, -1, 37, 17, 37, -1, 37, 18, 37, -1, 37, 14, 37, -1, 37, 13, 37, -1, 37, 12, 37, -1, -1, 37, 11, 39, 37, -1, -1, 37, 10, 40, 37, -1, -1, -1, 37, 7, 41, 37, 8, 42, 37, -1, 3, -1, 4, -1, 5, -1, -1, 32, 43, 33, 43, -1, 5, 43, -1 }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const unsigned short yyrline[] = { 0, 294, 294, 304, 305, 312, 317, 320, 322, 325, 330, 329, 336, 341, 354, 371, 384, 390, 396, 402, 408, 411, 414, 421, 428, 435, 442, 445, 448, 452, 451, 458, 457, 464, 466, 463, 471, 473, 475, 484, 485, 498 }; #endif #if YYDEBUG || YYERROR_VERBOSE /* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. First, the terminals, then, starting at YYNTOKENS, nonterminals. */ static const char *const yytname[] = { "$end", "error", "$undefined", "INT", "CHAR", "NAME", "ERROR", "'?'", "':'", "','", "OR", "AND", "'|'", "'^'", "'&'", "NOTEQUAL", "EQUAL", "'<'", "'>'", "GEQ", "LEQ", "RSH", "LSH", "'+'", "'-'", "'*'", "'/'", "'%'", "UNARY", "'!'", "'~'", "'#'", "'('", "')'", "$accept", "start", "exp1", "exp", "@1", "@2", "@3", "@4", "@5", "keywords", 0 }; #endif # ifdef YYPRINT /* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to token YYLEX-NUM. */ static const unsigned short yytoknum[] = { 0, 256, 257, 258, 259, 260, 261, 63, 58, 44, 262, 263, 124, 94, 38, 264, 265, 60, 62, 266, 267, 268, 269, 43, 45, 42, 47, 37, 270, 33, 126, 35, 40, 41 }; # endif /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const unsigned char yyr1[] = { 0, 34, 35, 36, 36, 37, 37, 37, 37, 37, 38, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 39, 37, 40, 37, 41, 42, 37, 37, 37, 37, 43, 43, 43 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ static const unsigned char yyr2[] = { 0, 2, 1, 1, 3, 2, 2, 2, 2, 2, 0, 6, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 4, 0, 4, 0, 0, 7, 1, 1, 1, 0, 4, 2 }; /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state STATE-NUM when YYTABLE doesn't specify something else to do. Zero means the default is an error. */ static const unsigned char yydefact[] = { 0, 36, 37, 38, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7, 5, 6, 8, 9, 0, 1, 0, 33, 31, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 4, 0, 0, 0, 28, 27, 26, 21, 20, 24, 25, 23, 22, 19, 18, 16, 17, 13, 14, 15, 39, 0, 32, 30, 39, 39, 0, 34, 41, 0, 11, 0, 39, 35, 40 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yysigned_char yydefgoto[] = { -1, 10, 11, 12, 40, 45, 44, 43, 73, 68 }; /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ #define YYPACT_NINF -63 static const short yypact[] = { 14, -63, -63, -63, 14, 14, 14, 14, 5, 14, 11, 6, 81, -63, -63, -63, -63, -18, 33, -63, 14, -63, -63, -63, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 32, -63, 81, 14, 14, 14, 112, 126, 139, 150, 150, 157, 157, 157, 157, 162, 162, -19, -19, -63, -63, -63, 4, 60, 36, 97, 4, 4, -20, -63, -63, 56, -63, 14, 4, 81, -63 }; /* YYPGOTO[NTERM-NUM]. */ static const short yypgoto[] = { -63, -63, 181, -4, -63, -63, -63, -63, -63, -62 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule which number is the opposite. If zero, do what YYDEFACT says. If YYTABLE_NINF, syntax error. */ #define YYTABLE_NINF -11 static const yysigned_char yytable[] = { 13, 14, 15, 16, 70, 71, 37, 38, 39, 66, 17, 19, 76, 72, -10, 20, 42, 1, 2, 3, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 67, 4, 5, 63, 64, 65, 20, 6, 7, 8, 9, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 62, 0, 41, 21, 69, 75, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 21, 74, 0, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 33, 34, 35, 36, 37, 38, 39, 35, 36, 37, 38, 39, 18 }; static const yysigned_char yycheck[] = { 4, 5, 6, 7, 66, 67, 25, 26, 27, 5, 5, 0, 74, 33, 32, 9, 20, 3, 4, 5, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 32, 23, 24, 43, 44, 45, 9, 29, 30, 31, 32, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 32, -1, 33, 7, 8, 73, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 7, 33, -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 21, 22, 23, 24, 25, 26, 27, 23, 24, 25, 26, 27, 9 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ static const unsigned char yystos[] = { 0, 3, 4, 5, 23, 24, 29, 30, 31, 32, 35, 36, 37, 37, 37, 37, 37, 5, 36, 0, 9, 7, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 38, 33, 37, 41, 40, 39, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 32, 37, 37, 37, 5, 32, 43, 8, 43, 43, 33, 42, 33, 37, 43 }; #if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__) # define YYSIZE_T __SIZE_TYPE__ #endif #if ! defined (YYSIZE_T) && defined (size_t) # define YYSIZE_T size_t #endif #if ! defined (YYSIZE_T) # if defined (__STDC__) || defined (__cplusplus) # include /* INFRINGES ON USER NAME SPACE */ # define YYSIZE_T size_t # endif #endif #if ! defined (YYSIZE_T) # define YYSIZE_T unsigned int #endif #define yyerrok (yyerrstatus = 0) #define yyclearin (yychar = YYEMPTY) #define YYEMPTY (-2) #define YYEOF 0 #define YYACCEPT goto yyacceptlab #define YYABORT goto yyabortlab #define YYERROR goto yyerrorlab /* Like YYERROR except do call yyerror. This remains here temporarily to ease the transition to the new meaning of YYERROR, for GCC. Once GCC version 2 has supplanted version 1, this can go. */ #define YYFAIL goto yyerrlab #define YYRECOVERING() (!!yyerrstatus) #define YYBACKUP(Token, Value) \ do \ if (yychar == YYEMPTY && yylen == 1) \ { \ yychar = (Token); \ yylval = (Value); \ yytoken = YYTRANSLATE (yychar); \ YYPOPSTACK; \ goto yybackup; \ } \ else \ { \ yyerror ("syntax error: cannot back up");\ YYERROR; \ } \ while (0) #define YYTERROR 1 #define YYERRCODE 256 /* YYLLOC_DEFAULT -- Compute the default location (before the actions are run). */ #ifndef YYLLOC_DEFAULT # define YYLLOC_DEFAULT(Current, Rhs, N) \ ((Current).first_line = (Rhs)[1].first_line, \ (Current).first_column = (Rhs)[1].first_column, \ (Current).last_line = (Rhs)[N].last_line, \ (Current).last_column = (Rhs)[N].last_column) #endif /* YYLEX -- calling `yylex' with the right arguments. */ #ifdef YYLEX_PARAM # define YYLEX yylex (YYLEX_PARAM) #else # define YYLEX yylex () #endif /* Enable debugging if requested. */ #if YYDEBUG # ifndef YYFPRINTF # include /* INFRINGES ON USER NAME SPACE */ # define YYFPRINTF fprintf # endif # define YYDPRINTF(Args) \ do { \ if (yydebug) \ YYFPRINTF Args; \ } while (0) # define YYDSYMPRINT(Args) \ do { \ if (yydebug) \ yysymprint Args; \ } while (0) # define YYDSYMPRINTF(Title, Token, Value, Location) \ do { \ if (yydebug) \ { \ YYFPRINTF (stderr, "%s ", Title); \ yysymprint (stderr, \ Token, Value); \ YYFPRINTF (stderr, "\n"); \ } \ } while (0) /*------------------------------------------------------------------. | yy_stack_print -- Print the state stack from its BOTTOM up to its | | TOP (included). | `------------------------------------------------------------------*/ #if defined (__STDC__) || defined (__cplusplus) static void yy_stack_print (short *bottom, short *top) #else static void yy_stack_print (bottom, top) short *bottom; short *top; #endif { YYFPRINTF (stderr, "Stack now"); for (/* Nothing. */; bottom <= top; ++bottom) YYFPRINTF (stderr, " %d", *bottom); YYFPRINTF (stderr, "\n"); } # define YY_STACK_PRINT(Bottom, Top) \ do { \ if (yydebug) \ yy_stack_print ((Bottom), (Top)); \ } while (0) /*------------------------------------------------. | Report that the YYRULE is going to be reduced. | `------------------------------------------------*/ #if defined (__STDC__) || defined (__cplusplus) static void yy_reduce_print (int yyrule) #else static void yy_reduce_print (yyrule) int yyrule; #endif { int yyi; unsigned int yylno = yyrline[yyrule]; YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ", yyrule - 1, yylno); /* Print the symbols being reduced, and their result. */ for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++) YYFPRINTF (stderr, "%s ", yytname [yyrhs[yyi]]); YYFPRINTF (stderr, "-> %s\n", yytname [yyr1[yyrule]]); } # define YY_REDUCE_PRINT(Rule) \ do { \ if (yydebug) \ yy_reduce_print (Rule); \ } while (0) /* Nonzero means print parse trace. It is left uninitialized so that multiple parsers can coexist. */ int yydebug; #else /* !YYDEBUG */ # define YYDPRINTF(Args) # define YYDSYMPRINT(Args) # define YYDSYMPRINTF(Title, Token, Value, Location) # define YY_STACK_PRINT(Bottom, Top) # define YY_REDUCE_PRINT(Rule) #endif /* !YYDEBUG */ /* YYINITDEPTH -- initial size of the parser's stacks. */ #ifndef YYINITDEPTH # define YYINITDEPTH 200 #endif /* YYMAXDEPTH -- maximum size the stacks can grow to (effective only if the built-in stack extension method is used). Do not make this value too large; the results are undefined if SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH) evaluated with infinite-precision integer arithmetic. */ #if defined (YYMAXDEPTH) && YYMAXDEPTH == 0 # undef YYMAXDEPTH #endif #ifndef YYMAXDEPTH # define YYMAXDEPTH 10000 #endif #if YYERROR_VERBOSE # ifndef yystrlen # if defined (__GLIBC__) && defined (_STRING_H) # define yystrlen strlen # else /* Return the length of YYSTR. */ static YYSIZE_T # if defined (__STDC__) || defined (__cplusplus) yystrlen (const char *yystr) # else yystrlen (yystr) const char *yystr; # endif { register const char *yys = yystr; while (*yys++ != '\0') continue; return yys - yystr - 1; } # endif # endif # ifndef yystpcpy # if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE) # define yystpcpy stpcpy # else /* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in YYDEST. */ static char * # if defined (__STDC__) || defined (__cplusplus) yystpcpy (char *yydest, const char *yysrc) # else yystpcpy (yydest, yysrc) char *yydest; const char *yysrc; # endif { register char *yyd = yydest; register const char *yys = yysrc; while ((*yyd++ = *yys++) != '\0') continue; return yyd - 1; } # endif # endif #endif /* !YYERROR_VERBOSE */ #if YYDEBUG /*--------------------------------. | Print this symbol on YYOUTPUT. | `--------------------------------*/ #if defined (__STDC__) || defined (__cplusplus) static void yysymprint (FILE *yyoutput, int yytype, YYSTYPE *yyvaluep) #else static void yysymprint (yyoutput, yytype, yyvaluep) FILE *yyoutput; int yytype; YYSTYPE *yyvaluep; #endif { /* Pacify ``unused variable'' warnings. */ (void) yyvaluep; if (yytype < YYNTOKENS) { YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); # ifdef YYPRINT YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); # endif } else YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); switch (yytype) { default: break; } YYFPRINTF (yyoutput, ")"); } #endif /* ! YYDEBUG */ /*-----------------------------------------------. | Release the memory associated to this symbol. | `-----------------------------------------------*/ #if defined (__STDC__) || defined (__cplusplus) static void yydestruct (int yytype, YYSTYPE *yyvaluep) #else static void yydestruct (yytype, yyvaluep) int yytype; YYSTYPE *yyvaluep; #endif { /* Pacify ``unused variable'' warnings. */ (void) yyvaluep; switch (yytype) { default: break; } } /* Prevent warnings from -Wmissing-prototypes. */ #ifdef YYPARSE_PARAM # if defined (__STDC__) || defined (__cplusplus) int yyparse (void *YYPARSE_PARAM); # else int yyparse (); # endif #else /* ! YYPARSE_PARAM */ #if defined (__STDC__) || defined (__cplusplus) int yyparse (void); #else int yyparse (); #endif #endif /* ! YYPARSE_PARAM */ /* The lookahead symbol. */ int yychar; /* The semantic value of the lookahead symbol. */ YYSTYPE yylval; /* Number of syntax errors so far. */ int yynerrs; /*----------. | yyparse. | `----------*/ #ifdef YYPARSE_PARAM # if defined (__STDC__) || defined (__cplusplus) int yyparse (void *YYPARSE_PARAM) # else int yyparse (YYPARSE_PARAM) void *YYPARSE_PARAM; # endif #else /* ! YYPARSE_PARAM */ #if defined (__STDC__) || defined (__cplusplus) int yyparse (void) #else int yyparse () #endif #endif { register int yystate; register int yyn; int yyresult; /* Number of tokens to shift before error messages enabled. */ int yyerrstatus; /* Lookahead token as an internal (translated) token number. */ int yytoken = 0; /* Three stacks and their tools: `yyss': related to states, `yyvs': related to semantic values, `yyls': related to locations. Refer to the stacks thru separate pointers, to allow yyoverflow to reallocate them elsewhere. */ /* The state stack. */ short yyssa[YYINITDEPTH]; short *yyss = yyssa; register short *yyssp; /* The semantic value stack. */ YYSTYPE yyvsa[YYINITDEPTH]; YYSTYPE *yyvs = yyvsa; register YYSTYPE *yyvsp; #define YYPOPSTACK (yyvsp--, yyssp--) YYSIZE_T yystacksize = YYINITDEPTH; /* The variables used to return semantic value and location from the action routines. */ YYSTYPE yyval; /* When reducing, the number of symbols on the RHS of the reduced rule. */ int yylen; YYDPRINTF ((stderr, "Starting parse\n")); yystate = 0; yyerrstatus = 0; yynerrs = 0; yychar = YYEMPTY; /* Cause a token to be read. */ /* Initialize stack pointers. Waste one element of value and location stack so that they stay on the same level as the state stack. The wasted elements are never initialized. */ yyssp = yyss; yyvsp = yyvs; goto yysetstate; /*------------------------------------------------------------. | yynewstate -- Push a new state, which is found in yystate. | `------------------------------------------------------------*/ yynewstate: /* In all cases, when you get here, the value and location stacks have just been pushed. so pushing a state here evens the stacks. */ yyssp++; yysetstate: *yyssp = yystate; if (yyss + yystacksize - 1 <= yyssp) { /* Get the current used size of the three stacks, in elements. */ YYSIZE_T yysize = yyssp - yyss + 1; #ifdef yyoverflow { /* Give user a chance to reallocate the stack. Use copies of these so that the &'s don't force the real ones into memory. */ YYSTYPE *yyvs1 = yyvs; short *yyss1 = yyss; /* Each stack pointer address is followed by the size of the data in use in that stack, in bytes. This used to be a conditional around just the two extra args, but that might be undefined if yyoverflow is a macro. */ yyoverflow ("parser stack overflow", &yyss1, yysize * sizeof (*yyssp), &yyvs1, yysize * sizeof (*yyvsp), &yystacksize); yyss = yyss1; yyvs = yyvs1; } #else /* no yyoverflow */ # ifndef YYSTACK_RELOCATE goto yyoverflowlab; # else /* Extend the stack our own way. */ if (YYMAXDEPTH <= yystacksize) goto yyoverflowlab; yystacksize *= 2; if (YYMAXDEPTH < yystacksize) yystacksize = YYMAXDEPTH; { short *yyss1 = yyss; union yyalloc *yyptr = (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); if (! yyptr) goto yyoverflowlab; YYSTACK_RELOCATE (yyss); YYSTACK_RELOCATE (yyvs); # undef YYSTACK_RELOCATE if (yyss1 != yyssa) YYSTACK_FREE (yyss1); } # endif #endif /* no yyoverflow */ yyssp = yyss + yysize - 1; yyvsp = yyvs + yysize - 1; YYDPRINTF ((stderr, "Stack size increased to %lu\n", (unsigned long int) yystacksize)); if (yyss + yystacksize - 1 <= yyssp) YYABORT; } YYDPRINTF ((stderr, "Entering state %d\n", yystate)); goto yybackup; /*-----------. | yybackup. | `-----------*/ yybackup: /* Do appropriate processing given the current state. */ /* Read a lookahead token if we need one and don't already have one. */ /* yyresume: */ /* First try to decide what to do without reference to lookahead token. */ yyn = yypact[yystate]; if (yyn == YYPACT_NINF) goto yydefault; /* Not known => get a lookahead token if don't already have one. */ /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ if (yychar == YYEMPTY) { YYDPRINTF ((stderr, "Reading a token: ")); yychar = YYLEX; } if (yychar <= YYEOF) { yychar = yytoken = YYEOF; YYDPRINTF ((stderr, "Now at end of input.\n")); } else { yytoken = YYTRANSLATE (yychar); YYDSYMPRINTF ("Next token is", yytoken, &yylval, &yylloc); } /* If the proper action on seeing token YYTOKEN is to reduce or to detect an error, take that action. */ yyn += yytoken; if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) goto yydefault; yyn = yytable[yyn]; if (yyn <= 0) { if (yyn == 0 || yyn == YYTABLE_NINF) goto yyerrlab; yyn = -yyn; goto yyreduce; } if (yyn == YYFINAL) YYACCEPT; /* Shift the lookahead token. */ YYDPRINTF ((stderr, "Shifting token %s, ", yytname[yytoken])); /* Discard the token being shifted unless it is eof. */ if (yychar != YYEOF) yychar = YYEMPTY; *++yyvsp = yylval; /* Count tokens shifted since error; after three, turn off error status. */ if (yyerrstatus) yyerrstatus--; yystate = yyn; goto yynewstate; /*-----------------------------------------------------------. | yydefault -- do the default action for the current state. | `-----------------------------------------------------------*/ yydefault: yyn = yydefact[yystate]; if (yyn == 0) goto yyerrlab; goto yyreduce; /*-----------------------------. | yyreduce -- Do a reduction. | `-----------------------------*/ yyreduce: /* yyn is the number of a rule to reduce with. */ yylen = yyr2[yyn]; /* If YYLEN is nonzero, implement the default value of the action: `$$ = $1'. Otherwise, the following line sets YYVAL to garbage. This behavior is undocumented and Bison users should not rely upon it. Assigning to YYVAL unconditionally makes the parser a bit smaller, and it avoids a GCC warning that YYVAL may be used uninitialized. */ yyval = yyvsp[1-yylen]; YY_REDUCE_PRINT (yyn); switch (yyn) { case 2: #line 295 "cexp.y" { expression_value = yyvsp[0].integer.value; #ifdef TEST_EXP_READER expression_signedp = yyvsp[0].integer.signedp; #endif ;} break; case 4: #line 306 "cexp.y" { if (pedantic) pedwarn ("comma operator in operand of `#if'"); yyval.integer = yyvsp[0].integer; ;} break; case 5: #line 313 "cexp.y" { yyval.integer.value = - yyvsp[0].integer.value; yyval.integer.signedp = yyvsp[0].integer.signedp; if ((yyval.integer.value & yyvsp[0].integer.value & yyval.integer.signedp) < 0) integer_overflow (); ;} break; case 6: #line 318 "cexp.y" { yyval.integer.value = ! yyvsp[0].integer.value; yyval.integer.signedp = SIGNED; ;} break; case 7: #line 321 "cexp.y" { yyval.integer = yyvsp[0].integer; ;} break; case 8: #line 323 "cexp.y" { yyval.integer.value = ~ yyvsp[0].integer.value; yyval.integer.signedp = yyvsp[0].integer.signedp; ;} break; case 9: #line 326 "cexp.y" { yyval.integer.value = check_assertion (yyvsp[0].name.address, yyvsp[0].name.length, 0, NULL_PTR); yyval.integer.signedp = SIGNED; ;} break; case 10: #line 330 "cexp.y" { keyword_parsing = 1; ;} break; case 11: #line 332 "cexp.y" { yyval.integer.value = check_assertion (yyvsp[-4].name.address, yyvsp[-4].name.length, 1, yyvsp[-1].keywords); keyword_parsing = 0; yyval.integer.signedp = SIGNED; ;} break; case 12: #line 337 "cexp.y" { yyval.integer = yyvsp[-1].integer; ;} break; case 13: #line 342 "cexp.y" { yyval.integer.signedp = yyvsp[-2].integer.signedp & yyvsp[0].integer.signedp; if (yyval.integer.signedp) { yyval.integer.value = yyvsp[-2].integer.value * yyvsp[0].integer.value; if (yyvsp[-2].integer.value && (yyval.integer.value / yyvsp[-2].integer.value != yyvsp[0].integer.value || (yyval.integer.value & yyvsp[-2].integer.value & yyvsp[0].integer.value) < 0)) integer_overflow (); } else yyval.integer.value = ((unsigned_HOST_WIDE_INT) yyvsp[-2].integer.value * yyvsp[0].integer.value); ;} break; case 14: #line 355 "cexp.y" { if (yyvsp[0].integer.value == 0) { if (!skip_evaluation) error ("division by zero in #if"); yyvsp[0].integer.value = 1; } yyval.integer.signedp = yyvsp[-2].integer.signedp & yyvsp[0].integer.signedp; if (yyval.integer.signedp) { yyval.integer.value = yyvsp[-2].integer.value / yyvsp[0].integer.value; if ((yyval.integer.value & yyvsp[-2].integer.value & yyvsp[0].integer.value) < 0) integer_overflow (); } else yyval.integer.value = ((unsigned_HOST_WIDE_INT) yyvsp[-2].integer.value / yyvsp[0].integer.value); ;} break; case 15: #line 372 "cexp.y" { if (yyvsp[0].integer.value == 0) { if (!skip_evaluation) error ("division by zero in #if"); yyvsp[0].integer.value = 1; } yyval.integer.signedp = yyvsp[-2].integer.signedp & yyvsp[0].integer.signedp; if (yyval.integer.signedp) yyval.integer.value = yyvsp[-2].integer.value % yyvsp[0].integer.value; else yyval.integer.value = ((unsigned_HOST_WIDE_INT) yyvsp[-2].integer.value % yyvsp[0].integer.value); ;} break; case 16: #line 385 "cexp.y" { yyval.integer.value = yyvsp[-2].integer.value + yyvsp[0].integer.value; yyval.integer.signedp = yyvsp[-2].integer.signedp & yyvsp[0].integer.signedp; if (overflow_sum_sign (yyvsp[-2].integer.value, yyvsp[0].integer.value, yyval.integer.value, yyval.integer.signedp)) integer_overflow (); ;} break; case 17: #line 391 "cexp.y" { yyval.integer.value = yyvsp[-2].integer.value - yyvsp[0].integer.value; yyval.integer.signedp = yyvsp[-2].integer.signedp & yyvsp[0].integer.signedp; if (overflow_sum_sign (yyval.integer.value, yyvsp[0].integer.value, yyvsp[-2].integer.value, yyval.integer.signedp)) integer_overflow (); ;} break; case 18: #line 397 "cexp.y" { yyval.integer.signedp = yyvsp[-2].integer.signedp; if ((yyvsp[0].integer.value & yyvsp[0].integer.signedp) < 0) yyval.integer.value = right_shift (&yyvsp[-2].integer, -yyvsp[0].integer.value); else yyval.integer.value = left_shift (&yyvsp[-2].integer, yyvsp[0].integer.value); ;} break; case 19: #line 403 "cexp.y" { yyval.integer.signedp = yyvsp[-2].integer.signedp; if ((yyvsp[0].integer.value & yyvsp[0].integer.signedp) < 0) yyval.integer.value = left_shift (&yyvsp[-2].integer, -yyvsp[0].integer.value); else yyval.integer.value = right_shift (&yyvsp[-2].integer, yyvsp[0].integer.value); ;} break; case 20: #line 409 "cexp.y" { yyval.integer.value = (yyvsp[-2].integer.value == yyvsp[0].integer.value); yyval.integer.signedp = SIGNED; ;} break; case 21: #line 412 "cexp.y" { yyval.integer.value = (yyvsp[-2].integer.value != yyvsp[0].integer.value); yyval.integer.signedp = SIGNED; ;} break; case 22: #line 415 "cexp.y" { yyval.integer.signedp = SIGNED; if (yyvsp[-2].integer.signedp & yyvsp[0].integer.signedp) yyval.integer.value = yyvsp[-2].integer.value <= yyvsp[0].integer.value; else yyval.integer.value = ((unsigned_HOST_WIDE_INT) yyvsp[-2].integer.value <= yyvsp[0].integer.value); ;} break; case 23: #line 422 "cexp.y" { yyval.integer.signedp = SIGNED; if (yyvsp[-2].integer.signedp & yyvsp[0].integer.signedp) yyval.integer.value = yyvsp[-2].integer.value >= yyvsp[0].integer.value; else yyval.integer.value = ((unsigned_HOST_WIDE_INT) yyvsp[-2].integer.value >= yyvsp[0].integer.value); ;} break; case 24: #line 429 "cexp.y" { yyval.integer.signedp = SIGNED; if (yyvsp[-2].integer.signedp & yyvsp[0].integer.signedp) yyval.integer.value = yyvsp[-2].integer.value < yyvsp[0].integer.value; else yyval.integer.value = ((unsigned_HOST_WIDE_INT) yyvsp[-2].integer.value < yyvsp[0].integer.value); ;} break; case 25: #line 436 "cexp.y" { yyval.integer.signedp = SIGNED; if (yyvsp[-2].integer.signedp & yyvsp[0].integer.signedp) yyval.integer.value = yyvsp[-2].integer.value > yyvsp[0].integer.value; else yyval.integer.value = ((unsigned_HOST_WIDE_INT) yyvsp[-2].integer.value > yyvsp[0].integer.value); ;} break; case 26: #line 443 "cexp.y" { yyval.integer.value = yyvsp[-2].integer.value & yyvsp[0].integer.value; yyval.integer.signedp = yyvsp[-2].integer.signedp & yyvsp[0].integer.signedp; ;} break; case 27: #line 446 "cexp.y" { yyval.integer.value = yyvsp[-2].integer.value ^ yyvsp[0].integer.value; yyval.integer.signedp = yyvsp[-2].integer.signedp & yyvsp[0].integer.signedp; ;} break; case 28: #line 449 "cexp.y" { yyval.integer.value = yyvsp[-2].integer.value | yyvsp[0].integer.value; yyval.integer.signedp = yyvsp[-2].integer.signedp & yyvsp[0].integer.signedp; ;} break; case 29: #line 452 "cexp.y" { skip_evaluation += !yyvsp[-1].integer.value; ;} break; case 30: #line 454 "cexp.y" { skip_evaluation -= !yyvsp[-3].integer.value; yyval.integer.value = (yyvsp[-3].integer.value && yyvsp[0].integer.value); yyval.integer.signedp = SIGNED; ;} break; case 31: #line 458 "cexp.y" { skip_evaluation += !!yyvsp[-1].integer.value; ;} break; case 32: #line 460 "cexp.y" { skip_evaluation -= !!yyvsp[-3].integer.value; yyval.integer.value = (yyvsp[-3].integer.value || yyvsp[0].integer.value); yyval.integer.signedp = SIGNED; ;} break; case 33: #line 464 "cexp.y" { skip_evaluation += !yyvsp[-1].integer.value; ;} break; case 34: #line 466 "cexp.y" { skip_evaluation += !!yyvsp[-4].integer.value - !yyvsp[-4].integer.value; ;} break; case 35: #line 468 "cexp.y" { skip_evaluation -= !!yyvsp[-6].integer.value; yyval.integer.value = yyvsp[-6].integer.value ? yyvsp[-3].integer.value : yyvsp[0].integer.value; yyval.integer.signedp = yyvsp[-3].integer.signedp & yyvsp[0].integer.signedp; ;} break; case 36: #line 472 "cexp.y" { yyval.integer = yylval.integer; ;} break; case 37: #line 474 "cexp.y" { yyval.integer = yylval.integer; ;} break; case 38: #line 476 "cexp.y" { if (warn_undef && !skip_evaluation) warning ("`%.*s' is not defined", yyvsp[0].name.length, yyvsp[0].name.address); yyval.integer.value = 0; yyval.integer.signedp = SIGNED; ;} break; case 39: #line 484 "cexp.y" { yyval.keywords = 0; ;} break; case 40: #line 486 "cexp.y" { struct arglist *temp; yyval.keywords = (struct arglist *) xmalloc (sizeof (struct arglist)); yyval.keywords->next = yyvsp[-2].keywords; yyval.keywords->name = (U_CHAR *) "("; yyval.keywords->length = 1; temp = yyval.keywords; while (temp != 0 && temp->next != 0) temp = temp->next; temp->next = (struct arglist *) xmalloc (sizeof (struct arglist)); temp->next->next = yyvsp[0].keywords; temp->next->name = (U_CHAR *) ")"; temp->next->length = 1; ;} break; case 41: #line 499 "cexp.y" { yyval.keywords = (struct arglist *) xmalloc (sizeof (struct arglist)); yyval.keywords->name = yyvsp[-1].name.address; yyval.keywords->length = yyvsp[-1].name.length; yyval.keywords->next = yyvsp[0].keywords; ;} break; } /* Line 1000 of yacc.c. */ #line 1641 "cexp.c" yyvsp -= yylen; yyssp -= yylen; YY_STACK_PRINT (yyss, yyssp); *++yyvsp = yyval; /* Now `shift' the result of the reduction. Determine what state that goes to, based on the state we popped back to and the rule number reduced by. */ yyn = yyr1[yyn]; yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) yystate = yytable[yystate]; else yystate = yydefgoto[yyn - YYNTOKENS]; goto yynewstate; /*------------------------------------. | yyerrlab -- here on detecting error | `------------------------------------*/ yyerrlab: /* If not already recovering from an error, report this error. */ if (!yyerrstatus) { ++yynerrs; #if YYERROR_VERBOSE yyn = yypact[yystate]; if (YYPACT_NINF < yyn && yyn < YYLAST) { YYSIZE_T yysize = 0; int yytype = YYTRANSLATE (yychar); const char* yyprefix; char *yymsg; int yyx; /* Start YYX at -YYN if negative to avoid negative indexes in YYCHECK. */ int yyxbegin = yyn < 0 ? -yyn : 0; /* Stay within bounds of both yycheck and yytname. */ int yychecklim = YYLAST - yyn; int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; int yycount = 0; yyprefix = ", expecting "; for (yyx = yyxbegin; yyx < yyxend; ++yyx) if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) { yysize += yystrlen (yyprefix) + yystrlen (yytname [yyx]); yycount += 1; if (yycount == 5) { yysize = 0; break; } } yysize += (sizeof ("syntax error, unexpected ") + yystrlen (yytname[yytype])); yymsg = (char *) YYSTACK_ALLOC (yysize); if (yymsg != 0) { char *yyp = yystpcpy (yymsg, "syntax error, unexpected "); yyp = yystpcpy (yyp, yytname[yytype]); if (yycount < 5) { yyprefix = ", expecting "; for (yyx = yyxbegin; yyx < yyxend; ++yyx) if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) { yyp = yystpcpy (yyp, yyprefix); yyp = yystpcpy (yyp, yytname[yyx]); yyprefix = " or "; } } yyerror (yymsg); YYSTACK_FREE (yymsg); } else yyerror ("syntax error; also virtual memory exhausted"); } else #endif /* YYERROR_VERBOSE */ yyerror ("syntax error"); } if (yyerrstatus == 3) { /* If just tried and failed to reuse lookahead token after an error, discard it. */ if (yychar <= YYEOF) { /* If at end of input, pop the error token, then the rest of the stack, then return failure. */ if (yychar == YYEOF) for (;;) { YYPOPSTACK; if (yyssp == yyss) YYABORT; YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp); yydestruct (yystos[*yyssp], yyvsp); } } else { YYDSYMPRINTF ("Error: discarding", yytoken, &yylval, &yylloc); yydestruct (yytoken, &yylval); yychar = YYEMPTY; } } /* Else will try to reuse lookahead token after shifting the error token. */ goto yyerrlab1; /*---------------------------------------------------. | yyerrorlab -- error raised explicitly by YYERROR. | `---------------------------------------------------*/ yyerrorlab: #ifdef __GNUC__ /* Pacify GCC when the user code never invokes YYERROR and the label yyerrorlab therefore never appears in user code. */ if (0) goto yyerrorlab; #endif yyvsp -= yylen; yyssp -= yylen; yystate = *yyssp; goto yyerrlab1; /*-------------------------------------------------------------. | yyerrlab1 -- common code for both syntax error and YYERROR. | `-------------------------------------------------------------*/ yyerrlab1: yyerrstatus = 3; /* Each real token shifted decrements this. */ for (;;) { yyn = yypact[yystate]; if (yyn != YYPACT_NINF) { yyn += YYTERROR; if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) { yyn = yytable[yyn]; if (0 < yyn) break; } } /* Pop the current state because it cannot handle the error token. */ if (yyssp == yyss) YYABORT; YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp); yydestruct (yystos[yystate], yyvsp); YYPOPSTACK; yystate = *yyssp; YY_STACK_PRINT (yyss, yyssp); } if (yyn == YYFINAL) YYACCEPT; YYDPRINTF ((stderr, "Shifting error token, ")); *++yyvsp = yylval; yystate = yyn; goto yynewstate; /*-------------------------------------. | yyacceptlab -- YYACCEPT comes here. | `-------------------------------------*/ yyacceptlab: yyresult = 0; goto yyreturn; /*-----------------------------------. | yyabortlab -- YYABORT comes here. | `-----------------------------------*/ yyabortlab: yyresult = 1; goto yyreturn; #ifndef yyoverflow /*----------------------------------------------. | yyoverflowlab -- parser overflow comes here. | `----------------------------------------------*/ yyoverflowlab: yyerror ("parser stack overflow"); yyresult = 2; /* Fall through. */ #endif yyreturn: #ifndef yyoverflow if (yyss != yyssa) YYSTACK_FREE (yyss); #endif return yyresult; } #line 504 "cexp.y" /* During parsing of a C expression, the pointer to the next character is in this variable. */ static char *lexptr; /* Take care of parsing a number (anything that starts with a digit). Set yylval and return the token type; update lexptr. LEN is the number of characters in it. */ /* maybe needs to actually deal with floating point numbers */ static int parse_number (olen) int olen; { register char *p = lexptr; register int c; register unsigned_HOST_WIDE_INT n = 0, nd, max_over_base; register int base = 10; register int len = olen; register int overflow = 0; register int digit, largest_digit = 0; int spec_long = 0; yylval.integer.signedp = SIGNED; if (*p == '0') { base = 8; if (len >= 3 && (p[1] == 'x' || p[1] == 'X')) { p += 2; base = 16; len -= 2; } } max_over_base = (unsigned_HOST_WIDE_INT) -1 / base; for (; len > 0; len--) { c = *p++; if (c >= '0' && c <= '9') digit = c - '0'; else if (base == 16 && c >= 'a' && c <= 'f') digit = c - 'a' + 10; else if (base == 16 && c >= 'A' && c <= 'F') digit = c - 'A' + 10; else { /* `l' means long, and `u' means unsigned. */ while (1) { if (c == 'l' || c == 'L') { if (!pedantic < spec_long) yyerror ("too many `l's in integer constant"); spec_long++; } else if (c == 'u' || c == 'U') { if (! yylval.integer.signedp) yyerror ("two `u's in integer constant"); yylval.integer.signedp = UNSIGNED; } else { if (c == '.' || c == 'e' || c == 'E' || c == 'p' || c == 'P') yyerror ("Floating point numbers not allowed in #if expressions"); else { char *buf = (char *) alloca (p - lexptr + 40); sprintf (buf, "missing white space after number `%.*s'", (int) (p - lexptr - 1), lexptr); yyerror (buf); } } if (--len == 0) break; c = *p++; } /* Don't look for any more digits after the suffixes. */ break; } if (largest_digit < digit) largest_digit = digit; nd = n * base + digit; overflow |= (max_over_base < n) | (nd < n); n = nd; } if (base <= largest_digit) pedwarn ("integer constant contains digits beyond the radix"); if (overflow) pedwarn ("integer constant out of range"); /* If too big to be signed, consider it unsigned. */ if (((HOST_WIDE_INT) n & yylval.integer.signedp) < 0) { if (base == 10) warning ("integer constant is so large that it is unsigned"); yylval.integer.signedp = UNSIGNED; } lexptr = p; yylval.integer.value = n; return INT; } struct token { char *operator; int token; }; static struct token tokentab2[] = { {"&&", AND}, {"||", OR}, {"<<", LSH}, {">>", RSH}, {"==", EQUAL}, {"!=", NOTEQUAL}, {"<=", LEQ}, {">=", GEQ}, {"++", ERROR}, {"--", ERROR}, {NULL, ERROR} }; /* Read one token, getting characters through lexptr. */ static int yylex () { register int c; register int namelen; register unsigned char *tokstart; register struct token *toktab; HOST_WIDE_INT mask; retry: tokstart = (unsigned char *) lexptr; c = *tokstart; /* See if it is a special token of length 2. */ if (! keyword_parsing) for (toktab = tokentab2; toktab->operator != NULL; toktab++) if (c == *toktab->operator && tokstart[1] == toktab->operator[1]) { lexptr += 2; if (toktab->token == ERROR) { char *buf = (char *) alloca (40); sprintf (buf, "`%s' not allowed in operand of `#if'", toktab->operator); yyerror (buf); } return toktab->token; } switch (c) { case '\n': return 0; case ' ': case '\t': case '\r': lexptr++; goto retry; case '\'': mask = MAX_CHAR_TYPE_MASK; char_constant: lexptr++; if (keyword_parsing) { char *start_ptr = lexptr - 1; while (1) { c = *lexptr++; if (c == '\\') c = parse_escape (&lexptr, mask); else if (c == '\'') break; } yylval.name.address = tokstart; yylval.name.length = lexptr - start_ptr; return NAME; } /* This code for reading a character constant handles multicharacter constants and wide characters. It is mostly copied from c-lex.c. */ { register HOST_WIDE_INT result = 0; register int num_chars = 0; unsigned width = MAX_CHAR_TYPE_SIZE; int max_chars; char *token_buffer; max_chars = MAX_LONG_TYPE_SIZE / width; token_buffer = (char *) alloca (max_chars + 1); while (1) { c = *lexptr++; if (c == '\'' || c == EOF) break; if (c == '\\') { c = parse_escape (&lexptr, mask); } num_chars++; /* Merge character into result; ignore excess chars. */ if (num_chars <= max_chars) { if (width < HOST_BITS_PER_WIDE_INT) result = (result << width) | c; else result = c; token_buffer[num_chars - 1] = c; } } token_buffer[num_chars] = 0; if (c != '\'') error ("malformatted character constant"); else if (num_chars == 0) error ("empty character constant"); else if (num_chars > max_chars) { num_chars = max_chars; error ("character constant too long"); } else if (num_chars != 1 && ! traditional) warning ("multi-character character constant"); /* If char type is signed, sign-extend the constant. */ { int num_bits = num_chars * width; if (lookup ((U_CHAR *) "__CHAR_UNSIGNED__", sizeof ("__CHAR_UNSIGNED__") - 1, -1) || ((result >> (num_bits - 1)) & 1) == 0) yylval.integer.value = result & (~ (unsigned_HOST_WIDE_INT) 0 >> (HOST_BITS_PER_WIDE_INT - num_bits)); else yylval.integer.value = result | ~(~ (unsigned_HOST_WIDE_INT) 0 >> (HOST_BITS_PER_WIDE_INT - num_bits)); } } /* This is always a signed type. */ yylval.integer.signedp = SIGNED; return CHAR; /* some of these chars are invalid in constant expressions; maybe do something about them later */ case '/': case '+': case '-': case '*': case '%': case '|': case '&': case '^': case '~': case '!': case '@': case '<': case '>': case '[': case ']': case '.': case '?': case ':': case '=': case '{': case '}': case ',': case '#': if (keyword_parsing) break; case '(': case ')': lexptr++; return c; case '"': mask = MAX_CHAR_TYPE_MASK; string_constant: if (keyword_parsing) { char *start_ptr = lexptr; lexptr++; while (1) { c = *lexptr++; if (c == '\\') c = parse_escape (&lexptr, mask); else if (c == '"') break; } yylval.name.address = tokstart; yylval.name.length = lexptr - start_ptr; return NAME; } yyerror ("string constants not allowed in #if expressions"); return ERROR; } if (c >= '0' && c <= '9' && !keyword_parsing) { /* It's a number */ for (namelen = 1; ; namelen++) { int d = tokstart[namelen]; if (! ((is_idchar[d] || d == '.') || ((d == '-' || d == '+') && (c == 'e' || c == 'E' || ((c == 'p' || c == 'P') && ! c89)) && ! traditional))) break; c = d; } return parse_number (namelen); } /* It is a name. See how long it is. */ if (keyword_parsing) { for (namelen = 0;; namelen++) { if (is_space[tokstart[namelen]]) break; if (tokstart[namelen] == '(' || tokstart[namelen] == ')') break; if (tokstart[namelen] == '"' || tokstart[namelen] == '\'') break; } } else { if (!is_idstart[c]) { yyerror ("Invalid token in expression"); return ERROR; } for (namelen = 0; is_idchar[tokstart[namelen]]; namelen++) ; } lexptr += namelen; yylval.name.address = tokstart; yylval.name.length = namelen; return NAME; } /* Parse a C escape sequence. STRING_PTR points to a variable containing a pointer to the string to parse. That pointer is updated past the characters we use. The value of the escape sequence is returned. RESULT_MASK is used to mask out the result; an error is reported if bits are lost thereby. A negative value means the sequence \ newline was seen, which is supposed to be equivalent to nothing at all. If \ is followed by a null character, we return a negative value and leave the string pointer pointing at the null character. If \ is followed by 000, we return 0 and leave the string pointer after the zeros. A value of 0 does not mean end of string. */ HOST_WIDE_INT parse_escape (string_ptr, result_mask) char **string_ptr; HOST_WIDE_INT result_mask; { register int c = *(*string_ptr)++; switch (c) { case 'a': return TARGET_BELL; case 'b': return TARGET_BS; case 'e': case 'E': if (pedantic) pedwarn ("non-ANSI-standard escape sequence, `\\%c'", c); return 033; case 'f': return TARGET_FF; case 'n': return TARGET_NEWLINE; case 'r': return TARGET_CR; case 't': return TARGET_TAB; case 'v': return TARGET_VT; case '\n': return -2; case 0: (*string_ptr)--; return 0; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': { register HOST_WIDE_INT i = c - '0'; register int count = 0; while (++count < 3) { c = *(*string_ptr)++; if (c >= '0' && c <= '7') i = (i << 3) + c - '0'; else { (*string_ptr)--; break; } } if (i != (i & result_mask)) { i &= result_mask; pedwarn ("octal escape sequence out of range"); } return i; } case 'x': { register unsigned_HOST_WIDE_INT i = 0, overflow = 0; register int digits_found = 0, digit; for (;;) { c = *(*string_ptr)++; if (c >= '0' && c <= '9') digit = c - '0'; else if (c >= 'a' && c <= 'f') digit = c - 'a' + 10; else if (c >= 'A' && c <= 'F') digit = c - 'A' + 10; else { (*string_ptr)--; break; } overflow |= i ^ (i << 4 >> 4); i = (i << 4) + digit; digits_found = 1; } if (!digits_found) yyerror ("\\x used with no following hex digits"); if (overflow | (i != (i & result_mask))) { i &= result_mask; pedwarn ("hex escape sequence out of range"); } return i; } default: return c; } } static void yyerror (s) char *s; { error ("%s", s); skip_evaluation = 0; longjmp (parse_return_error, 1); } static void integer_overflow () { if (!skip_evaluation && pedantic) pedwarn ("integer overflow in preprocessor expression"); } static HOST_WIDE_INT left_shift (a, b) struct constant *a; unsigned_HOST_WIDE_INT b; { /* It's unclear from the C standard whether shifts can overflow. The following code ignores overflow; perhaps a C standard interpretation ruling is needed. */ if (b >= HOST_BITS_PER_WIDE_INT) return 0; else return (unsigned_HOST_WIDE_INT) a->value << b; } static HOST_WIDE_INT right_shift (a, b) struct constant *a; unsigned_HOST_WIDE_INT b; { if (b >= HOST_BITS_PER_WIDE_INT) return a->signedp ? a->value >> (HOST_BITS_PER_WIDE_INT - 1) : 0; else if (a->signedp) return a->value >> b; else return (unsigned_HOST_WIDE_INT) a->value >> b; } /* This page contains the entry point to this file. */ /* Parse STRING as an expression, and complain if this fails to use up all of the contents of STRING. STRING may contain '\0' bytes; it is terminated by the first '\n' outside a string constant, so that we can diagnose '\0' properly. If WARN_UNDEFINED is nonzero, warn if undefined identifiers are evaluated. We do not support C comments. They should be removed before this function is called. */ HOST_WIDE_INT parse_c_expression (string, warn_undefined) char *string; int warn_undefined; { lexptr = string; warn_undef = warn_undefined; /* if there is some sort of scanning error, just return 0 and assume the parsing routine has printed an error message somewhere. there is surely a better thing to do than this. */ if (setjmp (parse_return_error)) return 0; if (yyparse () != 0) abort (); if (*lexptr != '\n') error ("Junk after end of expression."); return expression_value; /* set by yyparse () */ } #ifdef TEST_EXP_READER #if YYDEBUG extern int yydebug; #endif int pedantic; int traditional; int main PROTO((int, char **)); static void initialize_random_junk PROTO((void)); static void print_unsigned_host_wide_int PROTO((unsigned_HOST_WIDE_INT)); /* Main program for testing purposes. */ int main (argc, argv) int argc; char **argv; { int n, c; char buf[1024]; unsigned_HOST_WIDE_INT u; pedantic = 1 < argc; traditional = 2 < argc; #if YYDEBUG yydebug = 3 < argc; #endif initialize_random_junk (); for (;;) { printf ("enter expression: "); n = 0; while ((buf[n] = c = getchar ()) != '\n' && c != EOF) n++; if (c == EOF) break; parse_c_expression (buf, 1); printf ("parser returned "); u = (unsigned_HOST_WIDE_INT) expression_value; if (expression_value < 0 && expression_signedp) { u = -u; printf ("-"); } if (u == 0) printf ("0"); else print_unsigned_host_wide_int (u); if (! expression_signedp) printf("u"); printf ("\n"); } return 0; } static void print_unsigned_host_wide_int (u) unsigned_HOST_WIDE_INT u; { if (u) { print_unsigned_host_wide_int (u / 10); putchar ('0' + (int) (u % 10)); } } /* table to tell if char can be part of a C identifier. */ unsigned char is_idchar[256]; /* table to tell if char can be first char of a c identifier. */ unsigned char is_idstart[256]; /* table to tell if c is horizontal or vertical space. */ unsigned char is_space[256]; /* * initialize random junk in the hash table and maybe other places */ static void initialize_random_junk () { register int i; /* * Set up is_idchar and is_idstart tables. These should be * faster than saying (is_alpha (c) || c == '_'), etc. * Must do set up these things before calling any routines tthat * refer to them. */ for (i = 'a'; i <= 'z'; i++) { ++is_idchar[i - 'a' + 'A']; ++is_idchar[i]; ++is_idstart[i - 'a' + 'A']; ++is_idstart[i]; } for (i = '0'; i <= '9'; i++) ++is_idchar[i]; ++is_idchar['_']; ++is_idstart['_']; ++is_idchar['$']; ++is_idstart['$']; ++is_space[' ']; ++is_space['\t']; ++is_space['\v']; ++is_space['\f']; ++is_space['\n']; ++is_space['\r']; } void error (PRINTF_ALIST (msg)) PRINTF_DCL (msg) { va_list args; VA_START (args, msg); fprintf (stderr, "error: "); vfprintf (stderr, msg, args); fprintf (stderr, "\n"); va_end (args); } void pedwarn (PRINTF_ALIST (msg)) PRINTF_DCL (msg) { va_list args; VA_START (args, msg); fprintf (stderr, "pedwarn: "); vfprintf (stderr, msg, args); fprintf (stderr, "\n"); va_end (args); } void warning (PRINTF_ALIST (msg)) PRINTF_DCL (msg) { va_list args; VA_START (args, msg); fprintf (stderr, "warning: "); vfprintf (stderr, msg, args); fprintf (stderr, "\n"); va_end (args); } int check_assertion (name, sym_length, tokens_specified, tokens) U_CHAR *name; int sym_length; int tokens_specified; struct arglist *tokens; { return 0; } struct hashnode * lookup (name, len, hash) U_CHAR *name; int len; int hash; { return (DEFAULT_SIGNED_CHAR) ? 0 : ((struct hashnode *) -1); } GENERIC_PTR xmalloc (size) size_t size; { return (GENERIC_PTR) malloc (size); } #endif IceE-trans-1.2.0/src/icecpp/cexp.y0000664000076400007640000007072510556172214016217 0ustar dwaynedwayne/* Parse C expressions for CCCP. Copyright (C) 1987, 1992, 1994, 1995, 1996, 1997 Free Software Foundation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA In other words, you are welcome to use, share and improve this program. You are forbidden to forbid anyone else to use, share and improve what you give them. Help stamp out software-hoarding! Adapted from expread.y of GDB by Paul Rubin, July 1986. */ /* Parse a C expression from text in a string */ %{ #include "config.h" #include /* #define YYDEBUG 1 */ #ifdef HAVE_STRING_H # include #endif #ifdef HAVE_STDLIB_H # include #endif #ifdef HAVE_LIMITS_H # include #endif #ifdef MULTIBYTE_CHARS #include #endif #include typedef unsigned char U_CHAR; /* This is used for communicating lists of keywords with cccp.c. */ struct arglist { struct arglist *next; U_CHAR *name; int length; int argno; }; /* Define a generic NULL if one hasn't already been defined. */ #ifndef NULL #define NULL 0 #endif #ifndef GENERIC_PTR #if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__) #define GENERIC_PTR void * #else #define GENERIC_PTR char * #endif #endif #ifndef NULL_PTR #define NULL_PTR ((GENERIC_PTR) 0) #endif /* Find the largest host integer type and set its size and type. Watch out: on some crazy hosts `long' is shorter than `int'. */ #ifndef HOST_WIDE_INT # if HAVE_INTTYPES_H # include # define HOST_WIDE_INT intmax_t # define unsigned_HOST_WIDE_INT uintmax_t # else # if (HOST_BITS_PER_LONG <= HOST_BITS_PER_INT && HOST_BITS_PER_LONGLONG <= HOST_BITS_PER_INT) # define HOST_WIDE_INT int # else # if (HOST_BITS_PER_LONGLONG <= HOST_BITS_PER_LONG || ! (defined LONG_LONG_MAX || defined LLONG_MAX)) # define HOST_WIDE_INT long # else # define HOST_WIDE_INT long long # endif # endif # endif #endif #ifndef unsigned_HOST_WIDE_INT #define unsigned_HOST_WIDE_INT unsigned HOST_WIDE_INT #endif #ifndef CHAR_BIT #define CHAR_BIT 8 #endif #ifndef HOST_BITS_PER_WIDE_INT #define HOST_BITS_PER_WIDE_INT (CHAR_BIT * sizeof (HOST_WIDE_INT)) #endif #ifdef _MSC_VER // I get these warnings from some bison versions: // warning C4102: 'yyoverflowlab' : unreferenced label # pragma warning( disable : 4102 ) #endif #if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7) # define __attribute__(x) #endif #ifndef PROTO # if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__) # define PROTO(ARGS) ARGS # else # define PROTO(ARGS) () # endif #endif #if defined (__STDC__) && defined (HAVE_VPRINTF) # include # define VA_START(va_list, var) va_start (va_list, var) # define PRINTF_ALIST(msg) char *msg, ... # define PRINTF_DCL(msg) # define PRINTF_PROTO(ARGS, m, n) PROTO (ARGS) __attribute__ ((format (__printf__, m, n))) #else # include # define VA_START(va_list, var) va_start (va_list) # define PRINTF_ALIST(msg) msg, va_alist # define PRINTF_DCL(msg) char *msg; va_dcl # define PRINTF_PROTO(ARGS, m, n) () __attribute__ ((format (__printf__, m, n))) # define vfprintf(file, msg, args) \ { \ char *a0 = va_arg(args, char *); \ char *a1 = va_arg(args, char *); \ char *a2 = va_arg(args, char *); \ char *a3 = va_arg(args, char *); \ fprintf (file, msg, a0, a1, a2, a3); \ } #endif #define PRINTF_PROTO_1(ARGS) PRINTF_PROTO(ARGS, 1, 2) HOST_WIDE_INT parse_c_expression PROTO((char *, int)); static int yylex PROTO((void)); static void yyerror PROTO((char *)) __attribute__ ((noreturn)); static HOST_WIDE_INT expression_value; #ifdef TEST_EXP_READER static int expression_signedp; #endif static jmp_buf parse_return_error; /* Nonzero means count most punctuation as part of a name. */ static int keyword_parsing = 0; /* Nonzero means do not evaluate this expression. This is a count, since unevaluated expressions can nest. */ static int skip_evaluation; /* Nonzero means warn if undefined identifiers are evaluated. */ static int warn_undef; /* some external tables of character types */ extern unsigned char is_idstart[], is_idchar[], is_space[]; /* Flag for -pedantic. */ extern int pedantic; /* Flag for -traditional. */ extern int traditional; /* Flag for -lang-c89. */ extern int c89; #ifndef CHAR_TYPE_SIZE #define CHAR_TYPE_SIZE BITS_PER_UNIT #endif #ifndef INT_TYPE_SIZE #define INT_TYPE_SIZE BITS_PER_WORD #endif #ifndef LONG_TYPE_SIZE #define LONG_TYPE_SIZE BITS_PER_WORD #endif #ifndef MAX_CHAR_TYPE_SIZE #define MAX_CHAR_TYPE_SIZE CHAR_TYPE_SIZE #endif #ifndef MAX_INT_TYPE_SIZE #define MAX_INT_TYPE_SIZE INT_TYPE_SIZE #endif #ifndef MAX_LONG_TYPE_SIZE #define MAX_LONG_TYPE_SIZE LONG_TYPE_SIZE #endif #define MAX_CHAR_TYPE_MASK (MAX_CHAR_TYPE_SIZE < HOST_BITS_PER_WIDE_INT \ ? (~ (~ (HOST_WIDE_INT) 0 << MAX_CHAR_TYPE_SIZE)) \ : ~ (HOST_WIDE_INT) 0) /* Suppose A1 + B1 = SUM1, using 2's complement arithmetic ignoring overflow. Suppose A, B and SUM have the same respective signs as A1, B1, and SUM1. Suppose SIGNEDP is negative if the result is signed, zero if unsigned. Then this yields nonzero if overflow occurred during the addition. Overflow occurs if A and B have the same sign, but A and SUM differ in sign, and SIGNEDP is negative. Use `^' to test whether signs differ, and `< 0' to isolate the sign. */ #define overflow_sum_sign(a, b, sum, signedp) \ ((~((a) ^ (b)) & ((a) ^ (sum)) & (signedp)) < 0) struct constant; GENERIC_PTR xmalloc PROTO((size_t)); HOST_WIDE_INT parse_escape PROTO((char **, HOST_WIDE_INT)); int check_assertion PROTO((U_CHAR *, int, int, struct arglist *)); struct hashnode *lookup PROTO((U_CHAR *, int, int)); void error PRINTF_PROTO_1((char *, ...)); void pedwarn PRINTF_PROTO_1((char *, ...)); void warning PRINTF_PROTO_1((char *, ...)); static int parse_number PROTO((int)); static HOST_WIDE_INT left_shift PROTO((struct constant *, unsigned_HOST_WIDE_INT)); static HOST_WIDE_INT right_shift PROTO((struct constant *, unsigned_HOST_WIDE_INT)); static void integer_overflow PROTO((void)); /* `signedp' values */ #define SIGNED (~0) #define UNSIGNED 0 // // Required to allow the code to compile with VC 8 with bison 2.1. // #if defined(_MSC_VER) && _MSC_VER == 1400 # define __STDC__ # define YYMALLOC # define YYFREE #endif // // Required to allow the code to compile with VC 6 and VC 71 with // bison 2.3. // #if defined(_MSC_VER) && _MSC_VER < 1400 # define YYMALLOC malloc # define YYFREE free #endif %} %union { struct constant {HOST_WIDE_INT value; int signedp;} integer; struct name {U_CHAR *address; int length;} name; struct arglist *keywords; } %type exp exp1 start %type keywords %token INT CHAR %token NAME %token ERROR %right '?' ':' %left ',' %left OR %left AND %left '|' %left '^' %left '&' %left EQUAL NOTEQUAL %left '<' '>' LEQ GEQ %left LSH RSH %left '+' '-' %left '*' '/' '%' %right UNARY /* %expect 40 */ %% start : exp1 { expression_value = $1.value; #ifdef TEST_EXP_READER expression_signedp = $1.signedp; #endif } ; /* Expressions, including the comma operator. */ exp1 : exp | exp1 ',' exp { if (pedantic) pedwarn ("comma operator in operand of `#if'"); $$ = $3; } ; /* Expressions, not including the comma operator. */ exp : '-' exp %prec UNARY { $$.value = - $2.value; $$.signedp = $2.signedp; if (($$.value & $2.value & $$.signedp) < 0) integer_overflow (); } | '!' exp %prec UNARY { $$.value = ! $2.value; $$.signedp = SIGNED; } | '+' exp %prec UNARY { $$ = $2; } | '~' exp %prec UNARY { $$.value = ~ $2.value; $$.signedp = $2.signedp; } | '#' NAME { $$.value = check_assertion ($2.address, $2.length, 0, NULL_PTR); $$.signedp = SIGNED; } | '#' NAME { keyword_parsing = 1; } '(' keywords ')' { $$.value = check_assertion ($2.address, $2.length, 1, $5); keyword_parsing = 0; $$.signedp = SIGNED; } | '(' exp1 ')' { $$ = $2; } ; /* Binary operators in order of decreasing precedence. */ exp : exp '*' exp { $$.signedp = $1.signedp & $3.signedp; if ($$.signedp) { $$.value = $1.value * $3.value; if ($1.value && ($$.value / $1.value != $3.value || ($$.value & $1.value & $3.value) < 0)) integer_overflow (); } else $$.value = ((unsigned_HOST_WIDE_INT) $1.value * $3.value); } | exp '/' exp { if ($3.value == 0) { if (!skip_evaluation) error ("division by zero in #if"); $3.value = 1; } $$.signedp = $1.signedp & $3.signedp; if ($$.signedp) { $$.value = $1.value / $3.value; if (($$.value & $1.value & $3.value) < 0) integer_overflow (); } else $$.value = ((unsigned_HOST_WIDE_INT) $1.value / $3.value); } | exp '%' exp { if ($3.value == 0) { if (!skip_evaluation) error ("division by zero in #if"); $3.value = 1; } $$.signedp = $1.signedp & $3.signedp; if ($$.signedp) $$.value = $1.value % $3.value; else $$.value = ((unsigned_HOST_WIDE_INT) $1.value % $3.value); } | exp '+' exp { $$.value = $1.value + $3.value; $$.signedp = $1.signedp & $3.signedp; if (overflow_sum_sign ($1.value, $3.value, $$.value, $$.signedp)) integer_overflow (); } | exp '-' exp { $$.value = $1.value - $3.value; $$.signedp = $1.signedp & $3.signedp; if (overflow_sum_sign ($$.value, $3.value, $1.value, $$.signedp)) integer_overflow (); } | exp LSH exp { $$.signedp = $1.signedp; if (($3.value & $3.signedp) < 0) $$.value = right_shift (&$1, -$3.value); else $$.value = left_shift (&$1, $3.value); } | exp RSH exp { $$.signedp = $1.signedp; if (($3.value & $3.signedp) < 0) $$.value = left_shift (&$1, -$3.value); else $$.value = right_shift (&$1, $3.value); } | exp EQUAL exp { $$.value = ($1.value == $3.value); $$.signedp = SIGNED; } | exp NOTEQUAL exp { $$.value = ($1.value != $3.value); $$.signedp = SIGNED; } | exp LEQ exp { $$.signedp = SIGNED; if ($1.signedp & $3.signedp) $$.value = $1.value <= $3.value; else $$.value = ((unsigned_HOST_WIDE_INT) $1.value <= $3.value); } | exp GEQ exp { $$.signedp = SIGNED; if ($1.signedp & $3.signedp) $$.value = $1.value >= $3.value; else $$.value = ((unsigned_HOST_WIDE_INT) $1.value >= $3.value); } | exp '<' exp { $$.signedp = SIGNED; if ($1.signedp & $3.signedp) $$.value = $1.value < $3.value; else $$.value = ((unsigned_HOST_WIDE_INT) $1.value < $3.value); } | exp '>' exp { $$.signedp = SIGNED; if ($1.signedp & $3.signedp) $$.value = $1.value > $3.value; else $$.value = ((unsigned_HOST_WIDE_INT) $1.value > $3.value); } | exp '&' exp { $$.value = $1.value & $3.value; $$.signedp = $1.signedp & $3.signedp; } | exp '^' exp { $$.value = $1.value ^ $3.value; $$.signedp = $1.signedp & $3.signedp; } | exp '|' exp { $$.value = $1.value | $3.value; $$.signedp = $1.signedp & $3.signedp; } | exp AND { skip_evaluation += !$1.value; } exp { skip_evaluation -= !$1.value; $$.value = ($1.value && $4.value); $$.signedp = SIGNED; } | exp OR { skip_evaluation += !!$1.value; } exp { skip_evaluation -= !!$1.value; $$.value = ($1.value || $4.value); $$.signedp = SIGNED; } | exp '?' { skip_evaluation += !$1.value; } exp ':' { skip_evaluation += !!$1.value - !$1.value; } exp { skip_evaluation -= !!$1.value; $$.value = $1.value ? $4.value : $7.value; $$.signedp = $4.signedp & $7.signedp; } | INT { $$ = yylval.integer; } | CHAR { $$ = yylval.integer; } | NAME { if (warn_undef && !skip_evaluation) warning ("`%.*s' is not defined", $1.length, $1.address); $$.value = 0; $$.signedp = SIGNED; } ; keywords : { $$ = 0; } | '(' keywords ')' keywords { struct arglist *temp; $$ = (struct arglist *) xmalloc (sizeof (struct arglist)); $$->next = $2; $$->name = (U_CHAR *) "("; $$->length = 1; temp = $$; while (temp != 0 && temp->next != 0) temp = temp->next; temp->next = (struct arglist *) xmalloc (sizeof (struct arglist)); temp->next->next = $4; temp->next->name = (U_CHAR *) ")"; temp->next->length = 1; } | NAME keywords { $$ = (struct arglist *) xmalloc (sizeof (struct arglist)); $$->name = $1.address; $$->length = $1.length; $$->next = $2; } ; %% /* During parsing of a C expression, the pointer to the next character is in this variable. */ static char *lexptr; /* Take care of parsing a number (anything that starts with a digit). Set yylval and return the token type; update lexptr. LEN is the number of characters in it. */ /* maybe needs to actually deal with floating point numbers */ static int parse_number (olen) int olen; { register char *p = lexptr; register int c; register unsigned_HOST_WIDE_INT n = 0, nd, max_over_base; register int base = 10; register int len = olen; register int overflow = 0; register int digit, largest_digit = 0; int spec_long = 0; yylval.integer.signedp = SIGNED; if (*p == '0') { base = 8; if (len >= 3 && (p[1] == 'x' || p[1] == 'X')) { p += 2; base = 16; len -= 2; } } max_over_base = (unsigned_HOST_WIDE_INT) -1 / base; for (; len > 0; len--) { c = *p++; if (c >= '0' && c <= '9') digit = c - '0'; else if (base == 16 && c >= 'a' && c <= 'f') digit = c - 'a' + 10; else if (base == 16 && c >= 'A' && c <= 'F') digit = c - 'A' + 10; else { /* `l' means long, and `u' means unsigned. */ while (1) { if (c == 'l' || c == 'L') { if (!pedantic < spec_long) yyerror ("too many `l's in integer constant"); spec_long++; } else if (c == 'u' || c == 'U') { if (! yylval.integer.signedp) yyerror ("two `u's in integer constant"); yylval.integer.signedp = UNSIGNED; } else { if (c == '.' || c == 'e' || c == 'E' || c == 'p' || c == 'P') yyerror ("Floating point numbers not allowed in #if expressions"); else { char *buf = (char *) alloca (p - lexptr + 40); sprintf (buf, "missing white space after number `%.*s'", (int) (p - lexptr - 1), lexptr); yyerror (buf); } } if (--len == 0) break; c = *p++; } /* Don't look for any more digits after the suffixes. */ break; } if (largest_digit < digit) largest_digit = digit; nd = n * base + digit; overflow |= (max_over_base < n) | (nd < n); n = nd; } if (base <= largest_digit) pedwarn ("integer constant contains digits beyond the radix"); if (overflow) pedwarn ("integer constant out of range"); /* If too big to be signed, consider it unsigned. */ if (((HOST_WIDE_INT) n & yylval.integer.signedp) < 0) { if (base == 10) warning ("integer constant is so large that it is unsigned"); yylval.integer.signedp = UNSIGNED; } lexptr = p; yylval.integer.value = n; return INT; } struct token { char *operator; int token; }; static struct token tokentab2[] = { {"&&", AND}, {"||", OR}, {"<<", LSH}, {">>", RSH}, {"==", EQUAL}, {"!=", NOTEQUAL}, {"<=", LEQ}, {">=", GEQ}, {"++", ERROR}, {"--", ERROR}, {NULL, ERROR} }; /* Read one token, getting characters through lexptr. */ static int yylex () { register int c; register int namelen; register unsigned char *tokstart; register struct token *toktab; HOST_WIDE_INT mask; retry: tokstart = (unsigned char *) lexptr; c = *tokstart; /* See if it is a special token of length 2. */ if (! keyword_parsing) for (toktab = tokentab2; toktab->operator != NULL; toktab++) if (c == *toktab->operator && tokstart[1] == toktab->operator[1]) { lexptr += 2; if (toktab->token == ERROR) { char *buf = (char *) alloca (40); sprintf (buf, "`%s' not allowed in operand of `#if'", toktab->operator); yyerror (buf); } return toktab->token; } switch (c) { case '\n': return 0; case ' ': case '\t': case '\r': lexptr++; goto retry; case '\'': mask = MAX_CHAR_TYPE_MASK; char_constant: lexptr++; if (keyword_parsing) { char *start_ptr = lexptr - 1; while (1) { c = *lexptr++; if (c == '\\') c = parse_escape (&lexptr, mask); else if (c == '\'') break; } yylval.name.address = tokstart; yylval.name.length = lexptr - start_ptr; return NAME; } /* This code for reading a character constant handles multicharacter constants and wide characters. It is mostly copied from c-lex.c. */ { register HOST_WIDE_INT result = 0; register int num_chars = 0; unsigned width = MAX_CHAR_TYPE_SIZE; int max_chars; char *token_buffer; max_chars = MAX_LONG_TYPE_SIZE / width; token_buffer = (char *) alloca (max_chars + 1); while (1) { c = *lexptr++; if (c == '\'' || c == EOF) break; if (c == '\\') { c = parse_escape (&lexptr, mask); } num_chars++; /* Merge character into result; ignore excess chars. */ if (num_chars <= max_chars) { if (width < HOST_BITS_PER_WIDE_INT) result = (result << width) | c; else result = c; token_buffer[num_chars - 1] = c; } } token_buffer[num_chars] = 0; if (c != '\'') error ("malformatted character constant"); else if (num_chars == 0) error ("empty character constant"); else if (num_chars > max_chars) { num_chars = max_chars; error ("character constant too long"); } else if (num_chars != 1 && ! traditional) warning ("multi-character character constant"); /* If char type is signed, sign-extend the constant. */ { int num_bits = num_chars * width; if (lookup ((U_CHAR *) "__CHAR_UNSIGNED__", sizeof ("__CHAR_UNSIGNED__") - 1, -1) || ((result >> (num_bits - 1)) & 1) == 0) yylval.integer.value = result & (~ (unsigned_HOST_WIDE_INT) 0 >> (HOST_BITS_PER_WIDE_INT - num_bits)); else yylval.integer.value = result | ~(~ (unsigned_HOST_WIDE_INT) 0 >> (HOST_BITS_PER_WIDE_INT - num_bits)); } } /* This is always a signed type. */ yylval.integer.signedp = SIGNED; return CHAR; /* some of these chars are invalid in constant expressions; maybe do something about them later */ case '/': case '+': case '-': case '*': case '%': case '|': case '&': case '^': case '~': case '!': case '@': case '<': case '>': case '[': case ']': case '.': case '?': case ':': case '=': case '{': case '}': case ',': case '#': if (keyword_parsing) break; case '(': case ')': lexptr++; return c; case '"': mask = MAX_CHAR_TYPE_MASK; string_constant: if (keyword_parsing) { char *start_ptr = lexptr; lexptr++; while (1) { c = *lexptr++; if (c == '\\') c = parse_escape (&lexptr, mask); else if (c == '"') break; } yylval.name.address = tokstart; yylval.name.length = lexptr - start_ptr; return NAME; } yyerror ("string constants not allowed in #if expressions"); return ERROR; } if (c >= '0' && c <= '9' && !keyword_parsing) { /* It's a number */ for (namelen = 1; ; namelen++) { int d = tokstart[namelen]; if (! ((is_idchar[d] || d == '.') || ((d == '-' || d == '+') && (c == 'e' || c == 'E' || ((c == 'p' || c == 'P') && ! c89)) && ! traditional))) break; c = d; } return parse_number (namelen); } /* It is a name. See how long it is. */ if (keyword_parsing) { for (namelen = 0;; namelen++) { if (is_space[tokstart[namelen]]) break; if (tokstart[namelen] == '(' || tokstart[namelen] == ')') break; if (tokstart[namelen] == '"' || tokstart[namelen] == '\'') break; } } else { if (!is_idstart[c]) { yyerror ("Invalid token in expression"); return ERROR; } for (namelen = 0; is_idchar[tokstart[namelen]]; namelen++) ; } lexptr += namelen; yylval.name.address = tokstart; yylval.name.length = namelen; return NAME; } /* Parse a C escape sequence. STRING_PTR points to a variable containing a pointer to the string to parse. That pointer is updated past the characters we use. The value of the escape sequence is returned. RESULT_MASK is used to mask out the result; an error is reported if bits are lost thereby. A negative value means the sequence \ newline was seen, which is supposed to be equivalent to nothing at all. If \ is followed by a null character, we return a negative value and leave the string pointer pointing at the null character. If \ is followed by 000, we return 0 and leave the string pointer after the zeros. A value of 0 does not mean end of string. */ HOST_WIDE_INT parse_escape (string_ptr, result_mask) char **string_ptr; HOST_WIDE_INT result_mask; { register int c = *(*string_ptr)++; switch (c) { case 'a': return TARGET_BELL; case 'b': return TARGET_BS; case 'e': case 'E': if (pedantic) pedwarn ("non-ANSI-standard escape sequence, `\\%c'", c); return 033; case 'f': return TARGET_FF; case 'n': return TARGET_NEWLINE; case 'r': return TARGET_CR; case 't': return TARGET_TAB; case 'v': return TARGET_VT; case '\n': return -2; case 0: (*string_ptr)--; return 0; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': { register HOST_WIDE_INT i = c - '0'; register int count = 0; while (++count < 3) { c = *(*string_ptr)++; if (c >= '0' && c <= '7') i = (i << 3) + c - '0'; else { (*string_ptr)--; break; } } if (i != (i & result_mask)) { i &= result_mask; pedwarn ("octal escape sequence out of range"); } return i; } case 'x': { register unsigned_HOST_WIDE_INT i = 0, overflow = 0; register int digits_found = 0, digit; for (;;) { c = *(*string_ptr)++; if (c >= '0' && c <= '9') digit = c - '0'; else if (c >= 'a' && c <= 'f') digit = c - 'a' + 10; else if (c >= 'A' && c <= 'F') digit = c - 'A' + 10; else { (*string_ptr)--; break; } overflow |= i ^ (i << 4 >> 4); i = (i << 4) + digit; digits_found = 1; } if (!digits_found) yyerror ("\\x used with no following hex digits"); if (overflow | (i != (i & result_mask))) { i &= result_mask; pedwarn ("hex escape sequence out of range"); } return i; } default: return c; } } static void yyerror (s) char *s; { error ("%s", s); skip_evaluation = 0; longjmp (parse_return_error, 1); } static void integer_overflow () { if (!skip_evaluation && pedantic) pedwarn ("integer overflow in preprocessor expression"); } static HOST_WIDE_INT left_shift (a, b) struct constant *a; unsigned_HOST_WIDE_INT b; { /* It's unclear from the C standard whether shifts can overflow. The following code ignores overflow; perhaps a C standard interpretation ruling is needed. */ if (b >= HOST_BITS_PER_WIDE_INT) return 0; else return (unsigned_HOST_WIDE_INT) a->value << b; } static HOST_WIDE_INT right_shift (a, b) struct constant *a; unsigned_HOST_WIDE_INT b; { if (b >= HOST_BITS_PER_WIDE_INT) return a->signedp ? a->value >> (HOST_BITS_PER_WIDE_INT - 1) : 0; else if (a->signedp) return a->value >> b; else return (unsigned_HOST_WIDE_INT) a->value >> b; } /* This page contains the entry point to this file. */ /* Parse STRING as an expression, and complain if this fails to use up all of the contents of STRING. STRING may contain '\0' bytes; it is terminated by the first '\n' outside a string constant, so that we can diagnose '\0' properly. If WARN_UNDEFINED is nonzero, warn if undefined identifiers are evaluated. We do not support C comments. They should be removed before this function is called. */ HOST_WIDE_INT parse_c_expression (string, warn_undefined) char *string; int warn_undefined; { lexptr = string; warn_undef = warn_undefined; /* if there is some sort of scanning error, just return 0 and assume the parsing routine has printed an error message somewhere. there is surely a better thing to do than this. */ if (setjmp (parse_return_error)) return 0; if (yyparse () != 0) abort (); if (*lexptr != '\n') error ("Junk after end of expression."); return expression_value; /* set by yyparse () */ } #ifdef TEST_EXP_READER #if YYDEBUG extern int yydebug; #endif int pedantic; int traditional; int main PROTO((int, char **)); static void initialize_random_junk PROTO((void)); static void print_unsigned_host_wide_int PROTO((unsigned_HOST_WIDE_INT)); /* Main program for testing purposes. */ int main (argc, argv) int argc; char **argv; { int n, c; char buf[1024]; unsigned_HOST_WIDE_INT u; pedantic = 1 < argc; traditional = 2 < argc; #if YYDEBUG yydebug = 3 < argc; #endif initialize_random_junk (); for (;;) { printf ("enter expression: "); n = 0; while ((buf[n] = c = getchar ()) != '\n' && c != EOF) n++; if (c == EOF) break; parse_c_expression (buf, 1); printf ("parser returned "); u = (unsigned_HOST_WIDE_INT) expression_value; if (expression_value < 0 && expression_signedp) { u = -u; printf ("-"); } if (u == 0) printf ("0"); else print_unsigned_host_wide_int (u); if (! expression_signedp) printf("u"); printf ("\n"); } return 0; } static void print_unsigned_host_wide_int (u) unsigned_HOST_WIDE_INT u; { if (u) { print_unsigned_host_wide_int (u / 10); putchar ('0' + (int) (u % 10)); } } /* table to tell if char can be part of a C identifier. */ unsigned char is_idchar[256]; /* table to tell if char can be first char of a c identifier. */ unsigned char is_idstart[256]; /* table to tell if c is horizontal or vertical space. */ unsigned char is_space[256]; /* * initialize random junk in the hash table and maybe other places */ static void initialize_random_junk () { register int i; /* * Set up is_idchar and is_idstart tables. These should be * faster than saying (is_alpha (c) || c == '_'), etc. * Must do set up these things before calling any routines tthat * refer to them. */ for (i = 'a'; i <= 'z'; i++) { ++is_idchar[i - 'a' + 'A']; ++is_idchar[i]; ++is_idstart[i - 'a' + 'A']; ++is_idstart[i]; } for (i = '0'; i <= '9'; i++) ++is_idchar[i]; ++is_idchar['_']; ++is_idstart['_']; ++is_idchar['$']; ++is_idstart['$']; ++is_space[' ']; ++is_space['\t']; ++is_space['\v']; ++is_space['\f']; ++is_space['\n']; ++is_space['\r']; } void error (PRINTF_ALIST (msg)) PRINTF_DCL (msg) { va_list args; VA_START (args, msg); fprintf (stderr, "error: "); vfprintf (stderr, msg, args); fprintf (stderr, "\n"); va_end (args); } void pedwarn (PRINTF_ALIST (msg)) PRINTF_DCL (msg) { va_list args; VA_START (args, msg); fprintf (stderr, "pedwarn: "); vfprintf (stderr, msg, args); fprintf (stderr, "\n"); va_end (args); } void warning (PRINTF_ALIST (msg)) PRINTF_DCL (msg) { va_list args; VA_START (args, msg); fprintf (stderr, "warning: "); vfprintf (stderr, msg, args); fprintf (stderr, "\n"); va_end (args); } int check_assertion (name, sym_length, tokens_specified, tokens) U_CHAR *name; int sym_length; int tokens_specified; struct arglist *tokens; { return 0; } struct hashnode * lookup (name, len, hash) U_CHAR *name; int len; int hash; { return (DEFAULT_SIGNED_CHAR) ? 0 : ((struct hashnode *) -1); } GENERIC_PTR xmalloc (size) size_t size; { return (GENERIC_PTR) malloc (size); } #endif IceE-trans-1.2.0/src/icecpp/cccp.c0000664000076400007640000114143510560413774016144 0ustar dwaynedwayne/* C Compatible Compiler Preprocessor (CCCP) Copyright (C) 1986, 87, 89, 92-97, 1998 Free Software Foundation, Inc. Written by Paul Rubin, June 1986 Adapted to ANSI C, Richard Stallman, Jan 1987 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include #include #include #include #include #ifdef TIME_WITH_SYS_TIME # include # include #else # if HAVE_SYS_TIME_H # include # else # include #endif #endif #ifdef HAVE_SYS_RESOURCE_H # include #endif #if HAVE_FCNTL_H # include #endif #if HAVE_LIMITS_H # include #endif #if HAVE_UNISTD_H # include #endif #include #if HAVE_STDLIB_H # include #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include #endif #endif typedef unsigned char U_CHAR; #include "gansidecl.h" #include "pcp.h" #ifdef NEED_DECLARATION_INDEX extern char *index (); #endif #ifdef NEED_DECLARATION_RINDEX extern char *rindex (); #endif #ifdef NEED_DECLARATION_GETENV extern char *getenv (); #endif #if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7) # define __attribute__(x) #endif #ifndef STANDARD_INCLUDE_DIR # define STANDARD_INCLUDE_DIR "/usr/include" #endif /* By default, colon separates directories in a path. */ #ifndef PATH_SEPARATOR # define PATH_SEPARATOR ':' #endif /* By default, the suffix for object files is ".o". */ #ifdef OBJECT_SUFFIX # define HAVE_OBJECT_SUFFIX #else # define OBJECT_SUFFIX ".o" #endif #if defined (__STDC__) && defined (HAVE_VPRINTF) # include # define PRINTF_ALIST(msg) char *msg, ... # define PRINTF_DCL(msg) # define PRINTF_PROTO(ARGS, m, n) PROTO (ARGS) __attribute__ ((format (__printf__, m, n))) #else # include # define PRINTF_ALIST(msg) msg, va_alist # define PRINTF_DCL(msg) char *msg; va_dcl # define PRINTF_PROTO(ARGS, m, n) () __attribute__ ((format (__printf__, m, n))) # define vfprintf(file, msg, args) \ { \ char *a0 = va_arg(args, char *); \ char *a1 = va_arg(args, char *); \ char *a2 = va_arg(args, char *); \ char *a3 = va_arg(args, char *); \ fprintf (file, msg, a0, a1, a2, a3); \ } #endif #define PRINTF_PROTO_1(ARGS) PRINTF_PROTO(ARGS, 1, 2) #define PRINTF_PROTO_2(ARGS) PRINTF_PROTO(ARGS, 2, 3) #define PRINTF_PROTO_3(ARGS) PRINTF_PROTO(ARGS, 3, 4) /* VMS-specific definitions */ #ifdef VMS #include #define open(fname,mode,prot) VMS_open (fname,mode,prot) #define fopen(fname,mode) VMS_fopen (fname,mode) #define freopen(fname,mode,ofile) VMS_freopen (fname,mode,ofile) #define fstat(fd,stbuf) VMS_fstat (fd,stbuf) static int VMS_fstat (), VMS_stat (); static int VMS_open (); static FILE *VMS_fopen (); static FILE *VMS_freopen (); static void hack_vms_include_specification (); #define INO_T_EQ(a, b) (!bcmp((char *) &(a), (char *) &(b), sizeof (a))) #define INO_T_HASH(a) 0 #define INCLUDE_LEN_FUDGE 12 /* leave room for VMS syntax conversion */ #endif /* VMS */ /* Windows does not natively support inodes, and neither does MSDOS. */ #if (defined (_WIN32) && ! defined (CYGWIN32)) || defined (__MSDOS__) #define INO_T_EQ(a, b) 0 #endif #ifndef O_RDONLY #define O_RDONLY 0 #endif #undef MIN #undef MAX #define MIN(X,Y) ((X) < (Y) ? (X) : (Y)) #define MAX(X,Y) ((X) > (Y) ? (X) : (Y)) /* Find the largest host integer type and set its size and type. Watch out: on some crazy hosts `long' is shorter than `int'. */ #ifndef HOST_WIDE_INT # if HAVE_INTTYPES_H # include # define HOST_WIDE_INT intmax_t # else # if (HOST_BITS_PER_LONG <= HOST_BITS_PER_INT && HOST_BITS_PER_LONGLONG <= HOST_BITS_PER_INT) # define HOST_WIDE_INT int # else # if (HOST_BITS_PER_LONGLONG <= HOST_BITS_PER_LONG || ! (defined LONG_LONG_MAX || defined LLONG_MAX)) # define HOST_WIDE_INT long # else # define HOST_WIDE_INT long long # endif # endif # endif #endif #ifndef S_ISREG #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) #endif #ifndef S_ISDIR #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) #endif #ifndef INO_T_EQ #define INO_T_EQ(a, b) ((a) == (b)) #endif #ifndef INO_T_HASH #define INO_T_HASH(a) (a) #endif #ifndef INCLUDE_LEN_FUDGE #define INCLUDE_LEN_FUDGE 0 #endif /* External declarations. */ /* extern char *version_string; */ extern char *update_path PROTO((char *, char *)); //#ifndef VMS //#ifndef HAVE_STRERROR //extern int sys_nerr; //extern char *sys_errlist[]; //#else /* HAVE_STRERROR */ //char *strerror (); //#endif //#else /* VMS */ //char *strerror (int,...); //#endif HOST_WIDE_INT parse_escape PROTO((char **, HOST_WIDE_INT)); HOST_WIDE_INT parse_c_expression PROTO((char *, int)); #ifndef errno extern int errno; #endif /* Name under which this program was invoked. */ static char *progname; /* Nonzero means use extra default include directories for C++. */ static int cplusplus; /* Nonzero means handle cplusplus style comments */ static int cplusplus_comments; /* Nonzero means handle #import, for objective C. */ static int objc; /* Nonzero means this is an assembly file, and allow unknown directives, which could be comments. */ static int lang_asm; /* Current maximum length of directory names in the search path for include files. (Altered as we get more of them.) */ static int max_include_len; /* Nonzero means turn NOTREACHED into #pragma NOTREACHED etc */ static int for_lint = 0; /* Nonzero means copy comments into the output file. */ static int put_out_comments = 0; /* Nonzero means don't process the ANSI trigraph sequences. */ static int no_trigraphs = 0; /* Nonzero means print the names of included files rather than the preprocessed output. 1 means just the #include "...", 2 means #include <...> as well. */ static int print_deps = 0; /* Nonzero if missing .h files in -M output are assumed to be generated files and not errors. */ static int print_deps_missing_files = 0; /* Nonzero means print names of header files (-H). */ static int print_include_names = 0; /* Nonzero means don't output line number information. */ static int no_line_directives; /* Nonzero means output the text in failing conditionals, inside #failed ... #endfailed. */ static int output_conditionals; /* dump_only means inhibit output of the preprocessed text and instead output the definitions of all user-defined macros in a form suitable for use as input to cccp. dump_names means pass #define and the macro name through to output. dump_definitions means pass the whole definition (plus #define) through */ static enum {dump_none, dump_only, dump_names, dump_definitions} dump_macros = dump_none; /* Nonzero means pass all #define and #undef directives which we actually process through to the output stream. This feature is used primarily to allow cc1 to record the #defines and #undefs for the sake of debuggers which understand about preprocessor macros, but it may also be useful with -E to figure out how symbols are defined, and where they are defined. */ static int debug_output = 0; /* Nonzero means pass #include lines through to the output, even if they are ifdefed out. */ static int dump_includes; /* Nonzero indicates special processing used by the pcp program. The special effects of this mode are: Inhibit all macro expansion, except those inside #if directives. Process #define directives normally, and output their contents to the output file. Output preconditions to pcp_outfile indicating all the relevant preconditions for use of this file in a later cpp run. */ static FILE *pcp_outfile; /* Nonzero means we are inside an IF during a -pcp run. In this mode macro expansion is done, and preconditions are output for all macro uses requiring them. */ static int pcp_inside_if; /* Nonzero means never to include precompiled files. This is 1 since there's no way now to make precompiled files, so it's not worth testing for them. */ static int no_precomp = 1; /* Nonzero means give all the error messages the ANSI standard requires. */ int pedantic; /* Nonzero means try to make failure to fit ANSI C an error. */ static int pedantic_errors; /* Nonzero means don't print warning messages. -w. */ static int inhibit_warnings = 0; /* Nonzero means warn if slash-star appears in a slash-star comment, or if newline-backslash appears in a slash-slash comment. */ static int warn_comments; /* Nonzero means warn if a macro argument is (or would be) stringified with -traditional. */ static int warn_stringify; /* Nonzero means warn if there are any trigraphs. */ static int warn_trigraphs; /* Nonzero means warn if undefined identifiers are evaluated in an #if. */ static int warn_undef; /* Nonzero means warn if #import is used. */ static int warn_import = 1; /* Nonzero means turn warnings into errors. */ static int warnings_are_errors; /* Nonzero means try to imitate old fashioned non-ANSI preprocessor. */ int traditional; /* Nonzero for the 1989 C Standard, including corrigenda and amendments. */ int c89; /* Nonzero causes output not to be done, but directives such as #define that have side effects are still obeyed. */ static int no_output; /* Nonzero means we should look for header.gcc files that remap file names. */ static int remap; /* Nonzero means this file was included with a -imacros or -include command line and should not be recorded as an include file. */ static int no_record_file; /* Nonzero means that we have finished processing the command line options. This flag is used to decide whether or not to issue certain errors and/or warnings. */ static int done_initializing = 0; /* Line where a newline was first seen in a string constant. */ static int multiline_string_line = 0; /* I/O buffer structure. The `fname' field is nonzero for source files and #include files and for the dummy text used for -D and -U. It is zero for rescanning results of macro expansion and for expanding macro arguments. */ #define INPUT_STACK_MAX 400 static struct file_buf { char *fname; /* Filename specified with #line directive. */ char *nominal_fname; /* Include file description. */ struct include_file *inc; /* Record where in the search path this file was found. For #include_next. */ struct file_name_list *dir; int lineno; int length; U_CHAR *buf; U_CHAR *bufp; /* Macro that this level is the expansion of. Included so that we can reenable the macro at the end of this level. */ struct hashnode *macro; /* Value of if_stack at start of this file. Used to prohibit unmatched #endif (etc) in an include file. */ struct if_stack *if_stack; /* Object to be freed at end of input at this level. */ U_CHAR *free_ptr; /* True if this is a system header file; see is_system_include. */ char system_header_p; } instack[INPUT_STACK_MAX]; static int last_error_tick; /* Incremented each time we print it. */ static int input_file_stack_tick; /* Incremented when the status changes. */ /* Current nesting level of input sources. `instack[indepth]' is the level currently being read. */ static int indepth = -1; #define CHECK_DEPTH(code) \ if (indepth >= (INPUT_STACK_MAX - 1)) \ { \ error_with_line (line_for_error (instack[indepth].lineno), \ "macro or `#include' recursion too deep"); \ code; \ } /* Current depth in #include directives that use <...>. */ static int system_include_depth = 0; typedef struct file_buf FILE_BUF; /* The output buffer. Its LENGTH field is the amount of room allocated for the buffer, not the number of chars actually present. To get that, subtract outbuf.buf from outbuf.bufp. */ #define OUTBUF_SIZE 10 /* initial size of output buffer */ static FILE_BUF outbuf; /* Grow output buffer OBUF points at so it can hold at least NEEDED more chars. */ #define check_expand(OBUF, NEEDED) \ (((OBUF)->length - ((OBUF)->bufp - (OBUF)->buf) <= (NEEDED)) \ ? grow_outbuf ((OBUF), (NEEDED)) : 0) struct file_name_list { struct file_name_list *next; /* If the following is 1, it is a C-language system include directory. */ int c_system_include_path; /* Mapping of file names for this directory. */ struct file_name_map *name_map; /* Non-zero if name_map is valid. */ int got_name_map; /* The include directory status. */ struct stat st; /* The include prefix: "" denotes the working directory, otherwise fname must end in '/'. The actual size is dynamically allocated. */ char fname[1]; }; /* #include "file" looks in source file dir, then stack. */ /* #include just looks in the stack. */ /* -I directories are added to the end, then the defaults are added. */ /* The */ static struct default_include { char *fname; /* The name of the directory. */ char *component; /* The component containing the directory */ int cplusplus; /* Only look here if we're compiling C++. */ int cxx_aware; /* Includes in this directory don't need to be wrapped in extern "C" when compiling C++. */ } include_defaults_array[] #ifdef INCLUDE_DEFAULTS = INCLUDE_DEFAULTS; #else = { /* Pick up GNU C++ specific include files. */ { GPLUSPLUS_INCLUDE_DIR, "G++", 1, 1 }, { OLD_GPLUSPLUS_INCLUDE_DIR, 0, 1, 1 }, #ifdef CROSS_COMPILE /* This is the dir for fixincludes. Put it just before the files that we fix. */ { GCC_INCLUDE_DIR, "GCC", 0, 0 }, /* For cross-compilation, this dir name is generated automatically in Makefile.in. */ { CROSS_INCLUDE_DIR, "GCC", 0, 0 }, #ifdef TOOL_INCLUDE_DIR /* This is another place that the target system's headers might be. */ { TOOL_INCLUDE_DIR, "BINUTILS", 0, 0 }, #endif #else /* not CROSS_COMPILE */ #ifdef LOCAL_INCLUDE_DIR /* This should be /usr/local/include and should come before the fixincludes-fixed header files. */ { LOCAL_INCLUDE_DIR, 0, 0, 1 }, #endif #ifdef TOOL_INCLUDE_DIR /* This is here ahead of GCC_INCLUDE_DIR because assert.h goes here. Likewise, behind LOCAL_INCLUDE_DIR, where glibc puts its assert.h. */ { TOOL_INCLUDE_DIR, "BINUTILS", 0, 0 }, #endif /* This is the dir for fixincludes. Put it just before the files that we fix. */ { GCC_INCLUDE_DIR, "GCC", 0, 0 }, /* Some systems have an extra dir of include files. */ #ifdef SYSTEM_INCLUDE_DIR { SYSTEM_INCLUDE_DIR, 0, 0, 0 }, #endif #ifndef STANDARD_INCLUDE_COMPONENT #define STANDARD_INCLUDE_COMPONENT 0 #endif { STANDARD_INCLUDE_DIR, STANDARD_INCLUDE_COMPONENT, 0, 0 }, #endif /* not CROSS_COMPILE */ { 0, 0, 0, 0 } }; #endif /* no INCLUDE_DEFAULTS */ /* The code looks at the defaults through this pointer, rather than through the constant structure above. This pointer gets changed if an environment variable specifies other defaults. */ static struct default_include *include_defaults = include_defaults_array; static struct file_name_list *include = 0; /* First dir to search */ /* First dir to search for */ /* This is the first element to use for #include <...>. If it is 0, use the entire chain for such includes. */ static struct file_name_list *first_bracket_include = 0; /* This is the first element in the chain that corresponds to a directory of system header files. */ static struct file_name_list *first_system_include = 0; static struct file_name_list *last_include = 0; /* Last in chain */ /* Chain of include directories to put at the end of the other chain. */ static struct file_name_list *after_include = 0; static struct file_name_list *last_after_include = 0; /* Last in chain */ /* Chain to put at the start of the system include files. */ static struct file_name_list *before_system = 0; static struct file_name_list *last_before_system = 0; /* Last in chain */ /* Directory prefix that should replace `/usr' in the standard include file directories. */ static char *include_prefix; /* Maintain and search list of included files. */ struct include_file { struct include_file *next; /* for include_hashtab */ struct include_file *next_ino; /* for include_ino_hashtab */ char *fname; /* If the following is the empty string, it means #pragma once was seen in this include file, or #import was applied to the file. Otherwise, if it is nonzero, it is a macro name. Don't include the file again if that macro is defined. */ U_CHAR *control_macro; /* Nonzero if the dependency on this include file has been output. */ int deps_output; struct stat st; }; /* Hash tables of files already included with #include or #import. include_hashtab is by full name; include_ino_hashtab is by inode number. */ #define INCLUDE_HASHSIZE 61 static struct include_file *include_hashtab[INCLUDE_HASHSIZE]; static struct include_file *include_ino_hashtab[INCLUDE_HASHSIZE]; /* Global list of strings read in from precompiled files. This list is kept in the order the strings are read in, with new strings being added at the end through stringlist_tailp. We use this list to output the strings at the end of the run. */ static STRINGDEF *stringlist; static STRINGDEF **stringlist_tailp = &stringlist; /* Structure returned by create_definition */ typedef struct macrodef MACRODEF; struct macrodef { struct definition *defn; U_CHAR *symnam; int symlen; }; enum sharp_token_type { NO_SHARP_TOKEN = 0, /* token not present */ SHARP_TOKEN = '#', /* token spelled with # only */ WHITE_SHARP_TOKEN, /* token spelled with # and white space */ PERCENT_COLON_TOKEN = '%', /* token spelled with %: only */ WHITE_PERCENT_COLON_TOKEN /* token spelled with %: and white space */ }; /* Structure allocated for every #define. For a simple replacement such as #define foo bar , nargs = -1, the `pattern' list is null, and the expansion is just the replacement text. Nargs = 0 means a functionlike macro with no args, e.g., #define getchar() getc (stdin) . When there are args, the expansion is the replacement text with the args squashed out, and the reflist is a list describing how to build the output from the input: e.g., "3 chars, then the 1st arg, then 9 chars, then the 3rd arg, then 0 chars, then the 2nd arg". The chars here come from the expansion. Whatever is left of the expansion after the last arg-occurrence is copied after that arg. Note that the reflist can be arbitrarily long--- its length depends on the number of times the arguments appear in the replacement text, not how many args there are. Example: #define f(x) x+x+x+x+x+x+x would have replacement text "++++++" and pattern list { (0, 1), (1, 1), (1, 1), ..., (1, 1), NULL } where (x, y) means (nchars, argno). */ typedef struct definition DEFINITION; struct definition { int nargs; int length; /* length of expansion string */ int predefined; /* True if the macro was builtin or */ /* came from the command line */ U_CHAR *expansion; int line; /* Line number of definition */ char *file; /* File of definition */ char rest_args; /* Nonzero if last arg. absorbs the rest */ struct reflist { struct reflist *next; enum sharp_token_type stringify; /* set if a # operator before arg */ enum sharp_token_type raw_before; /* set if a ## operator before arg */ enum sharp_token_type raw_after; /* set if a ## operator after arg */ char rest_args; /* Nonzero if this arg. absorbs the rest */ int nchars; /* Number of literal chars to copy before this arg occurrence. */ int argno; /* Number of arg to substitute (origin-0) */ } *pattern; union { /* Names of macro args, concatenated in reverse order with comma-space between them. The only use of this is that we warn on redefinition if this differs between the old and new definitions. */ U_CHAR *argnames; } args; }; /* different kinds of things that can appear in the value field of a hash node. Actually, this may be useless now. */ union hashval { char *cpval; DEFINITION *defn; KEYDEF *keydef; }; /* * special extension string that can be added to the last macro argument to * allow it to absorb the "rest" of the arguments when expanded. Ex: * #define wow(a, b...) process (b, a, b) * { wow (1, 2, 3); } -> { process (2, 3, 1, 2, 3); } * { wow (one, two); } -> { process (two, one, two); } * if this "rest_arg" is used with the concat token '##' and if it is not * supplied then the token attached to with ## will not be outputted. Ex: * #define wow (a, b...) process (b ## , a, ## b) * { wow (1, 2); } -> { process (2, 1, 2); } * { wow (one); } -> { process (one); { */ static char rest_extension[] = "..."; #define REST_EXTENSION_LENGTH (sizeof (rest_extension) - 1) /* The structure of a node in the hash table. The hash table has entries for all tokens defined by #define directives (type T_MACRO), plus some special tokens like __LINE__ (these each have their own type, and the appropriate code is run when that type of node is seen. It does not contain control words like "#define", which are recognized by a separate piece of code. */ /* different flavors of hash nodes --- also used in keyword table */ enum node_type { T_DEFINE = 1, /* the `#define' keyword */ T_INCLUDE, /* the `#include' keyword */ T_INCLUDE_NEXT, /* the `#include_next' keyword */ T_IMPORT, /* the `#import' keyword */ T_IFDEF, /* the `#ifdef' keyword */ T_IFNDEF, /* the `#ifndef' keyword */ T_IF, /* the `#if' keyword */ T_ELSE, /* `#else' */ T_PRAGMA, /* `#pragma' */ T_ELIF, /* `#elif' */ T_UNDEF, /* `#undef' */ T_LINE, /* `#line' */ T_ERROR, /* `#error' */ T_WARNING, /* `#warning' */ T_ENDIF, /* `#endif' */ T_SCCS, /* `#sccs', used on system V. */ T_IDENT, /* `#ident', used on system V. */ T_ASSERT, /* `#assert', taken from system V. */ T_UNASSERT, /* `#unassert', taken from system V. */ T_SPECLINE, /* special symbol `__LINE__' */ T_DATE, /* `__DATE__' */ T_FILE, /* `__FILE__' */ T_BASE_FILE, /* `__BASE_FILE__' */ T_INCLUDE_LEVEL, /* `__INCLUDE_LEVEL__' */ T_VERSION, /* `__VERSION__' */ T_SIZE_TYPE, /* `__SIZE_TYPE__' */ T_PTRDIFF_TYPE, /* `__PTRDIFF_TYPE__' */ T_WCHAR_TYPE, /* `__WCHAR_TYPE__' */ T_USER_LABEL_PREFIX_TYPE, /* `__USER_LABEL_PREFIX__' */ T_REGISTER_PREFIX_TYPE, /* `__REGISTER_PREFIX__' */ T_IMMEDIATE_PREFIX_TYPE, /* `__IMMEDIATE_PREFIX__' */ T_TIME, /* `__TIME__' */ T_CONST, /* Constant value, used by `__STDC__' */ T_MACRO, /* macro defined by `#define' */ T_DISABLED, /* macro temporarily turned off for rescan */ T_SPEC_DEFINED, /* special `defined' macro for use in #if statements */ T_PCSTRING, /* precompiled string (hashval is KEYDEF *) */ T_UNUSED /* Used for something not defined. */ }; struct hashnode { struct hashnode *next; /* double links for easy deletion */ struct hashnode *prev; struct hashnode **bucket_hdr; /* also, a back pointer to this node's hash chain is kept, in case the node is the head of the chain and gets deleted. */ enum node_type type; /* type of special token */ int length; /* length of token, for quick comparison */ U_CHAR *name; /* the actual name */ union hashval value; /* pointer to expansion, or whatever */ }; typedef struct hashnode HASHNODE; /* Some definitions for the hash table. The hash function MUST be computed as shown in hashf () below. That is because the rescan loop computes the hash value `on the fly' for most tokens, in order to avoid the overhead of a lot of procedure calls to the hashf () function. Hashf () only exists for the sake of politeness, for use when speed isn't so important. */ #define HASHSIZE 1403 static HASHNODE *hashtab[HASHSIZE]; #define HASHSTEP(old, c) ((old << 2) + c) #define MAKE_POS(v) (v & 0x7fffffff) /* make number positive */ /* Symbols to predefine. */ #ifdef CPP_PREDEFINES static char *predefs = CPP_PREDEFINES; #else static char *predefs = ""; #endif /* We let tm.h override the types used here, to handle trivial differences such as the choice of unsigned int or long unsigned int for size_t. When machines start needing nontrivial differences in the size type, it would be best to do something here to figure out automatically from other information what type to use. */ /* The string value for __SIZE_TYPE__. */ #ifndef SIZE_TYPE #define SIZE_TYPE "long unsigned int" #endif /* The string value for __PTRDIFF_TYPE__. */ #ifndef PTRDIFF_TYPE #define PTRDIFF_TYPE "long int" #endif /* The string value for __WCHAR_TYPE__. */ #ifndef WCHAR_TYPE #define WCHAR_TYPE "int" #endif char * wchar_type = WCHAR_TYPE; #undef WCHAR_TYPE /* The string value for __USER_LABEL_PREFIX__ */ #ifndef USER_LABEL_PREFIX #define USER_LABEL_PREFIX "" #endif /* The string value for __REGISTER_PREFIX__ */ #ifndef REGISTER_PREFIX #define REGISTER_PREFIX "" #endif /* The string value for __IMMEDIATE_PREFIX__ */ #ifndef IMMEDIATE_PREFIX #define IMMEDIATE_PREFIX "" #endif /* In the definition of a #assert name, this structure forms a list of the individual values asserted. Each value is itself a list of "tokens". These are strings that are compared by name. */ struct tokenlist_list { struct tokenlist_list *next; struct arglist *tokens; }; struct assertion_hashnode { struct assertion_hashnode *next; /* double links for easy deletion */ struct assertion_hashnode *prev; /* also, a back pointer to this node's hash chain is kept, in case the node is the head of the chain and gets deleted. */ struct assertion_hashnode **bucket_hdr; int length; /* length of token, for quick comparison */ U_CHAR *name; /* the actual name */ /* List of token-sequences. */ struct tokenlist_list *value; }; typedef struct assertion_hashnode ASSERTION_HASHNODE; /* Some definitions for the hash table. The hash function MUST be computed as shown in hashf below. That is because the rescan loop computes the hash value `on the fly' for most tokens, in order to avoid the overhead of a lot of procedure calls to the hashf function. hashf only exists for the sake of politeness, for use when speed isn't so important. */ #define ASSERTION_HASHSIZE 37 static ASSERTION_HASHNODE *assertion_hashtab[ASSERTION_HASHSIZE]; /* Nonzero means inhibit macroexpansion of what seem to be assertion tests, in rescan. For #if. */ static int assertions_flag; /* `struct directive' defines one #-directive, including how to handle it. */ #define DO_PROTO PROTO((U_CHAR *, U_CHAR *, FILE_BUF *, struct directive *)) struct directive { int length; /* Length of name */ int (*func) DO_PROTO; /* Function to handle directive */ char *name; /* Name of directive */ enum node_type type; /* Code which describes which directive. */ }; #define IS_INCLUDE_DIRECTIVE_TYPE(t) \ ((int) T_INCLUDE <= (int) (t) && (int) (t) <= (int) T_IMPORT) /* These functions are declared to return int instead of void since they are going to be placed in the table and some old compilers have trouble with pointers to functions returning void. */ static int do_assert DO_PROTO; static int do_define DO_PROTO; static int do_elif DO_PROTO; static int do_else DO_PROTO; static int do_endif DO_PROTO; static int do_error DO_PROTO; static int do_ident DO_PROTO; static int do_if DO_PROTO; static int do_include DO_PROTO; static int do_line DO_PROTO; static int do_pragma DO_PROTO; #ifdef SCCS_DIRECTIVE static int do_sccs DO_PROTO; #endif static int do_unassert DO_PROTO; static int do_undef DO_PROTO; static int do_warning DO_PROTO; static int do_xifdef DO_PROTO; /* Here is the actual list of #-directives, most-often-used first. */ static struct directive directive_table[] = { { 6, do_define, "define", T_DEFINE}, { 2, do_if, "if", T_IF}, { 5, do_xifdef, "ifdef", T_IFDEF}, { 6, do_xifdef, "ifndef", T_IFNDEF}, { 5, do_endif, "endif", T_ENDIF}, { 4, do_else, "else", T_ELSE}, { 4, do_elif, "elif", T_ELIF}, { 4, do_line, "line", T_LINE}, { 7, do_include, "include", T_INCLUDE}, { 12, do_include, "include_next", T_INCLUDE_NEXT}, { 6, do_include, "import", T_IMPORT}, { 5, do_undef, "undef", T_UNDEF}, { 5, do_error, "error", T_ERROR}, { 7, do_warning, "warning", T_WARNING}, #ifdef SCCS_DIRECTIVE { 4, do_sccs, "sccs", T_SCCS}, #endif { 6, do_pragma, "pragma", T_PRAGMA}, { 5, do_ident, "ident", T_IDENT}, { 6, do_assert, "assert", T_ASSERT}, { 8, do_unassert, "unassert", T_UNASSERT}, { -1, 0, "", T_UNUSED}, }; /* When a directive handler is called, this points to the # (or the : of the %:) that started the directive. */ U_CHAR *directive_start; /* table to tell if char can be part of a C identifier. */ U_CHAR is_idchar[256]; /* table to tell if char can be first char of a c identifier. */ U_CHAR is_idstart[256]; /* table to tell if c is horizontal space. */ static U_CHAR is_hor_space[256]; /* table to tell if c is horizontal or vertical space. */ U_CHAR is_space[256]; /* names of some characters */ static char *char_name[256]; #define SKIP_WHITE_SPACE(p) do { while (is_hor_space[*p]) p++; } while (0) #define SKIP_ALL_WHITE_SPACE(p) do { while (is_space[*p]) p++; } while (0) static int errors = 0; /* Error counter for exit code */ /* Name of output file, for error messages. */ static char *out_fname; /* Stack of conditionals currently in progress (including both successful and failing conditionals). */ struct if_stack { struct if_stack *next; /* for chaining to the next stack frame */ char *fname; /* copied from input when frame is made */ int lineno; /* similarly */ int if_succeeded; /* true if a leg of this if-group has been passed through rescan */ U_CHAR *control_macro; /* For #ifndef at start of file, this is the macro name tested. */ enum node_type type; /* type of last directive seen in this group */ }; typedef struct if_stack IF_STACK_FRAME; static IF_STACK_FRAME *if_stack = NULL; /* Buffer of -M output. */ static char *deps_buffer; /* Number of bytes allocated in above. */ static int deps_allocated_size; /* Number of bytes used. */ static int deps_size; /* Number of bytes since the last newline. */ static int deps_column; /* Nonzero means -I- has been seen, so don't look for #include "foo" the source-file directory. */ static int ignore_srcdir; static int safe_read PROTO((int, char *, int)); static void safe_write PROTO((int, char *, int)); int main PROTO((int, char **)); static void path_include PROTO((char *)); static U_CHAR *index0 PROTO((U_CHAR *, int, size_t)); static void trigraph_pcp PROTO((FILE_BUF *)); static void newline_fix PROTO((U_CHAR *)); static void name_newline_fix PROTO((U_CHAR *)); static char *get_lintcmd PROTO((U_CHAR *, U_CHAR *, U_CHAR **, int *, int *)); static void rescan PROTO((FILE_BUF *, int)); static FILE_BUF expand_to_temp_buffer PROTO((U_CHAR *, U_CHAR *, int, int)); static int handle_directive PROTO((FILE_BUF *, FILE_BUF *)); static struct tm *timestamp PROTO((void)); static void special_symbol PROTO((HASHNODE *, FILE_BUF *)); static int is_system_include PROTO((char *)); static char *base_name PROTO((char *)); static int absolute_filename PROTO((char *)); static size_t simplify_filename PROTO((char *)); static char *read_filename_string PROTO((int, FILE *)); static struct file_name_map *read_name_map PROTO((char *)); static int open_include_file PROTO((char *, struct file_name_list *, U_CHAR *, struct include_file **)); static char *remap_include_file PROTO((char *, struct file_name_list *)); static int lookup_ino_include PROTO((struct include_file *)); static void finclude PROTO((int, struct include_file *, FILE_BUF *, int, struct file_name_list *)); static void record_control_macro PROTO((struct include_file *, U_CHAR *)); static char *check_precompiled PROTO((int, struct stat *, char *, char **)); static int check_preconditions PROTO((char *)); static void pcfinclude PROTO((U_CHAR *, U_CHAR *, U_CHAR *, FILE_BUF *)); static void pcstring_used PROTO((HASHNODE *)); static void write_output PROTO((void)); static void pass_thru_directive PROTO((U_CHAR *, U_CHAR *, FILE_BUF *, struct directive *)); static MACRODEF create_definition PROTO((U_CHAR *, U_CHAR *, FILE_BUF *)); static int check_macro_name PROTO((U_CHAR *, char *)); static int compare_defs PROTO((DEFINITION *, DEFINITION *)); static int comp_def_part PROTO((int, U_CHAR *, int, U_CHAR *, int, int)); static DEFINITION *collect_expansion PROTO((U_CHAR *, U_CHAR *, int, struct arglist *)); int check_assertion PROTO((U_CHAR *, int, int, struct arglist *)); static int compare_token_lists PROTO((struct arglist *, struct arglist *)); static struct arglist *read_token_list PROTO((U_CHAR **, U_CHAR *, int *)); static void free_token_list PROTO((struct arglist *)); static ASSERTION_HASHNODE *assertion_install PROTO((U_CHAR *, int, int)); static ASSERTION_HASHNODE *assertion_lookup PROTO((U_CHAR *, int, int)); static void delete_assertion PROTO((ASSERTION_HASHNODE *)); static void do_once PROTO((void)); static HOST_WIDE_INT eval_if_expression PROTO((U_CHAR *, int)); static void conditional_skip PROTO((FILE_BUF *, int, enum node_type, U_CHAR *, FILE_BUF *)); static void skip_if_group PROTO((FILE_BUF *, int, FILE_BUF *)); static void validate_else PROTO((U_CHAR *, U_CHAR *)); static U_CHAR *skip_to_end_of_comment PROTO((FILE_BUF *, int *, int)); static U_CHAR *skip_quoted_string PROTO((U_CHAR *, U_CHAR *, int, int *, int *, int *)); static char *quote_string PROTO((char *, char *)); static U_CHAR *skip_paren_group PROTO((FILE_BUF *)); /* Last arg to output_line_directive. */ enum file_change_code {same_file, enter_file, leave_file}; static void output_line_directive PROTO((FILE_BUF *, FILE_BUF *, int, enum file_change_code)); static void macroexpand PROTO((HASHNODE *, FILE_BUF *)); struct argdata; static char *macarg PROTO((struct argdata *, int)); static U_CHAR *macarg1 PROTO((U_CHAR *, U_CHAR *, struct hashnode *, int *, int *, int *, int)); static int discard_comments PROTO((U_CHAR *, int, int)); static int change_newlines PROTO((U_CHAR *, int)); char *my_strerror PROTO((int)); void error PRINTF_PROTO_1((char *, ...)); static void verror PROTO((char *, va_list)); static void error_from_errno PROTO((char *)); void warning PRINTF_PROTO_1((char *, ...)); static void vwarning PROTO((char *, va_list)); static void error_with_line PRINTF_PROTO_2((int, char *, ...)); static void verror_with_line PROTO((int, char *, va_list)); static void vwarning_with_line PROTO((int, char *, va_list)); static void warning_with_line PRINTF_PROTO_2((int, char *, ...)); void pedwarn PRINTF_PROTO_1((char *, ...)); void pedwarn_with_line PRINTF_PROTO_2((int, char *, ...)); static void pedwarn_with_file_and_line PRINTF_PROTO_3((char *, int, char *, ...)); static void print_containing_files PROTO((void)); static int line_for_error PROTO((int)); static int grow_outbuf PROTO((FILE_BUF *, int)); static HASHNODE *install PROTO((U_CHAR *, int, enum node_type, char *, int)); HASHNODE *lookup PROTO((U_CHAR *, int, int)); static void delete_macro PROTO((HASHNODE *)); static int hashf PROTO((U_CHAR *, int, int)); static void dump_single_macro PROTO((HASHNODE *, FILE *)); static void dump_all_macros PROTO((void)); static void dump_defn_1 PROTO((U_CHAR *, int, int, FILE *)); static void dump_arg_n PROTO((DEFINITION *, int, FILE *)); static void initialize_char_syntax PROTO((void)); static void initialize_builtins PROTO((FILE_BUF *, FILE_BUF *)); static void make_definition PROTO((char *, FILE_BUF *)); static void make_undef PROTO((char *, FILE_BUF *)); static void make_assertion PROTO((char *, char *)); static struct file_name_list *new_include_prefix PROTO((struct file_name_list *, char *, char *, char *)); static void append_include_chain PROTO((struct file_name_list *, struct file_name_list *)); static int quote_string_for_make PROTO((char *, char *)); static void deps_output PROTO((char *, int)); static void fatal PRINTF_PROTO_1((char *, ...)) __attribute__ ((noreturn)); void fancy_abort PROTO((void)) __attribute__ ((noreturn)); static void perror_with_name PROTO((char *)); static void pfatal_with_name PROTO((char *)) __attribute__ ((noreturn)); static void pipe_closed PROTO((int)) __attribute__ ((noreturn)); static void memory_full PROTO((void)) __attribute__ ((noreturn)); GENERIC_PTR xmalloc PROTO((size_t)); static GENERIC_PTR xrealloc PROTO((GENERIC_PTR, size_t)); static GENERIC_PTR xcalloc PROTO((size_t, size_t)); static char *savestring PROTO((char *)); /* Read LEN bytes at PTR from descriptor DESC, for file FILENAME, retrying if necessary. If MAX_READ_LEN is defined, read at most that bytes at a time. Return a negative value if an error occurs, otherwise return the actual number of bytes read, which must be LEN unless end-of-file was reached. */ static int safe_read (desc, ptr, len) int desc; char *ptr; int len; { int left, rcount, nchars; left = len; while (left > 0) { rcount = left; #ifdef MAX_READ_LEN if (rcount > MAX_READ_LEN) rcount = MAX_READ_LEN; #endif nchars = read (desc, ptr, rcount); if (nchars < 0) { #ifdef EINTR if (errno == EINTR) continue; #endif return nchars; } if (nchars == 0) break; ptr += nchars; left -= nchars; } return len - left; } /* Write LEN bytes at PTR to descriptor DESC, retrying if necessary, and treating any real error as fatal. If MAX_WRITE_LEN is defined, write at most that many bytes at a time. */ static void safe_write (desc, ptr, len) int desc; char *ptr; int len; { int wcount, written; while (len > 0) { wcount = len; #ifdef MAX_WRITE_LEN if (wcount > MAX_WRITE_LEN) wcount = MAX_WRITE_LEN; #endif written = write (desc, ptr, wcount); if (written < 0) { #ifdef EINTR if (errno == EINTR) continue; #endif pfatal_with_name (out_fname); } ptr += written; len -= written; } } int main (argc, argv) int argc; char **argv; { struct stat st; char *in_fname; char *cp; int f, i; FILE_BUF *fp; char **pend_files = (char **) xmalloc (argc * sizeof (char *)); char **pend_defs = (char **) xmalloc (argc * sizeof (char *)); char **pend_undefs = (char **) xmalloc (argc * sizeof (char *)); char **pend_assertions = (char **) xmalloc (argc * sizeof (char *)); char **pend_includes = (char **) xmalloc (argc * sizeof (char *)); /* Record the option used with each element of pend_assertions. This is preparation for supporting more than one option for making an assertion. */ char **pend_assertion_options = (char **) xmalloc (argc * sizeof (char *)); int inhibit_predefs = 0; int no_standard_includes = 0; int no_standard_cplusplus_includes = 0; int missing_newline = 0; /* Non-0 means don't output the preprocessed program. */ int inhibit_output = 0; /* Non-0 means -v, so print the full set of include dirs. */ int verbose = 0; /* File name which deps are being written to. This is 0 if deps are being written to stdout. */ char *deps_file = 0; /* Fopen file mode to open deps_file with. */ char *deps_mode = "a"; /* Stream on which to print the dependency information. */ FILE *deps_stream = 0; /* Target-name to write with the dependency information. */ char *deps_target = 0; #if defined (RLIMIT_STACK) && defined (HAVE_GETRLIMIT) && defined (HAVE_SETRLIMIT) /* Get rid of any avoidable limit on stack size. */ { struct rlimit rlim; /* Set the stack limit huge so that alloca (particularly stringtab in dbxread.c) does not fail. */ getrlimit (RLIMIT_STACK, &rlim); rlim.rlim_cur = rlim.rlim_max; setrlimit (RLIMIT_STACK, &rlim); } #endif #ifdef SIGPIPE signal (SIGPIPE, pipe_closed); #endif progname = base_name (argv[0]); #ifdef VMS { /* Remove extension from PROGNAME. */ char *p; char *s = progname = savestring (progname); if ((p = rindex (s, ';')) != 0) *p = '\0'; /* strip version number */ if ((p = rindex (s, '.')) != 0 /* strip type iff ".exe" */ && (p[1] == 'e' || p[1] == 'E') && (p[2] == 'x' || p[2] == 'X') && (p[3] == 'e' || p[3] == 'E') && !p[4]) *p = '\0'; } #endif in_fname = NULL; out_fname = NULL; /* Initialize is_idchar. */ initialize_char_syntax (); no_line_directives = 0; no_trigraphs = 1; dump_macros = dump_none; no_output = 0; cplusplus = 0; cplusplus_comments = 1; bzero ((char *) pend_files, argc * sizeof (char *)); bzero ((char *) pend_defs, argc * sizeof (char *)); bzero ((char *) pend_undefs, argc * sizeof (char *)); bzero ((char *) pend_assertions, argc * sizeof (char *)); bzero ((char *) pend_includes, argc * sizeof (char *)); /* Process switches and find input file name. */ for (i = 1; i < argc; i++) { if (argv[i][0] != '-') { if (out_fname != NULL) fatal ("Usage: %s [switches] input output", argv[0]); else if (in_fname != NULL) out_fname = argv[i]; else in_fname = argv[i]; } else { switch (argv[i][1]) { case 'i': if (!strcmp (argv[i], "-include")) { if (i + 1 == argc) fatal ("Filename missing after `-include' option"); else simplify_filename (pend_includes[i] = argv[++i]); } if (!strcmp (argv[i], "-imacros")) { if (i + 1 == argc) fatal ("Filename missing after `-imacros' option"); else simplify_filename (pend_files[i] = argv[++i]); } if (!strcmp (argv[i], "-iprefix")) { if (i + 1 == argc) fatal ("Filename missing after `-iprefix' option"); else include_prefix = argv[++i]; } if (!strcmp (argv[i], "-ifoutput")) { output_conditionals = 1; } if (!strcmp (argv[i], "-isystem")) { struct file_name_list *dirtmp; if (! (dirtmp = new_include_prefix (NULL_PTR, NULL_PTR, "", argv[++i]))) break; dirtmp->c_system_include_path = 1; if (before_system == 0) before_system = dirtmp; else last_before_system->next = dirtmp; last_before_system = dirtmp; /* Tail follows the last one */ } /* Add directory to end of path for includes, with the default prefix at the front of its name. */ if (!strcmp (argv[i], "-iwithprefix")) { struct file_name_list *dirtmp; char *prefix; if (include_prefix != 0) prefix = include_prefix; else { prefix = savestring (GCC_INCLUDE_DIR); /* Remove the `include' from /usr/local/lib/gcc.../include. */ if (!strcmp (prefix + strlen (prefix) - 8, "/include")) prefix[strlen (prefix) - 7] = 0; } if (! (dirtmp = new_include_prefix (NULL_PTR, NULL_PTR, prefix, argv[++i]))) break; if (after_include == 0) after_include = dirtmp; else last_after_include->next = dirtmp; last_after_include = dirtmp; /* Tail follows the last one */ } /* Add directory to main path for includes, with the default prefix at the front of its name. */ if (!strcmp (argv[i], "-iwithprefixbefore")) { struct file_name_list *dirtmp; char *prefix; if (include_prefix != 0) prefix = include_prefix; else { prefix = savestring (GCC_INCLUDE_DIR); /* Remove the `include' from /usr/local/lib/gcc.../include. */ if (!strcmp (prefix + strlen (prefix) - 8, "/include")) prefix[strlen (prefix) - 7] = 0; } dirtmp = new_include_prefix (NULL_PTR, NULL_PTR, prefix, argv[++i]); append_include_chain (dirtmp, dirtmp); } /* Add directory to end of path for includes. */ if (!strcmp (argv[i], "-idirafter")) { struct file_name_list *dirtmp; if (! (dirtmp = new_include_prefix (NULL_PTR, NULL_PTR, "", argv[++i]))) break; if (after_include == 0) after_include = dirtmp; else last_after_include->next = dirtmp; last_after_include = dirtmp; /* Tail follows the last one */ } break; case 'o': if (out_fname != NULL) fatal ("Output filename specified twice"); if (i + 1 == argc) fatal ("Filename missing after -o option"); out_fname = argv[++i]; if (!strcmp (out_fname, "-")) out_fname = ""; break; case 'p': if (!strcmp (argv[i], "-pedantic")) pedantic = 1; else if (!strcmp (argv[i], "-pedantic-errors")) { pedantic = 1; pedantic_errors = 1; } else if (!strcmp (argv[i], "-pcp")) { char *pcp_fname; if (i + 1 == argc) fatal ("Filename missing after -pcp option"); pcp_fname = argv[++i]; pcp_outfile = ((pcp_fname[0] != '-' || pcp_fname[1] != '\0') ? fopen (pcp_fname, "w") : stdout); if (pcp_outfile == 0) pfatal_with_name (pcp_fname); no_precomp = 1; } break; case 't': if (!strcmp (argv[i], "-traditional")) { traditional = 1; cplusplus_comments = 0; } else if (!strcmp (argv[i], "-trigraphs")) { no_trigraphs = 0; } break; case 'l': if (! strcmp (argv[i], "-lang-c")) cplusplus = 0, cplusplus_comments = 1, c89 = 0, objc = 0; if (! strcmp (argv[i], "-lang-c89")) cplusplus = 0, cplusplus_comments = 0, c89 = 1, objc = 0; if (! strcmp (argv[i], "-lang-c++")) cplusplus = 1, cplusplus_comments = 1, c89 = 0, objc = 0; if (! strcmp (argv[i], "-lang-objc")) cplusplus = 0, cplusplus_comments = 1, c89 = 0, objc = 1; if (! strcmp (argv[i], "-lang-objc++")) cplusplus = 1, cplusplus_comments = 1, c89 = 0, objc = 1; if (! strcmp (argv[i], "-lang-asm")) lang_asm = 1; if (! strcmp (argv[i], "-lint")) for_lint = 1; break; case '+': cplusplus = 1, cplusplus_comments = 1; break; case 'w': inhibit_warnings = 1; break; case 'W': if (!strcmp (argv[i], "-Wtrigraphs")) warn_trigraphs = 1; else if (!strcmp (argv[i], "-Wno-trigraphs")) warn_trigraphs = 0; else if (!strcmp (argv[i], "-Wcomment")) warn_comments = 1; else if (!strcmp (argv[i], "-Wno-comment")) warn_comments = 0; else if (!strcmp (argv[i], "-Wcomments")) warn_comments = 1; else if (!strcmp (argv[i], "-Wno-comments")) warn_comments = 0; else if (!strcmp (argv[i], "-Wtraditional")) warn_stringify = 1; else if (!strcmp (argv[i], "-Wno-traditional")) warn_stringify = 0; else if (!strcmp (argv[i], "-Wundef")) warn_undef = 1; else if (!strcmp (argv[i], "-Wno-undef")) warn_undef = 0; else if (!strcmp (argv[i], "-Wimport")) warn_import = 1; else if (!strcmp (argv[i], "-Wno-import")) warn_import = 0; else if (!strcmp (argv[i], "-Werror")) warnings_are_errors = 1; else if (!strcmp (argv[i], "-Wno-error")) warnings_are_errors = 0; else if (!strcmp (argv[i], "-Wall")) { warn_trigraphs = 1; warn_comments = 1; } break; case 'M': /* The style of the choices here is a bit mixed. The chosen scheme is a hybrid of keeping all options in one string and specifying each option in a separate argument: -M|-MM|-MD file|-MMD file [-MG]. An alternative is: -M|-MM|-MD file|-MMD file|-MG|-MMG; or more concisely: -M[M][G][D file]. This is awkward to handle in specs, and is not as extensible. */ /* ??? -MG must be specified in addition to one of -M or -MM. This can be relaxed in the future without breaking anything. The converse isn't true. */ /* -MG isn't valid with -MD or -MMD. This is checked for later. */ if (!strcmp (argv[i], "-MG")) { print_deps_missing_files = 1; break; } if (!strcmp (argv[i], "-M")) print_deps = 2; else if (!strcmp (argv[i], "-MM")) print_deps = 1; else if (!strcmp (argv[i], "-MD")) print_deps = 2; else if (!strcmp (argv[i], "-MMD")) print_deps = 1; /* For -MD and -MMD options, write deps on file named by next arg. */ if (!strcmp (argv[i], "-MD") || !strcmp (argv[i], "-MMD")) { if (i + 1 == argc) fatal ("Filename missing after %s option", argv[i]); i++; deps_file = argv[i]; deps_mode = "w"; } else { /* For -M and -MM, write deps on standard output and suppress the usual output. */ deps_stream = stdout; inhibit_output = 1; } break; case 'd': { char *p = argv[i] + 2; char c; while ((c = *p++)) { /* Arg to -d specifies what parts of macros to dump */ switch (c) { case 'M': dump_macros = dump_only; no_output = 1; break; case 'N': dump_macros = dump_names; break; case 'D': dump_macros = dump_definitions; break; case 'I': dump_includes = 1; break; } } } break; case 'g': if (argv[i][2] == '3') debug_output = 1; break; case 'v': fprintf (stderr, "GNU CPP version %s", version_string); #ifdef TARGET_VERSION TARGET_VERSION; #endif fprintf (stderr, "\n"); verbose = 1; break; case 'H': print_include_names = 1; break; case 'D': if (argv[i][2] != 0) pend_defs[i] = argv[i] + 2; else if (i + 1 == argc) fatal ("Macro name missing after -D option"); else i++, pend_defs[i] = argv[i]; break; case 'A': { char *p; if (argv[i][2] != 0) p = argv[i] + 2; else if (i + 1 == argc) fatal ("Assertion missing after -A option"); else p = argv[++i]; if (!strcmp (p, "-")) { /* -A- eliminates all predefined macros and assertions. Let's include also any that were specified earlier on the command line. That way we can get rid of any that were passed automatically in from GCC. */ int j; inhibit_predefs = 1; for (j = 0; j < i; j++) pend_defs[j] = pend_assertions[j] = 0; } else { pend_assertions[i] = p; pend_assertion_options[i] = "-A"; } } break; case 'U': /* JF #undef something */ if (argv[i][2] != 0) pend_undefs[i] = argv[i] + 2; else if (i + 1 == argc) fatal ("Macro name missing after -U option"); else pend_undefs[i] = argv[i+1], i++; break; case 'C': put_out_comments = 1; break; case 'E': /* -E comes from cc -E; ignore it. */ break; case 'P': no_line_directives = 1; break; case '$': /* Don't include $ in identifiers. */ is_idchar['$'] = is_idstart['$'] = 0; break; case 'I': /* Add directory to path for includes. */ { struct file_name_list *dirtmp; if (! ignore_srcdir && !strcmp (argv[i] + 2, "-")) { ignore_srcdir = 1; /* Don't use any preceding -I directories for #include <...>. */ first_bracket_include = 0; } else { dirtmp = new_include_prefix (last_include, NULL_PTR, "", argv[i][2] ? argv[i] + 2 : argv[++i]); append_include_chain (dirtmp, dirtmp); } } break; case 'n': if (!strcmp (argv[i], "-nostdinc")) /* -nostdinc causes no default include directories. You must specify all include-file directories with -I. */ no_standard_includes = 1; else if (!strcmp (argv[i], "-nostdinc++")) /* -nostdinc++ causes no default C++-specific include directories. */ no_standard_cplusplus_includes = 1; else if (!strcmp (argv[i], "-noprecomp")) no_precomp = 1; break; case 'r': if (!strcmp (argv[i], "-remap")) remap = 1; break; case 'u': /* Sun compiler passes undocumented switch "-undef". Let's assume it means to inhibit the predefined symbols. */ inhibit_predefs = 1; break; case '\0': /* JF handle '-' as file name meaning stdin or stdout */ if (in_fname == NULL) { in_fname = ""; break; } else if (out_fname == NULL) { out_fname = ""; break; } /* else fall through into error */ default: fatal ("Invalid option `%s'", argv[i]); } } } /* Add dirs from CPATH after dirs from -I. */ /* There seems to be confusion about what CPATH should do, so for the moment it is not documented. */ /* Some people say that CPATH should replace the standard include dirs, but that seems pointless: it comes before them, so it overrides them anyway. */ cp = getenv ("CPATH"); if (cp && ! no_standard_includes) path_include (cp); /* Initialize output buffer */ outbuf.buf = (U_CHAR *) xmalloc (OUTBUF_SIZE); outbuf.bufp = outbuf.buf; outbuf.length = OUTBUF_SIZE; /* Do partial setup of input buffer for the sake of generating early #line directives (when -g is in effect). */ fp = &instack[++indepth]; if (in_fname == NULL) in_fname = ""; fp->nominal_fname = fp->fname = in_fname; fp->lineno = 0; /* In C++, wchar_t is a distinct basic type, and we can expect __wchar_t to be defined by cc1plus. */ if (cplusplus) wchar_type = "__wchar_t"; /* Install __LINE__, etc. Must follow initialize_char_syntax and option processing. */ initialize_builtins (fp, &outbuf); /* Do standard #defines and assertions that identify system and machine type. */ if (!inhibit_predefs) { char *p = (char *) alloca (strlen (predefs) + 1); strcpy (p, predefs); while (*p) { char *q; while (*p == ' ' || *p == '\t') p++; /* Handle -D options. */ if (p[0] == '-' && p[1] == 'D') { q = &p[2]; while (*p && *p != ' ' && *p != '\t') p++; if (*p != 0) *p++= 0; if (debug_output) output_line_directive (fp, &outbuf, 0, same_file); make_definition (q, &outbuf); while (*p == ' ' || *p == '\t') p++; } else if (p[0] == '-' && p[1] == 'A') { /* Handle -A options (assertions). */ char *assertion; char *past_name; char *value; char *past_value; char *termination; int save_char; assertion = &p[2]; past_name = assertion; /* Locate end of name. */ while (*past_name && *past_name != ' ' && *past_name != '\t' && *past_name != '(') past_name++; /* Locate `(' at start of value. */ value = past_name; while (*value && (*value == ' ' || *value == '\t')) value++; if (*value++ != '(') abort (); while (*value && (*value == ' ' || *value == '\t')) value++; past_value = value; /* Locate end of value. */ while (*past_value && *past_value != ' ' && *past_value != '\t' && *past_value != ')') past_value++; termination = past_value; while (*termination && (*termination == ' ' || *termination == '\t')) termination++; if (*termination++ != ')') abort (); if (*termination && *termination != ' ' && *termination != '\t') abort (); /* Temporarily null-terminate the value. */ save_char = *termination; *termination = '\0'; /* Install the assertion. */ make_assertion ("-A", assertion); *termination = (char) save_char; p = termination; while (*p == ' ' || *p == '\t') p++; } else { abort (); } } } /* Now handle the command line options. */ /* Do -U's, -D's and -A's in the order they were seen. */ for (i = 1; i < argc; i++) { if (pend_undefs[i]) { if (debug_output) output_line_directive (fp, &outbuf, 0, same_file); make_undef (pend_undefs[i], &outbuf); } if (pend_defs[i]) { if (debug_output) output_line_directive (fp, &outbuf, 0, same_file); make_definition (pend_defs[i], &outbuf); } if (pend_assertions[i]) make_assertion (pend_assertion_options[i], pend_assertions[i]); } done_initializing = 1; { /* Read the appropriate environment variable and if it exists replace include_defaults with the listed path. */ char *epath = 0; switch ((objc << 1) + cplusplus) { case 0: epath = getenv ("C_INCLUDE_PATH"); break; case 1: epath = getenv ("CPLUS_INCLUDE_PATH"); break; case 2: epath = getenv ("OBJC_INCLUDE_PATH"); break; case 3: epath = getenv ("OBJCPLUS_INCLUDE_PATH"); break; } /* If the environment var for this language is set, add to the default list of include directories. */ if (epath) { int num_dirs; char *startp, *endp; for (num_dirs = 1, startp = epath; *startp; startp++) if (*startp == PATH_SEPARATOR) num_dirs++; include_defaults = (struct default_include *) xmalloc ((num_dirs * sizeof (struct default_include)) + sizeof (include_defaults_array)); startp = endp = epath; num_dirs = 0; while (1) { char c = *endp++; if (c == PATH_SEPARATOR || !c) { endp[-1] = 0; include_defaults[num_dirs].fname = startp == endp ? "." : savestring (startp); endp[-1] = c; include_defaults[num_dirs].component = 0; include_defaults[num_dirs].cplusplus = cplusplus; include_defaults[num_dirs].cxx_aware = 1; num_dirs++; if (!c) break; startp = endp; } } /* Put the usual defaults back in at the end. */ bcopy ((char *) include_defaults_array, (char *) &include_defaults[num_dirs], sizeof (include_defaults_array)); } } append_include_chain (before_system, last_before_system); first_system_include = before_system; /* Unless -fnostdinc, tack on the standard include file dirs to the specified list */ if (!no_standard_includes) { struct default_include *p = include_defaults; char *specd_prefix = include_prefix; char *default_prefix = savestring (GCC_INCLUDE_DIR); int default_len = 0; /* Remove the `include' from /usr/local/lib/gcc.../include. */ if (!strcmp (default_prefix + strlen (default_prefix) - 8, "/include")) { default_len = strlen (default_prefix) - 7; default_prefix[default_len] = 0; } /* Search "translated" versions of GNU directories. These have /usr/local/lib/gcc... replaced by specd_prefix. */ if (specd_prefix != 0 && default_len != 0) for (p = include_defaults; p->fname; p++) { /* Some standard dirs are only for C++. */ if (!p->cplusplus || (cplusplus && !no_standard_cplusplus_includes)) { /* Does this dir start with the prefix? */ if (!strncmp (p->fname, default_prefix, default_len)) { /* Yes; change prefix and add to search list. */ struct file_name_list *new = new_include_prefix (NULL_PTR, NULL_PTR, specd_prefix, p->fname + default_len); if (new) { new->c_system_include_path = !p->cxx_aware; append_include_chain (new, new); if (first_system_include == 0) first_system_include = new; } } } } /* Search ordinary names for GNU include directories. */ for (p = include_defaults; p->fname; p++) { /* Some standard dirs are only for C++. */ if (!p->cplusplus || (cplusplus && !no_standard_cplusplus_includes)) { struct file_name_list *new = new_include_prefix (NULL_PTR, p->component, "", p->fname); if (new) { new->c_system_include_path = !p->cxx_aware; append_include_chain (new, new); if (first_system_include == 0) first_system_include = new; } } } } /* Tack the after_include chain at the end of the include chain. */ append_include_chain (after_include, last_after_include); if (first_system_include == 0) first_system_include = after_include; /* With -v, print the list of dirs to search. */ if (verbose) { struct file_name_list *p; fprintf (stderr, "#include \"...\" search starts here:\n"); for (p = include; p; p = p->next) { if (p == first_bracket_include) fprintf (stderr, "#include <...> search starts here:\n"); if (!p->fname[0]) fprintf (stderr, " .\n"); else if (!strcmp (p->fname, "/") || !strcmp (p->fname, "//")) fprintf (stderr, " %s\n", p->fname); else /* Omit trailing '/'. */ fprintf (stderr, " %.*s\n", (int) strlen (p->fname) - 1, p->fname); } fprintf (stderr, "End of search list.\n"); } /* -MG doesn't select the form of output and must be specified with one of -M or -MM. -MG doesn't make sense with -MD or -MMD since they don't inhibit compilation. */ if (print_deps_missing_files && (print_deps == 0 || !inhibit_output)) fatal ("-MG must be specified with one of -M or -MM"); /* Either of two environment variables can specify output of deps. Its value is either "OUTPUT_FILE" or "OUTPUT_FILE DEPS_TARGET", where OUTPUT_FILE is the file to write deps info to and DEPS_TARGET is the target to mention in the deps. */ if (print_deps == 0 && (getenv ("SUNPRO_DEPENDENCIES") != 0 || getenv ("DEPENDENCIES_OUTPUT") != 0)) { char *spec = getenv ("DEPENDENCIES_OUTPUT"); char *s; char *output_file; if (spec == 0) { spec = getenv ("SUNPRO_DEPENDENCIES"); print_deps = 2; } else print_deps = 1; s = spec; /* Find the space before the DEPS_TARGET, if there is one. */ /* This should use index. (mrs) */ while (*s != 0 && *s != ' ') s++; if (*s != 0) { deps_target = s + 1; output_file = xmalloc (s - spec + 1); bcopy (spec, output_file, s - spec); output_file[s - spec] = 0; } else { deps_target = 0; output_file = spec; } deps_file = output_file; deps_mode = "a"; } /* For -M, print the expected object file name as the target of this Make-rule. */ if (print_deps) { deps_allocated_size = 200; deps_buffer = xmalloc (deps_allocated_size); deps_buffer[0] = 0; deps_size = 0; deps_column = 0; if (deps_target) { deps_output (deps_target, ':'); } else if (*in_fname == 0) { deps_output ("-", ':'); } else { char *p, *q; int len; q = base_name (in_fname); /* Copy remainder to mungable area. */ p = (char *) alloca (strlen(q) + 8); strcpy (p, q); /* Output P, but remove known suffixes. */ len = strlen (p); q = p + len; if (len >= 2 && p[len - 2] == '.' && index("cCsSm", p[len - 1])) q = p + (len - 2); else if (len >= 3 && p[len - 3] == '.' && p[len - 2] == 'c' && p[len - 1] == 'c') q = p + (len - 3); else if (len >= 4 && p[len - 4] == '.' && p[len - 3] == 'c' && p[len - 2] == 'x' && p[len - 1] == 'x') q = p + (len - 4); else if (len >= 4 && p[len - 4] == '.' && p[len - 3] == 'c' && p[len - 2] == 'p' && p[len - 1] == 'p') q = p + (len - 4); /* * The slice suffix. */ else if (len >= 4 && p[len - 4] == '.' && p[len - 3] == 'i' && p[len - 2] == 'c' && p[len - 1] == 'e') q = p + (len - 4); /* Supply our own suffix. */ strcpy (q, OBJECT_SUFFIX); deps_output (p, ':'); deps_output (in_fname, ' '); } } /* Scan the -imacros files before the main input. Much like #including them, but with no_output set so that only their macro definitions matter. */ no_output++; no_record_file++; for (i = 1; i < argc; i++) if (pend_files[i]) { struct include_file *inc; int fd = open_include_file (pend_files[i], NULL_PTR, NULL_PTR, &inc); if (fd < 0) { perror_with_name (pend_files[i]); return FATAL_EXIT_CODE; } finclude (fd, inc, &outbuf, 0, NULL_PTR); } no_output--; no_record_file--; /* Copy the entire contents of the main input file into the stacked input buffer previously allocated for it. */ /* JF check for stdin */ if (in_fname == NULL || *in_fname == 0) { in_fname = ""; f = 0; } else if ((f = open (in_fname, O_RDONLY, 0666)) < 0) goto perror; if (fstat (f, &st) != 0) pfatal_with_name (in_fname); fp->nominal_fname = fp->fname = in_fname; fp->lineno = 1; fp->system_header_p = 0; /* JF all this is mine about reading pipes and ttys */ if (! S_ISREG (st.st_mode)) { /* Read input from a file that is not a normal disk file. We cannot preallocate a buffer with the correct size, so we must read in the file a piece at the time and make it bigger. */ int size; int bsize; int cnt; if (S_ISDIR (st.st_mode)) fatal ("Input file `%s' is a directory", in_fname); bsize = 2000; size = 0; fp->buf = (U_CHAR *) xmalloc (bsize + 2); for (;;) { cnt = safe_read (f, (char *) fp->buf + size, bsize - size); if (cnt < 0) goto perror; /* error! */ size += cnt; if (size != bsize) break; /* End of file */ bsize *= 2; fp->buf = (U_CHAR *) xrealloc (fp->buf, bsize + 2); } fp->length = size; } else { /* Read a file whose size we can determine in advance. For the sake of VMS, st.st_size is just an upper bound. */ size_t s = (size_t) st.st_size; if (s != st.st_size || s + 2 < s) memory_full (); fp->buf = (U_CHAR *) xmalloc (s + 2); fp->length = safe_read (f, (char *) fp->buf, s); if (fp->length < 0) goto perror; } fp->bufp = fp->buf; fp->if_stack = if_stack; /* Make sure data ends with a newline. And put a null after it. */ if ((fp->length > 0 && fp->buf[fp->length - 1] != '\n') /* Backslash-newline at end is not good enough. */ || (fp->length > 1 && fp->buf[fp->length - 2] == '\\')) { fp->buf[fp->length++] = '\n'; missing_newline = 1; } fp->buf[fp->length] = '\0'; /* Unless inhibited, convert trigraphs in the input. */ if (!no_trigraphs) trigraph_pcp (fp); /* Now that we know the input file is valid, open the output. */ if (!out_fname || !strcmp (out_fname, "")) out_fname = "stdout"; else if (! freopen (out_fname, "w", stdout)) pfatal_with_name (out_fname); output_line_directive (fp, &outbuf, 0, same_file); /* Scan the -include files before the main input. */ no_record_file++; for (i = 1; i < argc; i++) if (pend_includes[i]) { struct include_file *inc; int fd = open_include_file (pend_includes[i], NULL_PTR, NULL_PTR, &inc); if (fd < 0) { perror_with_name (pend_includes[i]); return FATAL_EXIT_CODE; } finclude (fd, inc, &outbuf, 0, NULL_PTR); } no_record_file--; /* Scan the input, processing macros and directives. */ rescan (&outbuf, 0); if (missing_newline) fp->lineno--; if (pedantic && missing_newline) pedwarn ("file does not end in newline"); /* Now we have processed the entire input Write whichever kind of output has been requested. */ if (dump_macros == dump_only) dump_all_macros (); else if (! inhibit_output) { write_output (); } if (print_deps) { /* Don't actually write the deps file if compilation has failed. */ if (errors == 0) { if (deps_file && ! (deps_stream = fopen (deps_file, deps_mode))) pfatal_with_name (deps_file); fputs (deps_buffer, deps_stream); putc ('\n', deps_stream); if (deps_file) { if (ferror (deps_stream) || fclose (deps_stream) != 0) fatal ("I/O error on output"); } } } if (pcp_outfile && pcp_outfile != stdout && (ferror (pcp_outfile) || fclose (pcp_outfile) != 0)) fatal ("I/O error on `-pcp' output"); if (ferror (stdout) || fclose (stdout) != 0) fatal ("I/O error on output"); if (errors) exit (FATAL_EXIT_CODE); exit (SUCCESS_EXIT_CODE); perror: pfatal_with_name (in_fname); return 0; } /* Given a colon-separated list of file names PATH, add all the names to the search path for include files. */ static void path_include (path) char *path; { char *p; p = path; if (*p) while (1) { char *q = p; char c; struct file_name_list *dirtmp; /* Find the end of this name. */ while ((c = *q++) != PATH_SEPARATOR && c) continue; q[-1] = 0; dirtmp = new_include_prefix (last_include, NULL_PTR, "", p == q ? "." : p); q[-1] = c; append_include_chain (dirtmp, dirtmp); /* Advance past this name. */ p = q; if (! c) break; } } /* Return the address of the first character in S that equals C. S is an array of length N, possibly containing '\0's, and followed by '\0'. Return 0 if there is no such character. Assume that C itself is not '\0'. If we knew we could use memchr, we could just invoke memchr (S, C, N), but unfortunately memchr isn't autoconfigured yet. */ static U_CHAR * index0 (s, c, n) U_CHAR *s; int c; size_t n; { char *p = (char *) s; for (;;) { char *q = (char*) index (p, c); if (q) return (U_CHAR *) q; else { size_t l = strlen (p); if (l == n) return 0; l++; p += l; n -= l; } } } /* Pre-C-Preprocessor to translate ANSI trigraph idiocy in BUF before main CCCP processing. Name `pcp' is also in honor of the drugs the trigraph designers must have been on. Using an extra pass through the buffer takes a little extra time, but is infinitely less hairy than trying to handle trigraphs inside strings, etc. everywhere, and also makes sure that trigraphs are only translated in the top level of processing. */ static void trigraph_pcp (buf) FILE_BUF *buf; { register U_CHAR c, *fptr, *bptr, *sptr, *lptr; int len; fptr = bptr = sptr = buf->buf; lptr = fptr + buf->length; while ((sptr = index0 (sptr, '?', (size_t) (lptr - sptr))) != NULL) { if (*++sptr != '?') continue; switch (*++sptr) { case '=': c = '#'; break; case '(': c = '['; break; case '/': c = '\\'; break; case ')': c = ']'; break; case '\'': c = '^'; break; case '<': c = '{'; break; case '!': c = '|'; break; case '>': c = '}'; break; case '-': c = '~'; break; case '?': sptr--; continue; default: continue; } len = sptr - fptr - 2; /* BSD doc says bcopy () works right for overlapping strings. In ANSI C, this will be memmove (). */ if (bptr != fptr && len > 0) bcopy ((char *) fptr, (char *) bptr, len); bptr += len; *bptr++ = c; fptr = ++sptr; } len = buf->length - (fptr - buf->buf); if (bptr != fptr && len > 0) bcopy ((char *) fptr, (char *) bptr, len); buf->length -= fptr - bptr; buf->buf[buf->length] = '\0'; if (warn_trigraphs && fptr != bptr) warning_with_line (0, "%lu trigraph(s) encountered", (unsigned long) (fptr - bptr) / 2); } /* Move all backslash-newline pairs out of embarrassing places. Exchange all such pairs following BP with any potentially-embarrassing characters that follow them. Potentially-embarrassing characters are / and * (because a backslash-newline inside a comment delimiter would cause it not to be recognized). */ static void newline_fix (bp) U_CHAR *bp; { register U_CHAR *p = bp; /* First count the backslash-newline pairs here. */ while (p[0] == '\\' && p[1] == '\n') p += 2; /* What follows the backslash-newlines is not embarrassing. */ if (*p != '/' && *p != '*') return; /* Copy all potentially embarrassing characters that follow the backslash-newline pairs down to where the pairs originally started. */ while (*p == '*' || *p == '/') *bp++ = *p++; /* Now write the same number of pairs after the embarrassing chars. */ while (bp < p) { *bp++ = '\\'; *bp++ = '\n'; } } /* Like newline_fix but for use within a directive-name. Move any backslash-newlines up past any following symbol constituents. */ static void name_newline_fix (bp) U_CHAR *bp; { register U_CHAR *p = bp; /* First count the backslash-newline pairs here. */ while (p[0] == '\\' && p[1] == '\n') p += 2; /* What follows the backslash-newlines is not embarrassing. */ if (!is_idchar[*p]) return; /* Copy all potentially embarrassing characters that follow the backslash-newline pairs down to where the pairs originally started. */ while (is_idchar[*p]) *bp++ = *p++; /* Now write the same number of pairs after the embarrassing chars. */ while (bp < p) { *bp++ = '\\'; *bp++ = '\n'; } } /* Look for lint commands in comments. When we come in here, ibp points into a comment. Limit is as one expects. scan within the comment -- it should start, after lwsp, with a lint command. If so that command is returned as a (constant) string. Upon return, any arg will be pointed to with argstart and will be arglen long. Note that we don't parse that arg since it will just be printed out again. */ static char * get_lintcmd (ibp, limit, argstart, arglen, cmdlen) register U_CHAR *ibp; register U_CHAR *limit; U_CHAR **argstart; /* point to command arg */ int *arglen, *cmdlen; /* how long they are */ { HOST_WIDE_INT linsize; register U_CHAR *numptr; /* temp for arg parsing */ *arglen = 0; SKIP_WHITE_SPACE (ibp); if (ibp >= limit) return NULL; linsize = limit - ibp; /* Oh, I wish C had lexical functions... hell, I'll just open-code the set */ if ((linsize >= 10) && !bcmp (ibp, "NOTREACHED", 10)) { *cmdlen = 10; return "NOTREACHED"; } if ((linsize >= 8) && !bcmp (ibp, "ARGSUSED", 8)) { *cmdlen = 8; return "ARGSUSED"; } if ((linsize >= 11) && !bcmp (ibp, "LINTLIBRARY", 11)) { *cmdlen = 11; return "LINTLIBRARY"; } if ((linsize >= 7) && !bcmp (ibp, "VARARGS", 7)) { *cmdlen = 7; ibp += 7; linsize -= 7; if ((linsize == 0) || ! isdigit (*ibp)) return "VARARGS"; /* OK, read a number */ for (numptr = *argstart = ibp; (numptr < limit) && isdigit (*numptr); numptr++); *arglen = numptr - *argstart; return "VARARGS"; } return NULL; } /* * The main loop of the program. * * Read characters from the input stack, transferring them to the * output buffer OP. * * Macros are expanded and push levels on the input stack. * At the end of such a level it is popped off and we keep reading. * At the end of any other kind of level, we return. * #-directives are handled, except within macros. * * If OUTPUT_MARKS is nonzero, keep Newline markers found in the input * and insert them when appropriate. This is set while scanning macro * arguments before substitution. It is zero when scanning for final output. * There are three types of Newline markers: * * Newline - follows a macro name that was not expanded * because it appeared inside an expansion of the same macro. * This marker prevents future expansion of that identifier. * When the input is rescanned into the final output, these are deleted. * These are also deleted by ## concatenation. * * Newline Space (or Newline and any other whitespace character) * stands for a place that tokens must be separated or whitespace * is otherwise desirable, but where the ANSI standard specifies there * is no whitespace. This marker turns into a Space (or whichever other * whitespace char appears in the marker) in the final output, * but it turns into nothing in an argument that is stringified with #. * Such stringified arguments are the only place where the ANSI standard * specifies with precision that whitespace may not appear. * * During this function, IP->bufp is kept cached in IBP for speed of access. * Likewise, OP->bufp is kept in OBP. Before calling a subroutine * IBP, IP and OBP must be copied back to memory. IP and IBP are * copied back with the RECACHE macro. OBP must be copied back from OP->bufp * explicitly, and before RECACHE, since RECACHE uses OBP. */ static void rescan (op, output_marks) FILE_BUF *op; int output_marks; { /* Character being scanned in main loop. */ register U_CHAR c; /* Length of pending accumulated identifier. */ register int ident_length = 0; /* Hash code of pending accumulated identifier. */ register int hash = 0; /* Current input level (&instack[indepth]). */ FILE_BUF *ip; /* Pointer for scanning input. */ register U_CHAR *ibp; /* Pointer to end of input. End of scan is controlled by LIMIT. */ register U_CHAR *limit; /* Pointer for storing output. */ register U_CHAR *obp; /* REDO_CHAR is nonzero if we are processing an identifier after backing up over the terminating character. Sometimes we process an identifier without backing up over the terminating character, if the terminating character is not special. Backing up is done so that the terminating character will be dispatched on again once the identifier is dealt with. */ int redo_char = 0; /* 1 if within an identifier inside of which a concatenation marker (Newline -) has been seen. */ int concatenated = 0; /* While scanning a comment or a string constant, this records the line it started on, for error messages. */ int start_line; /* Record position of last `real' newline. */ U_CHAR *beg_of_line; /* Pop the innermost input stack level, assuming it is a macro expansion. */ #define POPMACRO \ do { ip->macro->type = T_MACRO; \ if (ip->free_ptr) free (ip->free_ptr); \ --indepth; } while (0) /* Reload `rescan's local variables that describe the current level of the input stack. */ #define RECACHE \ do { ip = &instack[indepth]; \ ibp = ip->bufp; \ limit = ip->buf + ip->length; \ op->bufp = obp; \ check_expand (op, limit - ibp); \ beg_of_line = 0; \ obp = op->bufp; } while (0) if (no_output && instack[indepth].fname != 0) skip_if_group (&instack[indepth], 1, NULL); obp = op->bufp; RECACHE; beg_of_line = ibp; /* Our caller must always put a null after the end of the input at each input stack level. */ if (*limit != 0) abort (); while (1) { c = *ibp++; *obp++ = c; switch (c) { case '\\': if (*ibp == '\n' && !ip->macro) { /* At the top level, always merge lines ending with backslash-newline, even in middle of identifier. But do not merge lines in a macro, since backslash might be followed by a newline-space marker. */ ++ibp; ++ip->lineno; --obp; /* remove backslash from obuf */ break; } /* If ANSI, backslash is just another character outside a string. */ if (!traditional) goto randomchar; /* Otherwise, backslash suppresses specialness of following char, so copy it here to prevent the switch from seeing it. But first get any pending identifier processed. */ if (ident_length > 0) goto specialchar; if (ibp < limit) *obp++ = *ibp++; break; case '%': if (ident_length || ip->macro || traditional) goto randomchar; while (*ibp == '\\' && ibp[1] == '\n') { ibp += 2; ++ip->lineno; } if (*ibp != ':') break; /* Treat this %: digraph as if it were #. */ /* Fall through. */ case '#': if (assertions_flag) { if (ident_length) goto specialchar; /* Copy #foo (bar lose) without macro expansion. */ obp[-1] = '#'; /* In case it was '%'. */ SKIP_WHITE_SPACE (ibp); while (is_idchar[*ibp]) *obp++ = *ibp++; SKIP_WHITE_SPACE (ibp); if (*ibp == '(') { ip->bufp = ibp; skip_paren_group (ip); bcopy ((char *) ibp, (char *) obp, ip->bufp - ibp); obp += ip->bufp - ibp; ibp = ip->bufp; } break; } /* If this is expanding a macro definition, don't recognize preprocessing directives. */ if (ip->macro != 0) goto randomchar; /* If this is expand_into_temp_buffer, don't recognize them either. Warn about them only after an actual newline at this level, not at the beginning of the input level. */ if (! ip->fname) { if (ip->buf != beg_of_line) warning ("preprocessing directive not recognized within macro arg"); goto randomchar; } if (ident_length) goto specialchar; /* # keyword: a # must be first nonblank char on the line */ if (beg_of_line == 0) goto randomchar; { U_CHAR *bp; /* Scan from start of line, skipping whitespace, comments and backslash-newlines, and see if we reach this #. If not, this # is not special. */ bp = beg_of_line; /* If -traditional, require # to be at beginning of line. */ if (!traditional) { while (1) { if (is_hor_space[*bp]) bp++; else if (*bp == '\\' && bp[1] == '\n') bp += 2; else if (*bp == '/' && bp[1] == '*') { bp += 2; while (!(*bp == '*' && bp[1] == '/')) bp++; bp += 2; } /* There is no point in trying to deal with C++ // comments here, because if there is one, then this # must be part of the comment and we would never reach here. */ else break; } if (c == '%') { if (bp[0] != '%') break; while (bp[1] == '\\' && bp[2] == '\n') bp += 2; if (bp + 1 != ibp) break; /* %: appears at start of line; skip past the ':' too. */ bp++; ibp++; } } if (bp + 1 != ibp) goto randomchar; } /* This # can start a directive. */ --obp; /* Don't copy the '#' */ ip->bufp = ibp; op->bufp = obp; if (! handle_directive (ip, op)) { #ifdef USE_C_ALLOCA alloca (0); #endif /* Not a known directive: treat it as ordinary text. IP, OP, IBP, etc. have not been changed. */ if (no_output && instack[indepth].fname) { /* If not generating expanded output, what we do with ordinary text is skip it. Discard everything until next # directive. */ skip_if_group (&instack[indepth], 1, 0); RECACHE; beg_of_line = ibp; break; } *obp++ = '#'; /* Copy # (even if it was originally %:). */ /* Don't expand an identifier that could be a macro directive. (Section 3.8.3 of the ANSI C standard) */ SKIP_WHITE_SPACE (ibp); if (is_idstart[*ibp]) { *obp++ = *ibp++; while (is_idchar[*ibp]) *obp++ = *ibp++; } goto randomchar; } #ifdef USE_C_ALLOCA alloca (0); #endif /* A # directive has been successfully processed. */ /* If not generating expanded output, ignore everything until next # directive. */ if (no_output && instack[indepth].fname) skip_if_group (&instack[indepth], 1, 0); obp = op->bufp; RECACHE; beg_of_line = ibp; break; case '\"': /* skip quoted string */ case '\'': /* A single quoted string is treated like a double -- some programs (e.g., troff) are perverse this way */ /* Handle any pending identifier; but the L in L'...' or L"..." is not an identifier. */ if (ident_length) { if (! (ident_length == 1 && hash == HASHSTEP (0, 'L'))) goto specialchar; ident_length = hash = 0; } start_line = ip->lineno; /* Skip ahead to a matching quote. */ while (1) { if (ibp >= limit) { if (ip->macro != 0) { /* try harder: this string crosses a macro expansion boundary. This can happen naturally if -traditional. Otherwise, only -D can make a macro with an unmatched quote. */ POPMACRO; RECACHE; continue; } if (!traditional) { error_with_line (line_for_error (start_line), "unterminated string or character constant"); if (multiline_string_line) { error_with_line (multiline_string_line, "possible real start of unterminated constant"); multiline_string_line = 0; } } break; } *obp++ = *ibp; switch (*ibp++) { case '\n': ++ip->lineno; ++op->lineno; /* Traditionally, end of line ends a string constant with no error. So exit the loop and record the new line. */ if (traditional) { beg_of_line = ibp; goto while2end; } if (c == '\'') { error_with_line (line_for_error (start_line), "unterminated character constant"); goto while2end; } if (multiline_string_line == 0) { if (pedantic) pedwarn_with_line (line_for_error (start_line), "string constant runs past end of line"); multiline_string_line = ip->lineno - 1; } break; case '\\': if (*ibp == '\n') { /* Backslash newline is replaced by nothing at all, but keep the line counts correct. But if we are reading from a macro, keep the backslash newline, since backslash newlines have already been processed. */ if (ip->macro) *obp++ = '\n'; else --obp; ++ibp; ++ip->lineno; } else { /* ANSI stupidly requires that in \\ the second \ is *not* prevented from combining with a newline. */ if (!ip->macro) { while (*ibp == '\\' && ibp[1] == '\n') { ibp += 2; ++ip->lineno; } } *obp++ = *ibp++; } break; case '\"': case '\'': if (ibp[-1] == c) goto while2end; break; } } while2end: break; case '/': if (ip->macro != 0) goto randomchar; if (*ibp == '\\' && ibp[1] == '\n') newline_fix (ibp); if (*ibp != '*' && !(cplusplus_comments && *ibp == '/')) goto randomchar; if (ident_length) goto specialchar; if (*ibp == '/') { /* C++ style comment... */ start_line = ip->lineno; /* Comments are equivalent to spaces. */ if (! put_out_comments) obp[-1] = ' '; { U_CHAR *before_bp = ibp; while (++ibp < limit) { if (*ibp == '\n') { if (ibp[-1] != '\\') { if (put_out_comments) { bcopy ((char *) before_bp, (char *) obp, ibp - before_bp); obp += ibp - before_bp; } break; } if (warn_comments) warning ("multiline `//' comment"); ++ip->lineno; /* Copy the newline into the output buffer, in order to avoid the pain of a #line every time a multiline comment is seen. */ if (!put_out_comments) *obp++ = '\n'; ++op->lineno; } } break; } } /* Ordinary C comment. Skip it, optionally copying it to output. */ start_line = ip->lineno; ++ibp; /* Skip the star. */ /* If this cpp is for lint, we peek inside the comments: */ if (for_lint) { U_CHAR *argbp; int cmdlen, arglen; char *lintcmd = get_lintcmd (ibp, limit, &argbp, &arglen, &cmdlen); if (lintcmd != NULL) { op->bufp = obp; check_expand (op, cmdlen + arglen + 14); obp = op->bufp; /* I believe it is always safe to emit this newline: */ obp[-1] = '\n'; bcopy ("#pragma lint ", (char *) obp, 13); obp += 13; bcopy (lintcmd, (char *) obp, cmdlen); obp += cmdlen; if (arglen != 0) { *(obp++) = ' '; bcopy (argbp, (char *) obp, arglen); obp += arglen; } /* OK, now bring us back to the state we were in before we entered this branch. We need #line because the #pragma's newline always messes up the line count. */ op->bufp = obp; output_line_directive (ip, op, 0, same_file); check_expand (op, limit - ibp + 2); obp = op->bufp; *(obp++) = '/'; } } /* Comments are equivalent to spaces. Note that we already output the slash; we might not want it. For -traditional, a comment is equivalent to nothing. */ if (! put_out_comments) { if (traditional) obp--; else obp[-1] = ' '; } else *obp++ = '*'; { U_CHAR *before_bp = ibp; for (;;) { switch (*ibp++) { case '*': if (ibp[-2] == '/' && warn_comments) warning ("`/*' within comment"); if (*ibp == '\\' && ibp[1] == '\n') newline_fix (ibp); if (*ibp == '/') goto comment_end; break; case '\n': ++ip->lineno; /* Copy the newline into the output buffer, in order to avoid the pain of a #line every time a multiline comment is seen. */ if (!put_out_comments) *obp++ = '\n'; ++op->lineno; break; case 0: if (limit < ibp) { error_with_line (line_for_error (start_line), "unterminated comment"); goto limit_reached; } break; } } comment_end: ibp++; if (put_out_comments) { bcopy ((char *) before_bp, (char *) obp, ibp - before_bp); obp += ibp - before_bp; } } break; case '$': if (! is_idchar['$']) goto randomchar; if (pedantic) pedwarn ("`$' in identifier"); goto letter; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': /* If digit is not part of identifier, it starts a number, which means that following letters are not an identifier. "0x5" does not refer to an identifier "x5". So copy all alphanumerics that follow without accumulating as an identifier. Periods also, for sake of "3.e7". */ if (ident_length == 0) { for (;;) { if (!ip->macro) { while (ibp[0] == '\\' && ibp[1] == '\n') { ++ip->lineno; ibp += 2; } } c = *ibp++; if (!is_idchar[c] && c != '.') { --ibp; break; } *obp++ = c; /* A sign can be part of a preprocessing number if it follows an `e' or `p'. */ if (c == 'e' || c == 'E' || c == 'p' || c == 'P') { if (!ip->macro) { while (ibp[0] == '\\' && ibp[1] == '\n') { ++ip->lineno; ibp += 2; } } if (*ibp == '+' || *ibp == '-') { *obp++ = *ibp++; /* But traditional C does not let the token go past the sign, and C89 does not allow `p'. */ if (traditional || (c89 && (c == 'p' || c == 'P'))) break; } } } break; } /* fall through */ case '_': case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': letter: ident_length++; /* Compute step of hash function, to avoid a proc call on every token */ hash = HASHSTEP (hash, c); break; case '\n': if (ip->fname == 0 && *ibp == '-') { /* Newline - inhibits expansion of preceding token. If expanding a macro arg, we keep the newline -. In final output, it is deleted. We recognize Newline - in macro bodies and macro args. */ if (! concatenated) { ident_length = 0; hash = 0; } ibp++; if (!output_marks) { obp--; } else { /* If expanding a macro arg, keep the newline -. */ *obp++ = '-'; } break; } /* If reprocessing a macro expansion, newline is a special marker. */ else if (ip->macro != 0) { /* Newline White is a "funny space" to separate tokens that are supposed to be separate but without space between. Here White means any whitespace character. Newline - marks a recursive macro use that is not supposed to be expandable. */ if (is_space[*ibp]) { /* Newline Space does not prevent expansion of preceding token so expand the preceding token and then come back. */ if (ident_length > 0) goto specialchar; /* If generating final output, newline space makes a space. */ if (!output_marks) { obp[-1] = *ibp++; /* And Newline Newline makes a newline, so count it. */ if (obp[-1] == '\n') op->lineno++; } else { /* If expanding a macro arg, keep the newline space. If the arg gets stringified, newline space makes nothing. */ *obp++ = *ibp++; } } else abort (); /* Newline followed by something random? */ break; } /* If there is a pending identifier, handle it and come back here. */ if (ident_length > 0) goto specialchar; beg_of_line = ibp; /* Update the line counts and output a #line if necessary. */ ++ip->lineno; ++op->lineno; if (ip->lineno != op->lineno) { op->bufp = obp; output_line_directive (ip, op, 1, same_file); check_expand (op, limit - ibp); obp = op->bufp; } break; /* Come here either after (1) a null character that is part of the input or (2) at the end of the input, because there is a null there. */ case 0: if (ibp <= limit) /* Our input really contains a null character. */ goto randomchar; limit_reached: /* At end of a macro-expansion level, pop it and read next level. */ if (ip->macro != 0) { obp--; ibp--; /* If traditional, and we have an identifier that ends here, process it now, so we get the right error for recursion. */ if (traditional && ident_length && ! is_idchar[*instack[indepth - 1].bufp]) { redo_char = 1; goto randomchar; } POPMACRO; RECACHE; break; } /* If we don't have a pending identifier, return at end of input. */ if (ident_length == 0) { obp--; ibp--; op->bufp = obp; ip->bufp = ibp; goto ending; } /* If we do have a pending identifier, just consider this null a special character and arrange to dispatch on it again. The second time, IDENT_LENGTH will be zero so we will return. */ /* Fall through */ specialchar: /* Handle the case of a character such as /, ', " or null seen following an identifier. Back over it so that after the identifier is processed the special char will be dispatched on again. */ ibp--; obp--; redo_char = 1; default: randomchar: if (ident_length > 0) { register HASHNODE *hp; /* We have just seen an identifier end. If it's a macro, expand it. IDENT_LENGTH is the length of the identifier and HASH is its hash code. The identifier has already been copied to the output, so if it is a macro we must remove it. If REDO_CHAR is 0, the char that terminated the identifier has been skipped in the output and the input. OBP-IDENT_LENGTH-1 points to the identifier. If the identifier is a macro, we must back over the terminator. If REDO_CHAR is 1, the terminating char has already been backed over. OBP-IDENT_LENGTH points to the identifier. */ if (!pcp_outfile || pcp_inside_if) { for (hp = hashtab[MAKE_POS (hash) % HASHSIZE]; hp != NULL; hp = hp->next) { if (hp->length == ident_length) { int obufp_before_macroname; int op_lineno_before_macroname; register int i = ident_length; register U_CHAR *p = hp->name; register U_CHAR *q = obp - i; int disabled; if (! redo_char) q--; do { /* All this to avoid a strncmp () */ if (*p++ != *q++) goto hashcollision; } while (--i); /* We found a use of a macro name. see if the context shows it is a macro call. */ /* Back up over terminating character if not already done. */ if (! redo_char) { ibp--; obp--; } /* Save this as a displacement from the beginning of the output buffer. We can not save this as a position in the output buffer, because it may get realloc'ed by RECACHE. */ obufp_before_macroname = (obp - op->buf) - ident_length; op_lineno_before_macroname = op->lineno; if (hp->type == T_PCSTRING) { pcstring_used (hp); /* Mark the definition of this key as needed, ensuring that it will be output. */ break; /* Exit loop, since the key cannot have a definition any longer. */ } /* Record whether the macro is disabled. */ disabled = hp->type == T_DISABLED; /* This looks like a macro ref, but if the macro was disabled, just copy its name and put in a marker if requested. */ if (disabled) { #if 0 /* This error check caught useful cases such as #define foo(x,y) bar (x (y,0), y) foo (foo, baz) */ if (traditional) error ("recursive use of macro `%s'", hp->name); #endif if (output_marks) { check_expand (op, limit - ibp + 2); *obp++ = '\n'; *obp++ = '-'; } break; } /* If macro wants an arglist, verify that a '(' follows. first skip all whitespace, copying it to the output after the macro name. Then, if there is no '(', decide this is not a macro call and leave things that way. */ if ((hp->type == T_MACRO || hp->type == T_DISABLED) && hp->value.defn->nargs >= 0) { U_CHAR *old_ibp = ibp; U_CHAR *old_obp = obp; int old_iln = ip->lineno; int old_oln = op->lineno; while (1) { /* Scan forward over whitespace, copying it to the output. */ if (ibp == limit && ip->macro != 0) { POPMACRO; RECACHE; old_ibp = ibp; old_obp = obp; old_iln = ip->lineno; old_oln = op->lineno; } else if (is_space[*ibp]) { *obp++ = *ibp++; if (ibp[-1] == '\n') { if (ip->macro == 0) { /* Newline in a file. Count it. */ ++ip->lineno; ++op->lineno; } else if (!output_marks) { /* A newline mark, and we don't want marks in the output. If it is newline-hyphen, discard it entirely. Otherwise, it is newline-whitechar, so keep the whitechar. */ obp--; if (*ibp == '-') ibp++; else { if (*ibp == '\n') ++op->lineno; *obp++ = *ibp++; } } else { /* A newline mark; copy both chars to the output. */ *obp++ = *ibp++; } } } else if (ip->macro) break; else if (*ibp == '/') { /* If a comment, copy it unchanged or discard it. */ if (ibp[1] == '\\' && ibp[2] == '\n') newline_fix (ibp + 1); if (ibp[1] == '*') { if (put_out_comments) { *obp++ = '/'; *obp++ = '*'; } else if (! traditional) { *obp++ = ' '; } for (ibp += 2; ibp < limit; ibp++) { /* We need not worry about newline-marks, since they are never found in comments. */ if (ibp[0] == '*') { if (ibp[1] == '\\' && ibp[2] == '\n') newline_fix (ibp + 1); if (ibp[1] == '/') { ibp += 2; if (put_out_comments) { *obp++ = '*'; *obp++ = '/'; } break; } } if (*ibp == '\n') { /* Newline in a file. Count it. */ ++ip->lineno; ++op->lineno; } if (put_out_comments) *obp++ = *ibp; } } else if (ibp[1] == '/' && cplusplus_comments) { if (put_out_comments) { *obp++ = '/'; *obp++ = '/'; } else if (! traditional) { *obp++ = ' '; } for (ibp += 2; *ibp != '\n' || ibp[-1] == '\\'; ibp++) if (put_out_comments) *obp++ = *ibp; } else break; } else if (ibp[0] == '\\' && ibp[1] == '\n') { ibp += 2; ++ip->lineno; } else break; } if (*ibp != '(') { /* It isn't a macro call. Put back the space that we just skipped. */ ibp = old_ibp; obp = old_obp; ip->lineno = old_iln; op->lineno = old_oln; /* Exit the for loop. */ break; } } /* This is now known to be a macro call. Discard the macro name from the output, along with any following whitespace just copied, but preserve newlines if not outputting marks since this is more likely to do the right thing with line numbers. */ obp = op->buf + obufp_before_macroname; if (output_marks) op->lineno = op_lineno_before_macroname; else { int newlines = op->lineno - op_lineno_before_macroname; while (0 < newlines--) *obp++ = '\n'; } /* Prevent accidental token-pasting with a character before the macro call. */ if (!traditional && obp != op->buf) { switch (obp[-1]) { case '!': case '%': case '&': case '*': case '+': case '-': case '.': case '/': case ':': case '<': case '=': case '>': case '^': case '|': /* If we are expanding a macro arg, make a newline marker to separate the tokens. If we are making real output, a plain space will do. */ if (output_marks) *obp++ = '\n'; *obp++ = ' '; } } /* Expand the macro, reading arguments as needed, and push the expansion on the input stack. */ ip->bufp = ibp; op->bufp = obp; macroexpand (hp, op); /* Reexamine input stack, since macroexpand has pushed a new level on it. */ obp = op->bufp; RECACHE; break; } hashcollision: ; } /* End hash-table-search loop */ } ident_length = hash = 0; /* Stop collecting identifier */ redo_char = 0; concatenated = 0; } /* End if (ident_length > 0) */ } /* End switch */ } /* End per-char loop */ /* Come here to return -- but first give an error message if there was an unterminated successful conditional. */ ending: if (if_stack != ip->if_stack) { char *str; switch (if_stack->type) { case T_IF: str = "if"; break; case T_IFDEF: str = "ifdef"; break; case T_IFNDEF: str = "ifndef"; break; case T_ELSE: str = "else"; break; case T_ELIF: str = "elif"; break; default: abort (); } error_with_line (line_for_error (if_stack->lineno), "unterminated `#%s' conditional", str); } if_stack = ip->if_stack; } /* * Rescan a string into a temporary buffer and return the result * as a FILE_BUF. Note this function returns a struct, not a pointer. * * OUTPUT_MARKS nonzero means keep Newline markers found in the input * and insert such markers when appropriate. See `rescan' for details. * OUTPUT_MARKS is 1 for macroexpanding a macro argument separately * before substitution; it is 0 for other uses. */ static FILE_BUF expand_to_temp_buffer (buf, limit, output_marks, assertions) U_CHAR *buf, *limit; int output_marks, assertions; { register FILE_BUF *ip; FILE_BUF obuf; int length = limit - buf; U_CHAR *buf1; int odepth = indepth; int save_assertions_flag = assertions_flag; assertions_flag = assertions; if (length < 0) abort (); /* Set up the input on the input stack. */ buf1 = (U_CHAR *) alloca (length + 1); { register U_CHAR *p1 = buf; register U_CHAR *p2 = buf1; while (p1 != limit) *p2++ = *p1++; } buf1[length] = 0; /* Set up to receive the output. */ obuf.length = length * 2 + 100; /* Usually enough. Why be stingy? */ obuf.bufp = obuf.buf = (U_CHAR *) xmalloc (obuf.length); obuf.fname = 0; obuf.macro = 0; obuf.free_ptr = 0; CHECK_DEPTH ({return obuf;}); ++indepth; ip = &instack[indepth]; ip->fname = 0; ip->nominal_fname = 0; ip->inc = 0; ip->system_header_p = 0; ip->macro = 0; ip->free_ptr = 0; ip->length = length; ip->buf = ip->bufp = buf1; ip->if_stack = if_stack; ip->lineno = obuf.lineno = 1; /* Scan the input, create the output. */ rescan (&obuf, output_marks); /* Pop input stack to original state. */ --indepth; if (indepth != odepth) abort (); /* Record the output. */ obuf.length = obuf.bufp - obuf.buf; assertions_flag = save_assertions_flag; return obuf; } /* * Process a # directive. Expects IP->bufp to point after the '#', as in * `#define foo bar'. Passes to the directive handler * (do_define, do_include, etc.): the addresses of the 1st and * last chars of the directive (starting immediately after the # * keyword), plus op and the keyword table pointer. If the directive * contains comments it is copied into a temporary buffer sans comments * and the temporary buffer is passed to the directive handler instead. * Likewise for backslash-newlines. * * Returns nonzero if this was a known # directive. * Otherwise, returns zero, without advancing the input pointer. */ static int handle_directive (ip, op) FILE_BUF *ip, *op; { register U_CHAR *bp, *cp; register struct directive *kt; register int ident_length; U_CHAR *resume_p; /* Nonzero means we must copy the entire directive to get rid of comments or backslash-newlines. */ int copy_directive = 0; U_CHAR *ident, *after_ident; bp = ip->bufp; /* Record where the directive started. do_xifdef needs this. */ directive_start = bp - 1; /* Skip whitespace and \-newline. */ while (1) { if (is_hor_space[*bp]) { if (*bp != ' ' && *bp != '\t' && pedantic) pedwarn ("%s in preprocessing directive", char_name[*bp]); bp++; } else if (*bp == '/') { if (bp[1] == '\\' && bp[2] == '\n') newline_fix (bp + 1); if (! (bp[1] == '*' || (cplusplus_comments && bp[1] == '/'))) break; ip->bufp = bp + 2; skip_to_end_of_comment (ip, &ip->lineno, 0); bp = ip->bufp; } else if (*bp == '\\' && bp[1] == '\n') { bp += 2; ip->lineno++; } else break; } /* Now find end of directive name. If we encounter a backslash-newline, exchange it with any following symbol-constituents so that we end up with a contiguous name. */ cp = bp; while (1) { if (is_idchar[*cp]) cp++; else { if (*cp == '\\' && cp[1] == '\n') name_newline_fix (cp); if (is_idchar[*cp]) cp++; else break; } } ident_length = cp - bp; ident = bp; after_ident = cp; /* A line of just `#' becomes blank. */ if (ident_length == 0 && *after_ident == '\n') { ip->bufp = after_ident; return 1; } if (ident_length == 0 || !is_idstart[*ident]) { U_CHAR *p = ident; while (is_idchar[*p]) { if (*p < '0' || *p > '9') break; p++; } /* Handle # followed by a line number. */ if (p != ident && !is_idchar[*p]) { static struct directive line_directive_table[] = { { 4, do_line, "line", T_LINE}, }; if (pedantic) pedwarn ("`#' followed by integer"); after_ident = ident; kt = line_directive_table; goto old_linenum; } /* Avoid error for `###' and similar cases unless -pedantic. */ if (p == ident) { while (*p == '#' || is_hor_space[*p]) p++; if (*p == '\n') { if (pedantic && !lang_asm) warning ("invalid preprocessing directive"); return 0; } } if (!lang_asm) error ("invalid preprocessing directive name"); return 0; } /* * Decode the keyword and call the appropriate expansion * routine, after moving the input pointer up to the next line. */ for (kt = directive_table; kt->length > 0; kt++) { if (kt->length == ident_length && !bcmp (kt->name, ident, ident_length)) { register U_CHAR *buf; register U_CHAR *limit; int unterminated; int junk; int *already_output; /* Nonzero means do not delete comments within the directive. #define needs this when -traditional. */ int keep_comments; old_linenum: limit = ip->buf + ip->length; unterminated = 0; already_output = 0; keep_comments = traditional && kt->type == T_DEFINE; /* #import is defined only in Objective C, or when on the NeXT. */ if (kt->type == T_IMPORT && !(objc || lookup ((U_CHAR *) "__NeXT__", -1, -1))) break; /* Find the end of this directive (first newline not backslashed and not in a string or comment). Set COPY_DIRECTIVE if the directive must be copied (it contains a backslash-newline or a comment). */ buf = bp = after_ident; while (bp < limit) { register U_CHAR c = *bp++; switch (c) { case '\\': if (bp < limit) { if (*bp == '\n') { ip->lineno++; copy_directive = 1; bp++; } else if (traditional) bp++; } break; case '"': /* "..." is special for #include. */ if (IS_INCLUDE_DIRECTIVE_TYPE (kt->type)) { while (bp < limit && *bp != '\n') { if (*bp == '"') { bp++; break; } if (*bp == '\\' && bp[1] == '\n') { ip->lineno++; copy_directive = 1; bp++; } bp++; } break; } /* Fall through. */ case '\'': bp = skip_quoted_string (bp - 1, limit, ip->lineno, &ip->lineno, ©_directive, &unterminated); /* Don't bother calling the directive if we already got an error message due to unterminated string. Skip everything and pretend we called the directive. */ if (unterminated) { if (traditional) { /* Traditional preprocessing permits unterminated strings. */ ip->bufp = bp; goto endloop1; } ip->bufp = bp; return 1; } break; /* <...> is special for #include. */ case '<': if (! IS_INCLUDE_DIRECTIVE_TYPE (kt->type)) break; while (bp < limit && *bp != '>' && *bp != '\n') { if (*bp == '\\' && bp[1] == '\n') { ip->lineno++; copy_directive = 1; bp++; } bp++; } break; case '/': if (*bp == '\\' && bp[1] == '\n') newline_fix (bp); if (*bp == '*' || (cplusplus_comments && *bp == '/')) { U_CHAR *obp = bp - 1; ip->bufp = bp + 1; skip_to_end_of_comment (ip, &ip->lineno, 0); bp = ip->bufp; /* No need to copy the directive because of a comment at the end; just don't include the comment in the directive. */ if (!put_out_comments) { U_CHAR *p; for (p = bp; *p == ' ' || *p == '\t'; p++) continue; if (*p == '\n') { bp = obp; goto endloop1; } } /* Don't remove the comments if -traditional. */ if (! keep_comments) copy_directive++; } break; case '\f': case '\r': case '\v': if (pedantic) pedwarn ("%s in preprocessing directive", char_name[c]); break; case '\n': --bp; /* Point to the newline */ ip->bufp = bp; goto endloop1; } } ip->bufp = bp; endloop1: resume_p = ip->bufp; /* BP is the end of the directive. RESUME_P is the next interesting data after the directive. A comment may come between. */ /* If a directive should be copied through, and -C was given, pass it through before removing comments. */ if (!no_output && put_out_comments && (kt->type == T_DEFINE ? dump_macros == dump_definitions : IS_INCLUDE_DIRECTIVE_TYPE (kt->type) ? dump_includes : kt->type == T_PRAGMA)) { int len; /* Output directive name. */ check_expand (op, kt->length + 2); /* Make sure # is at the start of a line */ if (op->bufp > op->buf && op->bufp[-1] != '\n') { op->lineno++; *op->bufp++ = '\n'; } *op->bufp++ = '#'; bcopy (kt->name, op->bufp, kt->length); op->bufp += kt->length; /* Output arguments. */ len = (bp - buf); check_expand (op, len); bcopy (buf, (char *) op->bufp, len); op->bufp += len; /* Take account of any (escaped) newlines just output. */ while (--len >= 0) if (buf[len] == '\n') op->lineno++; already_output = &junk; } /* Don't we need a newline or #line? */ if (copy_directive) { register U_CHAR *xp = buf; /* Need to copy entire directive into temp buffer before dispatching */ cp = (U_CHAR *) alloca (bp - buf + 5); /* room for directive plus some slop */ buf = cp; /* Copy to the new buffer, deleting comments and backslash-newlines (and whitespace surrounding the latter). */ while (xp < bp) { register U_CHAR c = *xp++; *cp++ = c; switch (c) { case '\n': abort (); /* A bare newline should never part of the line. */ break; /* <...> is special for #include. */ case '<': if (! IS_INCLUDE_DIRECTIVE_TYPE (kt->type)) break; while (xp < bp && c != '>') { c = *xp++; if (c == '\\' && xp < bp && *xp == '\n') xp++; else *cp++ = c; } break; case '\\': if (*xp == '\n') { xp++; cp--; if (cp != buf && is_hor_space[cp[-1]]) { while (cp - 1 != buf && is_hor_space[cp[-2]]) cp--; SKIP_WHITE_SPACE (xp); } else if (is_hor_space[*xp]) { *cp++ = *xp++; SKIP_WHITE_SPACE (xp); } } else if (traditional && xp < bp) { *cp++ = *xp++; } break; case '\'': case '\"': { register U_CHAR *bp1 = skip_quoted_string (xp - 1, bp, ip->lineno, NULL_PTR, NULL_PTR, NULL_PTR); while (xp != bp1) *cp++ = *xp++; } break; case '/': if (*xp == '*' || (cplusplus_comments && *xp == '/')) { ip->bufp = xp + 1; /* If we already copied the directive through, already_output != 0 prevents outputting comment now. */ skip_to_end_of_comment (ip, already_output, 0); if (keep_comments) while (xp != ip->bufp) *cp++ = *xp++; /* Delete or replace the slash. */ else if (traditional) cp--; else cp[-1] = ' '; xp = ip->bufp; } } } /* Null-terminate the copy. */ *cp = 0; } else cp = bp; ip->bufp = resume_p; /* Some directives should be written out for cc1 to process, just as if they were not defined. And sometimes we're copying directives through. */ if (!no_output && already_output == 0 && (kt->type == T_DEFINE ? (int) dump_names <= (int) dump_macros : IS_INCLUDE_DIRECTIVE_TYPE (kt->type) ? dump_includes : kt->type == T_PRAGMA)) { int len; /* Output directive name. */ check_expand (op, kt->length + 1); *op->bufp++ = '#'; bcopy (kt->name, (char *) op->bufp, kt->length); op->bufp += kt->length; if (kt->type == T_DEFINE && dump_macros == dump_names) { /* Output `#define name' only. */ U_CHAR *xp = buf; U_CHAR *yp; SKIP_WHITE_SPACE (xp); yp = xp; while (is_idchar[*xp]) xp++; len = (xp - yp); check_expand (op, len + 1); *op->bufp++ = ' '; bcopy (yp, (char *) op->bufp, len); } else { /* Output entire directive. */ len = (cp - buf); check_expand (op, len); bcopy (buf, (char *) op->bufp, len); } op->bufp += len; } /* Don't we need a newline or #line? */ /* Call the appropriate directive handler. buf now points to either the appropriate place in the input buffer, or to the temp buffer if it was necessary to make one. cp points to the first char after the contents of the (possibly copied) directive, in either case. */ (*kt->func) (buf, cp, op, kt); check_expand (op, ip->length - (ip->bufp - ip->buf)); return 1; } } /* It is deliberate that we don't warn about undefined directives. That is the responsibility of cc1. */ return 0; } static struct tm * timestamp () { static struct tm *timebuf; if (!timebuf) { time_t t = time ((time_t *) 0); timebuf = localtime (&t); } return timebuf; } static char *monthnames[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", }; /* * expand things like __FILE__. Place the expansion into the output * buffer *without* rescanning. */ static void special_symbol (hp, op) HASHNODE *hp; FILE_BUF *op; { char *buf; int i, len; int true_indepth; FILE_BUF *ip = NULL; struct tm *timebuf; int paren = 0; /* For special `defined' keyword */ if (pcp_outfile && pcp_inside_if && hp->type != T_SPEC_DEFINED && hp->type != T_CONST) error ("Predefined macro `%s' used inside `#if' during precompilation", hp->name); for (i = indepth; i >= 0; i--) if (instack[i].fname != NULL) { ip = &instack[i]; break; } if (ip == NULL) { error ("cccp error: not in any file?!"); return; /* the show must go on */ } switch (hp->type) { case T_FILE: case T_BASE_FILE: { char *string; if (hp->type == T_FILE) string = ip->nominal_fname; else string = instack[0].nominal_fname; if (string) { buf = (char *) alloca (3 + 4 * strlen (string)); quote_string (buf, string); } else buf = "\"\""; break; } case T_INCLUDE_LEVEL: true_indepth = 0; for (i = indepth; i >= 0; i--) if (instack[i].fname != NULL) true_indepth++; buf = (char *) alloca (8); /* Eight bytes ought to be more than enough */ sprintf (buf, "%d", true_indepth - 1); break; case T_VERSION: buf = (char *) alloca (3 + strlen (version_string)); sprintf (buf, "\"%s\"", version_string); break; #ifndef NO_BUILTIN_SIZE_TYPE case T_SIZE_TYPE: buf = SIZE_TYPE; break; #endif #ifndef NO_BUILTIN_PTRDIFF_TYPE case T_PTRDIFF_TYPE: buf = PTRDIFF_TYPE; break; #endif case T_WCHAR_TYPE: buf = wchar_type; break; case T_USER_LABEL_PREFIX_TYPE: buf = USER_LABEL_PREFIX; break; case T_REGISTER_PREFIX_TYPE: buf = REGISTER_PREFIX; break; case T_IMMEDIATE_PREFIX_TYPE: buf = IMMEDIATE_PREFIX; break; case T_CONST: buf = hp->value.cpval; #ifdef STDC_0_IN_SYSTEM_HEADERS if (ip->system_header_p && hp->length == 8 && bcmp (hp->name, "__STDC__", 8) == 0 && !lookup ((U_CHAR *) "__STRICT_ANSI__", -1, -1)) buf = "0"; #endif if (pcp_inside_if && pcp_outfile) /* Output a precondition for this macro use */ fprintf (pcp_outfile, "#define %s %s\n", hp->name, buf); break; case T_SPECLINE: buf = (char *) alloca (10); sprintf (buf, "%d", ip->lineno); break; case T_DATE: case T_TIME: buf = (char *) alloca (20); timebuf = timestamp (); if (hp->type == T_DATE) sprintf (buf, "\"%s %2d %4d\"", monthnames[timebuf->tm_mon], timebuf->tm_mday, timebuf->tm_year + 1900); else sprintf (buf, "\"%02d:%02d:%02d\"", timebuf->tm_hour, timebuf->tm_min, timebuf->tm_sec); break; case T_SPEC_DEFINED: buf = " 0 "; /* Assume symbol is not defined */ ip = &instack[indepth]; SKIP_WHITE_SPACE (ip->bufp); if (*ip->bufp == '(') { paren++; ip->bufp++; /* Skip over the paren */ SKIP_WHITE_SPACE (ip->bufp); } if (!is_idstart[*ip->bufp]) goto oops; if (ip->bufp[0] == 'L' && (ip->bufp[1] == '\'' || ip->bufp[1] == '"')) goto oops; if ((hp = lookup (ip->bufp, -1, -1))) { if (pcp_outfile && pcp_inside_if && (hp->type == T_CONST || (hp->type == T_MACRO && hp->value.defn->predefined))) /* Output a precondition for this macro use. */ fprintf (pcp_outfile, "#define %s\n", hp->name); buf = " 1 "; } else if (pcp_outfile && pcp_inside_if) { /* Output a precondition for this macro use */ U_CHAR *cp = ip->bufp; fprintf (pcp_outfile, "#undef "); while (is_idchar[*cp]) /* Ick! */ fputc (*cp++, pcp_outfile); putc ('\n', pcp_outfile); } while (is_idchar[*ip->bufp]) ++ip->bufp; SKIP_WHITE_SPACE (ip->bufp); if (paren) { if (*ip->bufp != ')') goto oops; ++ip->bufp; } break; oops: error ("`defined' without an identifier"); break; default: error ("cccp error: invalid special hash type"); /* time for gdb */ abort (); } len = strlen (buf); check_expand (op, len); bcopy (buf, (char *) op->bufp, len); op->bufp += len; return; } /* Routines to handle #directives */ /* Handle #include and #import. This function expects to see "fname" or on the input. */ static int do_include (buf, limit, op, keyword) U_CHAR *buf, *limit; FILE_BUF *op; struct directive *keyword; { U_CHAR *importing = keyword->type == T_IMPORT ? (U_CHAR *) "" : (U_CHAR *) 0; int skip_dirs = (keyword->type == T_INCLUDE_NEXT); static int import_warning = 0; char *fname; /* Dynamically allocated fname buffer */ char *pcftry; char *pcfname; char *fbeg, *fend; /* Beginning and end of fname */ U_CHAR *fin; struct file_name_list *search_start = include; /* Chain of dirs to search */ struct file_name_list *dsp; /* First in chain, if #include "..." */ struct file_name_list *searchptr = 0; size_t flen; int f = -3; /* file number */ struct include_file *inc = 0; int retried = 0; /* Have already tried macro expanding the include line*/ int angle_brackets = 0; /* 0 for "...", 1 for <...> */ #ifdef VMS int vaxc_include = 0; /* 1 for token without punctuation */ #endif int pcf = -1; char *pcfbuf; char *pcfbuflimit; int pcfnum; if (pedantic && !instack[indepth].system_header_p) { if (importing) pedwarn ("ANSI C does not allow `#import'"); if (skip_dirs) pedwarn ("ANSI C does not allow `#include_next'"); } if (importing && warn_import && !inhibit_warnings && !instack[indepth].system_header_p && !import_warning) { import_warning = 1; warning ("using `#import' is not recommended"); fprintf (stderr, "The fact that a certain header file need not be processed more than once\n"); fprintf (stderr, "should be indicated in the header file, not where it is used.\n"); fprintf (stderr, "The best way to do this is with a conditional of this form:\n\n"); fprintf (stderr, " #ifndef _FOO_H_INCLUDED\n"); fprintf (stderr, " #define _FOO_H_INCLUDED\n"); fprintf (stderr, " ... ...\n"); fprintf (stderr, " #endif /* Not _FOO_H_INCLUDED */\n\n"); fprintf (stderr, "Then users can use `#include' any number of times.\n"); fprintf (stderr, "GNU C automatically avoids processing the file more than once\n"); fprintf (stderr, "when it is equipped with such a conditional.\n"); } get_filename: fin = buf; SKIP_WHITE_SPACE (fin); /* Discard trailing whitespace so we can easily see if we have parsed all the significant chars we were given. */ while (limit != fin && is_hor_space[limit[-1]]) limit--; fbeg = fend = (char *) alloca (limit - fin); switch (*fin++) { case '\"': { FILE_BUF *fp; /* Copy the operand text, concatenating the strings. */ { for (;;) { for (;;) { if (fin == limit) goto invalid_include_file_name; *fend = *fin++; if (*fend == '"') break; fend++; } if (fin == limit) break; /* If not at the end, there had better be another string. */ /* Skip just horiz space, and don't go past limit. */ while (fin != limit && is_hor_space[*fin]) fin++; if (fin != limit && *fin == '\"') fin++; else goto fail; } } /* We have "filename". Figure out directory this source file is coming from and put it on the front of the list. */ /* If -I- was specified, don't search current dir, only spec'd ones. */ if (ignore_srcdir) break; for (fp = &instack[indepth]; fp >= instack; fp--) { int n; char *nam; if ((nam = fp->nominal_fname) != NULL) { /* Found a named file. Figure out dir of the file, and put it in front of the search list. */ dsp = ((struct file_name_list *) alloca (sizeof (struct file_name_list) + strlen (nam))); strcpy (dsp->fname, nam); simplify_filename (dsp->fname); nam = base_name (dsp->fname); *nam = 0; /* But for efficiency's sake, do not insert the dir if it matches the search list's first dir. */ dsp->next = search_start; if (!search_start || strcmp (dsp->fname, search_start->fname)) { search_start = dsp; n = nam - dsp->fname; if (n + INCLUDE_LEN_FUDGE > max_include_len) max_include_len = n + INCLUDE_LEN_FUDGE; } dsp[0].got_name_map = 0; break; } } break; } case '<': while (fin != limit && *fin != '>') *fend++ = *fin++; if (*fin == '>' && fin + 1 == limit) { angle_brackets = 1; /* If -I-, start with the first -I dir after the -I-. */ search_start = first_bracket_include; break; } goto fail; default: #ifdef VMS /* * Support '#include xyz' like VAX-C to allow for easy use of all the * decwindow include files. It defaults to '#include ' (so the * code from case '<' is repeated here) and generates a warning. * (Note: macro expansion of `xyz' takes precedence.) */ if (retried && isalpha(*(U_CHAR *) (--fbeg))) { while (fin != limit && (!isspace(*fin))) *fend++ = *fin++; warning ("VAX-C-style include specification found, use '#include ' !"); vaxc_include = 1; if (fin == limit) { angle_brackets = 1; /* If -I-, start with the first -I dir after the -I-. */ search_start = first_bracket_include; break; } } #endif fail: if (! retried) { /* Expand buffer and then remove any newline markers. We can't just tell expand_to_temp_buffer to omit the markers, since it would put extra spaces in include file names. */ FILE_BUF trybuf; U_CHAR *src; int errors_before_expansion = errors; trybuf = expand_to_temp_buffer (buf, limit, 1, 0); if (errors != errors_before_expansion) { free (trybuf.buf); goto invalid_include_file_name; } src = trybuf.buf; buf = (U_CHAR *) alloca (trybuf.bufp - trybuf.buf + 1); limit = buf; while (src != trybuf.bufp) { switch ((*limit++ = *src++)) { case '\n': limit--; src++; break; case '\'': case '\"': { U_CHAR *src1 = skip_quoted_string (src - 1, trybuf.bufp, 0, NULL_PTR, NULL_PTR, NULL_PTR); while (src != src1) *limit++ = *src++; } break; } } *limit = 0; free (trybuf.buf); retried = 1; goto get_filename; } invalid_include_file_name: error ("`#%s' expects \"FILENAME\" or ", keyword->name); return 0; } /* For #include_next, skip in the search path past the dir in which the containing file was found. */ if (skip_dirs) { FILE_BUF *fp; for (fp = &instack[indepth]; fp >= instack; fp--) if (fp->fname != NULL) { /* fp->dir is null if the containing file was specified with an absolute file name. In that case, don't skip anything. */ if (fp->dir) search_start = fp->dir->next; break; } } *fend = 0; flen = simplify_filename (fbeg); if (flen == 0) { error ("empty file name in `#%s'", keyword->name); return 0; } /* Allocate this permanently, because it gets stored in the definitions of macros. */ fname = xmalloc (max_include_len + flen + 1); /* + 1 above for terminating null. */ system_include_depth += angle_brackets; /* If specified file name is absolute, just open it. */ if (absolute_filename (fbeg)) { strcpy (fname, fbeg); f = open_include_file (fname, NULL_PTR, importing, &inc); } else { struct bypass_dir { struct bypass_dir *next; char *fname; struct file_name_list *searchptr; } **bypass_slot = 0; /* Search directory path, trying to open the file. Copy each filename tried into FNAME. */ for (searchptr = search_start; searchptr; searchptr = searchptr->next) { if (searchptr == first_bracket_include) { /* Go to bypass directory if we know we've seen this file before. */ static struct bypass_dir *bypass_hashtab[INCLUDE_HASHSIZE]; struct bypass_dir *p; bypass_slot = &bypass_hashtab[hashf ((U_CHAR *) fbeg, flen, INCLUDE_HASHSIZE)]; for (p = *bypass_slot; p; p = p->next) if (!strcmp (fbeg, p->fname)) { searchptr = p->searchptr; bypass_slot = 0; break; } } strcpy (fname, searchptr->fname); strcat (fname, fbeg); #ifdef VMS /* Change this 1/2 Unix 1/2 VMS file specification into a full VMS file specification */ if (searchptr->fname[0]) { /* Fix up the filename */ hack_vms_include_specification (fname, vaxc_include); } else { /* This is a normal VMS filespec, so use it unchanged. */ strcpy (fname, fbeg); /* if it's '#include filename', add the missing .h */ if (vaxc_include && index(fname,'.')==NULL) { strcat (fname, ".h"); } } #endif /* VMS */ f = open_include_file (fname, searchptr, importing, &inc); if (f != -1) { if (bypass_slot && searchptr != first_bracket_include) { /* This is the first time we found this include file, and we found it after first_bracket_include. Record its location so that we can bypass to here next time. */ struct bypass_dir *p = (struct bypass_dir *) xmalloc (sizeof (struct bypass_dir)); p->next = *bypass_slot; p->fname = fname + strlen (searchptr->fname); p->searchptr = searchptr; *bypass_slot = p; } break; } #ifdef VMS /* Our VMS hacks can produce invalid filespecs, so don't worry about errors other than EACCES. */ if (errno == EACCES) break; #else if (errno != ENOENT && errno != ENOTDIR) break; #endif } } if (f < 0) { if (f == -2) { /* The file was already included. */ /* If generating dependencies and -MG was specified, we assume missing files are leaf files, living in the same directory as the source file or other similar place; these missing files may be generated from other files and may not exist yet (eg: y.tab.h). */ } else if (print_deps_missing_files && (system_include_depth != 0) < print_deps) { /* If it was requested as a system header file, then assume it belongs in the first place to look for such. */ if (angle_brackets) { if (search_start) { char *p = (char *) alloca (strlen (search_start->fname) + strlen (fbeg) + 1); strcpy (p, search_start->fname); strcat (p, fbeg); deps_output (p, ' '); } } else { /* Otherwise, omit the directory, as if the file existed in the directory with the source. */ deps_output (fbeg, ' '); } } /* If -M was specified, and this header file won't be added to the dependency list, then don't count this as an error, because we can still produce correct output. Otherwise, we can't produce correct output, because there may be dependencies we need inside the missing file, and we don't know what directory this missing file exists in. */ else if (0 < print_deps && print_deps <= (system_include_depth != 0)) warning ("No include path in which to find %s", fbeg); else if (f != -3) error_from_errno (fbeg); else error ("No include path in which to find %s", fbeg); } else { /* Actually process the file. */ pcftry = (char *) alloca (strlen (fname) + 30); pcfbuf = 0; pcfnum = 0; if (!no_precomp) { do { sprintf (pcftry, "%s%d", fname, pcfnum++); pcf = open (pcftry, O_RDONLY, 0666); if (pcf != -1) { struct stat s; if (fstat (pcf, &s) != 0) pfatal_with_name (pcftry); if (! INO_T_EQ (inc->st.st_ino, s.st_ino) || inc->st.st_dev != s.st_dev) { pcfbuf = check_precompiled (pcf, &s, fname, &pcfbuflimit); /* Don't need it any more. */ close (pcf); } else { /* Don't need it at all. */ close (pcf); break; } } } while (pcf != -1 && !pcfbuf); } /* Actually process the file */ if (pcfbuf) { pcfname = xmalloc (strlen (pcftry) + 1); strcpy (pcfname, pcftry); pcfinclude ((U_CHAR *) pcfbuf, (U_CHAR *) pcfbuflimit, (U_CHAR *) fname, op); } else finclude (f, inc, op, is_system_include (fname), searchptr); } system_include_depth -= angle_brackets; return 0; } /* Return nonzero if the given FILENAME is an absolute pathname which designates a file within one of the known "system" include file directories. We assume here that if the given FILENAME looks like it is the name of a file which resides either directly in a "system" include file directory, or within any subdirectory thereof, then the given file must be a "system" include file. This function tells us if we should suppress pedantic errors/warnings for the given FILENAME. The value is 2 if the file is a C-language system header file for which C++ should (on most systems) assume `extern "C"'. */ static int is_system_include (filename) register char *filename; { struct file_name_list *searchptr; for (searchptr = first_system_include; searchptr; searchptr = searchptr->next) if (! strncmp (searchptr->fname, filename, strlen (searchptr->fname))) return searchptr->c_system_include_path + 1; return 0; } /* Yield the non-directory suffix of a file name. */ static char * base_name (fname) char *fname; { char *s = fname; char *p; #if defined (__MSDOS__) || defined (_WIN32) if (isalpha (s[0]) && s[1] == ':') s += 2; #endif #ifdef VMS if ((p = rindex (s, ':'))) s = p + 1; /* Skip device. */ if ((p = rindex (s, ']'))) s = p + 1; /* Skip directory. */ if ((p = rindex (s, '>'))) s = p + 1; /* Skip alternate (int'n'l) dir. */ if (s != fname) return s; #endif if ((p = (char*) rindex (s, '/'))) s = p + 1; #ifdef DIR_SEPARATOR if ((p = rindex (s, DIR_SEPARATOR))) s = p + 1; #endif return s; } /* Yield nonzero if FILENAME is absolute (i.e. not relative). */ static int absolute_filename (filename) char *filename; { #if defined (__MSDOS__) || (defined (_WIN32) && !defined (__CYGWIN32__)) if (isalpha (filename[0]) && filename[1] == ':') filename += 2; #endif #if defined (__CYGWIN32__) /* At present, any path that begins with a drive spec is absolute. */ if (isalpha (filename[0]) && filename[1] == ':') return 1; #endif if (filename[0] == '/') return 1; #ifdef DIR_SEPARATOR if (filename[0] == DIR_SEPARATOR) return 1; #endif return 0; } /* Remove unnecessary characters from FILENAME in place, to avoid unnecessary filename aliasing. Return the length of the resulting string. Do only the simplifications allowed by Posix. It is OK to miss simplifications on non-Posix hosts, since this merely leads to suboptimal results. */ static size_t simplify_filename (filename) char *filename; { register char *from = filename; register char *to = filename; char *to0; /* Remove redundant initial /s. */ if (*from == '/') { *to++ = '/'; if (*++from == '/') { if (*++from == '/') { /* 3 or more initial /s are equivalent to 1 /. */ while (*++from == '/') continue; } else { /* On some hosts // differs from /; Posix allows this. */ static int slashslash_vs_slash; if (slashslash_vs_slash == 0) { struct stat s1, s2; slashslash_vs_slash = ((stat ("/", &s1) == 0 && stat ("//", &s2) == 0 && INO_T_EQ (s1.st_ino, s2.st_ino) && s1.st_dev == s2.st_dev) ? 1 : -1); } if (slashslash_vs_slash < 0) *to++ = '/'; } } } to0 = to; for (;;) { if (from[0] == '.' && from[1] == '/') from += 2; else { /* Copy this component and trailing /, if any. */ while ((*to++ = *from++) != '/') { if (!to[-1]) { /* Trim . component at end of nonempty name. */ to -= filename <= to - 3 && to[-3] == '/' && to[-2] == '.'; /* Trim unnecessary trailing /s. */ while (to0 < --to && to[-1] == '/') continue; *to = 0; return to - filename; } } } /* Skip /s after a /. */ while (*from == '/') from++; } } /* The file_name_map structure holds a mapping of file names for a particular directory. This mapping is read from the file named FILE_NAME_MAP_FILE in that directory. Such a file can be used to map filenames on a file system with severe filename restrictions, such as DOS. The format of the file name map file is just a series of lines with two tokens on each line. The first token is the name to map, and the second token is the actual name to use. */ struct file_name_map { struct file_name_map *map_next; char *map_from; char *map_to; }; #define FILE_NAME_MAP_FILE "header.gcc" /* Read a space delimited string of unlimited length from a stdio file. */ static char * read_filename_string (ch, f) int ch; FILE *f; { char *alloc, *set; int len; len = 20; set = alloc = xmalloc (len + 1); if (! is_space[ch]) { *set++ = ch; while ((ch = getc (f)) != EOF && ! is_space[ch]) { if (set - alloc == len) { len *= 2; alloc = xrealloc (alloc, len + 1); set = alloc + len / 2; } *set++ = ch; } } *set = '\0'; ungetc (ch, f); return alloc; } /* Read the file name map file for DIRNAME. If DIRNAME is empty, read the map file for the working directory; otherwise DIRNAME must end in '/'. */ static struct file_name_map * read_name_map (dirname) char *dirname; { /* This structure holds a linked list of file name maps, one per directory. */ struct file_name_map_list { struct file_name_map_list *map_list_next; char *map_list_name; struct file_name_map *map_list_map; }; static struct file_name_map_list *map_list; register struct file_name_map_list *map_list_ptr; char *name; FILE *f; size_t dirlen; for (map_list_ptr = map_list; map_list_ptr; map_list_ptr = map_list_ptr->map_list_next) if (! strcmp (map_list_ptr->map_list_name, dirname)) return map_list_ptr->map_list_map; map_list_ptr = ((struct file_name_map_list *) xmalloc (sizeof (struct file_name_map_list))); map_list_ptr->map_list_name = savestring (dirname); map_list_ptr->map_list_map = NULL; dirlen = strlen (dirname); name = (char *) alloca (dirlen + strlen (FILE_NAME_MAP_FILE) + 1); strcpy (name, dirname); strcat (name, FILE_NAME_MAP_FILE); f = fopen (name, "r"); if (!f) map_list_ptr->map_list_map = NULL; else { int ch; while ((ch = getc (f)) != EOF) { char *from, *to; struct file_name_map *ptr; size_t tolen; if (is_space[ch]) continue; from = read_filename_string (ch, f); while ((ch = getc (f)) != EOF && is_hor_space[ch]) ; to = read_filename_string (ch, f); simplify_filename (from); tolen = simplify_filename (to); ptr = ((struct file_name_map *) xmalloc (sizeof (struct file_name_map))); ptr->map_from = from; /* Make the real filename absolute. */ if (absolute_filename (to)) ptr->map_to = to; else { ptr->map_to = xmalloc (dirlen + tolen + 1); strcpy (ptr->map_to, dirname); strcat (ptr->map_to, to); free (to); } ptr->map_next = map_list_ptr->map_list_map; map_list_ptr->map_list_map = ptr; while ((ch = getc (f)) != '\n') if (ch == EOF) break; } fclose (f); } map_list_ptr->map_list_next = map_list; map_list = map_list_ptr; return map_list_ptr->map_list_map; } /* Try to open include file FILENAME. SEARCHPTR is the directory being tried from the include file search path. IMPORTING is "" if we are importing, null otherwise. Return -2 if found, either a matching name or a matching inode. Otherwise, open the file and return a file descriptor if successful or -1 if unsuccessful. Unless unsuccessful, put a descriptor of the included file into *PINC. This function maps filenames on file systems based on information read by read_name_map. */ static int open_include_file (filename, searchptr, importing, pinc) char *filename; struct file_name_list *searchptr; U_CHAR *importing; struct include_file **pinc; { char *fname = remap ? remap_include_file (filename, searchptr) : filename; int fd = -2; /* Look up FNAME in include_hashtab. */ struct include_file **phead = &include_hashtab[hashf ((U_CHAR *) fname, strlen (fname), INCLUDE_HASHSIZE)]; struct include_file *inc, *head = *phead; for (inc = head; inc; inc = inc->next) if (!strcmp (fname, inc->fname)) break; if (!inc || ! inc->control_macro || (inc->control_macro[0] && ! lookup (inc->control_macro, -1, -1))) { fd = open (fname, O_RDONLY, 0); if (fd < 0) return fd; if (!inc) { /* FNAME was not in include_hashtab; insert a new entry. */ inc = (struct include_file *) xmalloc (sizeof (struct include_file)); inc->next = head; inc->fname = fname; inc->control_macro = 0; inc->deps_output = 0; if (fstat (fd, &inc->st) != 0) pfatal_with_name (fname); *phead = inc; /* Look for another file with the same inode and device. */ if (lookup_ino_include (inc) && inc->control_macro && (!inc->control_macro[0] || lookup (inc->control_macro, -1, -1))) { close (fd); fd = -2; } } /* For -M, add this file to the dependencies. */ if (! inc->deps_output && (system_include_depth != 0) < print_deps) { inc->deps_output = 1; deps_output (fname, ' '); } /* Handle -H option. */ if (print_include_names) fprintf (stderr, "%*s%s\n", indepth, "", fname); } if (importing) inc->control_macro = importing; *pinc = inc; return fd; } /* Return the remapped name of the the include file FILENAME. SEARCHPTR is the directory being tried from the include file path. */ static char * remap_include_file (filename, searchptr) char *filename; struct file_name_list *searchptr; { register struct file_name_map *map; register char *from; if (searchptr) { if (! searchptr->got_name_map) { searchptr->name_map = read_name_map (searchptr->fname); searchptr->got_name_map = 1; } /* Check the mapping for the directory we are using. */ from = filename + strlen (searchptr->fname); for (map = searchptr->name_map; map; map = map->map_next) if (! strcmp (map->map_from, from)) return map->map_to; } from = base_name (filename); if (from != filename || !searchptr) { /* Try to find a mapping file for the particular directory we are looking in. Thus #include will look up sys/types.h in /usr/include/header.gcc and look up types.h in /usr/include/sys/header.gcc. */ char *dir = (char *) alloca (from - filename + 1); bcopy (filename, dir, from - filename); dir[from - filename] = '\0'; for (map = read_name_map (dir); map; map = map->map_next) if (! strcmp (map->map_from, from)) return map->map_to; } return filename; } /* Insert INC into the include file table, hashed by device and inode number. If a file with different name but same dev+ino was already in the table, return 1 and set INC's control macro to the already-known macro. */ static int lookup_ino_include (inc) struct include_file *inc; { int hash = ((unsigned) (inc->st.st_dev + INO_T_HASH (inc->st.st_ino)) % INCLUDE_HASHSIZE); struct include_file *i = include_ino_hashtab[hash]; inc->next_ino = i; include_ino_hashtab[hash] = inc; for (; i; i = i->next_ino) if (INO_T_EQ (inc->st.st_ino, i->st.st_ino) && inc->st.st_dev == i->st.st_dev) { inc->control_macro = i->control_macro; return 1; } return 0; } /* Process file descriptor F, which corresponds to include file INC, with output to OP. SYSTEM_HEADER_P is 1 if this file resides in any one of the known "system" include directories (as decided by the `is_system_include' function above). DIRPTR is the link in the dir path through which this file was found, or 0 if the file name was absolute. */ static void finclude (f, inc, op, system_header_p, dirptr) int f; struct include_file *inc; FILE_BUF *op; int system_header_p; struct file_name_list *dirptr; { char *fname = inc->fname; int i; FILE_BUF *fp; /* For input stack frame */ int missing_newline = 0; CHECK_DEPTH (return;); fp = &instack[indepth + 1]; bzero ((char *) fp, sizeof (FILE_BUF)); fp->nominal_fname = fp->fname = fname; fp->inc = inc; fp->length = 0; fp->lineno = 1; fp->if_stack = if_stack; fp->system_header_p = system_header_p; fp->dir = dirptr; if (S_ISREG (inc->st.st_mode)) { size_t s = (size_t) inc->st.st_size; if (s != inc->st.st_size || s + 2 < s) memory_full (); fp->buf = (U_CHAR *) xmalloc (s + 2); fp->bufp = fp->buf; /* Read the file contents, knowing that s is an upper bound on the number of bytes we can read. */ fp->length = safe_read (f, (char *) fp->buf, s); if (fp->length < 0) goto nope; } else if (S_ISDIR (inc->st.st_mode)) { error ("directory `%s' specified in #include", fname); close (f); return; } else { /* Cannot count its file size before reading. First read the entire file into heap and copy them into buffer on stack. */ int bsize = 2000; int st_size = 0; fp->buf = (U_CHAR *) xmalloc (bsize + 2); for (;;) { i = safe_read (f, (char *) fp->buf + st_size, bsize - st_size); if (i < 0) goto nope; /* error! */ st_size += i; if (st_size != bsize) break; /* End of file */ bsize *= 2; fp->buf = (U_CHAR *) xrealloc (fp->buf, bsize + 2); } fp->bufp = fp->buf; fp->length = st_size; } if ((fp->length > 0 && fp->buf[fp->length - 1] != '\n') /* Backslash-newline at end is not good enough. */ || (fp->length > 1 && fp->buf[fp->length - 2] == '\\')) { fp->buf[fp->length++] = '\n'; missing_newline = 1; } fp->buf[fp->length] = '\0'; /* Close descriptor now, so nesting does not use lots of descriptors. */ close (f); /* Must do this before calling trigraph_pcp, so that the correct file name will be printed in warning messages. */ indepth++; input_file_stack_tick++; if (!no_trigraphs) trigraph_pcp (fp); output_line_directive (fp, op, 0, enter_file); rescan (op, 0); if (missing_newline) fp->lineno--; if (pedantic && missing_newline) pedwarn ("file does not end in newline"); indepth--; input_file_stack_tick++; output_line_directive (&instack[indepth], op, 0, leave_file); free (fp->buf); return; nope: perror_with_name (fname); close (f); free (fp->buf); } /* Record that inclusion of the include file INC should be controlled by the macro named MACRO_NAME. This means that trying to include the file again will do something if that macro is defined. */ static void record_control_macro (inc, macro_name) struct include_file *inc; U_CHAR *macro_name; { if (!inc->control_macro || inc->control_macro[0]) inc->control_macro = macro_name; } /* Load the specified precompiled header into core, and verify its preconditions. PCF indicates the file descriptor to read, which must be a regular file. *ST is its file status. FNAME indicates the file name of the original header. *LIMIT will be set to an address one past the end of the file. If the preconditions of the file are not satisfied, the buffer is freed and we return 0. If the preconditions are satisfied, return the address of the buffer following the preconditions. The buffer, in this case, should never be freed because various pieces of it will be referred to until all precompiled strings are output at the end of the run. */ static char * check_precompiled (pcf, st, fname, limit) int pcf; struct stat *st; char *fname; char **limit; { int length = 0; char *buf; char *cp; if (pcp_outfile) return 0; if (S_ISREG (st->st_mode)) { size_t s = (size_t) st->st_size; if (s != st->st_size || s + 2 < s) memory_full (); buf = xmalloc (s + 2); length = safe_read (pcf, buf, s); if (length < 0) goto nope; } else abort (); if (length > 0 && buf[length-1] != '\n') buf[length++] = '\n'; buf[length] = '\0'; *limit = buf + length; /* File is in core. Check the preconditions. */ if (!check_preconditions (buf)) goto nope; for (cp = buf; *cp; cp++) ; #ifdef DEBUG_PCP fprintf (stderr, "Using preinclude %s\n", fname); #endif return cp + 1; nope: #ifdef DEBUG_PCP fprintf (stderr, "Cannot use preinclude %s\n", fname); #endif free (buf); return 0; } /* PREC (null terminated) points to the preconditions of a precompiled header. These are a series of #define and #undef lines which must match the current contents of the hash table. */ static int check_preconditions (prec) char *prec; { MACRODEF mdef; char *lineend; while (*prec) { lineend = (char*) index (prec, '\n'); if (*prec++ != '#') { error ("Bad format encountered while reading precompiled file"); return 0; } if (!strncmp (prec, "define", 6)) { HASHNODE *hp; prec += 6; mdef = create_definition ((U_CHAR *) prec, (U_CHAR *) lineend, NULL_PTR); if (mdef.defn == 0) abort (); if ((hp = lookup (mdef.symnam, mdef.symlen, -1)) == NULL || (hp->type != T_MACRO && hp->type != T_CONST) || (hp->type == T_MACRO && !compare_defs (mdef.defn, hp->value.defn) && (mdef.defn->length != 2 || mdef.defn->expansion[0] != '\n' || mdef.defn->expansion[1] != ' '))) return 0; } else if (!strncmp (prec, "undef", 5)) { char *name; int len; prec += 5; while (is_hor_space[(U_CHAR) *prec]) prec++; name = prec; while (is_idchar[(U_CHAR) *prec]) prec++; len = prec - name; if (lookup ((U_CHAR *) name, len, -1)) return 0; } else { error ("Bad format encountered while reading precompiled file"); return 0; } prec = lineend + 1; } /* They all passed successfully */ return 1; } /* Process the main body of a precompiled file. BUF points to the string section of the file, following the preconditions. LIMIT is one character past the end. NAME is the name of the file being read in. OP is the main output buffer. */ static void pcfinclude (buf, limit, name, op) U_CHAR *buf, *limit, *name; FILE_BUF *op; { FILE_BUF tmpbuf; int nstrings; U_CHAR *cp = buf; /* First in the file comes 4 bytes indicating the number of strings, */ /* in network byte order. (MSB first). */ nstrings = *cp++; nstrings = (nstrings << 8) | *cp++; nstrings = (nstrings << 8) | *cp++; nstrings = (nstrings << 8) | *cp++; /* Looping over each string... */ while (nstrings--) { U_CHAR *string_start; U_CHAR *endofthiskey; STRINGDEF *str; int nkeys; /* Each string starts with a STRINGDEF structure (str), followed */ /* by the text of the string (string_start) */ /* First skip to a longword boundary */ /* ??? Why a 4-byte boundary? On all machines? */ /* NOTE: This works correctly even if size_t is narrower than a pointer. Do not try risky measures here to get another type to use! Do not include stddef.h--it will fail! */ if ((size_t) cp & 3) cp += 4 - ((size_t) cp & 3); /* Now get the string. */ str = (STRINGDEF *) (GENERIC_PTR) cp; string_start = cp += sizeof (STRINGDEF); for (; *cp; cp++) /* skip the string */ ; /* We need to macro expand the string here to ensure that the proper definition environment is in place. If it were only expanded when we find out it is needed, macros necessary for its proper expansion might have had their definitions changed. */ tmpbuf = expand_to_temp_buffer (string_start, cp++, 0, 0); /* Lineno is already set in the precompiled file */ str->contents = tmpbuf.buf; str->len = tmpbuf.length; str->writeflag = 0; str->filename = name; str->output_mark = outbuf.bufp - outbuf.buf; str->chain = 0; *stringlist_tailp = str; stringlist_tailp = &str->chain; /* Next comes a fourbyte number indicating the number of keys for this string. */ nkeys = *cp++; nkeys = (nkeys << 8) | *cp++; nkeys = (nkeys << 8) | *cp++; nkeys = (nkeys << 8) | *cp++; /* If this number is -1, then the string is mandatory. */ if (nkeys == -1) str->writeflag = 1; else /* Otherwise, for each key, */ for (; nkeys--; free (tmpbuf.buf), cp = endofthiskey + 1) { KEYDEF *kp = (KEYDEF *) (GENERIC_PTR) cp; HASHNODE *hp; /* It starts with a KEYDEF structure */ cp += sizeof (KEYDEF); /* Find the end of the key. At the end of this for loop we advance CP to the start of the next key using this variable. */ endofthiskey = cp + strlen ((char *) cp); kp->str = str; /* Expand the key, and enter it into the hash table. */ tmpbuf = expand_to_temp_buffer (cp, endofthiskey, 0, 0); tmpbuf.bufp = tmpbuf.buf; while (is_hor_space[*tmpbuf.bufp]) tmpbuf.bufp++; if (!is_idstart[*tmpbuf.bufp] || tmpbuf.bufp == tmpbuf.buf + tmpbuf.length) { str->writeflag = 1; continue; } hp = lookup (tmpbuf.bufp, -1, -1); if (hp == NULL) { kp->chain = 0; install (tmpbuf.bufp, -1, T_PCSTRING, (char *) kp, -1); } else if (hp->type == T_PCSTRING) { kp->chain = hp->value.keydef; hp->value.keydef = kp; } else str->writeflag = 1; } } /* This output_line_directive serves to switch us back to the current input file in case some of these strings get output (which will result in line directives for the header file being output). */ output_line_directive (&instack[indepth], op, 0, enter_file); } /* Called from rescan when it hits a key for strings. Mark them all used and clean up. */ static void pcstring_used (hp) HASHNODE *hp; { KEYDEF *kp; for (kp = hp->value.keydef; kp; kp = kp->chain) kp->str->writeflag = 1; delete_macro (hp); } /* Write the output, interspersing precompiled strings in their appropriate places. */ static void write_output () { STRINGDEF *next_string; U_CHAR *cur_buf_loc; int line_directive_len = 80; char *line_directive = xmalloc (line_directive_len); int len; /* In each run through the loop, either cur_buf_loc == next_string_loc, in which case we print a series of strings, or it is less than next_string_loc, in which case we write some of the buffer. */ cur_buf_loc = outbuf.buf; next_string = stringlist; while (cur_buf_loc < outbuf.bufp || next_string) { if (next_string && cur_buf_loc - outbuf.buf == next_string->output_mark) { if (next_string->writeflag) { len = 4 * strlen ((char *) next_string->filename) + 32; while (len > line_directive_len) line_directive = xrealloc (line_directive, line_directive_len *= 2); sprintf (line_directive, "\n# %d ", next_string->lineno); strcpy (quote_string (line_directive + strlen (line_directive), (char *) next_string->filename), "\n"); safe_write (fileno (stdout), line_directive, strlen (line_directive)); safe_write (fileno (stdout), (char *) next_string->contents, next_string->len); } next_string = next_string->chain; } else { len = (next_string ? (next_string->output_mark - (cur_buf_loc - outbuf.buf)) : outbuf.bufp - cur_buf_loc); safe_write (fileno (stdout), (char *) cur_buf_loc, len); cur_buf_loc += len; } } free (line_directive); } /* Pass a directive through to the output file. BUF points to the contents of the directive, as a contiguous string. LIMIT points to the first character past the end of the directive. KEYWORD is the keyword-table entry for the directive. */ static void pass_thru_directive (buf, limit, op, keyword) U_CHAR *buf, *limit; FILE_BUF *op; struct directive *keyword; { register unsigned keyword_length = keyword->length; check_expand (op, 1 + keyword_length + (limit - buf)); *op->bufp++ = '#'; bcopy (keyword->name, (char *) op->bufp, keyword_length); op->bufp += keyword_length; if (limit != buf && buf[0] != ' ') *op->bufp++ = ' '; bcopy ((char *) buf, (char *) op->bufp, limit - buf); op->bufp += (limit - buf); #if 0 *op->bufp++ = '\n'; /* Count the line we have just made in the output, to get in sync properly. */ op->lineno++; #endif } /* The arglist structure is built by do_define to tell collect_definition where the argument names begin. That is, for a define like "#define f(x,y,z) foo+x-bar*y", the arglist would contain pointers to the strings x, y, and z. Collect_definition would then build a DEFINITION node, with reflist nodes pointing to the places x, y, and z had appeared. So the arglist is just convenience data passed between these two routines. It is not kept around after the current #define has been processed and entered into the hash table. */ struct arglist { struct arglist *next; U_CHAR *name; int length; int argno; char rest_args; }; /* Create a DEFINITION node from a #define directive. Arguments are as for do_define. */ static MACRODEF create_definition (buf, limit, op) U_CHAR *buf, *limit; FILE_BUF *op; { U_CHAR *bp; /* temp ptr into input buffer */ U_CHAR *symname; /* remember where symbol name starts */ int sym_length; /* and how long it is */ int line = instack[indepth].lineno; char *file = instack[indepth].nominal_fname; int rest_args = 0; DEFINITION *defn; int arglengths = 0; /* Accumulate lengths of arg names plus number of args. */ MACRODEF mdef; bp = buf; while (is_hor_space[*bp]) bp++; symname = bp; /* remember where it starts */ sym_length = check_macro_name (bp, "macro"); bp += sym_length; /* Lossage will occur if identifiers or control keywords are broken across lines using backslash. This is not the right place to take care of that. */ if (*bp == '(') { struct arglist *arg_ptrs = NULL; int argno = 0; bp++; /* skip '(' */ SKIP_WHITE_SPACE (bp); /* Loop over macro argument names. */ while (*bp != ')') { struct arglist *temp; temp = (struct arglist *) alloca (sizeof (struct arglist)); temp->name = bp; temp->next = arg_ptrs; temp->argno = argno++; temp->rest_args = 0; arg_ptrs = temp; if (rest_args) pedwarn ("another parameter follows `%s'", rest_extension); if (!is_idstart[*bp]) pedwarn ("invalid character in macro parameter name"); /* Find the end of the arg name. */ while (is_idchar[*bp]) { bp++; /* do we have a "special" rest-args extension here? */ if (limit - bp > REST_EXTENSION_LENGTH && bcmp (rest_extension, bp, REST_EXTENSION_LENGTH) == 0) { rest_args = 1; temp->rest_args = 1; break; } } temp->length = bp - temp->name; if (rest_args == 1) bp += REST_EXTENSION_LENGTH; arglengths += temp->length + 2; SKIP_WHITE_SPACE (bp); if (temp->length == 0 || (*bp != ',' && *bp != ')')) { error ("badly punctuated parameter list in `#define'"); goto nope; } if (*bp == ',') { bp++; SKIP_WHITE_SPACE (bp); /* A comma at this point can only be followed by an identifier. */ if (!is_idstart[*bp]) { error ("badly punctuated parameter list in `#define'"); goto nope; } } if (bp >= limit) { error ("unterminated parameter list in `#define'"); goto nope; } { struct arglist *otemp; for (otemp = temp->next; otemp != NULL; otemp = otemp->next) if (temp->length == otemp->length && bcmp (temp->name, otemp->name, temp->length) == 0) { error ("duplicate argument name `%.*s' in `#define'", temp->length, temp->name); goto nope; } } } ++bp; /* skip paren */ SKIP_WHITE_SPACE (bp); /* now everything from bp before limit is the definition. */ defn = collect_expansion (bp, limit, argno, arg_ptrs); defn->rest_args = rest_args; /* Now set defn->args.argnames to the result of concatenating the argument names in reverse order with comma-space between them. */ defn->args.argnames = (U_CHAR *) xmalloc (arglengths + 1); { struct arglist *temp; int i = 0; for (temp = arg_ptrs; temp; temp = temp->next) { bcopy (temp->name, &defn->args.argnames[i], temp->length); i += temp->length; if (temp->next != 0) { defn->args.argnames[i++] = ','; defn->args.argnames[i++] = ' '; } } defn->args.argnames[i] = 0; } } else { /* Simple expansion or empty definition. */ if (bp < limit) { if (is_hor_space[*bp]) { bp++; SKIP_WHITE_SPACE (bp); } else if (sym_length) { switch (*bp) { case '!': case '"': case '#': case '%': case '&': case '\'': case ')': case '*': case '+': case ',': case '-': case '.': case '/': case ':': case ';': case '<': case '=': case '>': case '?': case '[': case '\\': case ']': case '^': case '{': case '|': case '}': case '~': warning ("missing white space after `#define %.*s'", sym_length, symname); break; default: pedwarn ("missing white space after `#define %.*s'", sym_length, symname); break; } } } /* Now everything from bp before limit is the definition. */ defn = collect_expansion (bp, limit, -1, NULL_PTR); defn->args.argnames = (U_CHAR *) ""; } defn->line = line; defn->file = file; /* OP is null if this is a predefinition */ defn->predefined = !op; mdef.defn = defn; mdef.symnam = symname; mdef.symlen = sym_length; return mdef; nope: mdef.defn = 0; return mdef; } /* Process a #define directive. BUF points to the contents of the #define directive, as a contiguous string. LIMIT points to the first character past the end of the definition. KEYWORD is the keyword-table entry for #define. */ static int do_define (buf, limit, op, keyword) U_CHAR *buf, *limit; FILE_BUF *op; struct directive *keyword; { int hashcode; MACRODEF mdef; /* If this is a precompiler run (with -pcp) pass thru #define directives. */ if (pcp_outfile && op) pass_thru_directive (buf, limit, op, keyword); mdef = create_definition (buf, limit, op); if (mdef.defn == 0) goto nope; hashcode = hashf (mdef.symnam, mdef.symlen, HASHSIZE); { HASHNODE *hp; if ((hp = lookup (mdef.symnam, mdef.symlen, hashcode)) != NULL) { int ok = 0; /* Redefining a precompiled key is ok. */ if (hp->type == T_PCSTRING) ok = 1; /* Redefining a macro is ok if the definitions are the same. */ else if (hp->type == T_MACRO) ok = ! compare_defs (mdef.defn, hp->value.defn); /* Redefining a constant is ok with -D. */ else if (hp->type == T_CONST) ok = ! done_initializing; /* Print the warning if it's not ok. */ if (!ok) { /* If we are passing through #define and #undef directives, do that for this re-definition now. */ if (debug_output && op) pass_thru_directive (buf, limit, op, keyword); pedwarn ("`%.*s' redefined", mdef.symlen, mdef.symnam); if (hp->type == T_MACRO) pedwarn_with_file_and_line (hp->value.defn->file, hp->value.defn->line, "this is the location of the previous definition"); } /* Replace the old definition. */ hp->type = T_MACRO; hp->value.defn = mdef.defn; } else { /* If we are passing through #define and #undef directives, do that for this new definition now. */ if (debug_output && op) pass_thru_directive (buf, limit, op, keyword); install (mdef.symnam, mdef.symlen, T_MACRO, (char *) mdef.defn, hashcode); } } return 0; nope: return 1; } /* Check a purported macro name SYMNAME, and yield its length. USAGE is the kind of name this is intended for. */ static int check_macro_name (symname, usage) U_CHAR *symname; char *usage; { U_CHAR *p; int sym_length; for (p = symname; is_idchar[*p]; p++) ; sym_length = p - symname; if (sym_length == 0 || (sym_length == 1 && *symname == 'L' && (*p == '\'' || *p == '"'))) error ("invalid %s name", usage); else if (!is_idstart[*symname] || (sym_length == 7 && ! bcmp (symname, "defined", 7))) error ("invalid %s name `%.*s'", usage, sym_length, symname); return sym_length; } /* Return zero if two DEFINITIONs are isomorphic. */ static int compare_defs (d1, d2) DEFINITION *d1, *d2; { register struct reflist *a1, *a2; register U_CHAR *p1 = d1->expansion; register U_CHAR *p2 = d2->expansion; int first = 1; if (d1->nargs != d2->nargs) return 1; if (pedantic && strcmp ((char *)d1->args.argnames, (char *)d2->args.argnames)) return 1; for (a1 = d1->pattern, a2 = d2->pattern; a1 && a2; a1 = a1->next, a2 = a2->next) { if (!((a1->nchars == a2->nchars && ! bcmp (p1, p2, a1->nchars)) || ! comp_def_part (first, p1, a1->nchars, p2, a2->nchars, 0)) || a1->argno != a2->argno || a1->stringify != a2->stringify || a1->raw_before != a2->raw_before || a1->raw_after != a2->raw_after) return 1; first = 0; p1 += a1->nchars; p2 += a2->nchars; } if (a1 != a2) return 1; if (comp_def_part (first, p1, d1->length - (p1 - d1->expansion), p2, d2->length - (p2 - d2->expansion), 1)) return 1; return 0; } /* Return 1 if two parts of two macro definitions are effectively different. One of the parts starts at BEG1 and has LEN1 chars; the other has LEN2 chars at BEG2. Any sequence of whitespace matches any other sequence of whitespace. FIRST means these parts are the first of a macro definition; so ignore leading whitespace entirely. LAST means these parts are the last of a macro definition; so ignore trailing whitespace entirely. */ static int comp_def_part (first, beg1, len1, beg2, len2, last) int first; U_CHAR *beg1, *beg2; int len1, len2; int last; { register U_CHAR *end1 = beg1 + len1; register U_CHAR *end2 = beg2 + len2; if (first) { while (beg1 != end1 && is_space[*beg1]) beg1++; while (beg2 != end2 && is_space[*beg2]) beg2++; } if (last) { while (beg1 != end1 && is_space[end1[-1]]) end1--; while (beg2 != end2 && is_space[end2[-1]]) end2--; } while (beg1 != end1 && beg2 != end2) { if (is_space[*beg1] && is_space[*beg2]) { while (beg1 != end1 && is_space[*beg1]) beg1++; while (beg2 != end2 && is_space[*beg2]) beg2++; } else if (*beg1 == *beg2) { beg1++; beg2++; } else break; } return (beg1 != end1) || (beg2 != end2); } /* Read a replacement list for a macro with parameters. Build the DEFINITION structure. Reads characters of text starting at BUF until END. ARGLIST specifies the formal parameters to look for in the text of the definition; NARGS is the number of args in that list, or -1 for a macro name that wants no argument list. MACRONAME is the macro name itself (so we can avoid recursive expansion) and NAMELEN is its length in characters. Note that comments, backslash-newlines, and leading white space have already been deleted from the argument. */ /* If there is no trailing whitespace, a Newline Space is added at the end to prevent concatenation that would be contrary to the standard. */ static DEFINITION * collect_expansion (buf, end, nargs, arglist) U_CHAR *buf, *end; int nargs; struct arglist *arglist; { DEFINITION *defn; register U_CHAR *p, *limit, *lastp, *exp_p; struct reflist *endpat = NULL; /* Pointer to first nonspace after last ## seen. */ U_CHAR *concat = 0; /* Pointer to first nonspace after last single-# seen. */ U_CHAR *stringify = 0; /* How those tokens were spelled. */ enum sharp_token_type concat_sharp_token_type = NO_SHARP_TOKEN; enum sharp_token_type stringify_sharp_token_type = NO_SHARP_TOKEN; int maxsize; int expected_delimiter = '\0'; /* Scan thru the replacement list, ignoring comments and quoted strings, picking up on the macro calls. It does a linear search thru the arg list on every potential symbol. Profiling might say that something smarter should happen. */ if (end < buf) abort (); /* Find the beginning of the trailing whitespace. */ limit = end; p = buf; while (p < limit && is_space[limit[-1]]) limit--; /* Allocate space for the text in the macro definition. Each input char may or may not need 1 byte, so this is an upper bound. The extra 3 are for invented trailing newline-marker and final null. */ maxsize = (sizeof (DEFINITION) + (limit - p) + 3); defn = (DEFINITION *) xcalloc (1, maxsize); defn->nargs = nargs; exp_p = defn->expansion = (U_CHAR *) defn + sizeof (DEFINITION); lastp = exp_p; if (p[0] == '#' ? p[1] == '#' : p[0] == '%' && p[1] == ':' && p[2] == '%' && p[3] == ':') { error ("`##' at start of macro definition"); p += p[0] == '#' ? 2 : 4; } /* Process the main body of the definition. */ while (p < limit) { int skipped_arg = 0; register U_CHAR c = *p++; *exp_p++ = c; if (!traditional) { switch (c) { case '\'': case '\"': if (expected_delimiter != '\0') { if (c == expected_delimiter) expected_delimiter = '\0'; } else expected_delimiter = c; break; case '\\': if (p < limit && expected_delimiter) { /* In a string, backslash goes through and makes next char ordinary. */ *exp_p++ = *p++; } break; case '%': if (!expected_delimiter && *p == ':') { /* %: is not a digraph if preceded by an odd number of '<'s. */ U_CHAR *p0 = p - 1; while (buf < p0 && p0[-1] == '<') p0--; if ((p - p0) & 1) { /* Treat %:%: as ## and %: as #. */ if (p[1] == '%' && p[2] == ':') { p += 2; goto sharp_sharp_token; } if (nargs >= 0) { p++; goto sharp_token; } } } break; case '#': /* # is ordinary inside a string. */ if (expected_delimiter) break; if (*p == '#') { sharp_sharp_token: /* ##: concatenate preceding and following tokens. */ /* Take out the first #, discard preceding whitespace. */ exp_p--; while (exp_p > lastp && is_hor_space[exp_p[-1]]) --exp_p; /* Skip the second #. */ p++; concat_sharp_token_type = c; if (is_hor_space[*p]) { concat_sharp_token_type = c + 1; p++; SKIP_WHITE_SPACE (p); } concat = p; if (p == limit) error ("`##' at end of macro definition"); } else if (nargs >= 0) { /* Single #: stringify following argument ref. Don't leave the # in the expansion. */ sharp_token: exp_p--; stringify_sharp_token_type = c; if (is_hor_space[*p]) { stringify_sharp_token_type = c + 1; p++; SKIP_WHITE_SPACE (p); } if (! is_idstart[*p] || nargs == 0 || (*p == 'L' && (p[1] == '\'' || p[1] == '"'))) error ("`#' operator is not followed by a macro argument name"); else stringify = p; } break; } } else { /* In -traditional mode, recognize arguments inside strings and and character constants, and ignore special properties of #. Arguments inside strings are considered "stringified", but no extra quote marks are supplied. */ switch (c) { case '\'': case '\"': if (expected_delimiter != '\0') { if (c == expected_delimiter) expected_delimiter = '\0'; } else expected_delimiter = c; break; case '\\': /* Backslash quotes delimiters and itself, but not macro args. */ if (expected_delimiter != 0 && p < limit && (*p == expected_delimiter || *p == '\\')) { *exp_p++ = *p++; continue; } break; case '/': if (expected_delimiter != '\0') /* No comments inside strings. */ break; if (*p == '*') { /* If we find a comment that wasn't removed by handle_directive, this must be -traditional. So replace the comment with nothing at all. */ exp_p--; while (++p < limit) { if (p[0] == '*' && p[1] == '/') { p += 2; break; } } #if 0 /* Mark this as a concatenation-point, as if it had been ##. */ concat = p; #endif } break; } } /* Handle the start of a symbol. */ if (is_idchar[c] && nargs > 0) { U_CHAR *id_beg = p - 1; int id_len; --exp_p; while (p != limit && is_idchar[*p]) p++; id_len = p - id_beg; if (is_idstart[c] && ! (id_len == 1 && c == 'L' && (*p == '\'' || *p == '"'))) { register struct arglist *arg; for (arg = arglist; arg != NULL; arg = arg->next) { struct reflist *tpat; if (arg->name[0] == c && arg->length == id_len && bcmp (arg->name, id_beg, id_len) == 0) { enum sharp_token_type tpat_stringify; if (expected_delimiter) { if (warn_stringify) { if (traditional) { warning ("macro argument `%.*s' is stringified.", id_len, arg->name); } else { warning ("macro arg `%.*s' would be stringified with -traditional.", id_len, arg->name); } } /* If ANSI, don't actually substitute inside a string. */ if (!traditional) break; tpat_stringify = SHARP_TOKEN; } else { tpat_stringify = (stringify == id_beg ? stringify_sharp_token_type : NO_SHARP_TOKEN); } /* make a pat node for this arg and append it to the end of the pat list */ tpat = (struct reflist *) xmalloc (sizeof (struct reflist)); tpat->next = NULL; tpat->raw_before = concat == id_beg ? concat_sharp_token_type : NO_SHARP_TOKEN; tpat->raw_after = NO_SHARP_TOKEN; tpat->rest_args = arg->rest_args; tpat->stringify = tpat_stringify; if (endpat == NULL) defn->pattern = tpat; else endpat->next = tpat; endpat = tpat; tpat->argno = arg->argno; tpat->nchars = exp_p - lastp; { register U_CHAR *p1 = p; SKIP_WHITE_SPACE (p1); if (p1[0]=='#' ? p1[1]=='#' : p1[0]=='%' && p1[1]==':' && p1[2]=='%' && p1[3]==':') tpat->raw_after = p1[0] + (p != p1); } lastp = exp_p; /* place to start copying from next time */ skipped_arg = 1; break; } } } /* If this was not a macro arg, copy it into the expansion. */ if (! skipped_arg) { register U_CHAR *lim1 = p; p = id_beg; while (p != lim1) *exp_p++ = *p++; if (stringify == id_beg) error ("`#' operator should be followed by a macro argument name"); } } } if (!traditional && expected_delimiter == 0) { /* If ANSI, put in a newline-space marker to prevent token pasting. But not if "inside a string" (which in ANSI mode happens only for -D option). */ *exp_p++ = '\n'; *exp_p++ = ' '; } *exp_p = '\0'; defn->length = exp_p - defn->expansion; /* Crash now if we overrun the allocated size. */ if (defn->length + 1 > maxsize) abort (); #if 0 /* This isn't worth the time it takes. */ /* give back excess storage */ defn->expansion = (U_CHAR *) xrealloc (defn->expansion, defn->length + 1); #endif return defn; } static int do_assert (buf, limit, op, keyword) U_CHAR *buf, *limit; FILE_BUF *op; struct directive *keyword; { U_CHAR *bp; /* temp ptr into input buffer */ U_CHAR *symname; /* remember where symbol name starts */ int sym_length; /* and how long it is */ struct arglist *tokens = NULL; if (pedantic && done_initializing && !instack[indepth].system_header_p) pedwarn ("ANSI C does not allow `#assert'"); bp = buf; while (is_hor_space[*bp]) bp++; symname = bp; /* remember where it starts */ sym_length = check_macro_name (bp, "assertion"); bp += sym_length; /* #define doesn't do this, but we should. */ SKIP_WHITE_SPACE (bp); /* Lossage will occur if identifiers or control tokens are broken across lines using backslash. This is not the right place to take care of that. */ if (*bp != '(') { error ("missing token-sequence in `#assert'"); return 1; } { int error_flag = 0; bp++; /* skip '(' */ SKIP_WHITE_SPACE (bp); tokens = read_token_list (&bp, limit, &error_flag); if (error_flag) return 1; if (tokens == 0) { error ("empty token-sequence in `#assert'"); return 1; } ++bp; /* skip paren */ SKIP_WHITE_SPACE (bp); } /* If this name isn't already an assertion name, make it one. Error if it was already in use in some other way. */ { ASSERTION_HASHNODE *hp; int hashcode = hashf (symname, sym_length, ASSERTION_HASHSIZE); struct tokenlist_list *value = (struct tokenlist_list *) xmalloc (sizeof (struct tokenlist_list)); hp = assertion_lookup (symname, sym_length, hashcode); if (hp == NULL) { if (sym_length == 7 && ! bcmp (symname, "defined", 7)) error ("`defined' redefined as assertion"); hp = assertion_install (symname, sym_length, hashcode); } /* Add the spec'd token-sequence to the list of such. */ value->tokens = tokens; value->next = hp->value; hp->value = value; } return 0; } static int do_unassert (buf, limit, op, keyword) U_CHAR *buf, *limit; FILE_BUF *op; struct directive *keyword; { U_CHAR *bp; /* temp ptr into input buffer */ U_CHAR *symname; /* remember where symbol name starts */ int sym_length; /* and how long it is */ struct arglist *tokens = NULL; int tokens_specified = 0; if (pedantic && done_initializing && !instack[indepth].system_header_p) pedwarn ("ANSI C does not allow `#unassert'"); bp = buf; while (is_hor_space[*bp]) bp++; symname = bp; /* remember where it starts */ sym_length = check_macro_name (bp, "assertion"); bp += sym_length; /* #define doesn't do this, but we should. */ SKIP_WHITE_SPACE (bp); /* Lossage will occur if identifiers or control tokens are broken across lines using backslash. This is not the right place to take care of that. */ if (*bp == '(') { int error_flag = 0; bp++; /* skip '(' */ SKIP_WHITE_SPACE (bp); tokens = read_token_list (&bp, limit, &error_flag); if (error_flag) return 1; if (tokens == 0) { error ("empty token list in `#unassert'"); return 1; } tokens_specified = 1; ++bp; /* skip paren */ SKIP_WHITE_SPACE (bp); } { ASSERTION_HASHNODE *hp; int hashcode = hashf (symname, sym_length, ASSERTION_HASHSIZE); struct tokenlist_list *tail, *prev; hp = assertion_lookup (symname, sym_length, hashcode); if (hp == NULL) return 1; /* If no token list was specified, then eliminate this assertion entirely. */ if (! tokens_specified) { struct tokenlist_list *next; for (tail = hp->value; tail; tail = next) { next = tail->next; free_token_list (tail->tokens); free (tail); } delete_assertion (hp); } else { /* If a list of tokens was given, then delete any matching list. */ tail = hp->value; prev = 0; while (tail) { struct tokenlist_list *next = tail->next; if (compare_token_lists (tail->tokens, tokens)) { if (prev) prev->next = next; else hp->value = tail->next; free_token_list (tail->tokens); free (tail); } else { prev = tail; } tail = next; } } } return 0; } /* Test whether there is an assertion named NAME and optionally whether it has an asserted token list TOKENS. NAME is not null terminated; its length is SYM_LENGTH. If TOKENS_SPECIFIED is 0, then don't check for any token list. */ int check_assertion (name, sym_length, tokens_specified, tokens) U_CHAR *name; int sym_length; int tokens_specified; struct arglist *tokens; { ASSERTION_HASHNODE *hp; int hashcode = hashf (name, sym_length, ASSERTION_HASHSIZE); if (pedantic && !instack[indepth].system_header_p) pedwarn ("ANSI C does not allow testing assertions"); hp = assertion_lookup (name, sym_length, hashcode); if (hp == NULL) /* It is not an assertion; just return false. */ return 0; /* If no token list was specified, then value is 1. */ if (! tokens_specified) return 1; { struct tokenlist_list *tail; tail = hp->value; /* If a list of tokens was given, then succeed if the assertion records a matching list. */ while (tail) { if (compare_token_lists (tail->tokens, tokens)) return 1; tail = tail->next; } /* Fail if the assertion has no matching list. */ return 0; } } /* Compare two lists of tokens for equality including order of tokens. */ static int compare_token_lists (l1, l2) struct arglist *l1, *l2; { while (l1 && l2) { if (l1->length != l2->length) return 0; if (bcmp (l1->name, l2->name, l1->length)) return 0; l1 = l1->next; l2 = l2->next; } /* Succeed if both lists end at the same time. */ return l1 == l2; } /* Read a space-separated list of tokens ending in a close parenthesis. Return a list of strings, in the order they were written. (In case of error, return 0 and store -1 in *ERROR_FLAG.) Parse the text starting at *BPP, and update *BPP. Don't parse beyond LIMIT. */ static struct arglist * read_token_list (bpp, limit, error_flag) U_CHAR **bpp; U_CHAR *limit; int *error_flag; { struct arglist *token_ptrs = 0; U_CHAR *bp = *bpp; int depth = 1; *error_flag = 0; /* Loop over the assertion value tokens. */ while (depth > 0) { struct arglist *temp; int eofp = 0; U_CHAR *beg = bp; /* Find the end of the token. */ if (*bp == '(') { bp++; depth++; } else if (*bp == ')') { depth--; if (depth == 0) break; bp++; } else if (*bp == '"' || *bp == '\'') bp = skip_quoted_string (bp, limit, 0, NULL_PTR, NULL_PTR, &eofp); else while (! is_hor_space[*bp] && *bp != '(' && *bp != ')' && *bp != '"' && *bp != '\'' && bp != limit) bp++; temp = (struct arglist *) xmalloc (sizeof (struct arglist)); temp->name = (U_CHAR *) xmalloc (bp - beg + 1); bcopy ((char *) beg, (char *) temp->name, bp - beg); temp->name[bp - beg] = 0; temp->next = token_ptrs; token_ptrs = temp; temp->length = bp - beg; SKIP_WHITE_SPACE (bp); if (bp >= limit) { error ("unterminated token sequence in `#assert' or `#unassert'"); *error_flag = -1; return 0; } } *bpp = bp; /* We accumulated the names in reverse order. Now reverse them to get the proper order. */ { register struct arglist *prev = 0, *this, *next; for (this = token_ptrs; this; this = next) { next = this->next; this->next = prev; prev = this; } return prev; } } static void free_token_list (tokens) struct arglist *tokens; { while (tokens) { struct arglist *next = tokens->next; free (tokens->name); free (tokens); tokens = next; } } /* Install a name in the assertion hash table. If LEN is >= 0, it is the length of the name. Otherwise, compute the length by scanning the entire name. If HASH is >= 0, it is the precomputed hash code. Otherwise, compute the hash code. */ static ASSERTION_HASHNODE * assertion_install (name, len, hash) U_CHAR *name; int len; int hash; { register ASSERTION_HASHNODE *hp; register int i, bucket; register U_CHAR *p, *q; i = sizeof (ASSERTION_HASHNODE) + len + 1; hp = (ASSERTION_HASHNODE *) xmalloc (i); bucket = hash; hp->bucket_hdr = &assertion_hashtab[bucket]; hp->next = assertion_hashtab[bucket]; assertion_hashtab[bucket] = hp; hp->prev = NULL; if (hp->next != NULL) hp->next->prev = hp; hp->length = len; hp->value = 0; hp->name = ((U_CHAR *) hp) + sizeof (ASSERTION_HASHNODE); p = hp->name; q = name; for (i = 0; i < len; i++) *p++ = *q++; hp->name[len] = 0; return hp; } /* Find the most recent hash node for name name (ending with first non-identifier char) installed by install If LEN is >= 0, it is the length of the name. Otherwise, compute the length by scanning the entire name. If HASH is >= 0, it is the precomputed hash code. Otherwise, compute the hash code. */ static ASSERTION_HASHNODE * assertion_lookup (name, len, hash) U_CHAR *name; int len; int hash; { register ASSERTION_HASHNODE *bucket; bucket = assertion_hashtab[hash]; while (bucket) { if (bucket->length == len && bcmp (bucket->name, name, len) == 0) return bucket; bucket = bucket->next; } return NULL; } static void delete_assertion (hp) ASSERTION_HASHNODE *hp; { if (hp->prev != NULL) hp->prev->next = hp->next; if (hp->next != NULL) hp->next->prev = hp->prev; /* Make sure that the bucket chain header that the deleted guy was on points to the right thing afterwards. */ if (hp == *hp->bucket_hdr) *hp->bucket_hdr = hp->next; free (hp); } /* * interpret #line directive. Remembers previously seen fnames * in its very own hash table. */ #define FNAME_HASHSIZE 37 static int do_line (buf, limit, op, keyword) U_CHAR *buf, *limit; FILE_BUF *op; struct directive *keyword; { register U_CHAR *bp; FILE_BUF *ip = &instack[indepth]; FILE_BUF tem; int new_lineno; enum file_change_code file_change = same_file; /* Expand any macros. */ tem = expand_to_temp_buffer (buf, limit, 0, 0); /* Point to macroexpanded line, which is null-terminated now. */ bp = tem.buf; SKIP_WHITE_SPACE (bp); if (!isdigit (*bp)) { error ("invalid format `#line' directive"); return 0; } /* The Newline at the end of this line remains to be processed. To put the next line at the specified line number, we must store a line number now that is one less. */ new_lineno = atoi ((char *) bp) - 1; /* NEW_LINENO is one less than the actual line number here. */ if (pedantic && new_lineno < 0) pedwarn ("line number out of range in `#line' directive"); /* skip over the line number. */ while (isdigit (*bp)) bp++; #if 0 /* #line 10"foo.c" is supposed to be allowed. */ if (*bp && !is_space[*bp]) { error ("invalid format `#line' directive"); return; } #endif SKIP_WHITE_SPACE (bp); if (*bp == '\"') { static HASHNODE *fname_table[FNAME_HASHSIZE]; HASHNODE *hp, **hash_bucket; U_CHAR *fname, *p; int fname_length; fname = ++bp; /* Turn the file name, which is a character string literal, into a null-terminated string. Do this in place. */ p = bp; for (;;) switch ((*p++ = *bp++)) { case '\0': error ("invalid format `#line' directive"); return 0; case '\\': { char *bpc = (char *) bp; HOST_WIDE_INT c = parse_escape (&bpc, (HOST_WIDE_INT) (U_CHAR) (-1)); bp = (U_CHAR *) bpc; if (c < 0) p--; else p[-1] = c; } break; case '\"': p[-1] = 0; goto fname_done; } fname_done: fname_length = p - fname; SKIP_WHITE_SPACE (bp); if (*bp) { if (pedantic) pedwarn ("garbage at end of `#line' directive"); if (*bp == '1') file_change = enter_file; else if (*bp == '2') file_change = leave_file; else if (*bp == '3') ip->system_header_p = 1; else if (*bp == '4') ip->system_header_p = 2; else { error ("invalid format `#line' directive"); return 0; } bp++; SKIP_WHITE_SPACE (bp); if (*bp == '3') { ip->system_header_p = 1; bp++; SKIP_WHITE_SPACE (bp); } if (*bp == '4') { ip->system_header_p = 2; bp++; SKIP_WHITE_SPACE (bp); } if (*bp) { error ("invalid format `#line' directive"); return 0; } } hash_bucket = &fname_table[hashf (fname, fname_length, FNAME_HASHSIZE)]; for (hp = *hash_bucket; hp != NULL; hp = hp->next) if (hp->length == fname_length && bcmp (hp->value.cpval, fname, fname_length) == 0) { ip->nominal_fname = hp->value.cpval; break; } if (hp == 0) { /* Didn't find it; cons up a new one. */ hp = (HASHNODE *) xcalloc (1, sizeof (HASHNODE) + fname_length + 1); hp->next = *hash_bucket; *hash_bucket = hp; hp->length = fname_length; ip->nominal_fname = hp->value.cpval = ((char *) hp) + sizeof (HASHNODE); bcopy (fname, hp->value.cpval, fname_length); } } else if (*bp) { error ("invalid format `#line' directive"); return 0; } ip->lineno = new_lineno; output_line_directive (ip, op, 0, file_change); check_expand (op, ip->length - (ip->bufp - ip->buf)); return 0; } /* Remove the definition of a symbol from the symbol table. according to un*x /lib/cpp, it is not an error to undef something that has no definitions, so it isn't one here either. */ static int do_undef (buf, limit, op, keyword) U_CHAR *buf, *limit; FILE_BUF *op; struct directive *keyword; { int sym_length; HASHNODE *hp; U_CHAR *orig_buf = buf; /* If this is a precompiler run (with -pcp) pass thru #undef directives. */ if (pcp_outfile && op) pass_thru_directive (buf, limit, op, keyword); SKIP_WHITE_SPACE (buf); sym_length = check_macro_name (buf, "macro"); while ((hp = lookup (buf, sym_length, -1)) != NULL) { /* If we are generating additional info for debugging (with -g) we need to pass through all effective #undef directives. */ if (debug_output && op) pass_thru_directive (orig_buf, limit, op, keyword); if (hp->type != T_MACRO) warning ("undefining `%s'", hp->name); delete_macro (hp); } if (pedantic) { buf += sym_length; SKIP_WHITE_SPACE (buf); if (buf != limit) pedwarn ("garbage after `#undef' directive"); } return 0; } /* Report an error detected by the program we are processing. Use the text of the line in the error message. (We use error because it prints the filename & line#.) */ static int do_error (buf, limit, op, keyword) U_CHAR *buf, *limit; FILE_BUF *op; struct directive *keyword; { int length = limit - buf; U_CHAR *copy = (U_CHAR *) alloca (length + 1); bcopy ((char *) buf, (char *) copy, length); copy[length] = 0; SKIP_WHITE_SPACE (copy); error ("#error %s", copy); return 0; } /* Report a warning detected by the program we are processing. Use the text of the line in the warning message, then continue. (We use error because it prints the filename & line#.) */ static int do_warning (buf, limit, op, keyword) U_CHAR *buf, *limit; FILE_BUF *op; struct directive *keyword; { int length = limit - buf; U_CHAR *copy = (U_CHAR *) alloca (length + 1); bcopy ((char *) buf, (char *) copy, length); copy[length] = 0; SKIP_WHITE_SPACE (copy); /* Use `pedwarn' not `warning', because #warning isn't in the C Standard; if -pedantic-errors is given, #warning should cause an error. */ pedwarn ("#warning %s", copy); return 0; } /* Remember the name of the current file being read from so that we can avoid ever including it again. */ static void do_once () { int i; for (i = indepth; i >= 0; i--) if (instack[i].inc) { record_control_macro (instack[i].inc, (U_CHAR *) ""); break; } } /* Report program identification. */ static int do_ident (buf, limit, op, keyword) U_CHAR *buf, *limit; FILE_BUF *op; struct directive *keyword; { FILE_BUF trybuf; int len; /* Allow #ident in system headers, since that's not user's fault. */ if (pedantic && !instack[indepth].system_header_p) pedwarn ("ANSI C does not allow `#ident'"); trybuf = expand_to_temp_buffer (buf, limit, 0, 0); buf = trybuf.buf; len = trybuf.bufp - buf; /* Output expanded directive. */ check_expand (op, 7 + len); bcopy ("#ident ", (char *) op->bufp, 7); op->bufp += 7; bcopy ((char *) buf, (char *) op->bufp, len); op->bufp += len; free (buf); return 0; } /* #pragma and its argument line have already been copied to the output file. Just check for some recognized pragmas that need validation here. */ static int do_pragma (buf, limit, op, keyword) U_CHAR *buf, *limit; FILE_BUF *op; struct directive *keyword; { SKIP_WHITE_SPACE (buf); if (!strncmp ((char *) buf, "once", 4)) { /* Allow #pragma once in system headers, since that's not the user's fault. */ if (!instack[indepth].system_header_p) warning ("`#pragma once' is obsolete"); do_once (); } if (!strncmp ((char *) buf, "implementation", 14)) { /* Be quiet about `#pragma implementation' for a file only if it hasn't been included yet. */ int h; U_CHAR *p = buf + 14, *fname; SKIP_WHITE_SPACE (p); if (*p != '\"') return 0; fname = p + 1; if ((p = (U_CHAR *) index ((char *) fname, '\"'))) *p = '\0'; for (h = 0; h < INCLUDE_HASHSIZE; h++) { struct include_file *inc; for (inc = include_hashtab[h]; inc; inc = inc->next) { if (!strcmp (base_name (inc->fname), (char *) fname)) { warning ("`#pragma implementation' for \"%s\" appears after its #include",fname); return 0; } } } } return 0; } #if 0 /* This was a fun hack, but #pragma seems to start to be useful. By failing to recognize it, we pass it through unchanged to cc1. */ /* The behavior of the #pragma directive is implementation defined. this implementation defines it as follows. */ static int do_pragma () { close (0); if (open ("/dev/tty", O_RDONLY, 0666) != 0) goto nope; close (1); if (open ("/dev/tty", O_WRONLY, 0666) != 1) goto nope; execl ("/usr/games/hack", "#pragma", 0); execl ("/usr/games/rogue", "#pragma", 0); execl ("/usr/new/emacs", "-f", "hanoi", "9", "-kill", 0); execl ("/usr/local/emacs", "-f", "hanoi", "9", "-kill", 0); nope: fatal ("You are in a maze of twisty compiler features, all different"); } #endif #ifdef SCCS_DIRECTIVE /* Just ignore #sccs, on systems where we define it at all. */ static int do_sccs (buf, limit, op, keyword) U_CHAR *buf, *limit; FILE_BUF *op; struct directive *keyword; { if (pedantic) pedwarn ("ANSI C does not allow `#sccs'"); return 0; } #endif /* defined (SCCS_DIRECTIVE) */ /* Handle #if directive by 1) inserting special `defined' keyword into the hash table that gets turned into 0 or 1 by special_symbol (thus, if the luser has a symbol called `defined' already, it won't work inside the #if directive) 2) rescan the input into a temporary output buffer 3) pass the output buffer to the yacc parser and collect a value 4) clean up the mess left from steps 1 and 2. 5) call conditional_skip to skip til the next #endif (etc.), or not, depending on the value from step 3. */ static int do_if (buf, limit, op, keyword) U_CHAR *buf, *limit; FILE_BUF *op; struct directive *keyword; { HOST_WIDE_INT value; FILE_BUF *ip = &instack[indepth]; value = eval_if_expression (buf, limit - buf); conditional_skip (ip, value == 0, T_IF, NULL_PTR, op); return 0; } /* Handle a #elif directive by not changing if_stack either. see the comment above do_else. */ static int do_elif (buf, limit, op, keyword) U_CHAR *buf, *limit; FILE_BUF *op; struct directive *keyword; { HOST_WIDE_INT value; FILE_BUF *ip = &instack[indepth]; if (if_stack == instack[indepth].if_stack) { error ("`#elif' not within a conditional"); return 0; } else { if (if_stack->type != T_IF && if_stack->type != T_ELIF) { error ("`#elif' after `#else'"); fprintf (stderr, " (matches line %d", if_stack->lineno); if (if_stack->fname != NULL && ip->fname != NULL && strcmp (if_stack->fname, ip->nominal_fname) != 0) fprintf (stderr, ", file %s", if_stack->fname); fprintf (stderr, ")\n"); } if_stack->type = T_ELIF; } if (if_stack->if_succeeded) skip_if_group (ip, 0, op); else { value = eval_if_expression (buf, limit - buf); if (value == 0) skip_if_group (ip, 0, op); else { ++if_stack->if_succeeded; /* continue processing input */ output_line_directive (ip, op, 1, same_file); } } return 0; } /* Evaluate a #if expression in BUF, of length LENGTH, then parse the result as a C expression and return the value as an int. */ static HOST_WIDE_INT eval_if_expression (buf, length) U_CHAR *buf; int length; { FILE_BUF temp_obuf; HASHNODE *save_defined; HOST_WIDE_INT value; save_defined = install ((U_CHAR *) "defined", -1, T_SPEC_DEFINED, NULL_PTR, -1); pcp_inside_if = 1; temp_obuf = expand_to_temp_buffer (buf, buf + length, 0, 1); pcp_inside_if = 0; delete_macro (save_defined); /* clean up special symbol */ temp_obuf.buf[temp_obuf.length] = '\n'; value = parse_c_expression ((char *) temp_obuf.buf, warn_undef && !instack[indepth].system_header_p); free (temp_obuf.buf); return value; } /* routine to handle ifdef/ifndef. Try to look up the symbol, then do or don't skip to the #endif/#else/#elif depending on what directive is actually being processed. */ static int do_xifdef (buf, limit, op, keyword) U_CHAR *buf, *limit; FILE_BUF *op; struct directive *keyword; { int skip; FILE_BUF *ip = &instack[indepth]; U_CHAR *end; int start_of_file = 0; U_CHAR *control_macro = 0; /* Detect a #ifndef at start of file (not counting comments). */ if (ip->fname != 0 && keyword->type == T_IFNDEF) { U_CHAR *p = ip->buf; while (p != directive_start) { U_CHAR c = *p++; if (is_space[c]) ; /* Make no special provision for backslash-newline here; this is slower if backslash-newlines are present, but it's correct, and it's not worth it to tune for the rare backslash-newline. */ else if (c == '/' && (*p == '*' || (cplusplus_comments && *p == '/'))) { /* Skip this comment. */ int junk = 0; U_CHAR *save_bufp = ip->bufp; ip->bufp = p + 1; p = skip_to_end_of_comment (ip, &junk, 1); ip->bufp = save_bufp; } else { goto fail; } } /* If we get here, this conditional is the beginning of the file. */ start_of_file = 1; fail: ; } /* Discard leading and trailing whitespace. */ SKIP_WHITE_SPACE (buf); while (limit != buf && is_hor_space[limit[-1]]) limit--; /* Find the end of the identifier at the beginning. */ for (end = buf; is_idchar[*end]; end++); if (end == buf) { skip = (keyword->type == T_IFDEF); if (! traditional) pedwarn (end == limit ? "`#%s' with no argument" : "`#%s' argument starts with punctuation", keyword->name); } else { HASHNODE *hp; if (! traditional) { if (isdigit (buf[0])) pedwarn ("`#%s' argument starts with a digit", keyword->name); else if (end != limit) pedwarn ("garbage at end of `#%s' argument", keyword->name); } hp = lookup (buf, end-buf, -1); if (pcp_outfile) { /* Output a precondition for this macro. */ if (hp && (hp->type == T_CONST || (hp->type == T_MACRO && hp->value.defn->predefined))) fprintf (pcp_outfile, "#define %s\n", hp->name); else { U_CHAR *cp = buf; fprintf (pcp_outfile, "#undef "); while (is_idchar[*cp]) /* Ick! */ fputc (*cp++, pcp_outfile); putc ('\n', pcp_outfile); } } skip = (hp == NULL) ^ (keyword->type == T_IFNDEF); if (start_of_file && !skip) { control_macro = (U_CHAR *) xmalloc (end - buf + 1); bcopy ((char *) buf, (char *) control_macro, end - buf); control_macro[end - buf] = 0; } } conditional_skip (ip, skip, T_IF, control_macro, op); return 0; } /* Push TYPE on stack; then, if SKIP is nonzero, skip ahead. If this is a #ifndef starting at the beginning of a file, CONTROL_MACRO is the macro name tested by the #ifndef. Otherwise, CONTROL_MACRO is 0. */ static void conditional_skip (ip, skip, type, control_macro, op) FILE_BUF *ip; int skip; enum node_type type; U_CHAR *control_macro; FILE_BUF *op; { IF_STACK_FRAME *temp; temp = (IF_STACK_FRAME *) xcalloc (1, sizeof (IF_STACK_FRAME)); temp->fname = ip->nominal_fname; temp->lineno = ip->lineno; temp->next = if_stack; temp->control_macro = control_macro; if_stack = temp; if_stack->type = type; if (skip != 0) { skip_if_group (ip, 0, op); return; } else { ++if_stack->if_succeeded; output_line_directive (ip, &outbuf, 1, same_file); } } /* Skip to #endif, #else, or #elif. adjust line numbers, etc. Leaves input ptr at the sharp sign found. If ANY is nonzero, return at next directive of any sort. */ static void skip_if_group (ip, any, op) FILE_BUF *ip; int any; FILE_BUF *op; { register U_CHAR *bp = ip->bufp, *cp; register U_CHAR *endb = ip->buf + ip->length; struct directive *kt; IF_STACK_FRAME *save_if_stack = if_stack; /* don't pop past here */ U_CHAR *beg_of_line = bp; register int ident_length; U_CHAR *ident, *after_ident; /* Save info about where the group starts. */ U_CHAR *beg_of_group = bp; int beg_lineno = ip->lineno; int skipping_include_directive = 0; if (output_conditionals && op != 0) { char *ptr = "#failed\n"; int len = strlen (ptr); if (op->bufp > op->buf && op->bufp[-1] != '\n') { *op->bufp++ = '\n'; op->lineno++; } check_expand (op, len); bcopy (ptr, (char *) op->bufp, len); op->bufp += len; op->lineno++; output_line_directive (ip, op, 1, 0); } while (bp < endb) { switch (*bp++) { case '/': /* possible comment */ if (*bp == '\\' && bp[1] == '\n') newline_fix (bp); if (*bp == '*' || (cplusplus_comments && *bp == '/')) { ip->bufp = ++bp; bp = skip_to_end_of_comment (ip, &ip->lineno, 0); } break; case '<': if (skipping_include_directive) { while (bp < endb && *bp != '>' && *bp != '\n') { if (*bp == '\\' && bp[1] == '\n') { ip->lineno++; bp++; } bp++; } } break; case '\"': if (skipping_include_directive) { while (bp < endb && *bp != '\n') { if (*bp == '"') { bp++; break; } if (*bp == '\\' && bp[1] == '\n') { ip->lineno++; bp++; } bp++; } break; } /* Fall through. */ case '\'': bp = skip_quoted_string (bp - 1, endb, ip->lineno, &ip->lineno, NULL_PTR, NULL_PTR); break; case '\\': /* Char after backslash loses its special meaning in some cases. */ if (*bp == '\n') { ++ip->lineno; bp++; } else if (traditional && bp < endb) bp++; break; case '\n': ++ip->lineno; beg_of_line = bp; skipping_include_directive = 0; break; case '%': if (beg_of_line == 0 || traditional) break; ip->bufp = bp - 1; while (bp[0] == '\\' && bp[1] == '\n') bp += 2; if (*bp == ':') goto sharp_token; break; case '#': /* # keyword: a # must be first nonblank char on the line */ if (beg_of_line == 0) break; ip->bufp = bp - 1; sharp_token: /* Scan from start of line, skipping whitespace, comments and backslash-newlines, and see if we reach this #. If not, this # is not special. */ bp = beg_of_line; /* If -traditional, require # to be at beginning of line. */ if (!traditional) { while (1) { if (is_hor_space[*bp]) bp++; else if (*bp == '\\' && bp[1] == '\n') bp += 2; else if (*bp == '/' && bp[1] == '*') { bp += 2; while (!(*bp == '*' && bp[1] == '/')) bp++; bp += 2; } /* There is no point in trying to deal with C++ // comments here, because if there is one, then this # must be part of the comment and we would never reach here. */ else break; } } if (bp != ip->bufp) { bp = ip->bufp + 1; /* Reset bp to after the #. */ break; } bp = ip->bufp + 1; /* Point after the '#' */ if (ip->bufp[0] == '%') { /* Skip past the ':' again. */ while (*bp == '\\') { ip->lineno++; bp += 2; } bp++; } /* Skip whitespace and \-newline. */ while (1) { if (is_hor_space[*bp]) bp++; else if (*bp == '\\' && bp[1] == '\n') bp += 2; else if (*bp == '/') { if (bp[1] == '\\' && bp[2] == '\n') newline_fix (bp + 1); if (bp[1] == '*') { for (bp += 2; ; bp++) { if (*bp == '\n') ip->lineno++; else if (*bp == '*') { if (bp[-1] == '/' && warn_comments) warning ("`/*' within comment"); if (bp[1] == '\\' && bp[2] == '\n') newline_fix (bp + 1); if (bp[1] == '/') break; } } bp += 2; } else if (bp[1] == '/' && cplusplus_comments) { for (bp += 2; ; bp++) { if (*bp == '\n') { if (bp[-1] != '\\') break; if (warn_comments) warning ("multiline `//' comment"); ip->lineno++; } } } else break; } else break; } cp = bp; /* Now find end of directive name. If we encounter a backslash-newline, exchange it with any following symbol-constituents so that we end up with a contiguous name. */ while (1) { if (is_idchar[*bp]) bp++; else { if (*bp == '\\' && bp[1] == '\n') name_newline_fix (bp); if (is_idchar[*bp]) bp++; else break; } } ident_length = bp - cp; ident = cp; after_ident = bp; /* A line of just `#' becomes blank. */ if (ident_length == 0 && *after_ident == '\n') { continue; } if (ident_length == 0 || !is_idstart[*ident]) { U_CHAR *p = ident; while (is_idchar[*p]) { if (*p < '0' || *p > '9') break; p++; } /* Handle # followed by a line number. */ if (p != ident && !is_idchar[*p]) { if (pedantic) pedwarn ("`#' followed by integer"); continue; } /* Avoid error for `###' and similar cases unless -pedantic. */ if (p == ident) { while (*p == '#' || is_hor_space[*p]) p++; if (*p == '\n') { if (pedantic && !lang_asm) pedwarn ("invalid preprocessing directive"); continue; } } if (!lang_asm && pedantic) pedwarn ("invalid preprocessing directive name"); continue; } for (kt = directive_table; kt->length >= 0; kt++) { IF_STACK_FRAME *temp; if (ident_length == kt->length && bcmp (cp, kt->name, kt->length) == 0) { /* If we are asked to return on next directive, do so now. */ if (any) goto done; switch (kt->type) { case T_IF: case T_IFDEF: case T_IFNDEF: temp = (IF_STACK_FRAME *) xcalloc (1, sizeof (IF_STACK_FRAME)); temp->next = if_stack; if_stack = temp; temp->lineno = ip->lineno; temp->fname = ip->nominal_fname; temp->type = kt->type; break; case T_ELSE: case T_ENDIF: if (pedantic && if_stack != save_if_stack) validate_else (bp, endb); case T_ELIF: if (if_stack == instack[indepth].if_stack) { error ("`#%s' not within a conditional", kt->name); break; } else if (if_stack == save_if_stack) goto done; /* found what we came for */ if (kt->type != T_ENDIF) { if (if_stack->type == T_ELSE) error ("`#else' or `#elif' after `#else'"); if_stack->type = kt->type; break; } temp = if_stack; if_stack = if_stack->next; free (temp); break; case T_INCLUDE: case T_INCLUDE_NEXT: case T_IMPORT: skipping_include_directive = 1; break; default: break; } break; } } /* Don't let erroneous code go by. */ if (kt->length < 0 && !lang_asm && pedantic) pedwarn ("invalid preprocessing directive name"); } } ip->bufp = bp; /* after this returns, rescan will exit because ip->bufp now points to the end of the buffer. rescan is responsible for the error message also. */ done: if (output_conditionals && op != 0) { char *ptr = "#endfailed\n"; int len = strlen (ptr); if (op->bufp > op->buf && op->bufp[-1] != '\n') { *op->bufp++ = '\n'; op->lineno++; } check_expand (op, beg_of_line - beg_of_group); bcopy ((char *) beg_of_group, (char *) op->bufp, beg_of_line - beg_of_group); op->bufp += beg_of_line - beg_of_group; op->lineno += ip->lineno - beg_lineno; check_expand (op, len); bcopy (ptr, (char *) op->bufp, len); op->bufp += len; op->lineno++; } } /* Handle a #else directive. Do this by just continuing processing without changing if_stack ; this is so that the error message for missing #endif's etc. will point to the original #if. It is possible that something different would be better. */ static int do_else (buf, limit, op, keyword) U_CHAR *buf, *limit; FILE_BUF *op; struct directive *keyword; { FILE_BUF *ip = &instack[indepth]; if (pedantic) { SKIP_WHITE_SPACE (buf); if (buf != limit) pedwarn ("text following `#else' violates ANSI standard"); } if (if_stack == instack[indepth].if_stack) { error ("`#else' not within a conditional"); return 0; } else { /* #ifndef can't have its special treatment for containing the whole file if it has a #else clause. */ if_stack->control_macro = 0; if (if_stack->type != T_IF && if_stack->type != T_ELIF) { error ("`#else' after `#else'"); fprintf (stderr, " (matches line %d", if_stack->lineno); if (strcmp (if_stack->fname, ip->nominal_fname) != 0) fprintf (stderr, ", file %s", if_stack->fname); fprintf (stderr, ")\n"); } if_stack->type = T_ELSE; } if (if_stack->if_succeeded) skip_if_group (ip, 0, op); else { ++if_stack->if_succeeded; /* continue processing input */ output_line_directive (ip, op, 1, same_file); } return 0; } /* Unstack after #endif directive. */ static int do_endif (buf, limit, op, keyword) U_CHAR *buf, *limit; FILE_BUF *op; struct directive *keyword; { if (pedantic) { SKIP_WHITE_SPACE (buf); if (buf != limit) pedwarn ("text following `#endif' violates ANSI standard"); } if (if_stack == instack[indepth].if_stack) error ("unbalanced `#endif'"); else { IF_STACK_FRAME *temp = if_stack; if_stack = if_stack->next; if (temp->control_macro != 0) { /* This #endif matched a #ifndef at the start of the file. See if it is at the end of the file. */ FILE_BUF *ip = &instack[indepth]; U_CHAR *p = ip->bufp; U_CHAR *ep = ip->buf + ip->length; while (p != ep) { U_CHAR c = *p++; if (!is_space[c]) { if (c == '/' && (*p == '*' || (cplusplus_comments && *p == '/'))) { /* Skip this comment. */ int junk = 0; U_CHAR *save_bufp = ip->bufp; ip->bufp = p + 1; p = skip_to_end_of_comment (ip, &junk, 1); ip->bufp = save_bufp; } else goto fail; } } /* If we get here, this #endif ends a #ifndef that contains all of the file (aside from whitespace). Arrange not to include the file again if the macro that was tested is defined. Do not do this for the top-level file in a -include or any file in a -imacros. */ if (indepth != 0 && ! (indepth == 1 && no_record_file) && ! (no_record_file && no_output)) record_control_macro (ip->inc, temp->control_macro); fail: ; } free (temp); output_line_directive (&instack[indepth], op, 1, same_file); } return 0; } /* When an #else or #endif is found while skipping failed conditional, if -pedantic was specified, this is called to warn about text after the directive name. P points to the first char after the directive name. */ static void validate_else (p, limit) register U_CHAR *p; register U_CHAR *limit; { /* Advance P over whitespace and comments. */ while (1) { while (*p == '\\' && p[1] == '\n') p += 2; if (is_hor_space[*p]) p++; else if (*p == '/') { while (p[1] == '\\' && p[2] == '\n') p += 2; if (p[1] == '*') { /* Don't bother warning about unterminated comments since that will happen later. Just be sure to exit. */ for (p += 2; ; p++) { if (p == limit) return; if (*p == '*') { while (p[1] == '\\' && p[2] == '\n') p += 2; if (p[1] == '/') { p += 2; break; } } } } else if (cplusplus_comments && p[1] == '/') return; else break; } else break; } if (*p != '\n') pedwarn ("text following `#else' or `#endif' violates ANSI standard"); } /* Skip a comment, assuming the input ptr immediately follows the initial slash-star. Bump *LINE_COUNTER for each newline. (The canonical line counter is &ip->lineno.) Don't use this routine (or the next one) if bumping the line counter is not sufficient to deal with newlines in the string. If NOWARN is nonzero, don't warn about slash-star inside a comment. This feature is useful when processing a comment that is going to be processed or was processed at another point in the preprocessor, to avoid a duplicate warning. Likewise for unterminated comment errors. */ static U_CHAR * skip_to_end_of_comment (ip, line_counter, nowarn) register FILE_BUF *ip; int *line_counter; /* place to remember newlines, or NULL */ int nowarn; { register U_CHAR *limit = ip->buf + ip->length; register U_CHAR *bp = ip->bufp; FILE_BUF *op = put_out_comments && !line_counter ? &outbuf : (FILE_BUF *) 0; int start_line = line_counter ? *line_counter : 0; /* JF this line_counter stuff is a crock to make sure the comment is only put out once, no matter how many times the comment is skipped. It almost works */ if (op) { *op->bufp++ = '/'; *op->bufp++ = bp[-1]; } if (cplusplus_comments && bp[-1] == '/') { for (; bp < limit; bp++) { if (*bp == '\n') { if (bp[-1] != '\\') break; if (!nowarn && warn_comments) warning ("multiline `//' comment"); if (line_counter) ++*line_counter; if (op) ++op->lineno; } if (op) *op->bufp++ = *bp; } ip->bufp = bp; return bp; } while (bp < limit) { if (op) *op->bufp++ = *bp; switch (*bp++) { case '\n': /* If this is the end of the file, we have an unterminated comment. Don't swallow the newline. We are guaranteed that there will be a trailing newline and various pieces assume it's there. */ if (bp == limit) { --bp; --limit; break; } if (line_counter != NULL) ++*line_counter; if (op) ++op->lineno; break; case '*': if (bp[-2] == '/' && !nowarn && warn_comments) warning ("`/*' within comment"); if (*bp == '\\' && bp[1] == '\n') newline_fix (bp); if (*bp == '/') { if (op) *op->bufp++ = '/'; ip->bufp = ++bp; return bp; } break; } } if (!nowarn) error_with_line (line_for_error (start_line), "unterminated comment"); ip->bufp = bp; return bp; } /* Skip over a quoted string. BP points to the opening quote. Returns a pointer after the closing quote. Don't go past LIMIT. START_LINE is the line number of the starting point (but it need not be valid if the starting point is inside a macro expansion). The input stack state is not changed. If COUNT_NEWLINES is nonzero, it points to an int to increment for each newline passed. If BACKSLASH_NEWLINES_P is nonzero, store 1 thru it if we pass a backslash-newline. If EOFP is nonzero, set *EOFP to 1 if the string is unterminated. */ static U_CHAR * skip_quoted_string (bp, limit, start_line, count_newlines, backslash_newlines_p, eofp) register U_CHAR *bp; register U_CHAR *limit; int start_line; int *count_newlines; int *backslash_newlines_p; int *eofp; { register U_CHAR c, match; match = *bp++; while (1) { if (bp >= limit) { error_with_line (line_for_error (start_line), "unterminated string or character constant"); error_with_line (multiline_string_line, "possible real start of unterminated constant"); multiline_string_line = 0; if (eofp) *eofp = 1; break; } c = *bp++; if (c == '\\') { while (*bp == '\\' && bp[1] == '\n') { if (backslash_newlines_p) *backslash_newlines_p = 1; if (count_newlines) ++*count_newlines; bp += 2; } if (*bp == '\n') { if (backslash_newlines_p) *backslash_newlines_p = 1; if (count_newlines) ++*count_newlines; } bp++; } else if (c == '\n') { if (traditional) { /* Unterminated strings and character constants are 'valid'. */ bp--; /* Don't consume the newline. */ if (eofp) *eofp = 1; break; } if (match == '\'') { error_with_line (line_for_error (start_line), "unterminated string or character constant"); bp--; if (eofp) *eofp = 1; break; } /* If not traditional, then allow newlines inside strings. */ if (count_newlines) ++*count_newlines; if (multiline_string_line == 0) { if (pedantic) pedwarn_with_line (line_for_error (start_line), "string constant runs past end of line"); multiline_string_line = start_line; } } else if (c == match) break; } return bp; } /* Place into DST a quoted string representing the string SRC. Return the address of DST's terminating null. */ static char * quote_string (dst, src) char *dst, *src; { U_CHAR c; *dst++ = '\"'; for (;;) switch ((c = *src++)) { default: if (isprint (c)) *dst++ = c; else { sprintf (dst, "\\%03o", c); dst += 4; } break; case '\"': case '\\': *dst++ = '\\'; *dst++ = c; break; case '\0': *dst++ = '\"'; *dst = '\0'; return dst; } } /* Skip across a group of balanced parens, starting from IP->bufp. IP->bufp is updated. Use this with IP->bufp pointing at an open-paren. This does not handle newlines, because it's used for the arg of #if, where there aren't any newlines. Also, backslash-newline can't appear. */ static U_CHAR * skip_paren_group (ip) register FILE_BUF *ip; { U_CHAR *limit = ip->buf + ip->length; U_CHAR *p = ip->bufp; int depth = 0; int lines_dummy = 0; while (p != limit) { int c = *p++; switch (c) { case '(': depth++; break; case ')': depth--; if (depth == 0) return ip->bufp = p; break; case '/': if (*p == '*') { ip->bufp = p; p = skip_to_end_of_comment (ip, &lines_dummy, 0); p = ip->bufp; } case '"': case '\'': { int eofp = 0; p = skip_quoted_string (p - 1, limit, 0, NULL_PTR, NULL_PTR, &eofp); if (eofp) return ip->bufp = p; } break; } } ip->bufp = p; return p; } /* Write out a #line directive, for instance, after an #include file. If CONDITIONAL is nonzero, we can omit the #line if it would appear to be a no-op, and we can output a few newlines instead if we want to increase the line number by a small amount. FILE_CHANGE says whether we are entering a file, leaving, or neither. */ static void output_line_directive (ip, op, conditional, file_change) FILE_BUF *ip, *op; int conditional; enum file_change_code file_change; { int len; char *line_directive_buf, *line_end; if (no_line_directives || ip->fname == NULL || no_output) { op->lineno = ip->lineno; return; } if (conditional) { if (ip->lineno == op->lineno) return; /* If the inherited line number is a little too small, output some newlines instead of a #line directive. */ if (ip->lineno > op->lineno && ip->lineno < op->lineno + 8) { check_expand (op, 10); while (ip->lineno > op->lineno) { *op->bufp++ = '\n'; op->lineno++; } return; } } /* Output a positive line number if possible. */ while (ip->lineno <= 0 && ip->bufp - ip->buf < ip->length && *ip->bufp == '\n') { ip->lineno++; ip->bufp++; } line_directive_buf = (char *) alloca (4 * strlen (ip->nominal_fname) + 100); sprintf (line_directive_buf, "# %d ", ip->lineno); line_end = quote_string (line_directive_buf + strlen (line_directive_buf), ip->nominal_fname); if (file_change != same_file) { *line_end++ = ' '; *line_end++ = file_change == enter_file ? '1' : '2'; } /* Tell cc1 if following text comes from a system header file. */ if (ip->system_header_p) { *line_end++ = ' '; *line_end++ = '3'; } #ifndef NO_IMPLICIT_EXTERN_C /* Tell cc1plus if following text should be treated as C. */ if (ip->system_header_p == 2 && cplusplus) { *line_end++ = ' '; *line_end++ = '4'; } #endif *line_end++ = '\n'; len = line_end - line_directive_buf; check_expand (op, len + 1); if (op->bufp > op->buf && op->bufp[-1] != '\n') *op->bufp++ = '\n'; bcopy ((char *) line_directive_buf, (char *) op->bufp, len); op->bufp += len; op->lineno = ip->lineno; } /* This structure represents one parsed argument in a macro call. `raw' points to the argument text as written (`raw_length' is its length). `expanded' points to the argument's macro-expansion (its length is `expand_length'). `stringified_length' is the length the argument would have if stringified. `use_count' is the number of times this macro arg is substituted into the macro. If the actual use count exceeds 10, the value stored is 10. `free1' and `free2', if nonzero, point to blocks to be freed when the macro argument data is no longer needed. */ struct argdata { U_CHAR *raw, *expanded; int raw_length, expand_length; int stringified_length; U_CHAR *free1, *free2; char newlines; char use_count; }; /* Expand a macro call. HP points to the symbol that is the macro being called. Put the result of expansion onto the input stack so that subsequent input by our caller will use it. If macro wants arguments, caller has already verified that an argument list follows; arguments come from the input stack. */ static void macroexpand (hp, op) HASHNODE *hp; FILE_BUF *op; { int nargs; DEFINITION *defn = hp->value.defn; register U_CHAR *xbuf; int xbuf_len; int start_line = instack[indepth].lineno; int rest_args, rest_zero; CHECK_DEPTH (return;); /* it might not actually be a macro. */ if (hp->type != T_MACRO) { special_symbol (hp, op); return; } /* This macro is being used inside a #if, which means it must be */ /* recorded as a precondition. */ if (pcp_inside_if && pcp_outfile && defn->predefined) dump_single_macro (hp, pcp_outfile); nargs = defn->nargs; if (nargs >= 0) { register int i; struct argdata *args; char *parse_error = 0; args = (struct argdata *) alloca ((nargs + 1) * sizeof (struct argdata)); for (i = 0; i < nargs; i++) { args[i].raw = (U_CHAR *) ""; args[i].expanded = 0; args[i].raw_length = args[i].expand_length = args[i].stringified_length = 0; args[i].free1 = args[i].free2 = 0; args[i].use_count = 0; } /* Parse all the macro args that are supplied. I counts them. The first NARGS args are stored in ARGS. The rest are discarded. If rest_args is set then we assume macarg absorbed the rest of the args. */ i = 0; rest_args = 0; do { /* Discard the open-parenthesis or comma before the next arg. */ ++instack[indepth].bufp; if (rest_args) continue; if (i < nargs || (nargs == 0 && i == 0)) { /* If we are working on last arg which absorbs rest of args... */ if (i == nargs - 1 && defn->rest_args) rest_args = 1; parse_error = macarg (&args[i], rest_args); } else parse_error = macarg (NULL_PTR, 0); if (parse_error) { error_with_line (line_for_error (start_line), parse_error); break; } i++; } while (*instack[indepth].bufp != ')'); /* If we got one arg but it was just whitespace, call that 0 args. */ if (i == 1) { register U_CHAR *bp = args[0].raw; register U_CHAR *lim = bp + args[0].raw_length; /* cpp.texi says for foo ( ) we provide one argument. However, if foo wants just 0 arguments, treat this as 0. */ if (nargs == 0) while (bp != lim && is_space[*bp]) bp++; if (bp == lim) i = 0; } /* Don't output an error message if we have already output one for a parse error above. */ rest_zero = 0; if (nargs == 0 && i > 0) { if (! parse_error) error ("arguments given to macro `%s'", hp->name); } else if (i < nargs) { /* traditional C allows foo() if foo wants one argument. */ if (nargs == 1 && i == 0 && traditional) ; /* the rest args token is allowed to absorb 0 tokens */ else if (i == nargs - 1 && defn->rest_args) rest_zero = 1; else if (parse_error) ; else if (i == 0) error ("macro `%s' used without args", hp->name); else if (i == 1) error ("macro `%s' used with just one arg", hp->name); else error ("macro `%s' used with only %d args", hp->name, i); } else if (i > nargs) { if (! parse_error) error ("macro `%s' used with too many (%d) args", hp->name, i); } /* Swallow the closeparen. */ ++instack[indepth].bufp; /* If macro wants zero args, we parsed the arglist for checking only. Read directly from the macro definition. */ if (nargs == 0) { xbuf = defn->expansion; xbuf_len = defn->length; } else { register U_CHAR *exp = defn->expansion; register int offset; /* offset in expansion, copied a piece at a time */ register int totlen; /* total amount of exp buffer filled so far */ register struct reflist *ap, *last_ap; /* Macro really takes args. Compute the expansion of this call. */ /* Compute length in characters of the macro's expansion. Also count number of times each arg is used. */ xbuf_len = defn->length; for (ap = defn->pattern; ap != NULL; ap = ap->next) { if (ap->stringify) xbuf_len += args[ap->argno].stringified_length; else if (ap->raw_before != 0 || ap->raw_after != 0 || traditional) /* Add 4 for two newline-space markers to prevent token concatenation. */ xbuf_len += args[ap->argno].raw_length + 4; else { /* We have an ordinary (expanded) occurrence of the arg. So compute its expansion, if we have not already. */ if (args[ap->argno].expanded == 0) { FILE_BUF obuf; obuf = expand_to_temp_buffer (args[ap->argno].raw, args[ap->argno].raw + args[ap->argno].raw_length, 1, 0); args[ap->argno].expanded = obuf.buf; args[ap->argno].expand_length = obuf.length; args[ap->argno].free2 = obuf.buf; } /* Add 4 for two newline-space markers to prevent token concatenation. */ xbuf_len += args[ap->argno].expand_length + 4; } if (args[ap->argno].use_count < 10) args[ap->argno].use_count++; } xbuf = (U_CHAR *) xmalloc (xbuf_len + 1); /* Generate in XBUF the complete expansion with arguments substituted in. TOTLEN is the total size generated so far. OFFSET is the index in the definition of where we are copying from. */ offset = totlen = 0; for (last_ap = NULL, ap = defn->pattern; ap != NULL; last_ap = ap, ap = ap->next) { register struct argdata *arg = &args[ap->argno]; int count_before = totlen; /* Add chars to XBUF. */ for (i = 0; i < ap->nchars; i++, offset++) xbuf[totlen++] = exp[offset]; /* If followed by an empty rest arg with concatenation, delete the last run of nonwhite chars. */ if (rest_zero && totlen > count_before && ((ap->rest_args && ap->raw_before != 0) || (last_ap != NULL && last_ap->rest_args && last_ap->raw_after != 0))) { /* Delete final whitespace. */ while (totlen > count_before && is_space[xbuf[totlen - 1]]) { totlen--; } /* Delete the nonwhites before them. */ while (totlen > count_before && ! is_space[xbuf[totlen - 1]]) { totlen--; } } if (ap->stringify != 0) { int arglen = arg->raw_length; int escaped = 0; int in_string = 0; int c; i = 0; while (i < arglen && (c = arg->raw[i], is_space[c])) i++; while (i < arglen && (c = arg->raw[arglen - 1], is_space[c])) arglen--; if (!traditional) xbuf[totlen++] = '\"'; /* insert beginning quote */ for (; i < arglen; i++) { c = arg->raw[i]; if (! in_string) { /* Special markers Newline Space generate nothing for a stringified argument. */ if (c == '\n' && arg->raw[i+1] != '\n') { i++; continue; } /* Internal sequences of whitespace are replaced by one space except within an string or char token. */ if (c == '\n' ? arg->raw[i+1] == '\n' : is_space[c]) { while (1) { /* Note that Newline Space does occur within whitespace sequences; consider it part of the sequence. */ if (c == '\n' && is_space[arg->raw[i+1]]) i += 2; else if (c != '\n' && is_space[c]) i++; else break; c = arg->raw[i]; } i--; c = ' '; } } if (escaped) escaped = 0; else { if (c == '\\') escaped = 1; if (in_string) { if (c == in_string) in_string = 0; } else if (c == '\"' || c == '\'') in_string = c; } /* Escape these chars */ if (c == '\"' || (in_string && c == '\\')) xbuf[totlen++] = '\\'; /* We used to output e.g. \008 for control characters here, but this doesn't conform to the C Standard. Just output the characters as-is. */ xbuf[totlen++] = c; } if (!traditional) xbuf[totlen++] = '\"'; /* insert ending quote */ } else if (ap->raw_before != 0 || ap->raw_after != 0 || traditional) { U_CHAR *p1 = arg->raw; U_CHAR *l1 = p1 + arg->raw_length; if (ap->raw_before != 0) { while (p1 != l1 && is_space[*p1]) p1++; while (p1 != l1 && is_idchar[*p1]) xbuf[totlen++] = *p1++; /* Delete any no-reexpansion marker that follows an identifier at the beginning of the argument if the argument is concatenated with what precedes it. */ if (p1[0] == '\n' && p1[1] == '-') p1 += 2; } else if (!traditional) { /* Ordinary expanded use of the argument. Put in newline-space markers to prevent token pasting. */ xbuf[totlen++] = '\n'; xbuf[totlen++] = ' '; } if (ap->raw_after != 0) { /* Arg is concatenated after: delete trailing whitespace, whitespace markers, and no-reexpansion markers. */ while (p1 != l1) { if (is_space[l1[-1]]) l1--; else if (l1[-1] == '-') { U_CHAR *p2 = l1 - 1; /* If a `-' is preceded by an odd number of newlines then it and the last newline are a no-reexpansion marker. */ while (p2 != p1 && p2[-1] == '\n') p2--; if ((l1 - 1 - p2) & 1) { l1 -= 2; } else break; } else break; } } bcopy ((char *) p1, (char *) (xbuf + totlen), l1 - p1); totlen += l1 - p1; if (!traditional && ap->raw_after == 0) { /* Ordinary expanded use of the argument. Put in newline-space markers to prevent token pasting. */ xbuf[totlen++] = '\n'; xbuf[totlen++] = ' '; } } else { /* Ordinary expanded use of the argument. Put in newline-space markers to prevent token pasting. */ if (!traditional) { xbuf[totlen++] = '\n'; xbuf[totlen++] = ' '; } bcopy ((char *) arg->expanded, (char *) (xbuf + totlen), arg->expand_length); totlen += arg->expand_length; if (!traditional) { xbuf[totlen++] = '\n'; xbuf[totlen++] = ' '; } /* If a macro argument with newlines is used multiple times, then only expand the newlines once. This avoids creating output lines which don't correspond to any input line, which confuses gdb and gcov. */ if (arg->use_count > 1 && arg->newlines > 0) { /* Don't bother doing change_newlines for subsequent uses of arg. */ arg->use_count = 1; arg->expand_length = change_newlines (arg->expanded, arg->expand_length); } } if (totlen > xbuf_len) abort (); } /* If there is anything left of the definition after handling the arg list, copy that in too. */ for (i = offset; i < defn->length; i++) { /* if we've reached the end of the macro */ if (exp[i] == ')') rest_zero = 0; if (! (rest_zero && last_ap != NULL && last_ap->rest_args && last_ap->raw_after != 0)) xbuf[totlen++] = exp[i]; } xbuf[totlen] = 0; xbuf_len = totlen; for (i = 0; i < nargs; i++) { if (args[i].free1 != 0) free (args[i].free1); if (args[i].free2 != 0) free (args[i].free2); } } } else { xbuf = defn->expansion; xbuf_len = defn->length; } /* Now put the expansion on the input stack so our caller will commence reading from it. */ { register FILE_BUF *ip2; ip2 = &instack[++indepth]; ip2->fname = 0; ip2->nominal_fname = 0; ip2->inc = 0; /* This may not be exactly correct, but will give much better error messages for nested macro calls than using a line number of zero. */ ip2->lineno = start_line; ip2->buf = xbuf; ip2->length = xbuf_len; ip2->bufp = xbuf; ip2->free_ptr = (nargs > 0) ? xbuf : 0; ip2->macro = hp; ip2->if_stack = if_stack; ip2->system_header_p = 0; /* Recursive macro use sometimes works traditionally. #define foo(x,y) bar (x (y,0), y) foo (foo, baz) */ if (!traditional) hp->type = T_DISABLED; } } /* Parse a macro argument and store the info on it into *ARGPTR. REST_ARGS is passed to macarg1 to make it absorb the rest of the args. Return nonzero to indicate a syntax error. */ static char * macarg (argptr, rest_args) register struct argdata *argptr; int rest_args; { FILE_BUF *ip = &instack[indepth]; int paren = 0; int newlines = 0; int comments = 0; char *result = 0; /* Try to parse as much of the argument as exists at this input stack level. */ U_CHAR *bp = macarg1 (ip->bufp, ip->buf + ip->length, ip->macro, &paren, &newlines, &comments, rest_args); /* If we find the end of the argument at this level, set up *ARGPTR to point at it in the input stack. */ if (!(ip->fname != 0 && (newlines != 0 || comments != 0)) && bp != ip->buf + ip->length) { if (argptr != 0) { argptr->raw = ip->bufp; argptr->raw_length = bp - ip->bufp; argptr->newlines = newlines; } ip->bufp = bp; } else { /* This input stack level ends before the macro argument does. We must pop levels and keep parsing. Therefore, we must allocate a temporary buffer and copy the macro argument into it. */ int bufsize = bp - ip->bufp; int extra = newlines; U_CHAR *buffer = (U_CHAR *) xmalloc (bufsize + extra + 1); int final_start = 0; bcopy ((char *) ip->bufp, (char *) buffer, bufsize); ip->bufp = bp; ip->lineno += newlines; while (bp == ip->buf + ip->length) { if (instack[indepth].macro == 0) { result = "unterminated macro call"; break; } ip->macro->type = T_MACRO; if (ip->free_ptr) free (ip->free_ptr); ip = &instack[--indepth]; newlines = 0; comments = 0; bp = macarg1 (ip->bufp, ip->buf + ip->length, ip->macro, &paren, &newlines, &comments, rest_args); final_start = bufsize; bufsize += bp - ip->bufp; extra += newlines; buffer = (U_CHAR *) xrealloc (buffer, bufsize + extra + 1); bcopy ((char *) ip->bufp, (char *) (buffer + bufsize - (bp - ip->bufp)), bp - ip->bufp); ip->bufp = bp; ip->lineno += newlines; } /* Now, if arg is actually wanted, record its raw form, discarding comments and duplicating newlines in whatever part of it did not come from a macro expansion. EXTRA space has been preallocated for duplicating the newlines. FINAL_START is the index of the start of that part. */ if (argptr != 0) { argptr->raw = buffer; argptr->raw_length = bufsize; argptr->free1 = buffer; argptr->newlines = newlines; if ((newlines || comments) && ip->fname != 0) argptr->raw_length = final_start + discard_comments (argptr->raw + final_start, argptr->raw_length - final_start, newlines); argptr->raw[argptr->raw_length] = 0; if (argptr->raw_length > bufsize + extra) abort (); } } /* If we are not discarding this argument, macroexpand it and compute its length as stringified. All this info goes into *ARGPTR. */ if (argptr != 0) { register U_CHAR *buf, *lim; register int totlen; buf = argptr->raw; lim = buf + argptr->raw_length; while (buf != lim && is_space[*buf]) buf++; while (buf != lim && is_space[lim[-1]]) lim--; totlen = traditional ? 0 : 2; /* Count opening and closing quote. */ while (buf != lim) { register U_CHAR c = *buf++; totlen++; /* Internal sequences of whitespace are replaced by one space in most cases, but not always. So count all the whitespace in case we need to keep it all. */ #if 0 if (is_space[c]) SKIP_ALL_WHITE_SPACE (buf); else #endif if (c == '\"' || c == '\\') /* escape these chars */ totlen++; } argptr->stringified_length = totlen; } return result; } /* Scan text from START (inclusive) up to LIMIT (exclusive), taken from the expansion of MACRO, counting parens in *DEPTHPTR, and return if reach LIMIT or before a `)' that would make *DEPTHPTR negative or before a comma when *DEPTHPTR is zero. Single and double quotes are matched and termination is inhibited within them. Comments also inhibit it. Value returned is pointer to stopping place. Increment *NEWLINES each time a newline is passed. REST_ARGS notifies macarg1 that it should absorb the rest of the args. Set *COMMENTS to 1 if a comment is seen. */ static U_CHAR * macarg1 (start, limit, macro, depthptr, newlines, comments, rest_args) U_CHAR *start; register U_CHAR *limit; struct hashnode *macro; int *depthptr, *newlines, *comments; int rest_args; { register U_CHAR *bp = start; while (bp < limit) { switch (*bp) { case '(': (*depthptr)++; break; case ')': if (--(*depthptr) < 0) return bp; break; case '\\': /* Traditionally, backslash makes following char not special. */ if (traditional && bp + 1 < limit && bp[1] != '\n') bp++; break; case '\n': ++*newlines; break; case '/': if (macro) break; if (bp[1] == '\\' && bp[2] == '\n') newline_fix (bp + 1); if (bp[1] == '*') { *comments = 1; for (bp += 2; bp < limit; bp++) { if (*bp == '\n') ++*newlines; else if (*bp == '*') { if (bp[-1] == '/' && warn_comments) warning ("`/*' within comment"); if (bp[1] == '\\' && bp[2] == '\n') newline_fix (bp + 1); if (bp[1] == '/') { bp++; break; } } } } else if (bp[1] == '/' && cplusplus_comments) { *comments = 1; for (bp += 2; bp < limit; bp++) { if (*bp == '\n') { ++*newlines; if (bp[-1] != '\\') break; if (warn_comments) warning ("multiline `//' comment"); } } } break; case '\'': case '\"': { int quotec; for (quotec = *bp++; bp + 1 < limit && *bp != quotec; bp++) { if (*bp == '\\') { bp++; if (*bp == '\n') ++*newlines; if (!macro) { while (*bp == '\\' && bp[1] == '\n') { bp += 2; ++*newlines; } } } else if (*bp == '\n') { ++*newlines; if (quotec == '\'') break; } } } break; case ',': /* if we've returned to lowest level and we aren't absorbing all args */ if ((*depthptr) == 0 && rest_args == 0) return bp; break; } bp++; } return bp; } /* Discard comments and duplicate newlines in the string of length LENGTH at START, except inside of string constants. The string is copied into itself with its beginning staying fixed. NEWLINES is the number of newlines that must be duplicated. We assume that that much extra space is available past the end of the string. */ static int discard_comments (start, length, newlines) U_CHAR *start; int length; int newlines; { register U_CHAR *ibp; register U_CHAR *obp; register U_CHAR *limit; register int c; /* If we have newlines to duplicate, copy everything that many characters up. Then, in the second part, we will have room to insert the newlines while copying down. NEWLINES may actually be too large, because it counts newlines in string constants, and we don't duplicate those. But that does no harm. */ if (newlines > 0) { ibp = start + length; obp = ibp + newlines; limit = start; while (limit != ibp) *--obp = *--ibp; } ibp = start + newlines; limit = start + length + newlines; obp = start; while (ibp < limit) { *obp++ = c = *ibp++; switch (c) { case '\n': /* Duplicate the newline. */ *obp++ = '\n'; break; case '\\': if (*ibp == '\n') { obp--; ibp++; } break; case '/': if (*ibp == '\\' && ibp[1] == '\n') newline_fix (ibp); /* Delete any comment. */ if (cplusplus_comments && ibp[0] == '/') { /* Comments are equivalent to spaces. */ obp[-1] = ' '; ibp++; while (ibp < limit && (*ibp != '\n' || ibp[-1] == '\\')) ibp++; break; } if (ibp[0] != '*' || ibp + 1 >= limit) break; /* Comments are equivalent to spaces. For -traditional, a comment is equivalent to nothing. */ if (traditional) obp--; else obp[-1] = ' '; while (++ibp < limit) { if (ibp[0] == '*') { if (ibp[1] == '\\' && ibp[2] == '\n') newline_fix (ibp + 1); if (ibp[1] == '/') { ibp += 2; break; } } } break; case '\'': case '\"': /* Notice and skip strings, so that we don't think that comments start inside them, and so we don't duplicate newlines in them. */ { int quotec = c; while (ibp < limit) { *obp++ = c = *ibp++; if (c == quotec) break; if (c == '\n' && quotec == '\'') break; if (c == '\\') { if (ibp < limit && *ibp == '\n') { ibp++; obp--; } else { while (*ibp == '\\' && ibp[1] == '\n') ibp += 2; if (ibp < limit) *obp++ = *ibp++; } } } } break; } } return obp - start; } /* Turn newlines to spaces in the string of length LENGTH at START, except inside of string constants. The string is copied into itself with its beginning staying fixed. */ static int change_newlines (start, length) U_CHAR *start; int length; { register U_CHAR *ibp; register U_CHAR *obp; register U_CHAR *limit; register int c; ibp = start; limit = start + length; obp = start; while (ibp < limit) { *obp++ = c = *ibp++; switch (c) { case '\n': /* If this is a NEWLINE NEWLINE, then this is a real newline in the string. Skip past the newline and its duplicate. Put a space in the output. */ if (*ibp == '\n') { ibp++; obp--; *obp++ = ' '; } break; case '\'': case '\"': /* Notice and skip strings, so that we don't delete newlines in them. */ { int quotec = c; while (ibp < limit) { *obp++ = c = *ibp++; if (c == quotec && ibp[-2] != '\\') break; if (c == '\n' && quotec == '\'') break; } } break; } } return obp - start; } /* my_strerror - return the descriptive text associated with an `errno' code. */ char * my_strerror (errnum) int errnum; { char *result; #ifndef VMS #ifndef HAVE_STRERROR result = (char *) ((errnum < sys_nerr) ? sys_errlist[errnum] : 0); #else result = strerror (errnum); #endif #else /* VMS */ /* VAXCRTL's strerror() takes an optional second argument, which only matters when the first argument is EVMSERR. However, it's simplest just to pass it unconditionally. `vaxc$errno' is declared in , and maintained by the library in parallel with `errno'. We assume that caller's `errnum' either matches the last setting of `errno' by the library or else does not have the value `EVMSERR'. */ result = strerror (errnum, vaxc$errno); #endif if (!result) result = "undocumented I/O error"; return result; } /* error - print error message and increment count of errors. */ void error (PRINTF_ALIST (msg)) PRINTF_DCL (msg) { va_list args; VA_START (args, msg); verror (msg, args); va_end (args); } static void verror (msg, args) char *msg; va_list args; { int i; FILE_BUF *ip = NULL; print_containing_files (); for (i = indepth; i >= 0; i--) if (instack[i].fname != NULL) { ip = &instack[i]; break; } if (ip != NULL) fprintf (stderr, "%s:%d: ", ip->nominal_fname, ip->lineno); vfprintf (stderr, msg, args); fprintf (stderr, "\n"); errors++; } /* Error including a message from `errno'. */ static void error_from_errno (name) char *name; { int e = errno; int i; FILE_BUF *ip = NULL; print_containing_files (); for (i = indepth; i >= 0; i--) if (instack[i].fname != NULL) { ip = &instack[i]; break; } if (ip != NULL) fprintf (stderr, "%s:%d: ", ip->nominal_fname, ip->lineno); fprintf (stderr, "%s: %s\n", name, my_strerror (e)); errors++; } /* Print error message but don't count it. */ void warning (PRINTF_ALIST (msg)) PRINTF_DCL (msg) { va_list args; VA_START (args, msg); vwarning (msg, args); va_end (args); } static void vwarning (msg, args) char *msg; va_list args; { int i; FILE_BUF *ip = NULL; if (inhibit_warnings) return; if (warnings_are_errors) errors++; print_containing_files (); for (i = indepth; i >= 0; i--) if (instack[i].fname != NULL) { ip = &instack[i]; break; } if (ip != NULL) fprintf (stderr, "%s:%d: ", ip->nominal_fname, ip->lineno); fprintf (stderr, "warning: "); vfprintf (stderr, msg, args); fprintf (stderr, "\n"); } static void #if defined (__STDC__) && defined (HAVE_VPRINTF) error_with_line (int line, PRINTF_ALIST (msg)) #else error_with_line (line, PRINTF_ALIST (msg)) int line; PRINTF_DCL (msg) #endif { va_list args; VA_START (args, msg); verror_with_line (line, msg, args); va_end (args); } static void verror_with_line (line, msg, args) int line; char *msg; va_list args; { int i; FILE_BUF *ip = NULL; print_containing_files (); for (i = indepth; i >= 0; i--) if (instack[i].fname != NULL) { ip = &instack[i]; break; } if (ip != NULL) fprintf (stderr, "%s:%d: ", ip->nominal_fname, line); vfprintf (stderr, msg, args); fprintf (stderr, "\n"); errors++; } static void #if defined (__STDC__) && defined (HAVE_VPRINTF) warning_with_line (int line, PRINTF_ALIST (msg)) #else warning_with_line (line, PRINTF_ALIST (msg)) int line; PRINTF_DCL (msg) #endif { va_list args; VA_START (args, msg); vwarning_with_line (line, msg, args); va_end (args); } static void vwarning_with_line (line, msg, args) int line; char *msg; va_list args; { int i; FILE_BUF *ip = NULL; if (inhibit_warnings) return; if (warnings_are_errors) errors++; print_containing_files (); for (i = indepth; i >= 0; i--) if (instack[i].fname != NULL) { ip = &instack[i]; break; } if (ip != NULL) fprintf (stderr, line ? "%s:%d: " : "%s: ", ip->nominal_fname, line); fprintf (stderr, "warning: "); vfprintf (stderr, msg, args); fprintf (stderr, "\n"); } /* Print an error message and maybe count it. */ void pedwarn (PRINTF_ALIST (msg)) PRINTF_DCL (msg) { va_list args; VA_START (args, msg); if (pedantic_errors) verror (msg, args); else vwarning (msg, args); va_end (args); } void #if defined (__STDC__) && defined (HAVE_VPRINTF) pedwarn_with_line (int line, PRINTF_ALIST (msg)) #else pedwarn_with_line (line, PRINTF_ALIST (msg)) int line; PRINTF_DCL (msg) #endif { va_list args; VA_START (args, msg); if (pedantic_errors) verror_with_line (line, msg, args); else vwarning_with_line (line, msg, args); va_end (args); } /* Report a warning (or an error if pedantic_errors) giving specified file name and line number, not current. */ static void #if defined (__STDC__) && defined (HAVE_VPRINTF) pedwarn_with_file_and_line (char *file, int line, PRINTF_ALIST (msg)) #else pedwarn_with_file_and_line (file, line, PRINTF_ALIST (msg)) char *file; int line; PRINTF_DCL (msg) #endif { va_list args; if (!pedantic_errors && inhibit_warnings) return; if (file != NULL) fprintf (stderr, "%s:%d: ", file, line); if (pedantic_errors) errors++; if (!pedantic_errors) fprintf (stderr, "warning: "); VA_START (args, msg); vfprintf (stderr, msg, args); va_end (args); fprintf (stderr, "\n"); } /* Print the file names and line numbers of the #include directives which led to the current file. */ static void print_containing_files () { FILE_BUF *ip = NULL; int i; int first = 1; /* If stack of files hasn't changed since we last printed this info, don't repeat it. */ if (last_error_tick == input_file_stack_tick) return; for (i = indepth; i >= 0; i--) if (instack[i].fname != NULL) { ip = &instack[i]; break; } /* Give up if we don't find a source file. */ if (ip == NULL) return; /* Find the other, outer source files. */ for (i--; i >= 0; i--) if (instack[i].fname != NULL) { ip = &instack[i]; if (first) { first = 0; fprintf (stderr, "In file included"); } else { fprintf (stderr, ",\n "); } fprintf (stderr, " from %s:%d", ip->nominal_fname, ip->lineno); } if (! first) fprintf (stderr, ":\n"); /* Record we have printed the status as of this time. */ last_error_tick = input_file_stack_tick; } /* Return the line at which an error occurred. The error is not necessarily associated with the current spot in the input stack, so LINE says where. LINE will have been copied from ip->lineno for the current input level. If the current level is for a file, we return LINE. But if the current level is not for a file, LINE is meaningless. In that case, we return the lineno of the innermost file. */ static int line_for_error (line) int line; { int i; int line1 = line; for (i = indepth; i >= 0; ) { if (instack[i].fname != 0) return line1; i--; if (i < 0) return 0; line1 = instack[i].lineno; } abort (); /*NOTREACHED*/ return 0; } /* * If OBUF doesn't have NEEDED bytes after OPTR, make it bigger. * * As things stand, nothing is ever placed in the output buffer to be * removed again except when it's KNOWN to be part of an identifier, * so flushing and moving down everything left, instead of expanding, * should work ok. */ /* You might think void was cleaner for the return type, but that would get type mismatch in check_expand in strict ANSI. */ static int grow_outbuf (obuf, needed) register FILE_BUF *obuf; register int needed; { register U_CHAR *p; int minsize; if (obuf->length - (obuf->bufp - obuf->buf) > needed) return 0; /* Make it at least twice as big as it is now. */ obuf->length *= 2; /* Make it have at least 150% of the free space we will need. */ minsize = (3 * needed) / 2 + (obuf->bufp - obuf->buf); if (minsize > obuf->length) obuf->length = minsize; if ((p = (U_CHAR *) xrealloc (obuf->buf, obuf->length)) == NULL) memory_full (); obuf->bufp = p + (obuf->bufp - obuf->buf); obuf->buf = p; return 0; } /* Symbol table for macro names and special symbols */ /* * install a name in the main hash table, even if it is already there. * name stops with first non alphanumeric, except leading '#'. * caller must check against redefinition if that is desired. * delete_macro () removes things installed by install () in fifo order. * this is important because of the `defined' special symbol used * in #if, and also if pushdef/popdef directives are ever implemented. * * If LEN is >= 0, it is the length of the name. * Otherwise, compute the length by scanning the entire name. * * If HASH is >= 0, it is the precomputed hash code. * Otherwise, compute the hash code. */ static HASHNODE * install (name, len, type, value, hash) U_CHAR *name; int len; enum node_type type; char *value; int hash; { register HASHNODE *hp; register int i, bucket; register U_CHAR *p, *q; if (len < 0) { p = name; while (is_idchar[*p]) p++; len = p - name; } if (hash < 0) hash = hashf (name, len, HASHSIZE); i = sizeof (HASHNODE) + len + 1; hp = (HASHNODE *) xmalloc (i); bucket = hash; hp->bucket_hdr = &hashtab[bucket]; hp->next = hashtab[bucket]; hashtab[bucket] = hp; hp->prev = NULL; if (hp->next != NULL) hp->next->prev = hp; hp->type = type; hp->length = len; hp->value.cpval = value; hp->name = ((U_CHAR *) hp) + sizeof (HASHNODE); p = hp->name; q = name; for (i = 0; i < len; i++) *p++ = *q++; hp->name[len] = 0; return hp; } /* * find the most recent hash node for name name (ending with first * non-identifier char) installed by install * * If LEN is >= 0, it is the length of the name. * Otherwise, compute the length by scanning the entire name. * * If HASH is >= 0, it is the precomputed hash code. * Otherwise, compute the hash code. */ HASHNODE * lookup (name, len, hash) U_CHAR *name; int len; int hash; { register U_CHAR *bp; register HASHNODE *bucket; if (len < 0) { for (bp = name; is_idchar[*bp]; bp++) ; len = bp - name; } if (hash < 0) hash = hashf (name, len, HASHSIZE); bucket = hashtab[hash]; while (bucket) { if (bucket->length == len && bcmp (bucket->name, name, len) == 0) return bucket; bucket = bucket->next; } return NULL; } /* * Delete a hash node. Some weirdness to free junk from macros. * More such weirdness will have to be added if you define more hash * types that need it. */ /* Note that the DEFINITION of a macro is removed from the hash table but its storage is not freed. This would be a storage leak except that it is not reasonable to keep undefining and redefining large numbers of macros many times. In any case, this is necessary, because a macro can be #undef'd in the middle of reading the arguments to a call to it. If #undef freed the DEFINITION, that would crash. */ static void delete_macro (hp) HASHNODE *hp; { if (hp->prev != NULL) hp->prev->next = hp->next; if (hp->next != NULL) hp->next->prev = hp->prev; /* Make sure that the bucket chain header that the deleted guy was on points to the right thing afterwards. */ if (hp == *hp->bucket_hdr) *hp->bucket_hdr = hp->next; #if 0 if (hp->type == T_MACRO) { DEFINITION *d = hp->value.defn; struct reflist *ap, *nextap; for (ap = d->pattern; ap != NULL; ap = nextap) { nextap = ap->next; free (ap); } free (d); } #endif free (hp); } /* * return hash function on name. must be compatible with the one * computed a step at a time, elsewhere */ static int hashf (name, len, hashsize) register U_CHAR *name; register int len; int hashsize; { register int r = 0; while (len--) r = HASHSTEP (r, *name++); return MAKE_POS (r) % hashsize; } /* Dump the definition of a single macro HP to OF. */ static void dump_single_macro (hp, of) register HASHNODE *hp; FILE *of; { register DEFINITION *defn = hp->value.defn; struct reflist *ap; int offset; int concat; /* Print the definition of the macro HP. */ fprintf (of, "#define %s", hp->name); if (defn->nargs >= 0) { int i; fprintf (of, "("); for (i = 0; i < defn->nargs; i++) { dump_arg_n (defn, i, of); if (i + 1 < defn->nargs) fprintf (of, ", "); } fprintf (of, ")"); } fprintf (of, " "); offset = 0; concat = 0; for (ap = defn->pattern; ap != NULL; ap = ap->next) { dump_defn_1 (defn->expansion, offset, ap->nchars, of); offset += ap->nchars; if (!traditional) { if (ap->nchars != 0) concat = 0; if (ap->stringify) { switch (ap->stringify) { case SHARP_TOKEN: fprintf (of, "#"); break; case WHITE_SHARP_TOKEN: fprintf (of, "# "); break; case PERCENT_COLON_TOKEN: fprintf (of, "%%:"); break; case WHITE_PERCENT_COLON_TOKEN: fprintf (of, "%%: "); break; default: abort (); } } if (ap->raw_before != 0) { if (concat) { switch (ap->raw_before) { case WHITE_SHARP_TOKEN: case WHITE_PERCENT_COLON_TOKEN: fprintf (of, " "); break; default: break; } } else { switch (ap->raw_before) { case SHARP_TOKEN: fprintf (of, "##"); break; case WHITE_SHARP_TOKEN: fprintf (of, "## "); break; case PERCENT_COLON_TOKEN: fprintf (of, "%%:%%:"); break; case WHITE_PERCENT_COLON_TOKEN: fprintf (of, "%%:%%: "); break; default: abort (); } } } concat = 0; } dump_arg_n (defn, ap->argno, of); if (!traditional && ap->raw_after != 0) { switch (ap->raw_after) { case SHARP_TOKEN: fprintf (of, "##"); break; case WHITE_SHARP_TOKEN: fprintf (of, " ##"); break; case PERCENT_COLON_TOKEN: fprintf (of, "%%:%%:"); break; case WHITE_PERCENT_COLON_TOKEN: fprintf (of, " %%:%%:"); break; default: abort (); } concat = 1; } } dump_defn_1 (defn->expansion, offset, defn->length - offset, of); fprintf (of, "\n"); } /* Dump all macro definitions as #defines to stdout. */ static void dump_all_macros () { int bucket; for (bucket = 0; bucket < HASHSIZE; bucket++) { register HASHNODE *hp; for (hp = hashtab[bucket]; hp; hp= hp->next) { if (hp->type == T_MACRO) dump_single_macro (hp, stdout); } } } /* Output to OF a substring of a macro definition. BASE is the beginning of the definition. Output characters START thru LENGTH. Unless traditional, discard newlines outside of strings, thus converting funny-space markers to ordinary spaces. */ static void dump_defn_1 (base, start, length, of) U_CHAR *base; int start; int length; FILE *of; { U_CHAR *p = base + start; U_CHAR *limit = base + start + length; if (traditional) fwrite (p, sizeof (*p), length, of); else { while (p < limit) { if (*p == '\"' || *p =='\'') { U_CHAR *p1 = skip_quoted_string (p, limit, 0, NULL_PTR, NULL_PTR, NULL_PTR); fwrite (p, sizeof (*p), p1 - p, of); p = p1; } else { if (*p != '\n') putc (*p, of); p++; } } } } /* Print the name of argument number ARGNUM of macro definition DEFN to OF. Recall that DEFN->args.argnames contains all the arg names concatenated in reverse order with comma-space in between. */ static void dump_arg_n (defn, argnum, of) DEFINITION *defn; int argnum; FILE *of; { register U_CHAR *p = defn->args.argnames; while (argnum + 1 < defn->nargs) { p = (U_CHAR *) index ((char *) p, ' ') + 1; argnum++; } while (*p && *p != ',') { putc (*p, of); p++; } } /* Initialize syntactic classifications of characters. */ static void initialize_char_syntax () { register int i; /* * Set up is_idchar and is_idstart tables. These should be * faster than saying (is_alpha (c) || c == '_'), etc. * Set up these things before calling any routines tthat * refer to them. */ for (i = 'a'; i <= 'z'; i++) { is_idchar[i - 'a' + 'A'] = 1; is_idchar[i] = 1; is_idstart[i - 'a' + 'A'] = 1; is_idstart[i] = 1; } for (i = '0'; i <= '9'; i++) is_idchar[i] = 1; is_idchar['_'] = 1; is_idstart['_'] = 1; is_idchar['$'] = 1; is_idstart['$'] = 1; /* horizontal space table */ is_hor_space[' '] = 1; is_hor_space['\t'] = 1; is_hor_space['\v'] = 1; is_hor_space['\f'] = 1; is_hor_space['\r'] = 1; is_space[' '] = 1; is_space['\t'] = 1; is_space['\v'] = 1; is_space['\f'] = 1; is_space['\n'] = 1; is_space['\r'] = 1; char_name['\v'] = "vertical tab"; char_name['\f'] = "formfeed"; char_name['\r'] = "carriage return"; } /* Initialize the built-in macros. */ static void initialize_builtins (inp, outp) FILE_BUF *inp; FILE_BUF *outp; { install ((U_CHAR *) "__LINE__", -1, T_SPECLINE, NULL_PTR, -1); install ((U_CHAR *) "__DATE__", -1, T_DATE, NULL_PTR, -1); install ((U_CHAR *) "__FILE__", -1, T_FILE, NULL_PTR, -1); install ((U_CHAR *) "__BASE_FILE__", -1, T_BASE_FILE, NULL_PTR, -1); install ((U_CHAR *) "__INCLUDE_LEVEL__", -1, T_INCLUDE_LEVEL, NULL_PTR, -1); install ((U_CHAR *) "__VERSION__", -1, T_VERSION, NULL_PTR, -1); #ifndef NO_BUILTIN_SIZE_TYPE install ((U_CHAR *) "__SIZE_TYPE__", -1, T_SIZE_TYPE, NULL_PTR, -1); #endif #ifndef NO_BUILTIN_PTRDIFF_TYPE install ((U_CHAR *) "__PTRDIFF_TYPE__ ", -1, T_PTRDIFF_TYPE, NULL_PTR, -1); #endif install ((U_CHAR *) "__WCHAR_TYPE__", -1, T_WCHAR_TYPE, NULL_PTR, -1); install ((U_CHAR *) "__USER_LABEL_PREFIX__", -1, T_USER_LABEL_PREFIX_TYPE, NULL_PTR, -1); install ((U_CHAR *) "__REGISTER_PREFIX__", -1, T_REGISTER_PREFIX_TYPE, NULL_PTR, -1); install ((U_CHAR *) "__IMMEDIATE_PREFIX__", -1, T_IMMEDIATE_PREFIX_TYPE, NULL_PTR, -1); install ((U_CHAR *) "__TIME__", -1, T_TIME, NULL_PTR, -1); if (!traditional) { install ((U_CHAR *) "__STDC__", -1, T_CONST, "1", -1); install ((U_CHAR *) "__STDC_VERSION__", -1, T_CONST, "199409L", -1); } if (objc) install ((U_CHAR *) "__OBJC__", -1, T_CONST, "1", -1); /* This is supplied using a -D by the compiler driver so that it is present only when truly compiling with GNU C. */ /* install ((U_CHAR *) "__GNUC__", -1, T_CONST, "2", -1); */ install ((U_CHAR *) "__HAVE_BUILTIN_SETJMP__", -1, T_CONST, "1", -1); if (debug_output) { char directive[2048]; U_CHAR *udirective = (U_CHAR *) directive; register struct directive *dp = &directive_table[0]; struct tm *timebuf = timestamp (); sprintf (directive, " __BASE_FILE__ \"%s\"\n", instack[0].nominal_fname); output_line_directive (inp, outp, 0, same_file); pass_thru_directive (udirective, &udirective[strlen (directive)], outp, dp); sprintf (directive, " __VERSION__ \"%s\"\n", version_string); output_line_directive (inp, outp, 0, same_file); pass_thru_directive (udirective, &udirective[strlen (directive)], outp, dp); #ifndef NO_BUILTIN_SIZE_TYPE sprintf (directive, " __SIZE_TYPE__ %s\n", SIZE_TYPE); output_line_directive (inp, outp, 0, same_file); pass_thru_directive (udirective, &udirective[strlen (directive)], outp, dp); #endif #ifndef NO_BUILTIN_PTRDIFF_TYPE sprintf (directive, " __PTRDIFF_TYPE__ %s\n", PTRDIFF_TYPE); output_line_directive (inp, outp, 0, same_file); pass_thru_directive (udirective, &udirective[strlen (directive)], outp, dp); #endif sprintf (directive, " __WCHAR_TYPE__ %s\n", wchar_type); output_line_directive (inp, outp, 0, same_file); pass_thru_directive (udirective, &udirective[strlen (directive)], outp, dp); sprintf (directive, " __DATE__ \"%s %2d %4d\"\n", monthnames[timebuf->tm_mon], timebuf->tm_mday, timebuf->tm_year + 1900); output_line_directive (inp, outp, 0, same_file); pass_thru_directive (udirective, &udirective[strlen (directive)], outp, dp); sprintf (directive, " __TIME__ \"%02d:%02d:%02d\"\n", timebuf->tm_hour, timebuf->tm_min, timebuf->tm_sec); output_line_directive (inp, outp, 0, same_file); pass_thru_directive (udirective, &udirective[strlen (directive)], outp, dp); if (!traditional) { sprintf (directive, " __STDC__ 1"); output_line_directive (inp, outp, 0, same_file); pass_thru_directive (udirective, &udirective[strlen (directive)], outp, dp); } if (objc) { sprintf (directive, " __OBJC__ 1"); output_line_directive (inp, outp, 0, same_file); pass_thru_directive (udirective, &udirective[strlen (directive)], outp, dp); } } } /* * process a given definition string, for initialization * If STR is just an identifier, define it with value 1. * If STR has anything after the identifier, then it should * be identifier=definition. */ static void make_definition (str, op) char *str; FILE_BUF *op; { FILE_BUF *ip; struct directive *kt; U_CHAR *buf, *p; p = buf = (U_CHAR *) str; if (!is_idstart[*p]) { error ("malformed option `-D %s'", str); return; } while (is_idchar[*++p]) ; if (*p == '(') { while (is_idchar[*++p] || *p == ',' || is_hor_space[*p]) ; if (*p++ != ')') p = (U_CHAR *) str; /* Error */ } if (*p == 0) { buf = (U_CHAR *) alloca (p - buf + 4); strcpy ((char *)buf, str); strcat ((char *)buf, " 1"); } else if (*p != '=') { error ("malformed option `-D %s'", str); return; } else { U_CHAR *q; /* Copy the entire option so we can modify it. */ buf = (U_CHAR *) alloca (2 * strlen (str) + 1); strncpy ((char *) buf, str, p - (U_CHAR *) str); /* Change the = to a space. */ buf[p - (U_CHAR *) str] = ' '; /* Scan for any backslash-newline and remove it. */ p++; q = &buf[p - (U_CHAR *) str]; while (*p) { if (*p == '\"' || *p == '\'') { int unterminated = 0; U_CHAR *p1 = skip_quoted_string (p, p + strlen ((char *) p), 0, NULL_PTR, NULL_PTR, &unterminated); if (unterminated) return; while (p != p1) *q++ = *p++; } else if (*p == '\\' && p[1] == '\n') p += 2; /* Change newline chars into newline-markers. */ else if (*p == '\n') { *q++ = '\n'; *q++ = '\n'; p++; } else *q++ = *p++; } *q = 0; } ip = &instack[++indepth]; ip->nominal_fname = ip->fname = "*Initialization*"; ip->buf = ip->bufp = buf; ip->length = strlen ((char *) buf); ip->lineno = 1; ip->macro = 0; ip->free_ptr = 0; ip->if_stack = if_stack; ip->system_header_p = 0; for (kt = directive_table; kt->type != T_DEFINE; kt++) ; /* Pass NULL instead of OP, since this is a "predefined" macro. */ do_define (buf, buf + strlen ((char *) buf), NULL_PTR, kt); --indepth; } /* JF, this does the work for the -U option */ static void make_undef (str, op) char *str; FILE_BUF *op; { FILE_BUF *ip; struct directive *kt; ip = &instack[++indepth]; ip->nominal_fname = ip->fname = "*undef*"; ip->buf = ip->bufp = (U_CHAR *) str; ip->length = strlen (str); ip->lineno = 1; ip->macro = 0; ip->free_ptr = 0; ip->if_stack = if_stack; ip->system_header_p = 0; for (kt = directive_table; kt->type != T_UNDEF; kt++) ; do_undef ((U_CHAR *) str, (U_CHAR *) str + strlen (str), op, kt); --indepth; } /* Process the string STR as if it appeared as the body of a #assert. OPTION is the option name for which STR was the argument. */ static void make_assertion (option, str) char *option; char *str; { FILE_BUF *ip; struct directive *kt; U_CHAR *buf, *p, *q; /* Copy the entire option so we can modify it. */ buf = (U_CHAR *) alloca (strlen (str) + 1); strcpy ((char *) buf, str); /* Scan for any backslash-newline and remove it. */ p = q = buf; while (*p) { if (*p == '\\' && p[1] == '\n') p += 2; else *q++ = *p++; } *q = 0; p = buf; if (!is_idstart[*p]) { error ("malformed option `%s %s'", option, str); return; } while (is_idchar[*++p]) ; SKIP_WHITE_SPACE (p); if (! (*p == 0 || *p == '(')) { error ("malformed option `%s %s'", option, str); return; } ip = &instack[++indepth]; ip->nominal_fname = ip->fname = "*Initialization*"; ip->buf = ip->bufp = buf; ip->length = strlen ((char *) buf); ip->lineno = 1; ip->macro = 0; ip->free_ptr = 0; ip->if_stack = if_stack; ip->system_header_p = 0; for (kt = directive_table; kt->type != T_ASSERT; kt++) ; /* Pass NULL as output ptr to do_define since we KNOW it never does any output.... */ do_assert (buf, buf + strlen ((char *) buf) , NULL_PTR, kt); --indepth; } #ifndef DIR_SEPARATOR #define DIR_SEPARATOR '/' #endif /* The previous include prefix, if any, is PREV_FILE_NAME. Translate any pathnames with COMPONENT. Allocate a new include prefix whose name is the simplified concatenation of PREFIX and NAME, with a trailing / added if needed. But return 0 if the include prefix should be ignored, e.g. because it is a duplicate of PREV_FILE_NAME. */ static struct file_name_list * new_include_prefix (prev_file_name, component, prefix, name) struct file_name_list *prev_file_name; char *component; char *prefix; char *name; { if (name == 0) fatal ("Directory name missing after command line option"); if (*name == 0) /* Ignore the empty string. */ return 0; prefix = update_path (prefix, component); name = update_path (name, component); { struct file_name_list *dir = ((struct file_name_list *) xmalloc (sizeof (struct file_name_list) + strlen (prefix) + strlen (name) + 2)); size_t len; strcpy (dir->fname, prefix); strcat (dir->fname, name); len = simplify_filename (dir->fname); /* Convert directory name to a prefix. */ if (dir->fname[len - 1] != DIR_SEPARATOR) { if (len == 1 && dir->fname[len - 1] == '.') len = 0; else dir->fname[len++] = DIR_SEPARATOR; dir->fname[len] = 0; } /* Ignore a directory whose name matches the previous one. */ if (prev_file_name && !strcmp (prev_file_name->fname, dir->fname)) { /* But treat `-Idir -I- -Idir' as `-I- -Idir'. */ if (!first_bracket_include) first_bracket_include = prev_file_name; free (dir); return 0; } #ifndef VMS /* VMS can't stat dir prefixes, so skip these optimizations in VMS. */ /* Add a trailing "." if there is a filename. This increases the number of systems that can stat directories. We remove it below. */ if (len != 0) { dir->fname[len] = '.'; dir->fname[len + 1] = 0; } /* Ignore a nonexistent directory. */ if (stat (len ? dir->fname : ".", &dir->st) != 0) { if (errno != ENOENT && errno != ENOTDIR) error_from_errno (dir->fname); free (dir); return 0; } if (len != 0) dir->fname[len] = 0; /* Ignore a directory whose identity matches the previous one. */ if (prev_file_name && INO_T_EQ (prev_file_name->st.st_ino, dir->st.st_ino) && prev_file_name->st.st_dev == dir->st.st_dev) { /* But treat `-Idir -I- -Idir' as `-I- -Idir'. */ if (!first_bracket_include) first_bracket_include = prev_file_name; free (dir); return 0; } #endif /* ! VMS */ dir->next = 0; dir->c_system_include_path = 0; dir->got_name_map = 0; return dir; } } /* Append a chain of `struct file_name_list's to the end of the main include chain. FIRST is the beginning of the chain to append, and LAST is the end. */ static void append_include_chain (first, last) struct file_name_list *first, *last; { struct file_name_list *dir; if (!first || !last) return; if (include == 0) include = first; else last_include->next = first; if (first_bracket_include == 0) first_bracket_include = first; for (dir = first; ; dir = dir->next) { int len = strlen (dir->fname) + INCLUDE_LEN_FUDGE; if (len > max_include_len) max_include_len = len; if (dir == last) break; } last->next = NULL; last_include = last; } /* Place into DST a representation of the file named SRC that is suitable for `make'. Do not null-terminate DST. Return its length. */ static int quote_string_for_make (dst, src) char *dst; char *src; { char *p = src; int i = 0; for (;;) { char c = *p++; switch (c) { case '\0': case ' ': case '\t': { /* GNU make uses a weird quoting scheme for white space. A space or tab preceded by 2N+1 backslashes represents N backslashes followed by space; a space or tab preceded by 2N backslashes represents N backslashes at the end of a file name; and backslashes in other contexts should not be doubled. */ char *q; for (q = p - 1; src < q && q[-1] == '\\'; q--) { if (dst) dst[i] = '\\'; i++; } } if (!c) return i; if (dst) dst[i] = '\\'; i++; goto ordinary_char; case '$': if (dst) dst[i] = c; i++; /* Fall through. This can mishandle things like "$(" but there's no easy fix. */ default: ordinary_char: /* This can mishandle characters in the string "\0\n%*?[\\~"; exactly which chars are mishandled depends on the `make' version. We know of no portable solution for this; even GNU make 3.76.1 doesn't solve the problem entirely. (Also, '\0' is mishandled due to our calling conventions.) */ if (dst) dst[i] = c; i++; break; } } } /* Add output to `deps_buffer' for the -M switch. STRING points to the text to be output. SPACER is ':' for targets, ' ' for dependencies. */ static void deps_output (string, spacer) char *string; int spacer; { int size = quote_string_for_make ((char *) 0, string); if (size == 0) return; #ifndef MAX_OUTPUT_COLUMNS #define MAX_OUTPUT_COLUMNS 72 #endif if (MAX_OUTPUT_COLUMNS - 1 /*spacer*/ - 2 /*` \'*/ < deps_column + size && 1 < deps_column) { bcopy (" \\\n ", &deps_buffer[deps_size], 4); deps_size += 4; deps_column = 1; if (spacer == ' ') spacer = 0; } if (deps_size + size + 8 > deps_allocated_size) { deps_allocated_size = (deps_size + size + 50) * 2; deps_buffer = xrealloc (deps_buffer, deps_allocated_size); } if (spacer == ' ') { deps_buffer[deps_size++] = ' '; deps_column++; } quote_string_for_make (&deps_buffer[deps_size], string); deps_size += size; deps_column += size; if (spacer == ':') { deps_buffer[deps_size++] = ':'; deps_column++; } deps_buffer[deps_size] = 0; } static void fatal (PRINTF_ALIST (msg)) PRINTF_DCL (msg) { va_list args; fprintf (stderr, "%s: ", progname); VA_START (args, msg); vfprintf (stderr, msg, args); va_end (args); fprintf (stderr, "\n"); exit (FATAL_EXIT_CODE); } /* More 'friendly' abort that prints the line and file. config.h can #define abort fancy_abort if you like that sort of thing. */ void fancy_abort () { fatal ("Internal gcc abort."); } static void perror_with_name (name) char *name; { fprintf (stderr, "%s: %s: %s\n", progname, name, my_strerror (errno)); errors++; } static void pfatal_with_name (name) char *name; { perror_with_name (name); #ifdef VMS exit (vaxc$errno); #else exit (FATAL_EXIT_CODE); #endif } /* Handler for SIGPIPE. */ static void pipe_closed (signo) /* If this is missing, some compilers complain. */ int signo; { fatal ("output pipe has been closed"); } static void memory_full () { fatal ("Memory exhausted."); } GENERIC_PTR xmalloc (size) size_t size; { register GENERIC_PTR ptr = (GENERIC_PTR) malloc (size); if (!ptr) memory_full (); return ptr; } static GENERIC_PTR xrealloc (old, size) GENERIC_PTR old; size_t size; { register GENERIC_PTR ptr = (GENERIC_PTR) realloc (old, size); if (!ptr) memory_full (); return ptr; } static GENERIC_PTR xcalloc (number, size) size_t number, size; { register size_t total = number * size; register GENERIC_PTR ptr = (GENERIC_PTR) malloc (total); if (!ptr) memory_full (); bzero (ptr, total); return ptr; } static char * savestring (input) char *input; { size_t size = strlen (input); char *output = xmalloc (size + 1); strcpy (output, input); return output; } #ifdef VMS /* Under VMS we need to fix up the "include" specification filename so that everything following the 1st slash is changed into its correct VMS file specification. */ static void hack_vms_include_specification (fname, vaxc_include) char *fname; int vaxc_include; { register char *cp, *cp1, *cp2; int f, check_filename_before_returning; char Local[512]; check_filename_before_returning = 0; cp = base_name (fname); /* * Check if we have a vax-c style '#include filename' * and add the missing .h */ if (vaxc_include && !index (cp,'.')) strcat (cp, ".h"); cp2 = Local; /* initialize */ /* We are trying to do a number of things here. First of all, we are trying to hammer the filenames into a standard format, such that later processing can handle them. If the file name contains something like [dir.], then it recognizes this as a root, and strips the ".]". Later processing will add whatever is needed to get things working properly. If no device is specified, then the first directory name is taken to be a device name (or a rooted logical). */ /* See if we found that 1st slash */ if (cp == 0) return; /* Nothing to do!!! */ if (*cp != '/') return; /* Nothing to do!!! */ /* Point to the UNIX filename part (which needs to be fixed!) */ cp1 = cp+1; /* If the directory spec is not rooted, we can just copy the UNIX filename part and we are done */ if (((cp - fname) > 1) && ((cp[-1] == ']') || (cp[-1] == '>'))) { if (cp[-2] != '.') { /* * The VMS part ends in a `]', and the preceding character is not a `.'. * We strip the `]', and then splice the two parts of the name in the * usual way. Given the default locations for include files in cccp.c, * we will only use this code if the user specifies alternate locations * with the /include (-I) switch on the command line. */ cp -= 1; /* Strip "]" */ cp1--; /* backspace */ } else { /* * The VMS part has a ".]" at the end, and this will not do. Later * processing will add a second directory spec, and this would be a syntax * error. Thus we strip the ".]", and thus merge the directory specs. * We also backspace cp1, so that it points to a '/'. This inhibits the * generation of the 000000 root directory spec (which does not belong here * in this case). */ cp -= 2; /* Strip ".]" */ cp1--; }; /* backspace */ } else { /* We drop in here if there is no VMS style directory specification yet. * If there is no device specification either, we make the first dir a * device and try that. If we do not do this, then we will be essentially * searching the users default directory (as if they did a #include "asdf.h"). * * Then all we need to do is to push a '[' into the output string. Later * processing will fill this in, and close the bracket. */ if (cp[-1] != ':') *cp2++ = ':'; /* dev not in spec. take first dir */ *cp2++ = '['; /* Open the directory specification */ } /* at this point we assume that we have the device spec, and (at least the opening "[" for a directory specification. We may have directories specified already */ /* If there are no other slashes then the filename will be in the "root" directory. Otherwise, we need to add directory specifications. */ if (index (cp1, '/') == 0) { /* Just add "000000]" as the directory string */ strcpy (cp2, "000000]"); cp2 += strlen (cp2); check_filename_before_returning = 1; /* we might need to fool with this later */ } else { /* As long as there are still subdirectories to add, do them. */ while (index (cp1, '/') != 0) { /* If this token is "." we can ignore it */ if ((cp1[0] == '.') && (cp1[1] == '/')) { cp1 += 2; continue; } /* Add a subdirectory spec. Do not duplicate "." */ if (cp2[-1] != '.' && cp2[-1] != '[' && cp2[-1] != '<') *cp2++ = '.'; /* If this is ".." then the spec becomes "-" */ if ((cp1[0] == '.') && (cp1[1] == '.') && (cp[2] == '/')) { /* Add "-" and skip the ".." */ *cp2++ = '-'; cp1 += 3; continue; } /* Copy the subdirectory */ while (*cp1 != '/') *cp2++= *cp1++; cp1++; /* Skip the "/" */ } /* Close the directory specification */ if (cp2[-1] == '.') /* no trailing periods */ cp2--; *cp2++ = ']'; } /* Now add the filename */ while (*cp1) *cp2++ = *cp1++; *cp2 = 0; /* Now append it to the original VMS spec. */ strcpy (cp, Local); /* If we put a [000000] in the filename, try to open it first. If this fails, remove the [000000], and return that name. This provides flexibility to the user in that they can use both rooted and non-rooted logical names to point to the location of the file. */ if (check_filename_before_returning) { f = open (fname, O_RDONLY, 0666); if (f >= 0) { /* The file name is OK as it is, so return it as is. */ close (f); return; } /* The filename did not work. Try to remove the [000000] from the name, and return it. */ cp = index (fname, '['); cp2 = index (fname, ']') + 1; strcpy (cp, cp2); /* this gets rid of it */ } return; } #endif /* VMS */ #ifdef VMS /* The following wrapper functions supply additional arguments to the VMS I/O routines to optimize performance with file handling. The arguments are: "mbc=16" - Set multi-block count to 16 (use a 8192 byte buffer). "deq=64" - When extending the file, extend it in chunks of 32Kbytes. "fop=tef"- Truncate unused portions of file when closing file. "shr=nil"- Disallow file sharing while file is open. */ static FILE * VMS_freopen (fname, type, oldfile) char *fname; char *type; FILE *oldfile; { #undef freopen /* Get back the real freopen routine. */ if (strcmp (type, "w") == 0) return freopen (fname, type, oldfile, "mbc=16", "deq=64", "fop=tef", "shr=nil"); return freopen (fname, type, oldfile, "mbc=16"); } static FILE * VMS_fopen (fname, type) char *fname; char *type; { #undef fopen /* Get back the real fopen routine. */ /* The gcc-vms-1.42 distribution's header files prototype fopen with two fixed arguments, which matches ANSI's specification but not VAXCRTL's pre-ANSI implementation. This hack circumvents the mismatch problem. */ FILE *(*vmslib_fopen)() = (FILE *(*)()) fopen; if (*type == 'w') return (*vmslib_fopen) (fname, type, "mbc=32", "deq=64", "fop=tef", "shr=nil"); else return (*vmslib_fopen) (fname, type, "mbc=32"); } static int VMS_open (fname, flags, prot) char *fname; int flags; int prot; { #undef open /* Get back the real open routine. */ return open (fname, flags, prot, "mbc=16", "deq=64", "fop=tef"); } /* more VMS hackery */ #include #include extern unsigned long sys$parse(), sys$search(); /* Work around another library bug. If a file is located via a searchlist, and if the device it's on is not the same device as the one specified in the first element of that searchlist, then both stat() and fstat() will fail to return info about it. `errno' will be set to EVMSERR, and `vaxc$errno' will be set to SS$_NORMAL due yet another bug in stat()! We can get around this by fully parsing the filename and then passing that absolute name to stat(). Without this fix, we can end up failing to find header files, which is bad enough, but then compounding the problem by reporting the reason for failure as "normal successful completion." */ #undef fstat /* Get back to the library version. */ static int VMS_fstat (fd, statbuf) int fd; struct stat *statbuf; { int result = fstat (fd, statbuf); if (result < 0) { FILE *fp; char nambuf[NAM$C_MAXRSS+1]; if ((fp = fdopen (fd, "r")) != 0 && fgetname (fp, nambuf) != 0) result = VMS_stat (nambuf, statbuf); /* No fclose(fp) here; that would close(fd) as well. */ } return result; } static int VMS_stat (name, statbuf) const char *name; struct stat *statbuf; { int result = stat (name, statbuf); if (result < 0) { struct FAB fab; struct NAM nam; char exp_nam[NAM$C_MAXRSS+1], /* expanded name buffer for sys$parse */ res_nam[NAM$C_MAXRSS+1]; /* resultant name buffer for sys$search */ fab = cc$rms_fab; fab.fab$l_fna = (char *) name; fab.fab$b_fns = (unsigned char) strlen (name); fab.fab$l_nam = (void *) &nam; nam = cc$rms_nam; nam.nam$l_esa = exp_nam, nam.nam$b_ess = sizeof exp_nam - 1; nam.nam$l_rsa = res_nam, nam.nam$b_rss = sizeof res_nam - 1; nam.nam$b_nop = NAM$M_PWD | NAM$M_NOCONCEAL; if (sys$parse (&fab) & 1) { if (sys$search (&fab) & 1) { res_nam[nam.nam$b_rsl] = '\0'; result = stat (res_nam, statbuf); } /* Clean up searchlist context cached by the system. */ nam.nam$b_nop = NAM$M_SYNCHK; fab.fab$l_fna = 0, fab.fab$b_fns = 0; (void) sys$parse (&fab); } } return result; } #endif /* VMS */ IceE-trans-1.2.0/src/icecpp/Makefile0000664000076400007640000000130610620635757016523 0ustar dwaynedwayne# ********************************************************************** # # Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. # # This copy of Ice is licensed to you under the terms described in the # ICE_LICENSE file included in this distribution. # # ********************************************************************** top_srcdir = ../.. NAME = $(top_srcdir)/bin/icecpp TARGETS = $(NAME) OBJS = cccp.o \ cexp.o \ prefix.o include $(top_srcdir)/config/Make.rules CFLAGS += -I. -DPREFIX=\"\" #cexp.c: cexp.y # bison -o cexp.c cexp.y $(NAME): $(OBJS) rm -f $@ $(CC) $(CFLAGS) -o $@ $(OBJS) install:: all $(call installprogram,$(NAME),$(install_bindir)) clean:: # rm -f cexp.c IceE-trans-1.2.0/src/icecpp/Makefile.mak0000664000076400007640000000250010620635757017267 0ustar dwaynedwayne# ********************************************************************** # # Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. # # This copy of Ice is licensed to you under the terms described in the # ICE_LICENSE file included in this distribution. # # ********************************************************************** top_srcdir = ..\.. NAME = $(top_srcdir)\bin\icecpp.exe TARGETS = $(NAME) OBJS = cccp.obj \ cexp.obj \ prefix.obj !include $(top_srcdir)/config/Make.rules.mak CFLAGS = $(CFLAGS) -I. -I../../include -DWIN32_LEAN_AND_MEAN !if "$(CPP_COMPILER)" != "BCC2006" LINKWITH = advapi32.lib !endif !if "$(CPP_COMPILER)" != "BCC2006" & "$(OPTIMIZE)" != "yes" PDBFLAGS = /pdb:$(NAME:.exe=.pdb) !endif #cexp.c: cexp.y # bison -o cexp.c cexp.y prefix.obj: prefix.c $(CC) /c $(CPPFLAGS) $(CFLAGS) -D__STDC__ prefix.c $(NAME): $(OBJS) $(LINK) $(LD_EXEFLAGS) $(PDBFLAGS) $(OBJS) $(SETARGV) $(PREOUT)$@ $(PRELIBS)$(LINKWITH) @if exist $@.manifest echo ^ ^ ^ Embedding manifest using $(MT) && \ $(MT) -nologo -manifest $@.manifest -outputresource:$@;#1 && del /q $@.manifest install:: all copy $(NAME) $(install_bindir) !if "$(CPP_COMPILER)" != "BCC2006" & "$(OPTIMIZE)" != "yes" install:: all copy $(NAME:.exe=.pdb) $(install_bindir) !endif clean:: # del /q cexp.c del /q $(NAME:.exe=.*) IceE-trans-1.2.0/src/icecpp/pcp.h0000664000076400007640000000624410560413774016020 0ustar dwaynedwayne/* pcp.h -- Describes the format of a precompiled file Copyright (C) 1990 Free Software Foundation, Inc. This file is part of GNU CC. GNU CC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU CC; see the file COPYING. If not, write to the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /* Structure allocated for every string in a precompiled file */ typedef struct stringdef STRINGDEF; struct stringdef { U_CHAR *contents; /* String to include */ int len; /* Its length */ int writeflag; /* Whether we write this */ int lineno; /* Linenumber of source file */ U_CHAR *filename; /* Name of source file */ STRINGDEF *chain; /* Global list of strings in natural order */ int output_mark; /* Where in the output this goes */ }; typedef struct keydef KEYDEF; struct keydef { STRINGDEF *str; KEYDEF *chain; }; /* Format: */ /* A precompiled file starts with a series of #define and #undef statements: #define MAC DEF --- Indicates MAC must be defined with defn DEF #define MAC --- Indicates MAC must be defined with any defn #undef MAC --- Indicates MAC cannot be defined These preconditions must be true for a precompiled file to be used. The preconditions section is null terminated. */ /* Then, there is a four byte number (in network byte order) which */ /* indicates the number of strings the file contains. */ /* Each string contains a STRINGDEF structure. The only component of */ /* the STRINGDEF structure which is used is the lineno field, which */ /* should hold the line number in the original header file. */ /* Then follows the string, followed by a null. Then comes a four */ /* byte number (again, in network byte order) indicating the number */ /* of keys for this string. Each key is a KEYDEF structure, with */ /* irrelevant contents, followed by the null-terminated string. */ /* If the number of keys is 0, then there are no keys for the string, */ /* in other words, the string will never be included. If the number */ /* of keys is -1, this is a special flag indicating there are no keys */ /* in the file, and the string is mandatory (that is, it must be */ /* included regardless in the included output). */ /* A file, then, looks like this: Precondition 1 Precondition 2 . . . Number of strings STRINGDEF String . . . Number of keys KEYDEF Key . . . KEYDEF Key . . . . . . STRINGDEF String . . . Number of keys KEYDEF Key . . . . . . . . . */ IceE-trans-1.2.0/src/slice2javae/0000775000076400007640000000000010620635757016010 5ustar dwaynedwayneIceE-trans-1.2.0/src/slice2javae/Gen.h0000664000076400007640000001316410576520443016672 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** #ifndef GEN_H #define GEN_H #include #include // // The Ice-E version. // #define ICEE_STRING_VERSION "1.2.0" // "A.B.C", with A=major, B=minor, C=patch #define ICEE_INT_VERSION 10200 // AABBCC, with AA=major, BB=minor, CC=patch namespace Slice { class JavaEOutput : public JavaOutput { public: virtual void printHeader(); }; class JavaVisitor : public JavaGenerator, public ParserVisitor { public: virtual ~JavaVisitor(); protected: JavaVisitor(const std::string&); virtual JavaOutput* createOutput(); // // Compose the parameter lists for an operation. // std::vector getParams(const OperationPtr&, const std::string&); // // Compose the argument lists for an operation. // std::vector getArgs(const OperationPtr&); // // Generate a throws clause containing only non-local exceptions. // void writeThrowsClause(const std::string&, const ExceptionList&); // // Generate code to compute a hash code for a type. // void writeHashCode(::IceUtil::Output&, const TypePtr&, const std::string&, int&); // // Generate dispatch methods for a class or interface. // void writeDispatch(::IceUtil::Output&, const ClassDefPtr&); }; class Gen : private ::IceUtil::noncopyable { public: Gen(const std::string&, const std::string&, const std::vector&, const std::string&); ~Gen(); bool operator!() const; // Returns true if there was a constructor error void generate(const UnitPtr&); void generateTie(const UnitPtr&); void generateImpl(const UnitPtr&); void generateImplTie(const UnitPtr&); private: std::string _base; std::vector _includePaths; std::string _dir; class OpsVisitor : public JavaVisitor { public: OpsVisitor(const std::string&); virtual bool visitClassDefStart(const ClassDefPtr&); private: void writeOperations(const ClassDefPtr&, bool); }; class TieVisitor : public JavaVisitor { public: TieVisitor(const std::string&); virtual bool visitClassDefStart(const ClassDefPtr&); }; class PackageVisitor : public JavaVisitor { public: PackageVisitor(const std::string&); virtual bool visitModuleStart(const ModulePtr&); }; class TypesVisitor : public JavaVisitor { public: TypesVisitor(const std::string&); virtual bool visitClassDefStart(const ClassDefPtr&); virtual void visitClassDefEnd(const ClassDefPtr&); virtual bool visitExceptionStart(const ExceptionPtr&); virtual void visitExceptionEnd(const ExceptionPtr&); virtual bool visitStructStart(const StructPtr&); virtual void visitStructEnd(const StructPtr&); virtual void visitEnum(const EnumPtr&); virtual void visitConst(const ConstPtr&); virtual void visitDataMember(const DataMemberPtr&); }; class HolderVisitor : public JavaVisitor { public: HolderVisitor(const std::string&); virtual bool visitClassDefStart(const ClassDefPtr&); virtual bool visitStructStart(const StructPtr&); virtual void visitSequence(const SequencePtr&); virtual void visitDictionary(const DictionaryPtr&); virtual void visitEnum(const EnumPtr&); private: void writeHolder(const TypePtr&); }; class HelperVisitor : public JavaVisitor { public: HelperVisitor(const std::string&); virtual bool visitClassDefStart(const ClassDefPtr&); virtual bool visitStructStart(const StructPtr&); virtual void visitSequence(const SequencePtr&); virtual void visitDictionary(const DictionaryPtr&); virtual void visitEnum(const EnumPtr&); }; class ProxyVisitor : public JavaVisitor { public: ProxyVisitor(const std::string&); virtual bool visitClassDefStart(const ClassDefPtr&); virtual void visitClassDefEnd(const ClassDefPtr&); virtual void visitOperation(const OperationPtr&); }; class DispatcherVisitor : public JavaVisitor { public: DispatcherVisitor(const std::string&); virtual bool visitClassDefStart(const ClassDefPtr&); }; class BaseImplVisitor : public JavaVisitor { public: BaseImplVisitor(const std::string&); protected: // // Generate code to emit a local variable declaration and initialize it // if necessary. // void writeDecl(::IceUtil::Output&, const std::string&, const std::string&, const TypePtr&, const StringList&); // // Generate code to return a value. // void writeReturn(::IceUtil::Output&, const TypePtr&); // // Generate an operation. // void writeOperation(::IceUtil::Output&, const std::string&, const OperationPtr&, bool); }; class ImplVisitor : public BaseImplVisitor { public: ImplVisitor(const std::string&); virtual bool visitClassDefStart(const ClassDefPtr&); }; class ImplTieVisitor : public BaseImplVisitor { public: ImplTieVisitor(const std::string&); virtual bool visitClassDefStart(const ClassDefPtr&); }; }; } #endif IceE-trans-1.2.0/src/slice2javae/.depend0000664000076400007640000000156110562516517017250 0ustar dwaynedwayneGen$(OBJEXT): Gen.cpp ../../include/IceUtil/DisableWarnings.h Gen.h ../../include/Slice/Parser.h ../../include/IceUtil/Shared.h ../../include/IceUtil/Config.h ../../include/IceUtil/Handle.h ../../include/IceUtil/Exception.h ../../include/IceUtil/InputUtil.h ../../include/Slice/JavaUtil.h ../../include/IceUtil/OutputUtil.h ../../include/IceUtil/Functional.h ../../include/IceUtil/Algorithm.h ../../include/IceUtil/Iterator.h Main$(OBJEXT): Main.cpp ../../include/IceUtil/Options.h ../../include/IceUtil/Config.h ../../include/IceUtil/RecMutex.h ../../include/IceUtil/Lock.h ../../include/IceUtil/ThreadException.h ../../include/IceUtil/Exception.h ../../include/IceUtil/Shared.h ../../include/IceUtil/Handle.h ../../include/Slice/Preprocessor.h Gen.h ../../include/Slice/Parser.h ../../include/IceUtil/InputUtil.h ../../include/Slice/JavaUtil.h ../../include/IceUtil/OutputUtil.h IceE-trans-1.2.0/src/slice2javae/Makefile0000664000076400007640000000126510550516551017444 0ustar dwaynedwayne# ********************************************************************** # # Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. # # This copy of Ice is licensed to you under the terms described in the # ICE_LICENSE file included in this distribution. # # ********************************************************************** top_srcdir = ../.. NAME = $(top_srcdir)/bin/slice2javae TARGETS = $(NAME) OBJS = Gen.o \ Main.o SRCS = $(OBJS:.o=.cpp) include $(top_srcdir)/config/Make.rules CPPFLAGS := -I. $(CPPFLAGS) $(NAME): $(OBJS) rm -f $@ $(CXX) $(LDFLAGS) -o $@ $(OBJS) -lSlice $(BASELIBS) install:: all $(INSTALL_PROGRAM) $(NAME) $(install_bindir) include .depend IceE-trans-1.2.0/src/slice2javae/Makefile.mak0000664000076400007640000000235610571526305020216 0ustar dwaynedwayne# ********************************************************************** # # Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. # # This copy of Ice is licensed to you under the terms described in the # ICE_LICENSE file included in this distribution. # # ********************************************************************** top_srcdir = ..\.. NAME = $(top_srcdir)\bin\slice2javae.exe TARGETS = $(NAME) OBJS = Gen.obj \ Main.obj SRCS = $(OBJS:.obj=.cpp) !include $(top_srcdir)/config/Make.rules.mak CPPFLAGS = -I. $(CPPFLAGS) -DWIN32_LEAN_AND_MEAN !if "$(CPP_COMPILER)" != "BCC2006" & "$(OPTIMIZE)" != "yes" PDBFLAGS = /pdb:$(NAME:.exe=.pdb) !endif $(NAME): $(OBJS) $(LINK) $(LD_EXEFLAGS) $(PDBFLAGS) $(OBJS) $(SETARGV) $(PREOUT)$@ $(PRELIBS)slice$(LIBSUFFIX).lib $(BASELIBS) @if exist $@.manifest echo ^ ^ ^ Embedding manifest using $(MT) && \ $(MT) -nologo -manifest $@.manifest -outputresource:$@;#1 && del /q $@.manifest clean:: del /q $(NAME:.exe=.*) install:: all copy $(NAME) $(install_bindir) !if "$(OPTIMIZE)" != "yes" !if "$(CPP_COMPILER)" == "BCC2006" install:: all copy $(NAME:.exe=.tds) $(install_bindir) !else install:: all copy $(NAME:.exe=.pdb) $(install_bindir) !endif !endif !include .depend IceE-trans-1.2.0/src/slice2javae/Main.cpp0000664000076400007640000001411610561612334017371 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 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 using namespace std; using namespace Slice; void usage(const char* n) { cerr << "Usage: " << n << " [options] slice-files...\n"; cerr << "Options:\n" "-h, --help Show this message.\n" "-v, --version Display the Ice version.\n" "-DNAME Define NAME as 1.\n" "-DNAME=DEF Define NAME as DEF.\n" "-UNAME Remove any definition for NAME.\n" "-IDIR Put DIR in the include file search path.\n" "-E Print preprocessor output on stdout.\n" "--output-dir DIR Create files in the directory DIR.\n" "--tie Generate TIE classes.\n" "--impl Generate sample implementations.\n" "--impl-tie Generate sample TIE implementations.\n" "--depend Generate Makefile dependencies.\n" "-d, --debug Print debug messages.\n" "--ice Permit `Ice' prefix (for building Ice source code only)\n" ; // Note: --case-sensitive is intentionally not shown here! } int main(int argc, char* argv[]) { IceUtil::Options opts; opts.addOpt("h", "help"); opts.addOpt("v", "version"); opts.addOpt("D", "", IceUtil::Options::NeedArg, "", IceUtil::Options::Repeat); opts.addOpt("U", "", IceUtil::Options::NeedArg, "", IceUtil::Options::Repeat); opts.addOpt("I", "", IceUtil::Options::NeedArg, "", IceUtil::Options::Repeat); opts.addOpt("E"); opts.addOpt("", "output-dir", IceUtil::Options::NeedArg); opts.addOpt("", "tie"); opts.addOpt("", "impl"); opts.addOpt("", "impl-tie"); opts.addOpt("", "depend"); opts.addOpt("d", "debug"); opts.addOpt("", "ice"); opts.addOpt("", "case-sensitive"); vectorargs; try { args = opts.parse(argc, (const char**)argv); } catch(const IceUtil::BadOptException& e) { cerr << argv[0] << ": " << e.reason << endl; usage(argv[0]); return EXIT_FAILURE; } if(opts.isSet("help")) { usage(argv[0]); return EXIT_SUCCESS; } if(opts.isSet("version")) { cout << ICEE_STRING_VERSION << endl; return EXIT_SUCCESS; } string cppArgs; vector optargs = opts.argVec("D"); vector::const_iterator i; for(i = optargs.begin(); i != optargs.end(); ++i) { cppArgs += " -D" + Preprocessor::addQuotes(*i); } optargs = opts.argVec("U"); for(i = optargs.begin(); i != optargs.end(); ++i) { cppArgs += " -U" + Preprocessor::addQuotes(*i); } vector includePaths = opts.argVec("I"); for(i = includePaths.begin(); i != includePaths.end(); ++i) { cppArgs += " -I" + Preprocessor::normalizeIncludePath(*i); } bool preprocess = opts.isSet("E"); string output = opts.optArg("output-dir"); bool tie = opts.isSet("tie"); bool impl = opts.isSet("impl"); bool implTie = opts.isSet("impl-tie"); bool depend = opts.isSet("depend"); bool debug = opts.isSet("debug"); bool ice = opts.isSet("ice"); bool caseSensitive = opts.isSet("case-sensitive"); if(args.empty()) { cerr << argv[0] << ": no input file" << endl; usage(argv[0]); return EXIT_FAILURE; } if(impl && implTie) { cerr << argv[0] << ": cannot specify both --impl and --impl-tie" << endl; usage(argv[0]); return EXIT_FAILURE; } int status = EXIT_SUCCESS; for(i = args.begin(); i != args.end(); ++i) { if(depend) { Preprocessor icecpp(argv[0], *i, cppArgs); icecpp.printMakefileDependencies(Preprocessor::Java); } else { Preprocessor icecpp(argv[0], *i, cppArgs); FILE* cppHandle = icecpp.preprocess(false); if(cppHandle == 0) { return EXIT_FAILURE; } if(preprocess) { char buf[4096]; while(fgets(buf, static_cast(sizeof(buf)), cppHandle) != NULL) { if(fputs(buf, stdout) == EOF) { return EXIT_FAILURE; } } if(!icecpp.close()) { return EXIT_FAILURE; } } else { UnitPtr p = Unit::createUnit(false, false, ice, caseSensitive); int parseStatus = p->parse(cppHandle, debug, Slice::IceE); if(!icecpp.close()) { p->destroy(); return EXIT_FAILURE; } if(parseStatus == EXIT_FAILURE) { status = EXIT_FAILURE; } else { Gen gen(argv[0], icecpp.getBaseName(), includePaths, output); if(!gen) { p->destroy(); return EXIT_FAILURE; } gen.generate(p); if(tie) { gen.generateTie(p); } if(impl) { gen.generateImpl(p); } if(implTie) { gen.generateImplTie(p); } } p->destroy(); } } } return status; } IceE-trans-1.2.0/src/slice2javae/Gen.cpp0000664000076400007640000026352310614370531017225 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 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 using namespace std; using namespace Slice; // // Don't use "using namespace IceUtil", or stupid VC++ 6.0 complains // about ambigious symbols for constructs like // "IceUtil::constMemFun(&Slice::Exception::isLocal)". // using IceUtil::Output; using IceUtil::nl; using IceUtil::sp; using IceUtil::sb; using IceUtil::eb; using IceUtil::spar; using IceUtil::epar; static string sliceModeToIceMode(Operation::Mode opMode) { string mode; switch(opMode) { case Operation::Normal: { mode = "Ice.OperationMode.Normal"; break; } case Operation::Nonmutating: { mode = "Ice.OperationMode.Nonmutating"; break; } case Operation::Idempotent: { mode = "Ice.OperationMode.Idempotent"; break; } default: { assert(false); break; } } return mode; } static string getDeprecateReason(const ContainedPtr& p1, const ContainedPtr& p2, const string& type) { string deprecateMetadata, deprecateReason; if(p1->findMetaData("deprecate", deprecateMetadata) || (p2 != 0 && p2->findMetaData("deprecate", deprecateMetadata))) { deprecateReason = "This " + type + " has been deprecated."; if(deprecateMetadata.find("deprecate:") == 0 && deprecateMetadata.size() > 10) { deprecateReason = deprecateMetadata.substr(10); } } return deprecateReason; } void Slice::JavaEOutput::printHeader() { static const char* header = "// **********************************************************************\n" "//\n" "// Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved.\n" "//\n" "// This copy of Ice-E is licensed to you under the terms described in the\n" "// ICEE_LICENSE file included in this distribution.\n" "//\n" "// **********************************************************************\n" ; print(header); print("\n// Ice-E version "); print(ICEE_STRING_VERSION); } Slice::JavaVisitor::JavaVisitor(const string& dir) : JavaGenerator(dir, Slice::IceE) { } Slice::JavaVisitor::~JavaVisitor() { } JavaOutput* Slice::JavaVisitor::createOutput() { return new JavaEOutput; } vector Slice::JavaVisitor::getParams(const OperationPtr& op, const string& package) { vector params; ParamDeclList paramList = op->parameters(); for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q) { StringList metaData = (*q)->getMetaData(); string typeString = typeToString((*q)->type(), (*q)->isOutParam() ? TypeModeOut : TypeModeIn, package, metaData); params.push_back(typeString + ' ' + fixKwd((*q)->name())); } return params; } vector Slice::JavaVisitor::getArgs(const OperationPtr& op) { vector args; ParamDeclList paramList = op->parameters(); for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q) { args.push_back(fixKwd((*q)->name())); } return args; } void Slice::JavaVisitor::writeThrowsClause(const string& package, const ExceptionList& throws) { Output& out = output(); if(throws.size() > 0) { out.inc(); out << nl << "throws "; out.useCurrentPosAsIndent(); ExceptionList::const_iterator r; int count = 0; for(r = throws.begin(); r != throws.end(); ++r) { if(count > 0) { out << "," << nl; } out << getAbsolute(*r, package); count++; } out.restoreIndent(); out.dec(); } } void Slice::JavaVisitor::writeHashCode(Output& out, const TypePtr& type, const string& name, int& iter) { BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); if(builtin) { switch(builtin->kind()) { case Builtin::KindByte: case Builtin::KindShort: case Builtin::KindLong: { out << nl << "__h = 5 * __h + (int)" << name << ';'; break; } case Builtin::KindBool: { out << nl << "__h = 5 * __h + (" << name << " ? 1 : 0);"; break; } case Builtin::KindInt: { out << nl << "__h = 5 * __h + " << name << ';'; break; } case Builtin::KindFloat: { out << nl << "__h = 5 * __h + java.lang.Float.floatToIntBits(" << name << ");"; break; } case Builtin::KindDouble: { out << nl << "__h = 5 * __h + (int)java.lang.Double.doubleToLongBits(" << name << ");"; break; } case Builtin::KindString: { out << nl << "if(" << name << " != null)"; out << sb; out << nl << "__h = 5 * __h + " << name << ".hashCode();"; out << eb; break; } case Builtin::KindObject: case Builtin::KindObjectProxy: case Builtin::KindLocalObject: { out << nl << "if(" << name << " != null)"; out << sb; out << nl << "__h = 5 * __h + " << name << ".hashCode();"; out << eb; break; } } return; } ProxyPtr prx = ProxyPtr::dynamicCast(type); ClassDeclPtr cl = ClassDeclPtr::dynamicCast(type); DictionaryPtr dict = DictionaryPtr::dynamicCast(type); if(prx || cl || dict) { out << nl << "if(" << name << " != null)"; out << sb; out << nl << "__h = 5 * __h + " << name << ".hashCode();"; out << eb; return; } SequencePtr seq = SequencePtr::dynamicCast(type); if(seq) { out << nl << "if(" << name << " != null)"; out << sb; out << nl << "for(int __i" << iter << " = 0; __i" << iter << " < " << name << ".length; __i" << iter << "++)"; out << sb; ostringstream elem; elem << name << "[__i" << iter << ']'; iter++; writeHashCode(out, seq->type(), elem.str(), iter); out << eb; out << eb; return; } ConstructedPtr constructed = ConstructedPtr::dynamicCast(type); assert(constructed); out << nl << "__h = 5 * __h + " << name << ".hashCode();"; } void Slice::JavaVisitor::writeDispatch(Output& out, const ClassDefPtr& p) { string name = fixKwd(p->name()); string package = getPackage(p); string scoped = p->scoped(); ClassList bases = p->bases(); ClassList allBases = p->allBases(); StringList ids; transform(allBases.begin(), allBases.end(), back_inserter(ids), ::IceUtil::constMemFun(&Contained::scoped)); StringList other; other.push_back(scoped); other.push_back("::Ice::Object"); other.sort(); ids.merge(other); ids.unique(); StringList::const_iterator firstIter = ids.begin(); StringList::const_iterator scopedIter = find(ids.begin(), ids.end(), scoped); assert(scopedIter != ids.end()); StringList::difference_type scopedPos = ice_distance(firstIter, scopedIter); out << sp << nl << "public static final String[] __ids ="; out << sb; { StringList::const_iterator q = ids.begin(); while(q != ids.end()) { out << nl << '"' << *q << '"'; if(++q != ids.end()) { out << ','; } } } out << eb << ';'; out << sp << nl << "public boolean" << nl << "ice_isA(String s)"; out << sb; out << nl << "return IceUtil.Arrays.search(__ids, s) >= 0;"; out << eb; out << sp << nl << "public boolean" << nl << "ice_isA(String s, Ice.Current __current)"; out << sb; out << nl << "return IceUtil.Arrays.search(__ids, s) >= 0;"; out << eb; out << sp << nl << "public String[]" << nl << "ice_ids()"; out << sb; out << nl << "return __ids;"; out << eb; out << sp << nl << "public String[]" << nl << "ice_ids(Ice.Current __current)"; out << sb; out << nl << "return __ids;"; out << eb; out << sp << nl << "public String" << nl << "ice_id()"; out << sb; out << nl << "return __ids[" << scopedPos << "];"; out << eb; out << sp << nl << "public String" << nl << "ice_id(Ice.Current __current)"; out << sb; out << nl << "return __ids[" << scopedPos << "];"; out << eb; out << sp << nl << "public static String" << nl << "ice_staticId()"; out << sb; out << nl << "return __ids[" << scopedPos << "];"; out << eb; OperationList ops = p->allOperations(); OperationList::const_iterator r; // // Write the "no Current" implementation of each operation. // for(r = ops.begin(); r != ops.end(); ++r) { OperationPtr op = *r; string opName = op->name(); ContainerPtr container = op->container(); ClassDefPtr cl = ClassDefPtr::dynamicCast(container); assert(cl); vector params; vector args; TypePtr ret; opName = fixKwd(opName); ret = op->returnType(); params = getParams(op, package); args = getArgs(op); ExceptionList throws = op->throws(); throws.sort(); throws.unique(); // // Only generate a "no current" version of the operation if it hasn't been done in a base // class already, because the "no current" version is final. // bool generateOperation = cl == p; // Generate if the operation is defined in this class. if(!generateOperation) { // // The operation is not defined in this class. // if(!bases.empty()) { // // Check if the operation is already implemented by a base class. // bool implementedByBase = false; if(!bases.front()->isInterface()) { OperationList baseOps = bases.front()->allOperations(); OperationList::const_iterator i; for(i = baseOps.begin(); i != baseOps.end(); ++i) { if((*i)->name() == op->name()) { implementedByBase = true; break; } } if(i == baseOps.end()) { generateOperation = true; } } if(!generateOperation && !implementedByBase) { // // No base class defines the operation. Check if one of the // interfaces defines it, in which case this class must provide it. // if(bases.front()->isInterface() || bases.size() > 1) { generateOperation = true; } } } } if(generateOperation) { out << sp << nl << "public final " << typeToString(ret, TypeModeReturn, package, op->getMetaData()) << nl << opName << spar << params << epar; writeThrowsClause(package, throws); out << sb << nl; if(ret) { out << nl << "return "; } out << opName << spar << args << "null" << epar << ';'; out << eb; } } // // Dispatch operations. We only generate methods for operations // defined in this ClassDef, because we reuse existing methods // for inherited operations. // ops = p->operations(); for(r = ops.begin(); r != ops.end(); ++r) { OperationPtr op = *r; StringList opMetaData = op->getMetaData(); ContainerPtr container = op->container(); ClassDefPtr cl = ClassDefPtr::dynamicCast(container); assert(cl); string opName = op->name(); out << sp << nl << "public static IceInternal.DispatchStatus" << nl << "___" << opName << '(' << name << " __obj, IceInternal.Incoming __in, Ice.Current __current)"; out << sb; TypePtr ret = op->returnType(); ParamDeclList inParams; ParamDeclList outParams; ParamDeclList paramList = op->parameters(); ParamDeclList::const_iterator pli; for(pli = paramList.begin(); pli != paramList.end(); ++pli) { if((*pli)->isOutParam()) { outParams.push_back(*pli); } else { inParams.push_back(*pli); } } ExceptionList throws = op->throws(); throws.sort(); throws.unique(); // // Arrange exceptions into most-derived to least-derived order. If we don't // do this, a base exception handler can appear before a derived exception // handler, causing compiler warnings and resulting in the base exception // being marshaled instead of the derived exception. // #if defined(__SUNPRO_CC) throws.sort(Slice::derivedToBaseCompare); #else throws.sort(Slice::DerivedToBaseCompare()); #endif int iter; out << nl << "__checkMode(" << sliceModeToIceMode(op->mode()) << ", __current.mode);"; if(!inParams.empty()) { out << nl << "IceInternal.BasicStream __is = __in.is();"; } if(!outParams.empty() || ret || !throws.empty()) { out << nl << "IceInternal.BasicStream __os = __in.os();"; } // // Unmarshal 'in' parameters. // iter = 0; for(pli = inParams.begin(); pli != inParams.end(); ++pli) { StringList metaData = (*pli)->getMetaData(); TypePtr paramType = (*pli)->type(); string paramName = fixKwd((*pli)->name()); string typeS = typeToString(paramType, TypeModeIn, package, metaData); BuiltinPtr builtin = BuiltinPtr::dynamicCast(paramType); if((builtin && builtin->kind() == Builtin::KindObject) || ClassDeclPtr::dynamicCast(paramType)) { out << nl << typeS << "Holder " << paramName << " = new " << typeS << "Holder();"; writeMarshalUnmarshalCode(out, package, paramType, paramName, false, iter, true, metaData, string()); } else { out << nl << typeS << ' ' << paramName << ';'; writeMarshalUnmarshalCode(out, package, paramType, paramName, false, iter, false, metaData); } } // // Create holders for 'out' parameters. // for(pli = outParams.begin(); pli != outParams.end(); ++pli) { string typeS = typeToString((*pli)->type(), TypeModeOut, package, (*pli)->getMetaData()); out << nl << typeS << ' ' << fixKwd((*pli)->name()) << " = new " << typeS << "();"; } // // Call on the servant. // if(!throws.empty()) { out << nl << "try"; out << sb; } out << nl; if(ret) { string retS = typeToString(ret, TypeModeReturn, package, opMetaData); out << retS << " __ret = "; } out << "__obj." << fixKwd(opName) << '('; for(pli = inParams.begin(); pli != inParams.end(); ++pli) { TypePtr paramType = (*pli)->type(); out << fixKwd((*pli)->name()); BuiltinPtr builtin = BuiltinPtr::dynamicCast(paramType); if((builtin && builtin->kind() == Builtin::KindObject) || ClassDeclPtr::dynamicCast(paramType)) { out << ".value"; } out << ", "; } for(pli = outParams.begin(); pli != outParams.end(); ++pli) { out << fixKwd((*pli)->name()) << ", "; } out << "__current);"; // // Marshal 'out' parameters and return value. // for(pli = outParams.begin(); pli != outParams.end(); ++pli) { writeMarshalUnmarshalCode(out, package, (*pli)->type(), fixKwd((*pli)->name()), true, iter, true, (*pli)->getMetaData()); } if(ret) { writeMarshalUnmarshalCode(out, package, ret, "__ret", true, iter, false, opMetaData); } out << nl << "return IceInternal.DispatchStatus.DispatchOK;"; // // Handle user exceptions. // if(!throws.empty()) { out << eb; ExceptionList::const_iterator t; for(t = throws.begin(); t != throws.end(); ++t) { string exS = getAbsolute(*t, package); out << nl << "catch(" << exS << " ex)"; out << sb; out << nl << "__os.writeUserException(ex);"; out << nl << "return IceInternal.DispatchStatus.DispatchUserException;"; out << eb; } } out << eb; } OperationList allOps = p->allOperations(); if(!allOps.empty()) { StringList allOpNames; transform(allOps.begin(), allOps.end(), back_inserter(allOpNames), ::IceUtil::constMemFun(&Contained::name)); allOpNames.push_back("ice_id"); allOpNames.push_back("ice_ids"); allOpNames.push_back("ice_isA"); allOpNames.push_back("ice_ping"); allOpNames.sort(); allOpNames.unique(); StringList::const_iterator q; out << sp << nl << "private final static String[] __all ="; out << sb; q = allOpNames.begin(); while(q != allOpNames.end()) { out << nl << '"' << *q << '"'; if(++q != allOpNames.end()) { out << ','; } } out << eb << ';'; out << sp << nl << "public IceInternal.DispatchStatus" << nl << "__dispatch(IceInternal.Incoming in, Ice.Current __current)"; out << sb; out << nl << "int pos = IceUtil.Arrays.search(__all, __current.operation);"; out << nl << "if(pos < 0)"; out << sb; out << nl << "return IceInternal.DispatchStatus.DispatchOperationNotExist;"; out << eb; out << sp << nl << "switch(pos)"; out << sb; int i = 0; for(q = allOpNames.begin(); q != allOpNames.end(); ++q) { string opName = *q; out << nl << "case " << i++ << ':'; out << sb; if(opName == "ice_id") { out << nl << "return ___ice_id(this, in, __current);"; } else if(opName == "ice_ids") { out << nl << "return ___ice_ids(this, in, __current);"; } else if(opName == "ice_isA") { out << nl << "return ___ice_isA(this, in, __current);"; } else if(opName == "ice_ping") { out << nl << "return ___ice_ping(this, in, __current);"; } else { // // There's probably a better way to do this. // for(OperationList::const_iterator t = allOps.begin(); t != allOps.end(); ++t) { if((*t)->name() == (*q)) { ContainerPtr container = (*t)->container(); ClassDefPtr cl = ClassDefPtr::dynamicCast(container); assert(cl); if(cl->scoped() == p->scoped()) { out << nl << "return ___" << opName << "(this, in, __current);"; } else { string base; if(cl->isInterface()) { base = getAbsolute(cl, package, "_", "Disp"); } else { base = getAbsolute(cl, package); } out << nl << "return " << base << ".___" << opName << "(this, in, __current);"; } break; } } } out << eb; } out << eb; out << nl << "if(IceUtil.Debug.ASSERT)"; out << sb; out << sp << nl << "IceUtil.Debug.Assert(false);"; out << eb; out << nl << "return IceInternal.DispatchStatus.DispatchOperationNotExist;"; out << eb; } } Slice::Gen::Gen(const string& name, const string& base, const vector& includePaths, const string& dir) : _base(base), _includePaths(includePaths), _dir(dir) { } Slice::Gen::~Gen() { } bool Slice::Gen::operator!() const { return false; } void Slice::Gen::generate(const UnitPtr& p) { JavaGenerator::validateMetaData(p); OpsVisitor opsVisitor(_dir); p->visit(&opsVisitor, false); PackageVisitor packageVisitor(_dir); p->visit(&packageVisitor, false); TypesVisitor typesVisitor(_dir); p->visit(&typesVisitor, false); HolderVisitor holderVisitor(_dir); p->visit(&holderVisitor, false); HelperVisitor helperVisitor(_dir); p->visit(&helperVisitor, false); ProxyVisitor proxyVisitor(_dir); p->visit(&proxyVisitor, false); DispatcherVisitor dispatcherVisitor(_dir); p->visit(&dispatcherVisitor, false); } void Slice::Gen::generateTie(const UnitPtr& p) { TieVisitor tieVisitor(_dir); p->visit(&tieVisitor, false); } void Slice::Gen::generateImpl(const UnitPtr& p) { ImplVisitor implVisitor(_dir); p->visit(&implVisitor, false); } void Slice::Gen::generateImplTie(const UnitPtr& p) { ImplTieVisitor implTieVisitor(_dir); p->visit(&implTieVisitor, false); } Slice::Gen::OpsVisitor::OpsVisitor(const string& dir) : JavaVisitor(dir) { } bool Slice::Gen::OpsVisitor::visitClassDefStart(const ClassDefPtr& p) { // // Don't generate an Operations interface for non-abstract classes // if(!p->isAbstract()) { return false; } writeOperations(p, false); writeOperations(p, true); return false; } void Slice::Gen::OpsVisitor::writeOperations(const ClassDefPtr& p, bool noCurrent) { string name = p->name(); ClassList bases = p->bases(); string package = getPackage(p); string opIntfName = "Operations"; if(noCurrent) { opIntfName += "NC"; } string absolute = getAbsolute(p, "", "_", opIntfName); if(!open(absolute)) { return; } Output& out = output(); // // Generate the operations interface // out << sp << nl << "public interface " << '_' << name << opIntfName; if((bases.size() == 1 && bases.front()->isAbstract()) || bases.size() > 1) { out << " extends "; out.useCurrentPosAsIndent(); ClassList::const_iterator q = bases.begin(); bool first = true; while(q != bases.end()) { if((*q)->isAbstract()) { if(!first) { out << ',' << nl; } else { first = false; } out << getAbsolute(*q, package, "_", opIntfName); } ++q; } out.restoreIndent(); } out << sb; OperationList ops = p->operations(); OperationList::const_iterator r; for(r = ops.begin(); r != ops.end(); ++r) { OperationPtr op = *r; ContainerPtr container = op->container(); ClassDefPtr cl = ClassDefPtr::dynamicCast(container); string opname = op->name(); TypePtr ret; vector params; params = getParams(op, package); ret = op->returnType(); string deprecateReason = getDeprecateReason(op, p, "operation"); string retS = typeToString(ret, TypeModeReturn, package, op->getMetaData()); ExceptionList throws = op->throws(); throws.sort(); throws.unique(); out << sp; if(!deprecateReason.empty()) { out << nl << "/**"; out << nl << " * @deprecated " << deprecateReason; out << nl << " **/"; } out << nl << retS << ' ' << fixKwd(opname) << spar << params; if(!noCurrent) { out << "Ice.Current __current"; } out << epar; writeThrowsClause(package, throws); out << ';'; } out << eb; close(); } Slice::Gen::TieVisitor::TieVisitor(const string& dir) : JavaVisitor(dir) { } bool Slice::Gen::TieVisitor::visitClassDefStart(const ClassDefPtr& p) { string name = p->name(); ClassList bases = p->bases(); string package = getPackage(p); string absolute = getAbsolute(p, "", "_", "Tie"); string opIntfName = "Operations"; // // Don't generate a TIE class for a non-abstract class // if(!p->isAbstract()) { return false; } if(!open(absolute)) { return false; } Output& out = output(); // // Generate the TIE class // out << sp << nl << "public class " << '_' << name << "Tie"; if(p->isInterface()) { out << " extends " << '_' << name << "Disp implements Ice.TieBase"; } else { out << " extends " << fixKwd(name) << " implements Ice.TieBase"; } out << sb; out << sp << nl << "public" << nl << '_' << name << "Tie()"; out << sb; out << eb; out << sp << nl << "public" << nl << '_' << name << "Tie(" << '_' << name << opIntfName << " delegate)"; out << sb; out << nl << "_ice_delegate = delegate;"; out << eb; out << sp << nl << "public java.lang.Object" << nl << "ice_delegate()"; out << sb; out << nl << "return _ice_delegate;"; out << eb; out << sp << nl << "public void" << nl << "ice_delegate(java.lang.Object delegate)"; out << sb; out << nl << "_ice_delegate = (_" << name << opIntfName << ")delegate;"; out << eb; out << sp << nl << "public boolean" << nl << "equals(java.lang.Object rhs)"; out << sb; out << nl << "if(this == rhs)"; out << sb; out << nl << "return true;"; out << eb; out << nl << "if(!(rhs instanceof " << '_' << name << "Tie))"; out << sb; out << nl << "return false;"; out << eb; out << sp << nl << "return _ice_delegate.equals(((" << '_' << name << "Tie)rhs)._ice_delegate);"; out << eb; out << sp << nl << "public int" << nl << "hashCode()"; out << sb; out << nl << "return _ice_delegate.hashCode();"; out << eb; OperationList ops = p->allOperations(); OperationList::const_iterator r; for(r = ops.begin(); r != ops.end(); ++r) { ContainerPtr container = (*r)->container(); ClassDefPtr cl = ClassDefPtr::dynamicCast(container); string opName = fixKwd((*r)->name()); TypePtr ret = (*r)->returnType(); string retS = typeToString(ret, TypeModeReturn, package, (*r)->getMetaData()); vector params = getParams((*r), package); vector args = getArgs(*r); out << sp; out << nl << "public " << retS << nl << opName << spar << params; out << "Ice.Current __current"; out << epar; ExceptionList throws = (*r)->throws(); throws.sort(); throws.unique(); writeThrowsClause(package, throws); out << sb; out << nl; if(ret) { out << "return "; } out << "_ice_delegate." << opName << spar << args; out << "__current"; out << epar << ';'; out << eb; } out << sp << nl << "private " << '_' << name << opIntfName << " _ice_delegate;"; out << eb; close(); return false; } Slice::Gen::PackageVisitor::PackageVisitor(const string& dir) : JavaVisitor(dir) { } bool Slice::Gen::PackageVisitor::visitModuleStart(const ModulePtr& p) { DefinitionContextPtr dc = p->definitionContext(); assert(dc); StringList globalMetaData = dc->getMetaData(); static const string packagePrefix = "java:package:"; for(StringList::const_iterator q = globalMetaData.begin(); q != globalMetaData.end(); ++q) { string s = *q; if(s.find(packagePrefix) == 0) { string markerClass = s.substr(packagePrefix.size()) + "." + fixKwd(p->name()) + "._Marker"; if(!open(markerClass)) { cerr << "can't open class `" << markerClass << "' for writing: " << strerror(errno) << endl; return false; } Output& out = output(); out << sp << nl << "interface _Marker"; out << sb; out << eb; close(); } } return false; } Slice::Gen::TypesVisitor::TypesVisitor(const string& dir) : JavaVisitor(dir) { } bool Slice::Gen::TypesVisitor::visitClassDefStart(const ClassDefPtr& p) { string name = p->name(); ClassList bases = p->bases(); ClassDefPtr baseClass; if(!bases.empty() && !bases.front()->isInterface()) { baseClass = bases.front(); } string package = getPackage(p); string absolute = getAbsolute(p); DataMemberList members = p->dataMembers(); DataMemberList allDataMembers = p->allDataMembers(); DataMemberList::const_iterator d; if(!open(absolute)) { return false; } Output& out = output(); // // Slice interfaces map to Java interfaces. // if(p->isInterface()) { out << sp << nl << "public interface " << fixKwd(name) << " extends "; out.useCurrentPosAsIndent(); out << "Ice.Object"; out << "," << nl << '_' << name; out << "Operations, _" << name << "OperationsNC"; if(!bases.empty()) { ClassList::const_iterator q = bases.begin(); while(q != bases.end()) { out << ',' << nl << getAbsolute(*q, package); q++; } } out.restoreIndent(); } else { out << sp << nl << "public "; if(p->isAbstract()) { out << "abstract "; } out << "class " << fixKwd(name); out.useCurrentPosAsIndent(); if(bases.empty() || bases.front()->isInterface()) { out << " extends Ice.ObjectImpl"; } else { out << " extends "; out << getAbsolute(baseClass, package); bases.pop_front(); } // // Implement interfaces // StringList implements; if(p->isAbstract()) { implements.push_back("_" + name + "Operations"); implements.push_back("_" + name + "OperationsNC"); } if(!bases.empty()) { ClassList::const_iterator q = bases.begin(); while(q != bases.end()) { implements.push_back(getAbsolute(*q, package)); q++; } } if(!implements.empty()) { out << nl << " implements "; out.useCurrentPosAsIndent(); StringList::const_iterator q = implements.begin(); while(q != implements.end()) { if(q != implements.begin()) { out << ',' << nl; } out << *q; q++; } out.restoreIndent(); } out.restoreIndent(); } out << sb; if(!p->isInterface() && !allDataMembers.empty()) { // // Constructors. // out << sp; out << nl << "public " << name << "()"; out << sb; if(baseClass) { out << nl << "super();"; } out << eb; out << sp << nl << "public " << name << spar; vector paramDecl; for(d = allDataMembers.begin(); d != allDataMembers.end(); ++d) { string memberName = fixKwd((*d)->name()); string memberType = typeToString((*d)->type(), TypeModeMember, package, (*d)->getMetaData()); paramDecl.push_back(memberType + " " + memberName); } out << paramDecl << epar; out << sb; if(baseClass && allDataMembers.size() != members.size()) { out << nl << "super" << spar; vector baseParamNames; DataMemberList baseDataMembers = baseClass->allDataMembers(); for(d = baseDataMembers.begin(); d != baseDataMembers.end(); ++d) { baseParamNames.push_back(fixKwd((*d)->name())); } out << baseParamNames << epar << ';'; } vector paramNames; for(d = members.begin(); d != members.end(); ++d) { paramNames.push_back(fixKwd((*d)->name())); } for(vector::const_iterator i = paramNames.begin(); i != paramNames.end(); ++i) { out << nl << "this." << *i << " = " << *i << ';'; } out << eb; } // // Marshalling & dispatch support. // if(!p->isInterface()) { writeDispatch(out, p); } if(!p->isInterface() && !members.empty()) { out << sp << nl << "protected void" << nl << "__copyFrom(java.lang.Object __obj)"; out << sb; if(baseClass) { out << nl << "super.__copyFrom(__obj);"; } out << nl << name << " __src = (" << name << ")__obj;"; for(d = members.begin(); d != members.end(); ++d) { string memberName = fixKwd((*d)->name()); out << nl << memberName << " = __src." << memberName << ";"; } out << eb; } return true; } void Slice::Gen::TypesVisitor::visitClassDefEnd(const ClassDefPtr& p) { Output& out = output(); out << eb; close(); } bool Slice::Gen::TypesVisitor::visitExceptionStart(const ExceptionPtr& p) { string name = fixKwd(p->name()); string scoped = p->scoped(); ExceptionPtr base = p->base(); string package = getPackage(p); string absolute = getAbsolute(p); DataMemberList allDataMembers = p->allDataMembers(); DataMemberList members = p->dataMembers(); DataMemberList::const_iterator d; if(!open(absolute)) { return false; } Output& out = output(); out << sp; string deprecateReason = getDeprecateReason(p, 0, "type"); if(!deprecateReason.empty()) { out << nl << "/**"; out << nl << " * @deprecated " << deprecateReason; out << nl << " **/"; } out << nl << "public class " << name << " extends "; if(!base) { if(p->isLocal()) { out << "Ice.LocalException"; } else { out << "Ice.UserException"; } } else { out << getAbsolute(base, package); } out << sb; if(!allDataMembers.empty()) { // // Constructors. // out << sp; out << nl << "public " << name << "()"; out << sb; if(base) { out << nl << "super();"; } out << eb; out << sp << nl << "public " << name << spar; vector paramDecl; for(d = allDataMembers.begin(); d != allDataMembers.end(); ++d) { string memberName = fixKwd((*d)->name()); string memberType = typeToString((*d)->type(), TypeModeMember, package, (*d)->getMetaData()); paramDecl.push_back(memberType + " " + memberName); } out << paramDecl << epar; out << sb; if(base && allDataMembers.size() != members.size()) { out << nl << "super" << spar; vector baseParamNames; DataMemberList baseDataMembers = base->allDataMembers(); for(d = baseDataMembers.begin(); d != baseDataMembers.end(); ++d) { baseParamNames.push_back(fixKwd((*d)->name())); } out << baseParamNames << epar << ';'; } vector paramNames; for(d = members.begin(); d != members.end(); ++d) { paramNames.push_back(fixKwd((*d)->name())); } for(vector::const_iterator i = paramNames.begin(); i != paramNames.end(); ++i) { out << nl << "this." << *i << " = " << *i << ';'; } out << eb; } out << sp << nl << "public String" << nl << "ice_name()"; out << sb; out << nl << "return \"" << scoped.substr(2) << "\";"; out << eb; return true; } void Slice::Gen::TypesVisitor::visitExceptionEnd(const ExceptionPtr& p) { Output& out = output(); if(!p->isLocal()) { string name = fixKwd(p->name()); string scoped = p->scoped(); string package = getPackage(p); ExceptionPtr base = p->base(); DataMemberList members = p->dataMembers(); DataMemberList::const_iterator d; int iter; out << sp << nl << "public void" << nl << "__write(IceInternal.BasicStream __os)"; out << sb; out << nl << "__os.writeString(\"" << scoped << "\");"; out << nl << "__os.startWriteSlice();"; iter = 0; for(d = members.begin(); d != members.end(); ++d) { StringList metaData = (*d)->getMetaData(); writeMarshalUnmarshalCode(out, package, (*d)->type(), fixKwd((*d)->name()), true, iter, false, metaData); } out << nl << "__os.endWriteSlice();"; if(base) { out << nl << "super.__write(__os);"; } out << eb; DataMemberList allClassMembers = p->allClassDataMembers(); if(allClassMembers.size() != 0) { out << sp << nl << "private class Patcher implements IceInternal.Patcher"; out << sb; if(allClassMembers.size() > 1) { out << sp << nl << "Patcher(int member)"; out << sb; out << nl << "__member = member;"; out << eb; } out << sp << nl << "public void" << nl << "patch(Ice.Object v)"; out << sb; if(allClassMembers.size() > 1) { out << nl << "switch(__member)"; out << sb; } int memberCount = 0; for(d = allClassMembers.begin(); d != allClassMembers.end(); ++d) { if(allClassMembers.size() > 1) { out.dec(); out << nl << "case " << memberCount << ":"; out.inc(); } if(allClassMembers.size() > 1) { out << nl << "__typeId = \"" << (*d)->type()->typeId() << "\";"; } string memberName = fixKwd((*d)->name()); string memberType = typeToString((*d)->type(), TypeModeMember, package); out << nl << memberName << " = (" << memberType << ")v;"; if(allClassMembers.size() > 1) { out << nl << "break;"; } memberCount++; } if(allClassMembers.size() > 1) { out << eb; } out << eb; out << sp << nl << "public String" << nl << "type()"; out << sb; if(allClassMembers.size() > 1) { out << nl << "return __typeId;"; } else { out << nl << "return \"" << (*allClassMembers.begin())->type()->typeId() << "\";"; } out << eb; if(allClassMembers.size() > 1) { out << sp << nl << "private int __member;"; out << nl << "private String __typeId;"; } out << eb; } out << sp << nl << "public void" << nl << "__read(IceInternal.BasicStream __is, boolean __rid)"; out << sb; out << nl << "if(__rid)"; out << sb; out << nl << "String myId = __is.readString();"; out << eb; out << nl << "__is.startReadSlice();"; iter = 0; DataMemberList classMembers = p->classDataMembers(); for(d = members.begin(); d != members.end(); ++d) { ostringstream patchParams; StringList metaData = (*d)->getMetaData(); writeMarshalUnmarshalCode(out, package, (*d)->type(), fixKwd((*d)->name()), false, iter, false, metaData, patchParams.str()); } out << nl << "__is.endReadSlice();"; if(base) { out << nl << "super.__read(__is, true);"; } out << eb; } out << eb; close(); } bool Slice::Gen::TypesVisitor::visitStructStart(const StructPtr& p) { string name = fixKwd(p->name()); string absolute = getAbsolute(p); if(!open(absolute)) { return false; } Output& out = output(); out << sp; string deprecateReason = getDeprecateReason(p, 0, "type"); if(!deprecateReason.empty()) { out << nl << "/**"; out << nl << " * @deprecated " << deprecateReason; out << nl << " **/"; } out << nl << "public final class " << name; out << sb; return true; } void Slice::Gen::TypesVisitor::visitStructEnd(const StructPtr& p) { string package = getPackage(p); Output& out = output(); DataMemberList members = p->dataMembers(); DataMemberList::const_iterator d; int iter; string name = fixKwd(p->name()); string typeS = typeToString(p, TypeModeIn, package); out << sp << nl << "public " << name << "()"; out << sb; out << eb; vector paramDecl; vector paramNames; vector::const_iterator q; for(d = members.begin(); d != members.end(); ++d) { string memberName = fixKwd((*d)->name()); string memberType = typeToString((*d)->type(), TypeModeMember, package, (*d)->getMetaData()); paramDecl.push_back(memberType + " " + memberName); paramNames.push_back(memberName); } out << sp << nl << "public " << name << spar << paramDecl << epar; out << sb; for(q = paramNames.begin(); q != paramNames.end(); ++q) { out << nl << "this." << *q << " = " << *q << ';'; } out << eb; out << sp << nl << "public boolean" << nl << "equals(java.lang.Object rhs)"; out << sb; out << nl << typeS << " _r = null;"; out << nl << "try"; out << sb; out << nl << "_r = (" << typeS << ")rhs;"; out << eb; out << nl << "catch(ClassCastException ex)"; out << sb; out << eb; out << sp << nl << "if(_r != null)"; out << sb; for(d = members.begin(); d != members.end(); ++d) { string memberName = fixKwd((*d)->name()); BuiltinPtr b = BuiltinPtr::dynamicCast((*d)->type()); if(b) { switch(b->kind()) { case Builtin::KindByte: case Builtin::KindBool: case Builtin::KindShort: case Builtin::KindInt: case Builtin::KindLong: case Builtin::KindFloat: case Builtin::KindDouble: { out << nl << "if(" << memberName << " != _r." << memberName << ')'; out << sb; out << nl << "return false;"; out << eb; break; } case Builtin::KindString: case Builtin::KindObject: case Builtin::KindObjectProxy: case Builtin::KindLocalObject: { out << nl << "if(" << memberName << " != _r." << memberName << " && " << memberName << " != null && !" << memberName << ".equals(_r." << memberName << "))"; out << sb; out << nl << "return false;"; out << eb; break; } } } else { // // We treat sequences differently because the native equals() method for // a Java array does not perform a deep comparison. We use the helper method // IceUtil.Arrays.equals() to compare native arrays. // // For all other types, we can use the native equals() method. // SequencePtr seq = SequencePtr::dynamicCast((*d)->type()); if(seq) { out << nl << "if(!IceUtil.Arrays.equals(" << memberName << ", _r." << memberName << "))"; out << sb; out << nl << "return false;"; out << eb; } else { out << nl << "if(" << memberName << " != _r." << memberName << " && " << memberName << " != null && !" << memberName << ".equals(_r." << memberName << "))"; out << sb; out << nl << "return false;"; out << eb; } } } out << sp << nl << "return true;"; out << eb; out << sp << nl << "return false;"; out << eb; out << sp << nl << "public int" << nl << "hashCode()"; out << sb; out << nl << "int __h = 0;"; iter = 0; for(d = members.begin(); d != members.end(); ++d) { string memberName = fixKwd((*d)->name()); writeHashCode(out, (*d)->type(), memberName, iter); } out << nl << "return __h;"; out << eb; out << sp << nl << "public java.lang.Object" << nl << "ice_clone()"; out.inc(); out << nl << "throws IceUtil.CloneException"; out.dec(); out << sb; out << nl << "return new " << name << '('; for(q = paramNames.begin(); q != paramNames.end(); ++q) { if(q != paramNames.begin()) { out << ", "; } out << *q; } out << ");"; out << eb; if(!p->isLocal()) { out << sp << nl << "public void" << nl << "__write(IceInternal.BasicStream __os)"; out << sb; iter = 0; for(d = members.begin(); d != members.end(); ++d) { StringList metaData = (*d)->getMetaData(); writeMarshalUnmarshalCode(out, package, (*d)->type(), fixKwd((*d)->name()), true, iter, false, metaData); } out << eb; DataMemberList classMembers = p->classDataMembers(); if(classMembers.size() != 0) { out << sp << nl << "private class Patcher implements IceInternal.Patcher"; out << sb; if(classMembers.size() > 1) { out << sp << nl << "Patcher(int member)"; out << sb; out << nl << "__member = member;"; out << eb; } out << sp << nl << "public void" << nl << "patch(Ice.Object v)"; out << sb; if(classMembers.size() > 1) { out << nl << "switch(__member)"; out << sb; } int memberCount = 0; for(d = classMembers.begin(); d != classMembers.end(); ++d) { if(classMembers.size() > 1) { out.dec(); out << nl << "case " << memberCount << ":"; out.inc(); } if(classMembers.size() > 1) { out << nl << "__typeId = \"" << (*d)->type()->typeId() << "\";"; } string memberName = fixKwd((*d)->name()); string memberType = typeToString((*d)->type(), TypeModeMember, package); out << nl << memberName << " = (" << memberType << ")v;"; if(classMembers.size() > 1) { out << nl << "break;"; } memberCount++; } if(classMembers.size() > 1) { out << eb; } out << eb; out << sp << nl << "public String" << nl << "type()"; out << sb; if(classMembers.size() > 1) { out << nl << "return __typeId;"; } else { out << nl << "return \"" << (*classMembers.begin())->type()->typeId() << "\";"; } out << eb; if(classMembers.size() > 1) { out << sp << nl << "private int __member;"; out << nl << "private String __typeId;"; } out << eb; } out << sp << nl << "public void" << nl << "__read(IceInternal.BasicStream __is)"; out << sb; iter = 0; for(d = members.begin(); d != members.end(); ++d) { ostringstream patchParams; StringList metaData = (*d)->getMetaData(); writeMarshalUnmarshalCode(out, package, (*d)->type(), fixKwd((*d)->name()), false, iter, false, metaData, patchParams.str()); } out << eb; } out << eb; close(); } void Slice::Gen::TypesVisitor::visitDataMember(const DataMemberPtr& p) { string name = fixKwd(p->name()); ContainerPtr container = p->container(); ContainedPtr contained = ContainedPtr::dynamicCast(container); StringList metaData = p->getMetaData(); string s = typeToString(p->type(), TypeModeMember, getPackage(contained), metaData); Output& out = output(); out << sp; string deprecateReason = getDeprecateReason(p, contained, "member"); if(!deprecateReason.empty()) { out << nl << "/**"; out << nl << " * @deprecated " << deprecateReason; out << nl << " **/"; } out << nl << "public " << s << ' ' << name << ';'; } void Slice::Gen::TypesVisitor::visitEnum(const EnumPtr& p) { string name = fixKwd(p->name()); string absolute = getAbsolute(p); EnumeratorList enumerators = p->getEnumerators(); EnumeratorList::const_iterator en; size_t sz = enumerators.size(); if(!open(absolute)) { return; } Output& out = output(); out << sp; string deprecateReason = getDeprecateReason(p, 0, "type"); if(!deprecateReason.empty()) { out << nl << "/**"; out << nl << " * @deprecated " << deprecateReason; out << nl << " **/"; } out << nl << "public final class " << name; out << sb; out << nl << "private static " << name << "[] __values = new " << name << "[" << sz << "];"; out << nl << "private int __value;"; out << sp; int n; for(en = enumerators.begin(), n = 0; en != enumerators.end(); ++en, ++n) { string member = fixKwd((*en)->name()); out << nl << "public static final int _" << member << " = " << n << ';'; out << nl << "public static final " << name << ' ' << fixKwd(member) << " = new " << name << "(_" << member << ");"; } out << sp << nl << "public static " << name << nl << "convert(int val)"; out << sb; out << nl << "if(IceUtil.Debug.ASSERT)"; out << sb; out << nl << "IceUtil.Debug.Assert(val < " << sz << ");"; out << eb; out << nl << "return __values[val];"; out << eb; out << sp << nl << "public int" << nl << "value()"; out << sb; out << nl << "return __value;"; out << eb; out << sp << nl << "public String" << nl << "toString()"; out << sb; out << nl << "return __T[__value];"; out << eb; out << sp << nl << "private" << nl << name << "(int val)"; out << sb; out << nl << "__value = val;"; out << nl << "__values[val] = this;"; out << eb; if(!p->isLocal()) { out << sp << nl << "public void" << nl << "__write(IceInternal.BasicStream __os)"; out << sb; if(sz <= 0x7f) { out << nl << "__os.writeByte((byte)__value);"; } else if(sz <= 0x7fff) { out << nl << "__os.writeShort((short)__value);"; } else { out << nl << "__os.writeInt(__value);"; } out << eb; out << sp << nl << "public static " << name << nl << "__read(IceInternal.BasicStream __is)"; out << sb; if(sz <= 0x7f) { out << nl << "int __v = __is.readByte();"; } else if(sz <= 0x7fff) { out << nl << "int __v = __is.readShort();"; } else { out << nl << "int __v = __is.readInt();"; } out << nl << "if(__v < 0 || __v >= " << sz << ')'; out << sb; out << nl << "throw new Ice.MarshalException();"; out << eb; out << nl << "return " << name << ".convert(__v);"; out << eb; } out << sp << nl << "final static private String[] __T ="; out << sb; en = enumerators.begin(); while(en != enumerators.end()) { out << nl << "\"" << (*en)->name() << "\""; if(++en != enumerators.end()) { out << ','; } } out << eb << ';'; out << eb; close(); } void Slice::Gen::TypesVisitor::visitConst(const ConstPtr& p) { string name = fixKwd(p->name()); string package = getPackage(p); string absolute = getAbsolute(p); TypePtr type = p->type(); if(!open(absolute)) { return; } Output& out = output(); out << sp << nl << "public interface " << name; out << sb; out << nl << typeToString(type, TypeModeIn, package) << " value = "; BuiltinPtr bp; EnumPtr ep; if(bp = BuiltinPtr::dynamicCast(type)) { switch(bp->kind()) { case Builtin::KindString: { out << "\""; const string val = p->value(); for(string::const_iterator c = val.begin(); c != val.end(); ++c) { if(isascii(*c) && isprint(*c)) { switch(*c) { case '\\': case '"': { out << "\\"; break; } } out << *c; } else { switch(*c) { case '\r': { out << "\\r"; break; } case '\n': { out << "\\n"; break; } default: { unsigned char uc = *c; ostringstream s; s << "\\u"; s.flags(ios_base::hex); s.width(4); s.fill('0'); s << static_cast(uc); out << s.str(); break; } } } } out << "\""; break; } case Builtin::KindByte: { int i = atoi(p->value().c_str()); if(i > 127) { i -= 256; } out << i; // Slice byte runs from 0-255, Java byte runs from -128 - 127. break; } case Builtin::KindLong: { out << p->value() << "L"; // Need to append "L" modifier for long constants. break; } case Builtin::KindBool: case Builtin::KindShort: case Builtin::KindInt: case Builtin::KindFloat: case Builtin::KindDouble: case Builtin::KindObject: case Builtin::KindObjectProxy: case Builtin::KindLocalObject: { out << p->value(); break; } } } else if(ep = EnumPtr::dynamicCast(type)) { string val = p->value(); string::size_type pos = val.rfind(':'); if(pos != string::npos) { val.erase(0, pos + 1); } out << getAbsolute(ep, package) << '.' << fixKwd(val); } else { out << p->value(); } out << ';' << eb; close(); } Slice::Gen::HolderVisitor::HolderVisitor(const string& dir) : JavaVisitor(dir) { } bool Slice::Gen::HolderVisitor::visitClassDefStart(const ClassDefPtr& p) { ClassDeclPtr decl = p->declaration(); writeHolder(decl); string name = p->name(); string absolute = getAbsolute(p, "", "", "PrxHolder"); if(open(absolute)) { Output& out = output(); out << sp << nl << "public final class " << name << "PrxHolder"; out << sb; out << sp << nl << "public" << nl << name << "PrxHolder()"; out << sb; out << eb; out << sp << nl << "public" << nl << name << "PrxHolder(" << name << "Prx value)"; out << sb; out << nl << "this.value = value;"; out << eb; out << sp << nl << "public " << name << "Prx value;"; out << eb; close(); } return false; } bool Slice::Gen::HolderVisitor::visitStructStart(const StructPtr& p) { writeHolder(p); return false; } void Slice::Gen::HolderVisitor::visitSequence(const SequencePtr& p) { writeHolder(p); } void Slice::Gen::HolderVisitor::visitDictionary(const DictionaryPtr& p) { writeHolder(p); } void Slice::Gen::HolderVisitor::visitEnum(const EnumPtr& p) { writeHolder(p); } void Slice::Gen::HolderVisitor::writeHolder(const TypePtr& p) { ContainedPtr contained = ContainedPtr::dynamicCast(p); assert(contained); string name = contained->name(); string absolute = getAbsolute(contained, "", "", "Holder"); if(open(absolute)) { Output& out = output(); string typeS = typeToString(p, TypeModeIn, getPackage(contained)); out << sp << nl << "public final class " << name << "Holder"; out << sb; out << sp << nl << "public" << nl << name << "Holder()"; out << sb; out << eb; out << sp << nl << "public" << nl << name << "Holder(" << typeS << " value)"; out << sb; out << nl << "this.value = value;"; out << eb; out << sp << nl << "public " << typeS << " value;"; out << eb; close(); } } Slice::Gen::HelperVisitor::HelperVisitor(const string& dir) : JavaVisitor(dir) { } bool Slice::Gen::HelperVisitor::visitClassDefStart(const ClassDefPtr& p) { // // Proxy helper // string name = p->name(); string scoped = p->scoped(); ClassList bases = p->bases(); string package = getPackage(p); string absolute = getAbsolute(p); if(!open(getAbsolute(p, "", "", "PrxHelper"))) { return false; } Output& out = output(); // // A proxy helper class serves two purposes: it implements the // proxy interface, and provides static helper methods for use // by applications (e.g., checkedCast, etc.) // out << sp << nl << "public final class " << name << "PrxHelper extends Ice.ObjectPrxHelperBase implements " << name << "Prx"; out << sb; OperationList ops = p->allOperations(); OperationList::const_iterator r; for(r = ops.begin(); r != ops.end(); ++r) { OperationPtr op = *r; StringList opMetaData = op->getMetaData(); ContainerPtr container = op->container(); ClassDefPtr cl = ClassDefPtr::dynamicCast(container); string opName = fixKwd(op->name()); TypePtr ret = op->returnType(); string retS = typeToString(ret, TypeModeReturn, package, op->getMetaData()); int iter; vector params = getParams(op, package); vector args = getArgs(op); ParamDeclList inParams; ParamDeclList outParams; ParamDeclList paramList = op->parameters(); ParamDeclList::const_iterator pli; for(pli = paramList.begin(); pli != paramList.end(); ++pli) { if((*pli)->isOutParam()) { outParams.push_back(*pli); } else { inParams.push_back(*pli); } } ExceptionList throws = op->throws(); throws.sort(); throws.unique(); // // Write two versions of the operation - with and without a // context parameter // out << sp; out << nl << "public " << retS << nl << opName << spar << params << epar; writeThrowsClause(package, throws); out << sb; out << nl; if(ret) { out << "return "; } out << opName << spar << args << "null, false" << epar << ';'; out << eb; out << sp; out << nl << "public " << retS << nl << opName << spar << params << "java.util.Hashtable __ctx" << epar; writeThrowsClause(package, throws); out << sb; out << nl; if(ret) { out << "return "; } out << opName << spar << args << "__ctx, true" << epar << ';'; out << eb; out << sp; out << nl << "public " << retS << nl << opName << spar << params << "java.util.Hashtable __ctx, boolean __explicitCtx" << epar; writeThrowsClause(package, throws); out << sb; out << nl << "if(__explicitCtx && __ctx == null)"; out << sb; out << nl << "__ctx = _emptyContext;"; out << eb; out << nl << "int __cnt = 0;"; out << nl << "while(true)"; out << sb; out << nl << "Ice.Connection __connection = null;"; out << nl << "try"; out << sb; if(op->returnsData()) { out << nl << "__checkTwowayOnly(\"" << opName << "\");"; } out << nl << "__connection = ice_getConnection();"; out << nl << "IceInternal.Outgoing __og = __connection.getOutgoing(_reference, \"" << op->name() << "\", " << sliceModeToIceMode(op->sendMode()) << ", __ctx);"; out << nl << "try"; out << sb; if(!inParams.empty()) { out << nl << "try"; out << sb; out << nl << "IceInternal.BasicStream __os = __og.stream();"; iter = 0; for(pli = inParams.begin(); pli != inParams.end(); ++pli) { writeMarshalUnmarshalCode(out, package, (*pli)->type(), fixKwd((*pli)->name()), true, iter, false, (*pli)->getMetaData()); } out << eb; out << nl << "catch(Ice.LocalException __ex)"; out << sb; out << nl << "__og.abort(__ex);"; out << eb; } out << nl << "boolean __ok = __og.invoke();"; out << nl << "try"; out << sb; out << nl << "IceInternal.BasicStream __is = __og.stream();"; out << nl << "if(!__ok)"; out << sb; out << nl << "try"; out << sb; out << nl << "__is.throwException();"; out << eb; for(ExceptionList::const_iterator t = throws.begin(); t != throws.end(); ++t) { out << nl << "catch(" << getAbsolute(*t, package) << " __ex)"; out << sb; out << nl << "throw __ex;"; out << eb; } out << nl << "catch(Ice.UserException __ex)"; out << sb; out << nl << "Ice.UnknownUserException __uex = new Ice.UnknownUserException();"; out << nl << "__uex.unknown = __ex.ice_name();"; out << nl << "throw __uex;"; out << eb; out << eb; for(pli = outParams.begin(); pli != outParams.end(); ++pli) { writeMarshalUnmarshalCode(out, package, (*pli)->type(), fixKwd((*pli)->name()), false, iter, true, (*pli)->getMetaData()); } if(ret) { out << nl << retS << " __ret;"; writeMarshalUnmarshalCode(out, package, ret, "__ret", false, iter, false, opMetaData); } if(ret) { out << nl << "return __ret;"; } out << eb; out << nl << "catch(Ice.LocalException __ex)"; out << sb; out << nl << "throw new IceInternal.LocalExceptionWrapper(__ex, false);"; out << eb; out << eb; out << nl << "finally"; out << sb; out << nl << "__connection.reclaimOutgoing(__og);"; out << eb; if(!ret) { out << nl << "return ;"; } out << eb; out << nl << "catch(IceInternal.LocalExceptionWrapper __ex)"; out << sb; if(op->mode() == Operation::Idempotent || op->mode() == Operation::Nonmutating) { out << nl << "__cnt = __handleExceptionWrapperRelaxed(__connection, __ex, __cnt);"; } else { out << nl << "__handleExceptionWrapper(__connection, __ex);"; } out << eb; out << nl << "catch(Ice.LocalException __ex)"; out << sb; out << nl << "__cnt = __handleException(__connection, __ex, __cnt);"; out << eb; out << eb; out << eb; } out << sp << nl << "public static " << name << "Prx" << nl << "checkedCast(Ice.ObjectPrx b)"; out << sb; out << nl << name << "Prx d = null;"; out << nl << "if(b != null)"; out << sb; out << nl << "try"; out << sb; out << nl << "d = (" << name << "Prx)b;"; out << eb; out << nl << "catch(ClassCastException ex)"; out << sb; out << nl << "if(b.ice_isA(\"" << scoped << "\"))"; out << sb; out << nl << name << "PrxHelper h = new " << name << "PrxHelper();"; out << nl << "h.__copyFrom(b);"; out << nl << "d = h;"; out << eb; out << eb; out << eb; out << nl << "return d;"; out << eb; out << sp << nl << "public static " << name << "Prx" << nl << "checkedCast(Ice.ObjectPrx b, java.util.Hashtable ctx)"; out << sb; out << nl << name << "Prx d = null;"; out << nl << "if(b != null)"; out << sb; out << nl << "try"; out << sb; out << nl << "d = (" << name << "Prx)b;"; out << eb; out << nl << "catch(ClassCastException ex)"; out << sb; out << nl << "if(b.ice_isA(\"" << scoped << "\", ctx))"; out << sb; out << nl << name << "PrxHelper h = new " << name << "PrxHelper();"; out << nl << "h.__copyFrom(b);"; out << nl << "d = h;"; out << eb; out << eb; out << eb; out << nl << "return d;"; out << eb; out << sp << nl << "public static " << name << "Prx" << nl << "checkedCast(Ice.ObjectPrx b, String f)"; out << sb; out << nl << name << "Prx d = null;"; out << nl << "if(b != null)"; out << sb; out << nl << "Ice.ObjectPrx bb = b.ice_facet(f);"; out << nl << "try"; out << sb; out << nl << "if(bb.ice_isA(\"" << scoped << "\"))"; out << sb; out << nl << name << "PrxHelper h = new " << name << "PrxHelper();"; out << nl << "h.__copyFrom(bb);"; out << nl << "d = h;"; out << eb; out << eb; out << nl << "catch(Ice.FacetNotExistException ex)"; out << sb; out << eb; out << eb; out << nl << "return d;"; out << eb; out << sp << nl << "public static " << name << "Prx" << nl << "checkedCast(Ice.ObjectPrx b, String f, java.util.Hashtable ctx)"; out << sb; out << nl << name << "Prx d = null;"; out << nl << "if(b != null)"; out << sb; out << nl << "Ice.ObjectPrx bb = b.ice_facet(f);"; out << nl << "try"; out << sb; out << nl << "if(bb.ice_isA(\"" << scoped << "\", ctx))"; out << sb; out << nl << name << "PrxHelper h = new " << name << "PrxHelper();"; out << nl << "h.__copyFrom(bb);"; out << nl << "d = h;"; out << eb; out << eb; out << nl << "catch(Ice.FacetNotExistException ex)"; out << sb; out << eb; out << eb; out << nl << "return d;"; out << eb; out << sp << nl << "public static " << name << "Prx" << nl << "uncheckedCast(Ice.ObjectPrx b)"; out << sb; out << nl << name << "Prx d = null;"; out << nl << "if(b != null)"; out << sb; out << nl << name << "PrxHelper h = new " << name << "PrxHelper();"; out << nl << "h.__copyFrom(b);"; out << nl << "d = h;"; out << eb; out << nl << "return d;"; out << eb; out << sp << nl << "public static " << name << "Prx" << nl << "uncheckedCast(Ice.ObjectPrx b, String f)"; out << sb; out << nl << name << "Prx d = null;"; out << nl << "if(b != null)"; out << sb; out << nl << "Ice.ObjectPrx bb = b.ice_facet(f);"; out << nl << name << "PrxHelper h = new " << name << "PrxHelper();"; out << nl << "h.__copyFrom(bb);"; out << nl << "d = h;"; out << eb; out << nl << "return d;"; out << eb; out << sp << nl << "public static void" << nl << "__write(IceInternal.BasicStream __os, " << name << "Prx v)"; out << sb; out << nl << "__os.writeProxy(v);"; out << eb; out << sp << nl << "public static " << name << "Prx" << nl << "__read(IceInternal.BasicStream __is)"; out << sb; out << nl << "Ice.ObjectPrx proxy = __is.readProxy();"; out << nl << "if(proxy != null)"; out << sb; out << nl << name << "PrxHelper result = new " << name << "PrxHelper();"; out << nl << "result.__copyFrom(proxy);"; out << nl << "return result;"; out << eb; out << nl << "return null;"; out << eb; out << eb; close(); return false; } bool Slice::Gen::HelperVisitor::visitStructStart(const StructPtr& p) { return false; } void Slice::Gen::HelperVisitor::visitSequence(const SequencePtr& p) { // // Don't generate helper for a sequence of a local type. // if(p->isLocal()) { return; } string name = p->name(); string absolute = getAbsolute(p); string helper = getAbsolute(p, "", "", "Helper"); string package = getPackage(p); string typeS = typeToString(p, TypeModeIn, package); if(open(helper)) { Output& out = output(); int iter; out << sp << nl << "public final class " << name << "Helper"; out << sb; out << nl << "public static void" << nl << "write(IceInternal.BasicStream __os, " << typeS << " __v)"; out << sb; iter = 0; writeSequenceMarshalUnmarshalCode(out, package, p, "__v", true, iter, false); out << eb; out << sp << nl << "public static " << typeS << nl << "read(IceInternal.BasicStream __is)"; out << sb; out << nl << typeS << " __v;"; iter = 0; writeSequenceMarshalUnmarshalCode(out, package, p, "__v", false, iter, false); out << nl << "return __v;"; out << eb; out << eb; close(); } } void Slice::Gen::HelperVisitor::visitDictionary(const DictionaryPtr& p) { // // Don't generate helper for a dictionary containing a local type. // if(p->isLocal()) { return; } TypePtr key = p->keyType(); TypePtr value = p->valueType(); string absolute = getAbsolute(p); string helper = getAbsolute(p, "", "", "Helper"); if(open(helper)) { Output& out = output(); string name = p->name(); string package = getPackage(p); string keyS = typeToString(key, TypeModeIn, package); string valueS = typeToString(value, TypeModeIn, package); int iter; int i; out << sp << nl << "public final class " << name << "Helper"; out << sb; out << nl << "public static void" << nl << "write(IceInternal.BasicStream __os, " << "java.util.Hashtable __v)"; out << sb; out << nl << "if(__v == null)"; out << sb; out << nl << "__os.writeSize(0);"; out << eb; out << nl << "else"; out << sb; out << nl << "__os.writeSize(__v.size());"; out << nl << "java.util.Enumeration __i = __v.keys();"; out << nl << "while(__i.hasMoreElements())"; out << sb; out << nl << "java.lang.Object key = __i.nextElement();"; out << nl << "java.lang.Object value = __v.get(key);"; iter = 0; for(i = 0; i < 2; i++) { string val; string arg; TypePtr type; if(i == 0) { arg = "key"; type = key; } else { arg = "value"; type = value; } BuiltinPtr b = BuiltinPtr::dynamicCast(type); if(b) { switch(b->kind()) { case Builtin::KindByte: { val = "((java.lang.Byte)" + arg + ").byteValue()"; break; } case Builtin::KindBool: { val = "((java.lang.Boolean)" + arg + ").booleanValue()"; break; } case Builtin::KindShort: { val = "((java.lang.Short)" + arg + ").shortValue()"; break; } case Builtin::KindInt: { val = "((java.lang.Integer)" + arg + ").intValue()"; break; } case Builtin::KindLong: { val = "((java.lang.Long)" + arg + ").longValue()"; break; } case Builtin::KindFloat: { val = "((java.lang.Float)" + arg + ").floatValue()"; break; } case Builtin::KindDouble: { val = "((java.lang.Double)" + arg + ").doubleValue()"; break; } case Builtin::KindString: case Builtin::KindObjectProxy: { break; } case Builtin::KindObject: case Builtin::KindLocalObject: { assert(false); break; } } } if(val.empty()) { val = "((" + typeToString(type, TypeModeIn, package) + ')' + arg + ')'; } writeMarshalUnmarshalCode(out, package, type, val, true, iter, false); } out << eb; out << eb; out << eb; out << sp << nl << "public static java.util.Hashtable"; out << nl << "read(IceInternal.BasicStream __is)"; out << sb; // // JDK 1.1 raises IllegalArgumentException if you pass 0 to the Hashtable constructor. // out << nl << "int __sz = __is.readSize();"; out << nl << "java.util.Hashtable __r = new java.util.Hashtable(__sz == 0 ? 1 : __sz);"; out << nl << "for(int __i = 0; __i < __sz; __i++)"; out << sb; iter = 0; for(i = 0; i < 2; i++) { string arg; TypePtr type; if(i == 0) { arg = "__key"; type = key; } else { arg = "__value"; type = value; } BuiltinPtr b = BuiltinPtr::dynamicCast(type); if(b) { switch(b->kind()) { case Builtin::KindByte: { out << nl << "java.lang.Byte " << arg << " = new java.lang.Byte(__is.readByte());"; break; } case Builtin::KindBool: { out << nl << "java.lang.Boolean " << arg << " = new java.lang.Boolean(__is.readBool());"; break; } case Builtin::KindShort: { out << nl << "java.lang.Short " << arg << " = new java.lang.Short(__is.readShort());"; break; } case Builtin::KindInt: { out << nl << "java.lang.Integer " << arg << " = new java.lang.Integer(__is.readInt());"; break; } case Builtin::KindLong: { out << nl << "java.lang.Long " << arg << " = new java.lang.Long(__is.readLong());"; break; } case Builtin::KindFloat: { out << nl << "java.lang.Float " << arg << " = new java.lang.Float(__is.readFloat());"; break; } case Builtin::KindDouble: { out << nl << "java.lang.Double " << arg << " = new java.lang.Double(__is.readDouble());"; break; } case Builtin::KindString: { out << nl << "java.lang.String " << arg << " = __is.readString();"; break; } case Builtin::KindObjectProxy: { out << nl << "Ice.ObjectPrx " << arg << " = __is.readProxy();"; break; } case Builtin::KindObject: case Builtin::KindLocalObject: { assert(false); break; } } } else { string s = typeToString(type, TypeModeIn, package); out << nl << s << ' ' << arg << ';'; writeMarshalUnmarshalCode(out, package, type, arg, false, iter, false); } } out << nl << "__r.put(__key, __value);"; out << eb; out << nl << "return __r;"; out << eb; out << eb; close(); } } void Slice::Gen::HelperVisitor::visitEnum(const EnumPtr& p) { } Slice::Gen::ProxyVisitor::ProxyVisitor(const string& dir) : JavaVisitor(dir) { } bool Slice::Gen::ProxyVisitor::visitClassDefStart(const ClassDefPtr& p) { string name = p->name(); ClassList bases = p->bases(); string package = getPackage(p); string absolute = getAbsolute(p, "", "", "Prx"); if(!open(absolute)) { return false; } Output& out = output(); // // Generate a Java interface as the user-visible type // out << sp << nl << "public interface " << name << "Prx extends "; if(bases.empty()) { out << "Ice.ObjectPrx"; } else { out.useCurrentPosAsIndent(); ClassList::const_iterator q = bases.begin(); while(q != bases.end()) { out << getAbsolute(*q, package, "", "Prx"); if(++q != bases.end()) { out << ',' << nl; } } out.restoreIndent(); } out << sb; return true; } void Slice::Gen::ProxyVisitor::visitClassDefEnd(const ClassDefPtr& p) { Output& out = output(); out << eb; close(); } void Slice::Gen::ProxyVisitor::visitOperation(const OperationPtr& p) { string name = fixKwd(p->name()); ContainerPtr container = p->container(); ClassDefPtr cl = ClassDefPtr::dynamicCast(container); string package = getPackage(cl); Output& out = output(); TypePtr ret = p->returnType(); string retS = typeToString(ret, TypeModeReturn, package, p->getMetaData()); vector params = getParams(p, package); ExceptionList throws = p->throws(); throws.sort(); throws.unique(); string deprecateReason = getDeprecateReason(p, cl, "type"); // // Write two versions of the operation - with and without a // context parameter. // out << sp; if(!deprecateReason.empty()) { out << nl << "/**"; out << nl << " * @deprecated " << deprecateReason; out << nl << " **/"; } out << nl << "public " << retS << ' ' << name << spar << params << epar; writeThrowsClause(package, throws); out << ';'; if(!deprecateReason.empty()) { out << nl << "/**"; out << nl << " * @deprecated " << deprecateReason; out << nl << " **/"; } out << nl << "public " << retS << ' ' << name << spar << params << "java.util.Hashtable __ctx" << epar; writeThrowsClause(package, throws); out << ';'; } Slice::Gen::DispatcherVisitor::DispatcherVisitor(const string& dir) : JavaVisitor(dir) { } bool Slice::Gen::DispatcherVisitor::visitClassDefStart(const ClassDefPtr& p) { if(!p->isInterface()) { return false; } string name = p->name(); ClassList bases = p->bases(); string absolute = getAbsolute(p, "", "_", "Disp"); if(!open(absolute)) { return false; } Output& out = output(); out << sp << nl << "public abstract class _" << name << "Disp extends Ice.ObjectImpl implements " << fixKwd(name); out << sb; out << sp << nl << "protected void" << nl << "ice_copyStateFrom(Ice.Object __obj)"; out.inc(); out << nl << "throws IceUtil.CloneException"; out.dec(); out << sb; out << nl << "throw new IceUtil.CloneException();"; out << eb; writeDispatch(out, p); out << eb; close(); return false; } Slice::Gen::BaseImplVisitor::BaseImplVisitor(const string& dir) : JavaVisitor(dir) { } void Slice::Gen::BaseImplVisitor::writeDecl(Output& out, const string& package, const string& name, const TypePtr& type, const StringList& metaData) { out << nl << typeToString(type, TypeModeIn, package, metaData) << ' ' << name; BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); if(builtin) { switch(builtin->kind()) { case Builtin::KindBool: { out << " = false"; break; } case Builtin::KindByte: { out << " = (byte)0"; break; } case Builtin::KindShort: { out << " = (short)0"; break; } case Builtin::KindInt: case Builtin::KindLong: { out << " = 0"; break; } case Builtin::KindFloat: { out << " = (float)0.0"; break; } case Builtin::KindDouble: { out << " = 0.0"; break; } case Builtin::KindString: { out << " = \"\""; break; } case Builtin::KindObject: case Builtin::KindObjectProxy: case Builtin::KindLocalObject: { out << " = null"; break; } } } else { EnumPtr en = EnumPtr::dynamicCast(type); if(en) { EnumeratorList enumerators = en->getEnumerators(); out << " = " << getAbsolute(en, package) << '.' << fixKwd(enumerators.front()->name()); } else { out << " = null"; } } out << ';'; } void Slice::Gen::BaseImplVisitor::writeReturn(Output& out, const TypePtr& type) { BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); if(builtin) { switch(builtin->kind()) { case Builtin::KindBool: { out << nl << "return false;"; break; } case Builtin::KindByte: { out << nl << "return (byte)0;"; break; } case Builtin::KindShort: { out << nl << "return (short)0;"; break; } case Builtin::KindInt: case Builtin::KindLong: { out << nl << "return 0;"; break; } case Builtin::KindFloat: { out << nl << "return (float)0.0;"; break; } case Builtin::KindDouble: { out << nl << "return 0.0;"; break; } case Builtin::KindString: case Builtin::KindObjectProxy: case Builtin::KindLocalObject: { out << nl << "return null;"; break; } case Builtin::KindObject: { cerr << "Ice objects cannot be returned by value in IceE." << endl; break; } } return; } out << nl << "return null;"; } void Slice::Gen::BaseImplVisitor::writeOperation(Output& out, const string& package, const OperationPtr& op, bool local) { string opName = op->name(); TypePtr ret = op->returnType(); StringList opMetaData = op->getMetaData(); string retS = typeToString(ret, TypeModeReturn, package, opMetaData); vector params = getParams(op, package); ContainerPtr container = op->container(); ClassDefPtr cl = ClassDefPtr::dynamicCast(container); out << sp << nl << "public " << retS << nl << fixKwd(opName) << spar << params; if(!local) { out << "Ice.Current __current"; } out << epar; ExceptionList throws = op->throws(); throws.sort(); throws.unique(); writeThrowsClause(package, throws); out << sb; // // Return value // if(ret) { writeReturn(out, ret); } out << eb; } Slice::Gen::ImplVisitor::ImplVisitor(const string& dir) : BaseImplVisitor(dir) { } bool Slice::Gen::ImplVisitor::visitClassDefStart(const ClassDefPtr& p) { if(!p->isAbstract()) { return false; } string name = p->name(); ClassList bases = p->bases(); string package = getPackage(p); string absolute = getAbsolute(p, "", "", "I"); if(!open(absolute)) { return false; } Output& out = output(); out << sp << nl << "public final class " << name << 'I'; if(p->isInterface()) { out << " extends _" << name << "Disp"; } else { out << " extends " << fixKwd(name); } out << sb; out << nl << "public" << nl << name << "I()"; out << sb; out << eb; OperationList ops = p->allOperations(); OperationList::const_iterator r; for(r = ops.begin(); r != ops.end(); ++r) { writeOperation(out, package, *r, false); } out << eb; close(); return false; } Slice::Gen::ImplTieVisitor::ImplTieVisitor(const string& dir) : BaseImplVisitor(dir) { } bool Slice::Gen::ImplTieVisitor::visitClassDefStart(const ClassDefPtr& p) { if(!p->isAbstract()) { return false; } string name = p->name(); ClassList bases = p->bases(); string package = getPackage(p); string absolute = getAbsolute(p, "", "", "I"); if(!open(absolute)) { return false; } Output& out = output(); // // Use implementation inheritance in the following situations: // // * if a class extends another class // * if a class implements a single interface // * if an interface extends only one interface // bool inheritImpl = (!p->isInterface() && !bases.empty() && !bases.front()->isInterface()) || (bases.size() == 1); out << sp << nl << "public class " << name << 'I'; if(inheritImpl) { out << " extends "; if(bases.front()->isAbstract()) { out << bases.front()->name() << 'I'; } else { out << fixKwd(bases.front()->name()); } } out << " implements " << '_' << name << "Operations"; out << sb; out << nl << "public" << nl << name << "I()"; out << sb; out << eb; OperationList ops = p->allOperations(); ops.sort(); OperationList baseOps; if(inheritImpl) { baseOps = bases.front()->allOperations(); baseOps.sort(); } OperationList::const_iterator r; for(r = ops.begin(); r != ops.end(); ++r) { if(inheritImpl && binary_search(baseOps.begin(), baseOps.end(), *r)) { out << sp; out << nl << "/*"; out << nl << " * Implemented by " << bases.front()->name() << 'I'; out << nl << " *"; writeOperation(out, package, *r, false); out << sp; out << nl << "*/"; } else { writeOperation(out, package, *r, false); } } out << eb; close(); return false; } IceE-trans-1.2.0/src/Makefile0000664000076400007640000000172310550516550015252 0ustar dwaynedwayne# ********************************************************************** # # Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. # # This copy of Ice is licensed to you under the terms described in the # ICE_LICENSE file included in this distribution. # # ********************************************************************** top_srcdir = .. include $(top_srcdir)/config/Make.rules SUBDIRS = IceUtil \ icecpp \ Slice \ slice2cpp \ slice2cs \ slice2vb \ slice2freeze \ slice2freezej \ slice2docbook \ slice2java \ slice2py \ slice2cppe \ slice2javae \ slice2rb \ slice2html \ Ice \ IceXML \ IceSSL \ Freeze \ FreezeScript \ IceBox \ IceStorm \ Glacier2 \ IcePatch2 \ IceGrid \ ca $(EVERYTHING):: @for subdir in $(SUBDIRS); \ do \ if test -d $$subdir ; \ then \ echo "making $@ in $$subdir"; \ ( cd $$subdir && $(MAKE) $@ ) || exit 1; \ fi; \ done IceE-trans-1.2.0/src/Makefile.mak0000664000076400007640000000200610550735637016025 0ustar dwaynedwayne# ********************************************************************** # # Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. # # This copy of Ice is licensed to you under the terms described in the # ICE_LICENSE file included in this distribution. # # ********************************************************************** top_srcdir = .. !include $(top_srcdir)/config/Make.rules.mak !if "$(CPP_COMPILER)" != "BCC2006" SUBDIRS = icecpp !endif SUBDIRS = $(SUBDIRS) IceUtil \ Slice \ slice2cpp \ slice2cs \ slice2vb \ slice2freeze \ slice2freezej \ slice2docbook \ slice2java \ slice2py \ slice2cppe \ slice2javae \ slice2rb \ slice2html \ Ice \ IceXML \ IceSSL \ IceBox \ IcePatch2 \ Glacier2 \ Freeze \ FreezeScript \ IceStorm \ IceGrid \ ca $(EVERYTHING):: @for %i in ( $(SUBDIRS) ) do \ @if exist %i \ @echo "making $@ in %i" & \ cmd /c "cd %i & $(MAKE) -nologo -f Makefile.mak $@" || exit 1 IceE-trans-1.2.0/src/IceUtil/0000775000076400007640000000000010620635752015151 5ustar dwaynedwayneIceE-trans-1.2.0/src/IceUtil/CtrlCHandler.cpp0000664000076400007640000001145310560413774020167 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 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. // // ********************************************************************** #ifdef __sun # define _POSIX_PTHREAD_SEMANTICS #endif #include #include #ifndef _WIN32 # include #endif using namespace std; using namespace IceUtil; static CtrlCHandlerCallback _callback = 0; static const CtrlCHandler* _handler = 0; CtrlCHandlerException::CtrlCHandlerException(const char* file, int line) : Exception(file, line) { } static const char* ctrlCHandlerName = "IceUtil::CtrlCHandlerException"; string CtrlCHandlerException::ice_name() const { return ctrlCHandlerName; } Exception* CtrlCHandlerException::ice_clone() const { return new CtrlCHandlerException(*this); } void CtrlCHandlerException::ice_throw() const { throw *this; } void CtrlCHandler::setCallback(CtrlCHandlerCallback callback) { StaticMutex::Lock lock(globalMutex); _callback = callback; } CtrlCHandlerCallback CtrlCHandler::getCallback() const { StaticMutex::Lock lock(globalMutex); return _callback; } #ifdef _WIN32 static BOOL WINAPI handlerRoutine(DWORD dwCtrlType) { CtrlCHandlerCallback callback = _handler->getCallback(); if(callback != 0) { callback(dwCtrlType); } return TRUE; } CtrlCHandler::CtrlCHandler(CtrlCHandlerCallback callback) { StaticMutex::Lock lock(globalMutex); if(_handler != 0) { throw CtrlCHandlerException(__FILE__, __LINE__); } else { _callback = callback; _handler = this; lock.release(); SetConsoleCtrlHandler(handlerRoutine, TRUE); } } CtrlCHandler::~CtrlCHandler() { SetConsoleCtrlHandler(handlerRoutine, FALSE); { StaticMutex::Lock lock(globalMutex); _handler = 0; } } #else extern "C" { static void* sigwaitThread(void*) { sigset_t ctrlCLikeSignals; sigemptyset(&ctrlCLikeSignals); sigaddset(&ctrlCLikeSignals, SIGHUP); sigaddset(&ctrlCLikeSignals, SIGINT); sigaddset(&ctrlCLikeSignals, SIGTERM); // // Run until I'm cancelled (in sigwait()) // for(;;) { int signal = 0; int rc = sigwait(&ctrlCLikeSignals, &signal); #if defined(__APPLE__) // // WORKAROUND: sigwait is not a cancelation point on MacOS X. To cancel this thread, the // destructor cancels the thread and send a signal to the thread to unblock sigwait, then // we explicitly test for cancellation. // pthread_testcancel(); #endif // // Some sigwait() implementations incorrectly return EINTR // when interrupted by an unblocked caught signal // if(rc == EINTR) { continue; } assert(rc == 0); rc = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, 0); assert(rc == 0); CtrlCHandlerCallback callback = _handler->getCallback(); if(callback != 0) { callback(signal); } rc = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, 0); assert(rc == 0); } return 0; } } static pthread_t _tid; CtrlCHandler::CtrlCHandler(CtrlCHandlerCallback callback) { StaticMutex::Lock lock(globalMutex); if(_handler != 0) { throw CtrlCHandlerException(__FILE__, __LINE__); } else { _callback = callback; _handler = this; lock.release(); // We block these CTRL+C like signals in the main thread, // and by default all other threads will inherit this signal // disposition. sigset_t ctrlCLikeSignals; sigemptyset(&ctrlCLikeSignals); sigaddset(&ctrlCLikeSignals, SIGHUP); sigaddset(&ctrlCLikeSignals, SIGINT); sigaddset(&ctrlCLikeSignals, SIGTERM); int rc = pthread_sigmask(SIG_BLOCK, &ctrlCLikeSignals, 0); assert(rc == 0); // Joinable thread rc = pthread_create(&_tid, 0, sigwaitThread, 0); assert(rc == 0); } } CtrlCHandler::~CtrlCHandler() { int rc = pthread_cancel(_tid); assert(rc == 0); #if defined(__APPLE__) // // WORKAROUND: sigwait isn't a cancellation point on MacOS X, see // comment in sigwaitThread // rc = pthread_kill(_tid, SIGTERM); //assert(rc == 0); For some reaosns, this assert is sometime triggered #endif void* status = 0; rc = pthread_join(_tid, &status); assert(rc == 0); #if !defined(__APPLE__) assert(status == PTHREAD_CANCELED); #endif { StaticMutex::Lock lock(globalMutex); _handler = 0; } } #endif IceE-trans-1.2.0/src/IceUtil/.depend0000664000076400007640000000765610577402726016433 0ustar dwaynedwayneArgVector$(OBJEXT): ArgVector.cpp ../../include/IceUtil/ArgVector.h ../../include/IceUtil/Config.h ../../include/IceUtil/DisableWarnings.h Base64$(OBJEXT): Base64.cpp ../../include/IceUtil/Base64.h ../../include/IceUtil/Config.h Cond$(OBJEXT): Cond.cpp ../../include/IceUtil/Cond.h ../../include/IceUtil/Config.h ../../include/IceUtil/Time.h ../../include/IceUtil/ThreadException.h ../../include/IceUtil/Exception.h ConvertUTF$(OBJEXT): ConvertUTF.cpp ../IceUtil/ConvertUTF.h ../../include/IceUtil/Unicode.h ../../include/IceUtil/Config.h ../../include/IceUtil/Exception.h CountDownLatch$(OBJEXT): CountDownLatch.cpp ../../include/IceUtil/CountDownLatch.h ../../include/IceUtil/Config.h ../../include/IceUtil/ThreadException.h ../../include/IceUtil/Exception.h CtrlCHandler$(OBJEXT): CtrlCHandler.cpp ../../include/IceUtil/CtrlCHandler.h ../../include/IceUtil/Config.h ../../include/IceUtil/Exception.h ../../include/IceUtil/StaticMutex.h ../../include/IceUtil/Lock.h ../../include/IceUtil/ThreadException.h Exception$(OBJEXT): Exception.cpp ../../include/IceUtil/Exception.h ../../include/IceUtil/Config.h ../../include/IceUtil/StaticMutex.h ../../include/IceUtil/Lock.h ../../include/IceUtil/ThreadException.h Shared$(OBJEXT): Shared.cpp ../../include/IceUtil/Shared.h ../../include/IceUtil/Config.h InputUtil$(OBJEXT): InputUtil.cpp ../../include/IceUtil/InputUtil.h ../../include/IceUtil/Config.h MD5$(OBJEXT): MD5.cpp ../../include/IceUtil/MD5.h ../../include/IceUtil/Config.h ../IceUtil/MD5I.h MD5I$(OBJEXT): MD5I.cpp ../IceUtil/MD5I.h Options$(OBJEXT): Options.cpp ../../include/IceUtil/Options.h ../../include/IceUtil/Config.h ../../include/IceUtil/RecMutex.h ../../include/IceUtil/Lock.h ../../include/IceUtil/ThreadException.h ../../include/IceUtil/Exception.h ../../include/IceUtil/Shared.h ../../include/IceUtil/Handle.h OutputUtil$(OBJEXT): OutputUtil.cpp ../../include/IceUtil/OutputUtil.h ../../include/IceUtil/Config.h Random$(OBJEXT): Random.cpp ../../include/IceUtil/Random.h ../../include/IceUtil/Config.h ../../include/IceUtil/Exception.h ../../include/IceUtil/StaticMutex.h ../../include/IceUtil/Lock.h ../../include/IceUtil/ThreadException.h RWRecMutex$(OBJEXT): RWRecMutex.cpp ../../include/IceUtil/RWRecMutex.h ../../include/IceUtil/Mutex.h ../../include/IceUtil/Config.h ../../include/IceUtil/Lock.h ../../include/IceUtil/ThreadException.h ../../include/IceUtil/Exception.h ../../include/IceUtil/Cond.h ../../include/IceUtil/Time.h ../../include/IceUtil/Thread.h ../../include/IceUtil/Shared.h ../../include/IceUtil/Handle.h RecMutex$(OBJEXT): RecMutex.cpp ../../include/IceUtil/RecMutex.h ../../include/IceUtil/Config.h ../../include/IceUtil/Lock.h ../../include/IceUtil/ThreadException.h ../../include/IceUtil/Exception.h StaticMutex$(OBJEXT): StaticMutex.cpp ../../include/IceUtil/StaticMutex.h ../../include/IceUtil/Config.h ../../include/IceUtil/Lock.h ../../include/IceUtil/ThreadException.h ../../include/IceUtil/Exception.h StringUtil$(OBJEXT): StringUtil.cpp ../../include/IceUtil/StringUtil.h ../../include/IceUtil/Config.h ../../include/IceUtil/Unicode.h ../../include/IceUtil/Exception.h Thread$(OBJEXT): Thread.cpp ../../include/IceUtil/Thread.h ../../include/IceUtil/Shared.h ../../include/IceUtil/Config.h ../../include/IceUtil/Handle.h ../../include/IceUtil/Exception.h ../../include/IceUtil/Mutex.h ../../include/IceUtil/Lock.h ../../include/IceUtil/ThreadException.h ../../include/IceUtil/Time.h ThreadException$(OBJEXT): ThreadException.cpp ../../include/IceUtil/ThreadException.h ../../include/IceUtil/Exception.h ../../include/IceUtil/Config.h Time$(OBJEXT): Time.cpp ../../include/IceUtil/DisableWarnings.h ../../include/IceUtil/Time.h ../../include/IceUtil/Config.h UUID$(OBJEXT): UUID.cpp ../../include/IceUtil/UUID.h ../../include/IceUtil/Config.h ../../include/IceUtil/Random.h ../../include/IceUtil/Exception.h Unicode$(OBJEXT): Unicode.cpp ../../include/IceUtil/Unicode.h ../../include/IceUtil/Config.h ../../include/IceUtil/Exception.h ../IceUtil/ConvertUTF.h IceE-trans-1.2.0/src/IceUtil/StaticMutex.cpp0000664000076400007640000000524210560413774020133 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 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 #ifdef _WIN32 # include # include using namespace std; static CRITICAL_SECTION _criticalSection; # if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0400 typedef list MutexList; # else typedef list MutexList; # endif static MutexList* _mutexList; // // Although apparently not documented by Microsoft, static objects are // initialized before DllMain/DLL_PROCESS_ATTACH and finalized after // DllMain/DLL_PROCESS_DETACH ... that's why we use a static object. // namespace IceUtil { class Init { public: Init(); ~Init(); }; static Init _init; Init::Init() { InitializeCriticalSection(&_criticalSection); _mutexList = new MutexList; } Init::~Init() { # if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0400 for(MutexList::iterator p = _mutexList->begin(); p != _mutexList->end(); ++p) { DeleteCriticalSection(*p); delete *p; } # else for_each(_mutexList->begin(), _mutexList->end(), CloseHandle); # endif delete _mutexList; DeleteCriticalSection(&_criticalSection); } } void IceUtil::StaticMutex::initialize() const { // // Yes, a double-check locking. It should be safe since we use memory barriers // (through InterlockedCompareExchangePointer) in both reader and writer threads // EnterCriticalSection(&_criticalSection); // // The second check // if(_mutex == 0) { # if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0400 CRITICAL_SECTION* newMutex = new CRITICAL_SECTION; InitializeCriticalSection(newMutex); # else _recursionCount = 0; HANDLE newMutex = CreateMutex(0, false, 0); if(newMutex == 0) { LeaveCriticalSection(&_criticalSection); throw ThreadSyscallException(__FILE__, __LINE__, GetLastError()); } # endif // // _mutex is written after the new initialized CRITICAL_SECTION/Mutex // void* oldVal = InterlockedCompareExchangePointer(reinterpret_cast(&_mutex), newMutex, 0); assert(oldVal == 0); _mutexList->push_back(_mutex); } LeaveCriticalSection(&_criticalSection); } #endif IceUtil::StaticMutex IceUtil::globalMutex = ICE_STATIC_MUTEX_INITIALIZER; IceE-trans-1.2.0/src/IceUtil/OutputUtil.cpp0000664000076400007640000002156010560413774020020 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 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 using namespace std; using namespace IceUtil; namespace IceUtil { NextLine nl; StartBlock sb; EndBlock eb; StartPar spar; EndPar epar; Separator sp; EndElement ee; StartEscapes startEscapes; EndEscapes endEscapes; } // ---------------------------------------------------------------------- // OutputBase // ---------------------------------------------------------------------- IceUtil::OutputBase::OutputBase() : _out(_fout), _pos(0), _indent(0), _indentSize(4), _useTab(false), _separator(true) { } IceUtil::OutputBase::OutputBase(ostream& os) : _out(os), _pos(0), _indent(0), _indentSize(4), _useTab(false), _separator(true) { } IceUtil::OutputBase::OutputBase(const char* s) : _out(_fout), _pos(0), _indent(0), _indentSize(4), _useTab(false), _separator(true) { open(s); } IceUtil::OutputBase::~OutputBase() { } void IceUtil::OutputBase::open(const char* s) { _fout.open(s); } bool IceUtil::OutputBase::isOpen() { return _fout.is_open(); } void IceUtil::OutputBase::print(const char* s) { for(unsigned int i = 0; i < strlen(s); ++i) { if(s[i] == '\n') { _pos = 0; } else { ++_pos; } } _out << s; } void IceUtil::OutputBase::inc() { _indent += _indentSize; } void IceUtil::OutputBase::dec() { assert(_indent >= _indentSize); _indent -= _indentSize; } void IceUtil::OutputBase::useCurrentPosAsIndent() { _indentSave.push(_indent); _indent = _pos; } void IceUtil::OutputBase::zeroIndent() { _indentSave.push(_indent); _indent = 0; } void IceUtil::OutputBase::restoreIndent() { assert(!_indentSave.empty()); _indent = _indentSave.top(); _indentSave.pop(); } int IceUtil::OutputBase::currIndent() { return _indent; } void IceUtil::OutputBase::setIndent(int indentSize) { _indentSize = indentSize; } void IceUtil::OutputBase::setUseTab(bool useTab) { _useTab = useTab; } void IceUtil::OutputBase::newline() { _out << '\n'; _pos = 0; _separator = true; int indent = _indent; if(_useTab) { while(indent >= 8) { indent -= 8; _out << '\t'; _pos += 8; } } else { while(indent >= _indentSize) { indent -= _indentSize; _out << " "; _pos += _indentSize; } } while(indent > 0) { --indent; _out << ' '; ++_pos; } _out.flush(); } void IceUtil::OutputBase::separator() { if(_separator) { _out << '\n'; } } bool IceUtil::OutputBase::operator!() const { return !_out; } // ---------------------------------------------------------------------- // Output // ---------------------------------------------------------------------- IceUtil::Output::Output() : OutputBase(), _blockStart("{"), _blockEnd("}"), _par(-1) { } IceUtil::Output::Output(ostream& os) : OutputBase(os), _blockStart("{"), _blockEnd("}"), _par(-1) { } IceUtil::Output::Output(const char* s) : OutputBase(s), _blockStart("{"), _blockEnd("}"), _par(-1) { } void IceUtil::Output::print(const char* s) { if(_par >= 0) { if(++_par > 1) // No comma for the first parameter. { _out << ", "; } } OutputBase::print(s); } void IceUtil::Output::setBeginBlock(const char *bb) { _blockStart = bb; } void IceUtil::Output::setEndBlock(const char *eb) { _blockEnd = eb; } void IceUtil::Output::sb() { if(_blockStart.length()) { newline(); _out << _blockStart; } ++_pos; inc(); _separator = false; } void IceUtil::Output::eb() { dec(); if(_blockEnd.length()) { newline(); _out << _blockEnd; } --_pos; } void IceUtil::Output::spar() { _out << '('; _par = 0; } void IceUtil::Output::epar() { _par = -1; _out << ')'; } Output& IceUtil::operator<<(Output& out, ios_base& (*val)(ios_base&)) { ostringstream s; s << val; out.print(s.str().c_str()); return out; } // ---------------------------------------------------------------------- // XMLOutput // ---------------------------------------------------------------------- IceUtil::XMLOutput::XMLOutput() : OutputBase(), _se(false), _text(false), _escape(false) { } IceUtil::XMLOutput::XMLOutput(ostream& os) : OutputBase(os), _se(false), _text(false), _escape(false) { } IceUtil::XMLOutput::XMLOutput(const char* s) : OutputBase(s), _se(false), _text(false), _escape(false) { } void IceUtil::XMLOutput::print(const char* s) { if(_se) { _out << '>'; _se = false; } _text = true; if(_escape) { string escaped = escape(s); OutputBase::print(escaped.c_str()); } else { OutputBase::print(s); } } void IceUtil::XMLOutput::newline() { if(_se) { _se = false; _out << '>'; } OutputBase::newline(); } void IceUtil::XMLOutput::startElement(const string& element) { newline(); // // If we're not in SGML mode the output of the '>' character is // deferred until either the //end-element (in which case a /> is // emitted) or until something //is displayed. // if(_escape) { _out << '<' << escape(element); } else { _out << '<' << element; } _se = true; _text = false; string::size_type pos = element.find_first_of(" \t"); if(pos == string::npos) { _elementStack.push(element); } else { _elementStack.push(element.substr(0, pos)); } ++_pos; // TODO: ??? inc(); _separator = false; } void IceUtil::XMLOutput::endElement() { string element = _elementStack.top(); _elementStack.pop(); dec(); if(_se) { _out << ">'; } else { if(!_text) { newline(); } _out << "'; } --_pos; // TODO: ??? _se = false; _text = false; } void IceUtil::XMLOutput::attr(const string& name, const string& value) { // // Precondition: Attributes can only be attached to elements. // assert(_se); _out << " " << name << "=\"" << escape(value) << '"'; } void IceUtil::XMLOutput::startEscapes() { _escape = true; } void IceUtil::XMLOutput::endEscapes() { _escape = false; } string IceUtil::XMLOutput::currentElement() const { if(_elementStack.size() > 0) { return _elementStack.top(); } else { return string(); } } string IceUtil::XMLOutput::escape(const string& input) const { string v = input; // // Find out whether there is a reserved character to avoid // conversion if not necessary. // const string allReserved = "<>'\"&"; if(v.find_first_of(allReserved) != string::npos) { // // First convert all & to & // size_t pos = 0; while((pos = v.find_first_of('&', pos)) != string::npos) { v.insert(pos+1, "amp;"); pos += 4; } // // Next convert remaining reserved characters. // const string reserved = "<>'\""; pos = 0; while((pos = v.find_first_of(reserved, pos)) != string::npos) { string replace; switch(v[pos]) { case '>': replace = ">"; break; case '<': replace = "<"; break; case '\'': replace = "'"; break; case '"': replace = """; break; default: assert(false); } v.erase(pos, 1); v.insert(pos, replace); pos += replace.size(); } } return v; } XMLOutput& IceUtil::operator<<(XMLOutput& out, ios_base& (*val)(ios_base&)) { ostringstream s; s << val; out.print(s.str().c_str()); return out; } IceUtil::StartElement::StartElement(const string& name) : _name(name) { } const string& IceUtil::StartElement::getName() const { return _name; } IceUtil::Attribute::Attribute(const string& name, const string& value) : _name(name), _value(value) { } const string& IceUtil::Attribute::getName() const { return _name; } const string& IceUtil::Attribute::getValue() const { return _value; } IceE-trans-1.2.0/src/IceUtil/RWRecMutex.cpp0000664000076400007640000002142510560413774017667 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 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 IceUtil::DeadlockException::DeadlockException(const char* file, int line) : Exception(file, line) { } const char* IceUtil::DeadlockException::_name = "IceUtil::DeadlockException"; ::std::string IceUtil::DeadlockException::ice_name() const { return _name; } IceUtil::Exception* IceUtil::DeadlockException::ice_clone() const { return new DeadlockException(*this); } void IceUtil::DeadlockException::ice_throw() const { throw *this; } IceUtil::RWRecMutex::RWRecMutex() : _count(0), _waitingWriters(0), _upgrading(false) { } IceUtil::RWRecMutex::~RWRecMutex() { } void IceUtil::RWRecMutex::readLock() const { Mutex::Lock lock(_mutex); // // Wait while a writer holds the lock or while writers or an upgrader // are waiting to get the lock. // while(_count < 0 || _waitingWriters != 0) { _readers.wait(lock); } ++_count; } bool IceUtil::RWRecMutex::tryReadLock() const { Mutex::Lock lock(_mutex); // // Would block if a writer holds the lock or if writers or an upgrader // are waiting to get the lock. // if(_count < 0 || _waitingWriters != 0) { return false; } ++_count; return true; } bool IceUtil::RWRecMutex::timedReadLock(const Time& timeout) const { Mutex::Lock lock(_mutex); // // Wait while a writer holds the lock or while writers or an upgrader // are waiting to get the lock. // Time end = Time::now() + timeout; while(_count < 0 || _waitingWriters != 0) { Time remainder = end - Time::now(); if(remainder > Time()) { if(_readers.timedWait(lock, remainder) == false) { return false; } } else { return false; } } ++_count; return true; } void IceUtil::RWRecMutex::writeLock() const { Mutex::Lock lock(_mutex); // // If the mutex is already write locked by this writer then // decrement _count, and return. // if(_count < 0 && _writerId == ThreadControl()) { --_count; return; } // // Wait for the lock to become available and increment the number // of waiting writers. // while(_count != 0) { ++_waitingWriters; try { _writers.wait(lock); } catch(...) { --_waitingWriters; throw; } --_waitingWriters; } // // Got the lock, indicate it's held by a writer. // _count = -1; _writerId = ThreadControl(); } bool IceUtil::RWRecMutex::tryWriteLock() const { Mutex::Lock lock(_mutex); // // If the mutex is already write locked by this writer then // decrement _count, and return. // if(_count < 0 && _writerId == ThreadControl()) { --_count; return true; } // // If there are readers or another writer then the call would block. // if(_count != 0) { return false; } // // Got the lock, indicate it's held by a writer. // _count = -1; _writerId = ThreadControl(); return true; } bool IceUtil::RWRecMutex::timedWriteLock(const Time& timeout) const { Mutex::Lock lock(_mutex); // // If the mutex is already write locked by this writer then // decrement _count, and return. if(_count < 0 && _writerId == ThreadControl()) { --_count; return true; } // // Wait for the lock to become available and increment the number // of waiting writers. // Time end = Time::now() + timeout; while(_count != 0) { Time remainder = end - Time::now(); if(remainder > Time()) { ++_waitingWriters; try { bool result = _writers.timedWait(lock, remainder); --_waitingWriters; if(result == false) { return false; } } catch(...) { --_waitingWriters; throw; } } else { return false; } } // // Got the lock, indicate it's held by a writer. // _count = -1; _writerId = ThreadControl(); return true; } void IceUtil::RWRecMutex::unlock() const { bool ww = false; bool wr = false; { Mutex::Lock lock(_mutex); assert(_count != 0); // // If _count < 0, the calling thread is a writer that holds the // lock, so release the lock. Otherwise, _count is guaranteed to // be > 0, so the calling thread is a reader releasing the lock. // if(_count < 0) { // // Writer called unlock // ++_count; // // If the write lock wasn't totally released we're done. // if(_count != 0) { return; } } else { // // Reader called unlock // --_count; } // // Writers are waiting (ww) if _waitingWriters > 0. In that // case, it's OK to let another writer into the region once there // are no more readers (_count == 0). Otherwise, no writers are // waiting but readers may be waiting (wr). // ww = (_waitingWriters != 0 && _count == 0); wr = (_waitingWriters == 0); } // Unlock mutex. // // Wake up a waiting writer if there is one. If not, wake up all // readers (just in case--there may be none). // if(ww) { if(_upgrading) { // // If there is an untimed upgrader, it runs. // _upgrader.signal(); } else { // // Wake a normal writer. // _writers.signal(); } } else if(wr) { // // Wake readers // _readers.broadcast(); } } void IceUtil::RWRecMutex::upgrade() const { Mutex::Lock lock(_mutex); if(_upgrading) { throw DeadlockException(__FILE__, __LINE__); } // // Reader owns at least one count. // assert(_count > 0); --_count; // // Wait to acquire the write lock. // _upgrading = true; while(_count != 0) { ++_waitingWriters; try { _upgrader.wait(lock); } catch(...) { _upgrading = false; --_waitingWriters; ++_count; throw; } --_waitingWriters; } // // Got the lock, indicate it's held by a writer. // _count = -1; _writerId = ThreadControl(); _upgrading = false; } bool IceUtil::RWRecMutex::timedUpgrade(const Time& timeout) const { Mutex::Lock lock(_mutex); // // If another reader is already waiting for an upgrade, // this upgrade cannot possibly succeed. // if(_upgrading) { return false; } // Reader owns at least one count // assert(_count > 0); --_count; // // Wait to acquire the write lock. // _upgrading = true; Time end = Time::now() + timeout; while(_count != 0) { Time remainder = end - Time::now(); if(remainder > Time()) { ++_waitingWriters; try { bool result = _upgrader.timedWait(lock, remainder); --_waitingWriters; if(!result) { _upgrading = false; ++_count; return false; } } catch(...) { _upgrading = false; --_waitingWriters; ++_count; throw; } } else { // // The lock isn't acquired if a timeout occurred. // ++_count; _upgrading = false; return false; } } // // Got the lock, indicate it's held by a writer. // _count = -1; _writerId = ThreadControl(); _upgrading = false; return true; } void IceUtil::RWRecMutex::downgrade() const { Mutex::Lock lock(_mutex); if(++_count == 0) { _count = 1; } } IceE-trans-1.2.0/src/IceUtil/ThreadException.cpp0000664000076400007640000000765610560413774020762 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 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 using namespace std; IceUtil::ThreadSyscallException::ThreadSyscallException(const char* file, int line, int err ): Exception(file, line), _error(err) { } const char* IceUtil::ThreadSyscallException::_name = "IceUtil::ThreadSyscallException"; string IceUtil::ThreadSyscallException::ice_name() const { return _name; } void IceUtil::ThreadSyscallException::ice_print(ostream& os) const { Exception::ice_print(os); if(_error != 0) { os << ":\nthread syscall exception: "; #ifdef _WIN32 LPVOID lpMsgBuf = 0; DWORD ok = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, _error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR)&lpMsgBuf, 0, NULL); if(ok) { LPCTSTR msg = (LPCTSTR)lpMsgBuf; assert(msg && strlen((char*)msg) > 0); os << msg; LocalFree(lpMsgBuf); } else { os << "unknown thread error"; } #else os << strerror(_error); #endif } } IceUtil::Exception* IceUtil::ThreadSyscallException::ice_clone() const { return new ThreadSyscallException(*this); } void IceUtil::ThreadSyscallException::ice_throw() const { throw *this; } int IceUtil::ThreadSyscallException::error() const { return _error; } IceUtil::ThreadLockedException::ThreadLockedException(const char* file, int line) : Exception(file, line) { } const char* IceUtil::ThreadLockedException::_name = "IceUtil::ThreadLockedException"; string IceUtil::ThreadLockedException::ice_name() const { return _name; } IceUtil::Exception* IceUtil::ThreadLockedException::ice_clone() const { return new ThreadLockedException(*this); } void IceUtil::ThreadLockedException::ice_throw() const { throw *this; } IceUtil::ThreadStartedException::ThreadStartedException(const char* file, int line) : Exception(file, line) { } const char* IceUtil::ThreadStartedException::_name = "IceUtil::ThreadStartedException"; string IceUtil::ThreadStartedException::ice_name() const { return _name; } IceUtil::Exception* IceUtil::ThreadStartedException::ice_clone() const { return new ThreadStartedException(*this); } void IceUtil::ThreadStartedException::ice_throw() const { throw *this; } IceUtil::ThreadNotStartedException::ThreadNotStartedException(const char* file, int line) : Exception(file, line) { } const char* IceUtil::ThreadNotStartedException::_name = "IceUtil::ThreadNotStartedException"; string IceUtil::ThreadNotStartedException::ice_name() const { return _name; } IceUtil::Exception* IceUtil::ThreadNotStartedException::ice_clone() const { return new ThreadNotStartedException(*this); } void IceUtil::ThreadNotStartedException::ice_throw() const { throw *this; } IceUtil::BadThreadControlException::BadThreadControlException(const char* file, int line) : Exception(file, line) { } const char* IceUtil::BadThreadControlException::_name = "IceUtil::BadThreadControlException"; string IceUtil::BadThreadControlException::ice_name() const { return _name; } IceUtil::Exception* IceUtil::BadThreadControlException::ice_clone() const { return new BadThreadControlException(*this); } void IceUtil::BadThreadControlException::ice_throw() const { throw *this; } IceE-trans-1.2.0/src/IceUtil/UUID.cpp0000664000076400007640000000712310560413774016427 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 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 // On Windows, we use Windows's RPC UUID generator. // On other platforms, we use a high quality random number generator // (/dev/random) to generate "version 4" UUIDs, as described in // http://www.ietf.org/internet-drafts/draft-mealling-uuid-urn-00.txt #ifdef _WIN32 # include #else # include # include # include #endif using namespace std; #ifndef _WIN32 static char myPid[2]; namespace IceUtil { // // Initialize the pid. // class PidInitializer { public: PidInitializer() { pid_t p = getpid(); myPid[0] = (p >> 8) & 0x7F; myPid[1] = p & 0xFF; } }; static PidInitializer pidInitializer; }; #endif // Helper char to hex functions // inline void halfByteToHex(unsigned char hb, char*& hexBuffer) { if(hb < 10) { *hexBuffer++ = '0' + hb; } else { *hexBuffer++ = 'A' + (hb - 10); } } inline void bytesToHex(unsigned char* bytes, size_t len, char*& hexBuffer) { for(size_t i = 0; i < len; i++) { halfByteToHex((bytes[i] & 0xF0) >> 4, hexBuffer); halfByteToHex((bytes[i] & 0x0F), hexBuffer); } } string IceUtil::generateUUID() { #ifdef _WIN32 UUID uuid; UuidCreate(&uuid); unsigned char* str; UuidToString(&uuid, &str); string result = reinterpret_cast(str); RpcStringFree(&str); return result; #else struct UUID { unsigned char timeLow[4]; unsigned char timeMid[2]; unsigned char timeHighAndVersion[2]; unsigned char clockSeqHiAndReserved; unsigned char clockSeqLow; unsigned char node[6]; }; UUID uuid; assert(sizeof(UUID) == 16); // // Get a random sequence of bytes. Instead of using 122 random // bits that could be duplicated (because of a bug with some Linux // kernels and potentially other Unix platforms -- see comment in // Random.cpp), we replace the last 15 bits of all "random" // Randoms by the last 15 bits of the process id. // char* buffer = reinterpret_cast(&uuid); generateRandom(buffer, static_cast(sizeof(UUID))); // // Adjust the bits that say "version 4" UUID // uuid.timeHighAndVersion[0] &= 0x0F; uuid.timeHighAndVersion[0] |= (4 << 4); uuid.clockSeqHiAndReserved &= 0x3F; uuid.clockSeqHiAndReserved |= 0x80; // // Replace the end of the node by myPid (15 bits) // uuid.node[4] = (uuid.node[4] & 0x80) | myPid[0]; uuid.node[5] = myPid[1]; // // Convert to a UUID string // char uuidString[16 * 2 + 4 + 1]; // 16 bytes, 4 '-' and a final '\0' char* uuidIndex = uuidString; bytesToHex(uuid.timeLow, sizeof(uuid.timeLow), uuidIndex); *uuidIndex++ = '-'; bytesToHex(uuid.timeMid, sizeof(uuid.timeMid), uuidIndex); *uuidIndex++ = '-'; bytesToHex(uuid.timeHighAndVersion, sizeof(uuid.timeHighAndVersion), uuidIndex); *uuidIndex++ = '-'; bytesToHex(&uuid.clockSeqHiAndReserved, sizeof(uuid.clockSeqHiAndReserved), uuidIndex); bytesToHex(&uuid.clockSeqLow, sizeof(uuid.clockSeqLow), uuidIndex); *uuidIndex++ = '-'; bytesToHex(uuid.node, sizeof(uuid.node), uuidIndex); *uuidIndex = '\0'; return uuidString; #endif } IceE-trans-1.2.0/src/IceUtil/InputUtil.cpp0000664000076400007640000001026410560413774017616 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 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 #if defined(_MSC_VER) && (_MSC_VER < 1300) #include #endif #if defined(__hpux) #include #endif using namespace std; namespace IceUtil { #if defined(__BCPLUSPLUS__) || (defined(_MSC_VER) && (_MSC_VER < 1300)) // // The VC60 runtime does not include _strtoi64, so we provide our own implementation // static const string allDigits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; // // Table to convert ASCII digits/letters into their value (100 for unused slots) // static const char digitVal[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, // '0' - '9' 100, 100, 100, 100, 100, 100, 100, // punctuation 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, // 'A' - 'J' 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, // 'K' - 'T' 30, 31, 32, 33, 34, 35 // 'U' - 'Z' }; static IceUtil::Int64 strToInt64Impl(const char* s, char** endptr, int base) { // // Assume nothing will be there to convert for now // if(endptr) { *endptr = const_cast(s); } // // Skip leading whitespace // while(*s && isspace(*s)) { ++s; } // // Check for sign // int sign = 1; if(*s == '+') { ++s; } else if(*s == '-') { sign = -1; ++s; } // // Check that base is valid // if(base == 0) { if(*s == '0') { base = 8; ++s; // // We have at least this zero // if(endptr) { *endptr = const_cast(s); } if(*s == 'x' || *s == 'X') { base = 16; ++s; } } else { base = 10; } } else if(base < 2 || base > 36) { errno = EINVAL; return 0; } // // Check that we have something left to parse // if(*s == '\0') { // // We did not read any new digit so we don't update endptr // return 0; } Int64 result = 0; bool overflow = false; bool digitFound = false; const string validDigits(allDigits.begin(), allDigits.begin() + base); while(*s && validDigits.find_first_of(toupper(*s)) != validDigits.npos) { digitFound = true; if(!overflow) { int digit = digitVal[toupper(*s) - '0']; assert(digit != 100); if(result < _I64_MAX / base) { result *= base; result += digit; } else if((digit <= _I64_MAX % base) || (sign == -1 && digit == _I64_MAX % base + 1)) { result *= base; result += digit; } else { overflow = true; result = sign == -1 ? _I64_MIN : _I64_MAX; } } ++s; } if(overflow) { errno = ERANGE; } else { result *= sign; } if(digitFound && endptr != 0) { *endptr = const_cast(s); } return result; } #endif Int64 strToInt64(const char* s, char** endptr, int base) { #if defined(_WIN32) # if defined(__BCPLUSPLUS__) || (defined(_MSC_VER) && (_MSC_VER < 1300)) return strToInt64Impl(s, endptr, base); # else return _strtoi64(s, endptr, base); # endif #elif defined(ICE_64) return strtol(s, endptr, base); #elif defined(__hpux) return __strtoll(s, endptr, base); #else return strtoll(s, endptr, base); #endif } bool stringToInt64(const string& s, Int64& result) { const char* start = s.c_str(); char* end = 0; errno = 0; result = strToInt64(start, &end, 0); return (errno == 0 && start != end); } } IceE-trans-1.2.0/src/IceUtil/CountDownLatch.cpp0000664000076400007640000000677210560413774020566 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 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 IceUtil::CountDownLatch::CountDownLatch(int count) : _count(count) { if(count < 0) { throw Exception(__FILE__, __LINE__); } #ifdef _WIN32 _event = CreateEvent(0, TRUE, FALSE, 0); if(_event == 0) { throw ThreadSyscallException(__FILE__, __LINE__, GetLastError()); } #else int rc = pthread_mutex_init(&_mutex, 0); if(rc != 0) { throw ThreadSyscallException(__FILE__, __LINE__, rc); } rc = pthread_cond_init(&_cond, 0); if(rc != 0) { throw ThreadSyscallException(__FILE__, __LINE__, rc); } #endif } IceUtil::CountDownLatch::~CountDownLatch() { #ifdef _WIN32 CloseHandle(_event); #else int rc = 0; rc = pthread_mutex_destroy(&_mutex); assert(rc == 0); rc = pthread_cond_destroy(&_cond); assert(rc == 0); #endif } void IceUtil::CountDownLatch::await() const { #ifdef _WIN32 while(InterlockedExchangeAdd(&_count, 0) > 0) { DWORD rc = WaitForSingleObject(_event, INFINITE); assert(rc == WAIT_OBJECT_0 || rc == WAIT_FAILED); if(rc == WAIT_FAILED) { throw ThreadSyscallException(__FILE__, __LINE__, GetLastError()); } } #else lock(); while(_count > 0) { int rc = pthread_cond_wait(&_cond, &_mutex); if(rc != 0) { pthread_mutex_unlock(&_mutex); throw ThreadSyscallException(__FILE__, __LINE__, rc); } } unlock(); #endif } void IceUtil::CountDownLatch::countDown() { #ifdef _WIN32 if(InterlockedDecrement(&_count) == 0) { if(SetEvent(_event) == 0) { throw ThreadSyscallException(__FILE__, __LINE__, GetLastError()); } } #else bool broadcast = false; lock(); if(_count > 0 && --_count == 0) { broadcast = true; } #if defined(__APPLE__) // // On MacOS X we do the broadcast with the mutex held. This seems to be necessary to prevent the // broadcast call to hang (spinning in an infinite loop). // if(broadcast) { int rc = pthread_cond_broadcast(&_cond); if(rc != 0) { pthread_mutex_unlock(&_mutex); throw ThreadSyscallException(__FILE__, __LINE__, rc); } } unlock(); #else unlock(); if(broadcast) { int rc = pthread_cond_broadcast(&_cond); if(rc != 0) { throw ThreadSyscallException(__FILE__, __LINE__, rc); } } #endif #endif } int IceUtil::CountDownLatch::getCount() const { #ifdef _WIN32 int count = InterlockedExchangeAdd(&_count, 0); return count > 0 ? count : 0; #else lock(); int result = _count; unlock(); return result; #endif } #ifndef _WIN32 void IceUtil::CountDownLatch::lock() const { int rc = pthread_mutex_lock(&_mutex); if(rc != 0) { throw ThreadSyscallException(__FILE__, __LINE__, rc); } } void IceUtil::CountDownLatch::unlock() const { int rc = pthread_mutex_unlock(&_mutex); if(rc != 0) { throw ThreadSyscallException(__FILE__, __LINE__, rc); } } #endif IceE-trans-1.2.0/src/IceUtil/Base64.cpp0000664000076400007640000001157710620001574016701 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 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 #ifdef __BCPLUSPLUS__ # include #endif using namespace std; string IceUtil::Base64::encode(const vector& plainSeq) { string retval; if(plainSeq.size() == 0) { return retval; } // Reserve enough space for the returned base64 string size_t base64Bytes = (((plainSeq.size() * 4) / 3) + 1); size_t newlineBytes = (((base64Bytes * 2) / 76) + 1); size_t totalBytes = base64Bytes + newlineBytes; retval.reserve(totalBytes); unsigned char by1 = 0; unsigned char by2 = 0; unsigned char by3 = 0; unsigned char by4 = 0; unsigned char by5 = 0; unsigned char by6 = 0; unsigned char by7 = 0; for(size_t i = 0; i < plainSeq.size(); i += 3) { by1 = plainSeq[i]; by2 = 0; by3 = 0; if((i + 1) < plainSeq.size()) { by2 = plainSeq[i+1]; } if((i + 2) < plainSeq.size()) { by3 = plainSeq[i+2]; } by4 = by1 >> 2; by5 = ((by1 & 0x3) << 4) | (by2 >> 4); by6 = ((by2 & 0xf) << 2) | (by3 >> 6); by7 = by3 & 0x3f; retval += encode(by4); retval += encode(by5); if((i + 1) < plainSeq.size()) { retval += encode(by6); } else { retval += "="; } if((i + 2) < plainSeq.size()) { retval += encode(by7); } else { retval += "="; } } string outString; outString.reserve(totalBytes); string::iterator iter = retval.begin(); while((retval.end() - iter) > 76) { copy(iter, iter+76, back_inserter(outString)); outString += "\r\n"; iter += 76; } copy(iter, retval.end(), back_inserter(outString)); return outString; } vector IceUtil::Base64::decode(const string& str) { string newStr; newStr.reserve(str.length()); for(size_t j = 0; j < str.length(); j++) { if(isBase64(str[j])) { newStr += str[j]; } } vector retval; if(newStr.length() == 0) { return retval; } // Note: This is how we were previously computing the size of the return // sequence. The method below is more efficient (and correct). // size_t lines = str.size() / 78; // size_t totalBytes = (lines * 76) + (((str.size() - (lines * 78)) * 3) / 4); // Figure out how long the final sequence is going to be. size_t totalBytes = (newStr.size() * 3 / 4) + 1; retval.reserve(totalBytes); unsigned char by1 = 0; unsigned char by2 = 0; unsigned char by3 = 0; unsigned char by4 = 0; char c1, c2, c3, c4; for(size_t i = 0; i < newStr.length(); i += 4) { c1 = 'A'; c2 = 'A'; c3 = 'A'; c4 = 'A'; c1 = newStr[i]; if((i + 1) < newStr.length()) { c2 = newStr[i + 1]; } if((i + 2) < newStr.length()) { c3 = newStr[i + 2]; } if((i + 3) < newStr.length()) { c4 = newStr[i + 3]; } by1 = decode(c1); by2 = decode(c2); by3 = decode(c3); by4 = decode(c4); retval.push_back((by1 << 2) | (by2 >> 4)); if(c3 != '=') { retval.push_back(((by2 & 0xf) << 4) | (by3 >> 2)); } if(c4 != '=') { retval.push_back(((by3 & 0x3) << 6) | by4); } } return retval; } bool IceUtil::Base64::isBase64(char c) { if(c >= 'A' && c <= 'Z') { return true; } if(c >= 'a' && c <= 'z') { return true; } if(c >= '0' && c <= '9') { return true; } if(c == '+') { return true; } if(c == '/') { return true; } if(c == '=') { return true; } return false; } char IceUtil::Base64::encode(unsigned char uc) { if(uc < 26) { return 'A' + uc; } if(uc < 52) { return 'a' + (uc - 26); } if(uc < 62) { return '0' + (uc - 52); } if(uc == 62) { return '+'; } return '/'; } unsigned char IceUtil::Base64::decode(char c) { if(c >= 'A' && c <= 'Z') { return c - 'A'; } if(c >= 'a' && c <= 'z') { return c - 'a' + 26; } if(c >= '0' && c <= '9') { return c - '0' + 52; } if(c == '+') { return 62; } return 63; } IceE-trans-1.2.0/src/IceUtil/Unicode.cpp0000664000076400007640000001572510560413774017256 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 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 using namespace std; using namespace IceUtil; namespace { // // Helper class, base never defined // Usage: WstringHelper::toUTF8 and fromUTF8. // template struct WstringHelper { static ConversionResult toUTF8( const wchar_t*& sourceStart, const wchar_t* sourceEnd, Byte*& targetStart, Byte* targetEnd, ConversionFlags flags); static ConversionResult fromUTF8( const Byte*& sourceStart, const Byte* sourceEnd, wchar_t*& targetStart, wchar_t* targetEnd, ConversionFlags flags); }; template<> struct WstringHelper<2> { static ConversionResult toUTF8( const wchar_t*& sourceStart, const wchar_t* sourceEnd, Byte*& targetStart, Byte* targetEnd, ConversionFlags flags) { return ConvertUTF16toUTF8( reinterpret_cast(&sourceStart), reinterpret_cast(sourceEnd), &targetStart, targetEnd, flags); } static ConversionResult fromUTF8( const Byte*& sourceStart, const Byte* sourceEnd, wchar_t*& targetStart, wchar_t* targetEnd, ConversionFlags flags) { return ConvertUTF8toUTF16( &sourceStart, sourceEnd, reinterpret_cast(&targetStart), reinterpret_cast(targetEnd), flags); } }; template<> struct WstringHelper<4> { static ConversionResult toUTF8( const wchar_t*& sourceStart, const wchar_t* sourceEnd, Byte*& targetStart, Byte* targetEnd, ConversionFlags flags) { return ConvertUTF32toUTF8( reinterpret_cast(&sourceStart), reinterpret_cast(sourceEnd), &targetStart, targetEnd, flags); } static ConversionResult fromUTF8( const Byte*& sourceStart, const Byte* sourceEnd, wchar_t*& targetStart, wchar_t* targetEnd, ConversionFlags flags) { return ConvertUTF8toUTF32( &sourceStart, sourceEnd, reinterpret_cast(&targetStart), reinterpret_cast(targetEnd), flags); } }; } // // convertXXX functions // ConversionResult IceUtil::convertUTFWstringToUTF8( const wchar_t*& sourceStart, const wchar_t* sourceEnd, Byte*& targetStart, Byte* targetEnd, ConversionFlags flags) { return WstringHelper::toUTF8( sourceStart, sourceEnd, targetStart, targetEnd, flags); } ConversionResult IceUtil::convertUTF8ToUTFWstring( const Byte*& sourceStart, const Byte* sourceEnd, wchar_t*& targetStart, wchar_t* targetEnd, ConversionFlags flags) { return WstringHelper::fromUTF8( sourceStart, sourceEnd, targetStart, targetEnd, flags); } ConversionResult IceUtil::convertUTF8ToUTFWstring(const Byte*& sourceStart, const Byte* sourceEnd, std::wstring& target, ConversionFlags flags) { // // Could be reimplemented without this temporary wchar_t buffer // size_t size = static_cast(sourceEnd - sourceStart); wchar_t* outBuf = new wchar_t[size]; wchar_t* targetStart = outBuf; wchar_t* targetEnd = targetStart + size; ConversionResult result = convertUTF8ToUTFWstring(sourceStart, sourceEnd, targetStart, targetEnd, flags); if(result == conversionOK) { std::wstring s(outBuf, static_cast(targetStart - outBuf)); s.swap(target); } delete[] outBuf; return result; } // // wstringToString and stringToWstring // const char* IceUtil::UTFConversionException::_name = "IceUtil::UTFConversionException"; IceUtil::UTFConversionException::UTFConversionException(const char* file, int line, ConversionResult cr): Exception(file, line), _conversionResult(cr) {} string IceUtil::UTFConversionException::ice_name() const { return _name; } void IceUtil::UTFConversionException::ice_print(ostream& os) const { Exception::ice_print(os); switch(_conversionResult) { case sourceExhausted: os << ": source exhausted"; break; case targetExhausted: os << ": target exhausted"; break; case sourceIllegal: os << ": illegal source"; break; default: assert(0); break; }; } IceUtil::Exception* IceUtil::UTFConversionException::ice_clone() const { return new UTFConversionException(*this); } void IceUtil::UTFConversionException::ice_throw() const { throw *this; } IceUtil::ConversionResult IceUtil::UTFConversionException::conversionResult() const { return _conversionResult; } string IceUtil::wstringToString(const wstring& wstr) { string target; size_t size = wstr.size() * 3 * (sizeof(wchar_t) / 2); Byte* outBuf = new Byte[size]; Byte* targetStart = outBuf; Byte* targetEnd = outBuf + size; const wchar_t* sourceStart = wstr.data(); ConversionResult cr = convertUTFWstringToUTF8( sourceStart, sourceStart + wstr.size(), targetStart, targetEnd, lenientConversion); if(cr != conversionOK) { delete[] outBuf; throw UTFConversionException(__FILE__, __LINE__, cr); } string s(reinterpret_cast(outBuf), static_cast(targetStart - outBuf)); s.swap(target); delete[] outBuf; return target; } wstring IceUtil::stringToWstring(const string& str) { wstring result; const Byte* sourceStart = reinterpret_cast(str.data()); ConversionResult cr = convertUTF8ToUTFWstring(sourceStart, sourceStart + str.size(), result, lenientConversion); if(cr != conversionOK) { throw UTFConversionException(__FILE__, __LINE__, cr); } return result; } #if defined(_MSC_VER) && (_MSC_VER >= 1300) // // See comments in IceUtil/Unicode.h // # if _MSC_VER < 1400 string IceUtil::wstringToString(const basic_string<__wchar_t>& str) { return wstringToString(*reinterpret_cast(&str)); } basic_string<__wchar_t> IceUtil::stringToNativeWstring(const string& str) { return reinterpret_cast& >(stringToWstring(str)); } # else string IceUtil::wstringToString(const basic_string& str) { return wstringToString(*reinterpret_cast(&str)); } basic_string IceUtil::stringToTypedefWstring(const string& str) { return reinterpret_cast& >(stringToWstring(str)); } # endif #endif IceE-trans-1.2.0/src/IceUtil/Shared.cpp0000774000076400007640000000256110550516551017066 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 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 using namespace IceUtil; IceUtil::SimpleShared::SimpleShared() : _ref(0), _noDelete(false) { } IceUtil::SimpleShared::SimpleShared(const SimpleShared&) : _ref(0), _noDelete(false) { } IceUtil::Shared::Shared() : #ifndef ICE_HAS_ATOMIC_FUNCTIONS _ref(0), #endif _noDelete(false) { #ifdef ICE_HAS_ATOMIC_FUNCTIONS ice_atomic_set(&_ref, 0); #endif } IceUtil::Shared::Shared(const Shared&) : #ifndef ICE_HAS_ATOMIC_FUNCTIONS _ref(0), #endif _noDelete(false) { #ifdef ICE_HAS_ATOMIC_FUNCTIONS ice_atomic_set(&_ref, 0); #endif } int IceUtil::Shared::__getRef() const { #if defined(_WIN32) return InterlockedExchangeAdd(const_cast(&_ref), 0); #elif defined(ICE_HAS_ATOMIC_FUNCTIONS) return ice_atomic_exchange_add(0, const_cast(&_ref)); #else _mutex.lock(); int ref = _ref; _mutex.unlock(); return ref; #endif } void IceUtil::Shared::__setNoDelete(bool b) { _noDelete = b; } IceE-trans-1.2.0/src/IceUtil/Makefile0000664000076400007640000000327510620635757016625 0ustar dwaynedwayne# ********************************************************************** # # Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. # # This copy of Ice is licensed to you under the terms described in the # ICE_LICENSE file included in this distribution. # # ********************************************************************** top_srcdir = ../.. LIBFILENAME = $(call mklibfilename,IceUtil,$(VERSION)) SONAME = $(call mksoname,IceUtil,$(SOVERSION)) LIBNAME = $(call mklibname,IceUtil) TARGETS = $(call mklibtargets,$(libdir)/$(LIBFILENAME),$(libdir)/$(SONAME),$(libdir)/$(LIBNAME)) OBJS = ArgVector.o \ Base64.o \ Cond.o \ ConvertUTF.o \ CountDownLatch.o \ CtrlCHandler.o \ Exception.o \ Shared.o \ InputUtil.o \ MD5.o \ MD5I.o \ Options.o \ OutputUtil.o \ Random.o \ RWRecMutex.o \ RecMutex.o \ StaticMutex.o \ StringUtil.o \ Thread.o \ ThreadException.o \ Time.o \ UUID.o \ Unicode.o SRCS = $(OBJS:.o=.cpp) include $(top_srcdir)/config/Make.rules CPPFLAGS := $(CPPFLAGS) -DICE_UTIL_API_EXPORTS -I.. LINKWITH := $(STLPORT_LIBS) $(ICEUTIL_OS_LIBS) ifeq ($(STATICLIBS),yes) $(libdir)/$(LIBNAME): $(OBJS) rm -f $@ $(call mklib,$@,$(OBJS)) else $(libdir)/$(LIBFILENAME): $(OBJS) rm -f $@ $(call mkshlib,$@,$(SONAME),$(OBJS),$(LINKWITH)) $(libdir)/$(SONAME): $(libdir)/$(LIBFILENAME) rm -f $@ ln -s $(LIBFILENAME) $@ $(libdir)/$(LIBNAME): $(libdir)/$(SONAME) rm -f $@ ln -s $(SONAME) $@ endif install:: all # $(call installlib,$(install_libdir),$(libdir),$(LIBFILENAME),$(SONAME),$(LIBNAME)) include .depend parser: parser.o rm -f $@ $(CXX) $(LDFLAGS) -o $@ parser.o $(BASELIBS) IceE-trans-1.2.0/src/IceUtil/RecMutex.cpp0000664000076400007640000001340410560413774017414 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 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 using namespace std; #ifdef _WIN32 # if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0400 IceUtil::RecMutex::RecMutex() : _count(0) { InitializeCriticalSection(&_mutex); } IceUtil::RecMutex::~RecMutex() { assert(_count == 0); DeleteCriticalSection(&_mutex); } void IceUtil::RecMutex::lock() const { EnterCriticalSection(&_mutex); if(++_count > 1) { LeaveCriticalSection(&_mutex); } } bool IceUtil::RecMutex::tryLock() const { if(!TryEnterCriticalSection(&_mutex)) { return false; } if(++_count > 1) { LeaveCriticalSection(&_mutex); } return true; } void IceUtil::RecMutex::unlock() const { if(--_count == 0) { LeaveCriticalSection(&_mutex); } } void IceUtil::RecMutex::unlock(LockState& state) const { state.count = _count; _count = 0; LeaveCriticalSection(&_mutex); } void IceUtil::RecMutex::lock(LockState& state) const { EnterCriticalSection(&_mutex); _count = state.count; } # else IceUtil::RecMutex::RecMutex() : _count(0) { _mutex = CreateMutex(0, false, 0); if(_mutex == 0) { throw ThreadSyscallException(__FILE__, __LINE__, GetLastError()); } } IceUtil::RecMutex::~RecMutex() { assert(_count == 0); BOOL rc = CloseHandle(_mutex); if(rc == 0) { throw ThreadSyscallException(__FILE__, __LINE__, GetLastError()); } } void IceUtil::RecMutex::lock() const { DWORD rc = WaitForSingleObject(_mutex, INFINITE); if(rc != WAIT_OBJECT_0) { if(rc == WAIT_FAILED) { throw ThreadSyscallException(__FILE__, __LINE__, GetLastError()); } else { throw ThreadSyscallException(__FILE__, __LINE__, 0); } } if(++_count > 1) { BOOL rc2 = ReleaseMutex(_mutex); if(rc2 == 0) { throw ThreadSyscallException(__FILE__, __LINE__, GetLastError()); } } } bool IceUtil::RecMutex::tryLock() const { DWORD rc = WaitForSingleObject(_mutex, 0); if(rc != WAIT_OBJECT_0) { return false; } if(++_count > 1) { BOOL rc2 = ReleaseMutex(_mutex); if(rc2 == 0) { throw ThreadSyscallException(__FILE__, __LINE__, GetLastError()); } } return true; } void IceUtil::RecMutex::unlock() const { if(--_count == 0) { BOOL rc = ReleaseMutex(_mutex); if(rc == 0) { throw ThreadSyscallException(__FILE__, __LINE__, GetLastError()); } } } void IceUtil::RecMutex::unlock(LockState& state) const { state.count = _count; _count = 0; BOOL rc = ReleaseMutex(_mutex); if(rc == 0) { throw ThreadSyscallException(__FILE__, __LINE__, GetLastError()); } } void IceUtil::RecMutex::lock(LockState& state) const { DWORD rc = WaitForSingleObject(_mutex, INFINITE); if(rc != WAIT_OBJECT_0) { if(rc == WAIT_FAILED) { throw ThreadSyscallException(__FILE__, __LINE__, GetLastError()); } else { throw ThreadSyscallException(__FILE__, __LINE__, 0); } } _count = state.count; } # endif #else IceUtil::RecMutex::RecMutex() : _count(0) { int rc; #if defined(__linux) && !defined(__USE_UNIX98) const pthread_mutexattr_t attr = { PTHREAD_MUTEX_RECURSIVE_NP }; #else pthread_mutexattr_t attr; rc = pthread_mutexattr_init(&attr); if(rc != 0) { throw ThreadSyscallException(__FILE__, __LINE__, rc); } rc = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); if(rc != 0) { throw ThreadSyscallException(__FILE__, __LINE__, rc); } #endif rc = pthread_mutex_init(&_mutex, &attr); if(rc != 0) { throw ThreadSyscallException(__FILE__, __LINE__, rc); } #if defined(__linux) && !defined(__USE_UNIX98) // Nothing to do #else rc = pthread_mutexattr_destroy(&attr); if(rc != 0) { throw ThreadSyscallException(__FILE__, __LINE__, rc); } #endif } IceUtil::RecMutex::~RecMutex() { assert(_count == 0); int rc = 0; rc = pthread_mutex_destroy(&_mutex); assert(rc == 0); } void IceUtil::RecMutex::lock() const { int rc = pthread_mutex_lock(&_mutex); if(rc != 0) { throw ThreadSyscallException(__FILE__, __LINE__, rc); } if(++_count > 1) { rc = pthread_mutex_unlock(&_mutex); assert(rc == 0); } } bool IceUtil::RecMutex::tryLock() const { int rc = pthread_mutex_trylock(&_mutex); bool result = (rc == 0); if(!result) { if(rc != EBUSY) { throw ThreadSyscallException(__FILE__, __LINE__, rc); } } else if(++_count > 1) { rc = pthread_mutex_unlock(&_mutex); if(rc != 0) { throw ThreadSyscallException(__FILE__, __LINE__, rc); } } return result; } void IceUtil::RecMutex::unlock() const { if(--_count == 0) { int rc = 0; // Prevent warnings when NDEBUG is defined. rc = pthread_mutex_unlock(&_mutex); assert(rc == 0); } } void IceUtil::RecMutex::unlock(LockState& state) const { state.mutex = &_mutex; state.count = _count; _count = 0; } void IceUtil::RecMutex::lock(LockState& state) const { _count = state.count; } #endif bool IceUtil::RecMutex::willUnlock() const { return _count == 1; } IceE-trans-1.2.0/src/IceUtil/Options.cpp0000774000076400007640000007511110560413774017320 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 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 using namespace std; IceUtil::APIException::APIException(const char* file, int line, const string& r) : IceUtil::Exception(file, line), reason(r) { } IceUtil::APIException::~APIException() throw() { } const char* IceUtil::APIException::_name = "IceUtil::APIException"; string IceUtil::APIException::ice_name() const { return _name; } void IceUtil::APIException::ice_print(ostream& out) const { Exception::ice_print(out); if(!reason.empty()) { out << ": " << reason; } } IceUtil::Exception* IceUtil::APIException::ice_clone() const { return new APIException(*this); } void IceUtil::APIException::ice_throw() const { throw *this; } ostream& IceUtil::operator<<(ostream& out, const IceUtil::APIException& ex) { ex.ice_print(out); return out; } IceUtil::BadOptException::BadOptException(const char* file, int line, const string& r) : IceUtil::Exception(file, line), reason(r) { } IceUtil::BadOptException::~BadOptException() throw() { } const char* IceUtil::BadOptException::_name = "IceUtil::BadOptException"; string IceUtil::BadOptException::ice_name() const { return _name; } void IceUtil::BadOptException::ice_print(ostream& out) const { Exception::ice_print(out); if(!reason.empty()) { out << ": " << reason; } } IceUtil::Exception* IceUtil::BadOptException::ice_clone() const { return new BadOptException(*this); } void IceUtil::BadOptException::ice_throw() const { throw *this; } ostream& IceUtil::operator<<(ostream& out, const IceUtil::BadOptException& ex) { ex.ice_print(out); return out; } IceUtil::Options::Options() : parseCalled(false) { } void IceUtil::Options::checkArgs(const string& shortOpt, const string& longOpt, bool needArg, const string& dflt) { if(shortOpt.empty() && longOpt.empty()) { throw IllegalArgumentException(__FILE__, __LINE__, "short and long option cannot both be empty"); } if(!shortOpt.empty()) { if(shortOpt.size() != 1) { string err = "`"; err += shortOpt; err += "': a short option cannot specify more than one option"; throw IllegalArgumentException(__FILE__, __LINE__, err); } if(shortOpt.find_first_of(" \t\n\r\f\v") != string::npos) { string err = "`"; err += shortOpt; err += "': a short option cannot be whitespace"; throw IllegalArgumentException(__FILE__, __LINE__, err); } if(shortOpt[0] == '-') { string err = "`"; err += shortOpt; err += "': a short option cannot be `-'"; throw IllegalArgumentException(__FILE__, __LINE__, err); } } if(!longOpt.empty()) { if(longOpt.find_first_of(" \t\n\r\f\v") != string::npos) { string err = "`"; err += longOpt; err += "': a long option cannot contain whitespace"; throw IllegalArgumentException(__FILE__, __LINE__, err); } if(longOpt[0] == '-') { string err = "`"; err += longOpt; err += "': a long option must not contain a leading `-'"; throw IllegalArgumentException(__FILE__, __LINE__, err); } } if(!needArg && !dflt.empty()) { throw IllegalArgumentException(__FILE__, __LINE__, "a default value can be specified only for options requiring an argument"); } } void IceUtil::Options::addOpt(const string& shortOpt, const string& longOpt, ArgType at, string dflt, RepeatType rt) { IceUtil::RecMutex::Lock sync(_m); if(parseCalled) { throw APIException(__FILE__, __LINE__, "cannot add options after parse() was called"); } checkArgs(shortOpt, longOpt, at == NeedArg, dflt); addValidOpt(shortOpt, longOpt, at, dflt, rt); } // // Split a command line into argv-style arguments, applying // bash quoting rules. The return value is the arguments // in the command line, with all shell escapes applied, and // quotes removed. // IceUtil::Options::StringVector IceUtil::Options::split(const string& line) { const string IFS = " \t\n"; // Internal Field Separator. // // Strip leading and trailing whitespace. // string::size_type start = line.find_first_not_of(IFS); if(start == string::npos) { return StringVector(); } string::size_type end = line.find_last_not_of(IFS); assert(end != string::npos); string l(line, start, end - start + 1); StringVector vec; enum ParseState { Normal, DoubleQuote, SingleQuote, ANSIQuote }; ParseState state = Normal; string arg; for(string::size_type i = 0; i < l.size(); ++i) { char c = l[i]; switch(state) { case Normal: { switch(c) { case '\\': { // // Ignore a backslash at the end of the string, // and strip backslash-newline pairs. If a // backslash is followed by a space, single quote, // double quote, or dollar sign, we drop the backslash // and write the space, single quote, double quote, // or dollar sign. This is necessary to allow quotes // to be escaped. Dropping the backslash preceding a // space deviates from bash quoting rules, but is // necessary so we don't drop backslashes from Windows // path names.) // if(i < l.size() - 1 && l[++i] != '\n') { switch(l[i]) { case ' ': case '$': case '\'': case '"': { arg.push_back(l[i]); break; } default: { arg.push_back('\\'); arg.push_back(l[i]); break; } } } break; } case '\'': { state = SingleQuote; break; } case '"': { state = DoubleQuote; break; } case '$': { if(i < l.size() - 1 && l[i + 1] == '\'') { state = ANSIQuote; // Bash uses $'' to allow ANSI escape sequences within . ++i; } else { arg.push_back('$'); } break; } default: { if(IFS.find(l[i]) != string::npos) { vec.push_back(arg); arg.clear(); // // Move to start of next argument. // while(++i < l.size() && IFS.find(l[i]) != string::npos) { ; } --i; } else { arg.push_back(l[i]); } break; } } break; } case DoubleQuote: { // // Within double quotes, only backslash retains its special // meaning, and only if followed by double quote, backslash, // or newline. If not followed by one of these characters, // both the backslash and the character are preserved. // if(c == '\\' && i < l.size() - 1) { switch(c = l[++i]) { case '"': case '\\': case '\n': { arg.push_back(c); break; } default: { arg.push_back('\\'); arg.push_back(c); break; } } } else if(c == '"') // End of double-quote mode. { state = Normal; } else { arg.push_back(c); // Everything else is taken literally. } break; } case SingleQuote: { if(c == '\'') // End of single-quote mode. { state = Normal; } else { arg.push_back(c); // Everything else is taken literally. } break; } case ANSIQuote: { switch(c) { case '\\': { if(i == l.size() - 1) { break; } switch(c = l[++i]) { // // Single-letter escape sequences. // case 'a': { arg.push_back('\a'); break; } case 'b': { arg.push_back('\b'); break; } case 'f': { arg.push_back('\f'); break; } case 'n': { arg.push_back('\n'); break; } case 'r': { arg.push_back('\r'); break; } case 't': { arg.push_back('\t'); break; } case 'v': { arg.push_back('\v'); break; } case '\\': { arg.push_back('\\'); break; } case '\'': { arg.push_back('\''); break; } case 'e': // Not ANSI-C, but used by bash. { arg.push_back('\033'); break; } // // Process up to three octal digits. // case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': { static string octalDigits = "01234567"; unsigned short us = 0; string::size_type j; for(j = i; j < i + 3 && j < l.size() && octalDigits.find_first_of(c = l[j]) != string::npos; ++j) { us = us * 8 + c - '0'; } i = j - 1; arg.push_back(static_cast(us)); break; } // // Process up to two hex digits. // case 'x': { if(i < l.size() - 1 && !isxdigit(l[i + 1])) { arg.push_back('\\'); arg.push_back('x'); break; } IceUtil::Int64 ull = 0; string::size_type j; for(j = i + 1; j < i + 3 && j < l.size() && isxdigit(c = l[j]); ++j) { ull *= 16; if(isdigit(c)) { ull += c - '0'; } else if(islower(c)) { ull += c - 'a' + 10; } else { ull += c - 'A' + 10; } } i = j - 1; arg.push_back(static_cast(ull)); break; } // // Process control-chars. // case 'c': { c = l[++i]; if(isalpha(c) || c == '@' || (c >= '[' && c <= '_')) { arg.push_back(static_cast(toupper(c) - '@')); } else { // // Bash does not define what should happen if a \c // is not followed by a recognized control character. // We simply treat this case like other unrecognized // escape sequences, that is, we preserve the escape // sequence unchanged. // arg.push_back('\\'); arg.push_back('c'); arg.push_back(c); } break; } // // If inside an ANSI-quoted string, a backslash isn't followed by // one of the recognized characters, both the backslash and the // character are preserved. // default: { arg.push_back('\\'); arg.push_back(c); break; } } break; } case '\'': // End of ANSI-quote mode. { state = Normal; break; } default: { arg.push_back(c); // Everything else is taken literally. break; } } break; } default: { assert(!"Impossible parse state"); break; } } } switch(state) { case Normal: { vec.push_back(arg); break; } case SingleQuote: { throw BadOptException(__FILE__, __LINE__, "missing closing single quote"); break; } case DoubleQuote: { throw BadOptException(__FILE__, __LINE__, "missing closing double quote"); break; } case ANSIQuote: { throw BadOptException(__FILE__, __LINE__, "unterminated $' quote"); break; } default: { assert(!"Impossible parse state"); break; } } return vec; } // // Parse a vector of arguments and return the non-option // arguments as the return value. Throw BadOptException if any of the // options are invalid. // Note that args[0] is ignored because that is the name // of the executable. // IceUtil::Options::StringVector IceUtil::Options::parse(const StringVector& args) { IceUtil::RecMutex::Lock sync(_m); if(parseCalled) { throw APIException(__FILE__, __LINE__, "cannot call parse() more than once on the same Option instance"); } parseCalled = true; set seenNonRepeatableOpts; // To catch repeated non-repeatable options. StringVector result; string::size_type i; for(i = 1; i < args.size(); ++i) { if(args[i] == "-" || args[i] == "--") { ++i; break; // "-" and "--" indicate end of options. } string opt; ValidOpts::iterator pos; bool argDone = false; if(args[i].compare(0, 2, "--") == 0) { // // Long option. If the option has an argument, it can either be separated by '=' // or appear as a separate argument. For example, "--name value" is the same // as "--name=value". // string::size_type p = args[i].find('=', 2); if(p != string::npos) { opt = args[i].substr(2, p - 2); } else { opt = args[i].substr(2); } pos = checkOpt(opt, LongOpt); if(pos->second->repeat == NoRepeat) { set::iterator seenPos = seenNonRepeatableOpts.find(opt); if(seenPos != seenNonRepeatableOpts.end()) { string err = "`--"; err += opt + ":' option cannot be repeated"; throw BadOptException(__FILE__, __LINE__, err); } seenNonRepeatableOpts.insert(seenPos, opt); string synonym = getSynonym(opt); if(!synonym.empty()) { seenNonRepeatableOpts.insert(synonym); } } if(p != string::npos) { if(pos->second->arg == NoArg && p != args[i].size() - 1) { string err = "`"; err += args[i]; err += "': option does not take an argument"; throw BadOptException(__FILE__, __LINE__, err); } setOpt(opt, "", args[i].substr(p + 1), pos->second->repeat); argDone = true; } } else if(!args[i].empty() && args[i][0] == '-') { // // Short option. // for(string::size_type p = 1; p < args[i].size(); ++p) { opt.clear(); opt.push_back(args[i][p]); pos = checkOpt(opt, ShortOpt); if(pos->second->repeat == NoRepeat) { set::iterator seenPos = seenNonRepeatableOpts.find(opt); if(seenPos != seenNonRepeatableOpts.end()) { string err = "`-"; err += opt + ":' option cannot be repeated"; throw BadOptException(__FILE__, __LINE__, err); } seenNonRepeatableOpts.insert(seenPos, opt); string synonym = getSynonym(opt); if(!synonym.empty()) { seenNonRepeatableOpts.insert(synonym); } } if(pos->second->arg == NeedArg && p != args[i].size() - 1) { string optArg = args[i].substr(p + 1); setOpt(opt, "", optArg, pos->second->repeat); argDone = true; break; } } } else { // // Not an option or option argument. // result.push_back(args[i]); argDone = true; } if(!argDone) { if(pos->second->arg == NeedArg) // Need an argument that is separated by whitespace. { if(i == args.size() - 1) { string err = "`-"; if(opt.size() != 1) { err += "-"; } err += opt; err += "' option requires an argument"; throw BadOptException(__FILE__, __LINE__, err); } setOpt(opt, "", args[++i], pos->second->repeat); } else { setOpt(opt, "", "1", pos->second->repeat); } } } _synonyms.clear(); // Don't need the contents anymore. while(i < args.size()) { result.push_back(args[i++]); } return result; } // // Parse a normal argc/argv pair and return the non-option // arguments as the return value. // IceUtil::Options::StringVector IceUtil::Options::parse(int argc, const char* const argv[]) { StringVector vec; for(int i = 0; i < argc; ++i) { vec.push_back(argv[i]); } return parse(vec); } bool IceUtil::Options::isSet(const string& opt) const { IceUtil::RecMutex::Lock sync(_m); if(!parseCalled) { throw APIException(__FILE__, __LINE__, "cannot lookup options before calling parse()"); } ValidOpts::const_iterator pos = checkOptIsValid(opt); return pos->second->repeat == NoRepeat ? _opts.find(opt) != _opts.end() : _ropts.find(opt) != _ropts.end(); } string IceUtil::Options::optArg(const string& opt) const { IceUtil::RecMutex::Lock sync(_m); if(!parseCalled) { throw APIException(__FILE__, __LINE__, "cannot lookup options before calling parse()"); } ValidOpts::const_iterator pos = checkOptHasArg(opt); if(pos->second->repeat == Repeat) { string err = "`-"; if(pos->second->length == LongOpt) { err.push_back('-'); } err += opt; err += "': is a repeating option -- use argVec() to get its arguments"; throw IllegalArgumentException(__FILE__, __LINE__, err); } Opts::const_iterator p = _opts.find(opt); if(p == _opts.end()) { return ""; } return p->second->val; } IceUtil::Options::StringVector IceUtil::Options::argVec(const string& opt) const { IceUtil::RecMutex::Lock sync(_m); if(!parseCalled) { throw APIException(__FILE__, __LINE__, "cannot lookup options before calling parse()"); } ValidOpts::const_iterator pos = checkOptHasArg(opt); if(pos->second->repeat == NoRepeat) { string err = "`-"; if(pos->second->length == LongOpt) { err.push_back('-'); } err += opt + "': is a non-repeating option -- use optArg() to get its argument"; throw IllegalArgumentException(__FILE__, __LINE__, err); } ROpts::const_iterator p = _ropts.find(opt); return p == _ropts.end() ? StringVector() : p->second->vals; } void IceUtil::Options::addValidOpt(const string& shortOpt, const string& longOpt, ArgType at, const string& dflt, RepeatType rt) { if(!shortOpt.empty() && _validOpts.find(shortOpt) != _validOpts.end()) { string err = "`"; err += shortOpt; err += "': duplicate option"; throw IllegalArgumentException(__FILE__, __LINE__, err); } if(!longOpt.empty() && _validOpts.find(longOpt) != _validOpts.end()) { string err = "`"; err += longOpt; err += "': duplicate option"; throw IllegalArgumentException(__FILE__, __LINE__, err); } ODPtr odp = new OptionDetails; odp->arg = at; odp->repeat = rt; odp->hasDefault = !dflt.empty(); if(!shortOpt.empty()) { odp->length = ShortOpt; _validOpts[shortOpt] = odp; } if(!longOpt.empty()) { odp->length = LongOpt; _validOpts[longOpt] = odp; } updateSynonyms(shortOpt, longOpt); if(at == NeedArg && !dflt.empty()) { setOpt(shortOpt, longOpt, dflt, rt); } } IceUtil::Options::ValidOpts::iterator IceUtil::Options::checkOpt(const string& opt, LengthType lt) { ValidOpts::iterator pos = _validOpts.find(opt); if(pos == _validOpts.end()) { string err = "invalid option: `-"; if(lt == LongOpt) { err.push_back('-'); } err += opt; err.push_back('\''); throw BadOptException(__FILE__, __LINE__, err); } return pos; } void IceUtil::Options::setOpt(const string& opt1, const string& opt2, const string& val, RepeatType rt) { // // opt1 and opt2 (short and long opt) can't both be empty. // assert(!(opt1.empty() && opt2.empty())); if(rt == NoRepeat) { setNonRepeatingOpt(opt1, val); setNonRepeatingOpt(opt2, val); } else { setRepeatingOpt(opt1, val); setRepeatingOpt(opt2, val); } } void IceUtil::Options::setNonRepeatingOpt(const string& opt, const string& val) { if(opt.empty()) { return; } // // The option must not have been set before or, if it was set, it must have // been because of a default value. // assert(_opts.find(opt) == _opts.end() || _validOpts.find(opt)->second->hasDefault); OValPtr ovp = new OptionValue; ovp->val = val; _opts[opt] = ovp; const string synonym = getSynonym(opt); if(!synonym.empty()) { _opts[synonym] = ovp; } } void IceUtil::Options::setRepeatingOpt(const string& opt, const string& val) { if(opt.empty()) { return; } ValidOpts::const_iterator vpos = _validOpts.find(opt); assert(vpos != _validOpts.end()); ROpts::iterator pos = _ropts.find(opt); const string synonym = getSynonym(opt); ROpts::iterator spos = _ropts.find(synonym); if(pos != _ropts.end()) { assert(_validOpts.find(opt) != _validOpts.end()); assert(vpos->second->repeat == Repeat); _ropts[opt] = pos->second; if(vpos->second->hasDefault && pos->second->vals.size() == 1) { pos->second->vals[0] = val; vpos->second->hasDefault = false; } else { pos->second->vals.push_back(val); } } else if(spos != _ropts.end()) { assert(_validOpts.find(synonym) != _validOpts.end()); assert(_validOpts.find(synonym)->second->repeat == Repeat); _ropts[synonym] = spos->second; if(vpos->second->hasDefault && spos->second->vals.size() == 1) { spos->second->vals[0] = val; vpos->second->hasDefault = false; } else { spos->second->vals.push_back(val); } } else { OVecPtr ovp = new OptionValueVector; ovp->vals.push_back(val); _ropts[opt] = ovp; if(!synonym.empty()) { _ropts[synonym] = ovp; } } } IceUtil::Options::ValidOpts::const_iterator IceUtil::Options::checkOptIsValid(const string& opt) const { ValidOpts::const_iterator pos = _validOpts.find(opt); if(pos == _validOpts.end()) { string err = "`"; err += opt; err += "': invalid option"; throw IllegalArgumentException(__FILE__, __LINE__, err); } return pos; } IceUtil::Options::ValidOpts::const_iterator IceUtil::Options::checkOptHasArg(const string& opt) const { ValidOpts::const_iterator pos = checkOptIsValid(opt); if(pos->second->arg == NoArg) { string err = "`-"; if(pos->second->length == LongOpt) { err.push_back('-'); } err += opt; err += "': option does not take arguments"; throw IllegalArgumentException(__FILE__, __LINE__, err); } return pos; } void IceUtil::Options::updateSynonyms(const ::std::string& shortOpt, const ::std::string& longOpt) { if(!shortOpt.empty() && !longOpt.empty()) { _synonyms[shortOpt] = longOpt; _synonyms[longOpt] = shortOpt; } } string IceUtil::Options::getSynonym(const ::std::string& optName) const { Synonyms::const_iterator pos = _synonyms.find(optName); return pos != _synonyms.end() ? pos->second : string(""); } IceE-trans-1.2.0/src/IceUtil/Makefile.mak0000664000076400007640000000406110620635757017366 0ustar dwaynedwayne# ********************************************************************** # # Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. # # This copy of Ice is licensed to you under the terms described in the # ICE_LICENSE file included in this distribution. # # ********************************************************************** top_srcdir = ..\.. LIBNAME = $(top_srcdir)\lib\iceutil$(LIBSUFFIX).lib DLLNAME = $(top_srcdir)\bin\iceutil$(SOVERSION)$(LIBSUFFIX).dll TARGETS = $(LIBNAME) $(DLLNAME) OBJS = ArgVector.obj \ Base64.obj \ Cond.obj \ ConvertUTF.obj \ CountDownLatch.obj \ CtrlCHandler.obj \ Exception.obj \ Shared.obj \ InputUtil.obj \ MD5.obj \ MD5I.obj \ Options.obj \ OutputUtil.obj \ Random.obj \ RWRecMutex.obj \ RecMutex.obj \ StaticMutex.obj \ StringUtil.obj \ Thread.obj \ ThreadException.obj \ Time.obj \ UUID.obj \ Unicode.obj SRCS = $(OBJS:.obj=.cpp) !include $(top_srcdir)/config/Make.rules.mak CPPFLAGS = $(CPPFLAGS) -DICE_UTIL_API_EXPORTS -I.. -DWIN32_LEAN_AND_MEAN !if "$(CPP_COMPILER)" != "BCC2006" & "$(OPTIMIZE)" != "yes" PDBFLAGS = /pdb:$(DLLNAME:.dll=.pdb) !endif !if "$(STATICLIBS)" == "yes" $(DLLNAME): $(LIBNAME): $(OBJS) $(AR) $(ARFLAGS) $(PDBFLAGS) $(OBJS) $(PREOUT)$@ !else $(LIBNAME): $(DLLNAME) $(DLLNAME): $(OBJS) $(LINK) $(LD_DLLFLAGS) $(PDBFLAGS) $(OBJS) $(PREOUT)$@ $(PRELIBS)$(ICE_OS_LIBS) move $(DLLNAME:.dll=.lib) $(LIBNAME) @if exist $@.manifest echo ^ ^ ^ Embedding manifest using $(MT) && \ $(MT) -nologo -manifest $@.manifest -outputresource:$@;#2 && del /q $@.manifest @if exist $(DLLNAME:.dll=.exp) del /q $(DLLNAME:.dll=.exp) !endif clean:: del /q $(DLLNAME:.dll=.*) install:: all # copy $(LIBNAME) $(install_libdir) # copy $(DLLNAME) $(install_bindir) !if "$(OPTIMIZE)" != "yes" !if "$(CPP_COMPILER)" == "BCC2006" install:: all # copy $(DLLNAME:.dll=.tds) $(install_bindir) !else install:: all # copy $(DLLNAME:.dll=.pdb) $(install_bindir) !endif !endif !include .depend IceE-trans-1.2.0/src/IceUtil/ArgVector.cpp0000664000076400007640000000626010562634427017560 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 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 IceUtil::ArgVector::ArgVector(int argc, char *argv[]) { assert(argc >= 0); _noDelete = false; copyVec(argc, argc, argv); } IceUtil::ArgVector::ArgVector(const ::std::vector< ::std::string>& vec) { _noDelete = false; copyVec(vec); } IceUtil::ArgVector::ArgVector(const ArgVector& rhs) { _noDelete = false; copyVec(rhs.argc, rhs._origArgc, rhs.argv); } IceUtil::ArgVector& IceUtil::ArgVector::operator=(const ArgVector& rhs) { ArgVector tmp(rhs); swap(tmp); return *this; } IceUtil::ArgVector::~ArgVector() { // // For use with putenv()--see man putenv. // if(!_noDelete) { for(int i = 0; i < _origArgc; ++i) { delete[] argv[i]; } } delete[] argv; } void IceUtil::ArgVector::setNoDelete() { _noDelete = true; } void IceUtil::ArgVector::copyVec(int argc, int origArgc, char** argv) { this->argc = argc; this->_origArgc = origArgc; if((this->argv = new char*[argc + 1]) == 0) { throw ::std::bad_alloc(); } for(int i = 0; i < argc; ++i) { try { if((this->argv[i] = new char[strlen(argv[i]) + 1]) == 0) { throw ::std::bad_alloc(); } } catch(...) { for(int j = 0; j < i; ++j) { delete[] this->argv[j]; } delete[] this->argv; throw; } #if defined(_MSC_VER) && (_MSC_VER >= 1400) strcpy_s(this->argv[i], strlen(argv[i]) + 1, argv[i]); #else strcpy(this->argv[i], argv[i]); #endif } this->argv[argc] = 0; } void IceUtil::ArgVector::copyVec(const ::std::vector< ::std::string>& vec) { argc = _origArgc = static_cast(vec.size()); if((argv = new char*[argc + 1]) == 0) { throw ::std::bad_alloc(); } for(int i = 0; i < argc; ++i) { try { if((argv[i] = new char[vec[i].size() + 1]) == 0) { throw ::std::bad_alloc(); } } catch(...) { for(int j = 0; j < i; ++j) { delete[] argv[j]; } delete[] argv; throw; } #if defined(_MSC_VER) && (_MSC_VER >= 1400) strcpy_s(argv[i], vec[i].size() + 1, vec[i].c_str()); #else strcpy(argv[i], vec[i].c_str()); #endif } argv[argc] = 0; } void IceUtil::ArgVector::swap(ArgVector& rhs) throw() { int argcTmp = rhs.argc; int origArgcTmp = rhs._origArgc; char** argvTmp = rhs.argv; bool noDeleteTmp = rhs._noDelete; rhs.argc = argc; rhs._origArgc = _origArgc; rhs.argv = argv; rhs._noDelete = _noDelete; argc = argcTmp; _origArgc = origArgcTmp; argv = argvTmp; _noDelete = noDeleteTmp; } IceE-trans-1.2.0/src/IceUtil/Exception.cpp0000664000076400007640000000637710607422775017634 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 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 using namespace std; namespace IceUtil { bool ICE_UTIL_API nullHandleAbort = false; }; IceUtil::Exception::Exception() : _file(0), _line(0) { } IceUtil::Exception::Exception(const char* file, int line) : _file(file), _line(line) { } IceUtil::Exception::~Exception() throw() { } const char* IceUtil::Exception::_name = "IceUtil::Exception"; string IceUtil::Exception::ice_name() const { return _name; } void IceUtil::Exception::ice_print(ostream& out) const { if(_file && _line > 0) { out << _file << ':' << _line << ": "; } out << ice_name(); } const char* IceUtil::Exception::what() const throw() { try { StaticMutex::Lock lock(globalMutex); { if(_str.empty()) { stringstream s; ice_print(s); _str = s.str(); // Lazy initialization. } } return _str.c_str(); } catch(...) { } return ""; } IceUtil::Exception* IceUtil::Exception::ice_clone() const { return new Exception(*this); } void IceUtil::Exception::ice_throw() const { throw *this; } const char* IceUtil::Exception::ice_file() const { return _file; } int IceUtil::Exception::ice_line() const { return _line; } ostream& IceUtil::operator<<(ostream& out, const IceUtil::Exception& ex) { ex.ice_print(out); return out; } IceUtil::NullHandleException::NullHandleException(const char* file, int line) : Exception(file, line) { if(nullHandleAbort) { abort(); } } IceUtil::NullHandleException::~NullHandleException() throw() { } const char* IceUtil::NullHandleException::_name = "IceUtil::NullHandleException"; string IceUtil::NullHandleException::ice_name() const { return _name; } IceUtil::Exception* IceUtil::NullHandleException::ice_clone() const { return new NullHandleException(*this); } void IceUtil::NullHandleException::ice_throw() const { throw *this; } IceUtil::IllegalArgumentException::IllegalArgumentException(const char* file, int line) : Exception(file, line) { } IceUtil::IllegalArgumentException::IllegalArgumentException(const char* file, int line, const string& r) : Exception(file, line), reason(r) { } IceUtil::IllegalArgumentException::~IllegalArgumentException() throw() { } const char* IceUtil::IllegalArgumentException::_name = "IceUtil::IllegalArgumentException"; string IceUtil::IllegalArgumentException::ice_name() const { return _name; } IceUtil::Exception* IceUtil::IllegalArgumentException::ice_clone() const { return new IllegalArgumentException(*this); } void IceUtil::IllegalArgumentException::ice_throw() const { throw *this; } ostream& IceUtil::operator<<(ostream& out, const IceUtil::IllegalArgumentException& ex) { ex.ice_print(out); out << ": " << ex.reason; return out; } IceE-trans-1.2.0/src/IceUtil/ConvertUTF.h0000775000076400007640000001321210560413774017324 0ustar dwaynedwayne/* * Copyright 2001-2004 Unicode, Inc. * * Disclaimer * * This source code is provided as is by Unicode, Inc. No claims are * made as to fitness for any particular purpose. No warranties of any * kind are expressed or implied. The recipient agrees to determine * applicability of information provided. If this file has been * purchased on magnetic or optical media from Unicode, Inc., the * sole remedy for any claim will be exchange of defective media * within 90 days of receipt. * * Limitations on Rights to Redistribute This Code * * Unicode, Inc. hereby grants the right to freely use the information * supplied in this file in the creation of products supporting the * Unicode Standard, and to make copies of this file in any form * for internal or external distribution as long as this notice * remains attached. */ // ********************************************************************** // // Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** #ifndef ICE_UTIL_CONVERT_UTF_H #define ICE_UTIL_CONVERT_UTF_H #include /* --------------------------------------------------------------------- Conversions between UTF32, UTF-16, and UTF-8. Header file. Several funtions are included here, forming a complete set of conversions between the three formats. UTF-7 is not included here, but is handled in a separate source file. Each of these routines takes pointers to input buffers and output buffers. The input buffers are const. Each routine converts the text between *sourceStart and sourceEnd, putting the result into the buffer between *targetStart and targetEnd. Note: the end pointers are *after* the last item: e.g. *(sourceEnd - 1) is the last item. The return result indicates whether the conversion was successful, and if not, whether the problem was in the source or target buffers. (Only the first encountered problem is indicated.) After the conversion, *sourceStart and *targetStart are both updated to point to the end of last text successfully converted in the respective buffers. Input parameters: sourceStart - pointer to a pointer to the source buffer. The contents of this are modified on return so that it points at the next thing to be converted. targetStart - similarly, pointer to pointer to the target buffer. sourceEnd, targetEnd - respectively pointers to the ends of the two buffers, for overflow checking only. These conversion functions take a ConversionFlags argument. When this flag is set to strict, both irregular sequences and isolated surrogates will cause an error. When the flag is set to lenient, both irregular sequences and isolated surrogates are converted. Whether the flag is strict or lenient, all illegal sequences will cause an error return. This includes sequences such as: , , or in UTF-8, and values above 0x10FFFF in UTF-32. Conformant code must check for illegal sequences. When the flag is set to lenient, characters over 0x10FFFF are converted to the replacement character; otherwise (when the flag is set to strict) they constitute an error. Output parameters: The value "sourceIllegal" is returned from some routines if the input sequence is malformed. When "sourceIllegal" is returned, the source value will point to the illegal value that caused the problem. E.g., in UTF-8 when a sequence is malformed, it points to the start of the malformed sequence. Author: Mark E. Davis, 1994. Rev History: Rick McGowan, fixes & updates May 2001. Fixes & updates, Sept 2001. ------------------------------------------------------------------------ */ /* --------------------------------------------------------------------- The following 4 definitions are compiler-specific. The C standard does not guarantee that wchar_t has at least 16 bits, so wchar_t is no less portable than unsigned short! All should be unsigned values to avoid sign extension during bit mask & shift operations. ------------------------------------------------------------------------ */ namespace IceUtil { typedef unsigned int UTF32; /* at least 32 bits */ typedef unsigned short UTF16; /* at least 16 bits */ typedef unsigned char UTF8; /* typically 8 bits */ typedef bool Boolean; /* 0 or 1 */ /* Some fundamental constants */ #define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD #define UNI_MAX_BMP (UTF32)0x0000FFFF #define UNI_MAX_UTF16 (UTF32)0x0010FFFF #define UNI_MAX_UTF32 (UTF32)0x7FFFFFFF #define UNI_MAX_LEGAL_UTF32 (UTF32)0x0010FFFF ConversionResult ConvertUTF8toUTF16( const UTF8** sourceStart, const UTF8* sourceEnd, UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags); ConversionResult ConvertUTF16toUTF8 ( const UTF16** sourceStart, const UTF16* sourceEnd, UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags); ConversionResult ConvertUTF8toUTF32( const UTF8** sourceStart, const UTF8* sourceEnd, UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags); ConversionResult ConvertUTF32toUTF8( const UTF32** sourceStart, const UTF32* sourceEnd, UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags); // // isLegalUTFSequence is declared in IceUtil/Unicode.h // /* --------------------------------------------------------------------- */ } #endif IceE-trans-1.2.0/src/IceUtil/Cond.cpp0000664000076400007640000001004710560413774016543 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 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 #ifndef _WIN32 # include #endif #ifdef _WIN32 IceUtil::Semaphore::Semaphore(long initial) { _sem = CreateSemaphore(0, initial, 0x7fffffff, 0); if(_sem == INVALID_HANDLE_VALUE) { throw ThreadSyscallException(__FILE__, __LINE__, GetLastError()); } } IceUtil::Semaphore::~Semaphore() { CloseHandle(_sem); } void IceUtil::Semaphore::wait() const { int rc = WaitForSingleObject(_sem, INFINITE); if(rc != WAIT_OBJECT_0) { throw ThreadSyscallException(__FILE__, __LINE__, GetLastError()); } } bool IceUtil::Semaphore::timedWait(const Time& timeout) const { int rc = WaitForSingleObject(_sem, static_cast(timeout.toMilliSeconds())); if(rc != WAIT_TIMEOUT && rc != WAIT_OBJECT_0) { throw ThreadSyscallException(__FILE__, __LINE__, GetLastError()); } return rc != WAIT_TIMEOUT; } void IceUtil::Semaphore::post(int count) const { int rc = ReleaseSemaphore(_sem, count, 0); if(rc == 0) { throw ThreadSyscallException(__FILE__, __LINE__, GetLastError()); } } IceUtil::Cond::Cond() : _gate(1), _blocked(0), _unblocked(0), _toUnblock(0) { } IceUtil::Cond::~Cond() { } void IceUtil::Cond::signal() { wake(false); } void IceUtil::Cond::broadcast() { wake(true); } void IceUtil::Cond::wake(bool broadcast) { // // Lock gate & mutex. // _gate.wait(); _internal.lock(); if(_unblocked != 0) { _blocked -= _unblocked; _unblocked = 0; } if(_blocked > 0) { // // Unblock some number of waiters. // _toUnblock = (broadcast) ? _blocked : 1; _internal.unlock(); _queue.post(); } else { // // Otherwise no blocked waiters, release gate & mutex. // _gate.post(); _internal.unlock(); } } void IceUtil::Cond::preWait() const { _gate.wait(); _blocked++; _gate.post(); } void IceUtil::Cond::postWait(bool timedOut) const { _internal.lock(); _unblocked++; if(_toUnblock != 0) { bool last = --_toUnblock == 0; _internal.unlock(); if(timedOut) { _queue.wait(); } if(last) { _gate.post(); } else { _queue.post(); } } else { _internal.unlock(); } } void IceUtil::Cond::dowait() const { try { _queue.wait(); postWait(false); } catch(...) { postWait(false); throw; } } bool IceUtil::Cond::timedDowait(const Time& timeout) const { try { bool rc = _queue.timedWait(timeout); postWait(!rc); return rc; } catch(...) { postWait(false); throw; } } #else IceUtil::Cond::Cond() { int rc; pthread_condattr_t attr; rc = pthread_condattr_init(&attr); if(rc != 0) { throw ThreadSyscallException(__FILE__, __LINE__, rc); } rc = pthread_cond_init(&_cond, &attr); if(rc != 0) { throw ThreadSyscallException(__FILE__, __LINE__, rc); } rc = pthread_condattr_destroy(&attr); if(rc != 0) { throw ThreadSyscallException(__FILE__, __LINE__, rc); } } IceUtil::Cond::~Cond() { int rc = 0; rc = pthread_cond_destroy(&_cond); assert(rc == 0); } void IceUtil::Cond::signal() { int rc = pthread_cond_signal(&_cond); if(rc != 0) { throw ThreadSyscallException(__FILE__, __LINE__, rc); } } void IceUtil::Cond::broadcast() { int rc = pthread_cond_broadcast(&_cond); if(rc != 0) { throw ThreadSyscallException(__FILE__, __LINE__, rc); } } #endif IceE-trans-1.2.0/src/IceUtil/MD5.cpp0000664000076400007640000000216110550516551016237 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 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 using namespace std; // // This class is a C++ wrapper around the C implementation contained in // MD5I.cpp, obtained from http://sourceforge.net/projects/libmd5-rfc/. // IceUtil::MD5::MD5() { _state = new md5_state_s; md5_init(_state); } IceUtil::MD5::MD5(const unsigned char* data, int n) { _state = new md5_state_s; md5_init(_state); update(data, n); finish(); } IceUtil::MD5::~MD5() { delete _state; } void IceUtil::MD5::update(const unsigned char* data, int n) { md5_append(_state, data, n); } void IceUtil::MD5::finish() { md5_finish(_state, _digest); md5_init(_state); } void IceUtil::MD5::getDigest(unsigned char* digest) const { memcpy(digest, _digest, sizeof(unsigned char) * 16); } IceE-trans-1.2.0/src/IceUtil/MD5I.h0000664000076400007640000000657510560413774016036 0ustar dwaynedwayne/* Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved. This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. L. Peter Deutsch ghost@aladdin.com */ /* $Id: MD5I.h,v 1.2 2007/02/01 16:40:28 bernard Exp $ */ /* Independent implementation of MD5 (RFC 1321). This code implements the MD5 Algorithm defined in RFC 1321, whose text is available at http://www.ietf.org/rfc/rfc1321.txt The code is derived from the text of the RFC, including the test suite (section A.5) but excluding the rest of Appendix A. It does not include any code or documentation that is identified in the RFC as being copyrighted. The original and principal author of md5.h is L. Peter Deutsch . Other authors are noted in the change history that follows (in reverse chronological order): 2002-04-13 lpd Removed support for non-ANSI compilers; removed references to Ghostscript; clarified derivation from RFC 1321; now handles byte order either statically or dynamically. 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5); added conditionalization for C++ compilation from Martin Purschke . 1999-05-03 lpd Original version. */ #ifndef md5_INCLUDED # define md5_INCLUDED /* * This package supports both compile-time and run-time determination of CPU * byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is * defined as non-zero, the code will be compiled to run only on big-endian * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to * run on either big- or little-endian CPUs, but will run slightly less * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined. */ typedef unsigned char md5_byte_t; /* 8-bit byte */ typedef unsigned int md5_word_t; /* 32-bit word */ /* Define the state of the MD5 Algorithm. */ typedef struct md5_state_s { md5_word_t count[2]; /* message length in bits, lsw first */ md5_word_t abcd[4]; /* digest buffer */ md5_byte_t buf[64]; /* accumulate block */ } md5_state_t; #ifdef __cplusplus extern "C" { #endif /* Initialize the algorithm. */ void md5_init(md5_state_t *pms); /* Append a string to the message. */ void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes); /* Finish the message and return the digest. */ void md5_finish(md5_state_t *pms, md5_byte_t digest[16]); #ifdef __cplusplus } /* end extern "C" */ #endif #endif /* md5_INCLUDED */ IceE-trans-1.2.0/src/IceUtil/MD5I.cpp0000664000076400007640000003124410560413774016360 0ustar dwaynedwayne/* Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved. This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. L. Peter Deutsch ghost@aladdin.com */ /* $Id: MD5I.cpp,v 1.2 2007/02/01 16:40:28 bernard Exp $ */ /* Independent implementation of MD5 (RFC 1321). This code implements the MD5 Algorithm defined in RFC 1321, whose text is available at http://www.ietf.org/rfc/rfc1321.txt The code is derived from the text of the RFC, including the test suite (section A.5) but excluding the rest of Appendix A. It does not include any code or documentation that is identified in the RFC as being copyrighted. The original and principal author of md5.c is L. Peter Deutsch . Other authors are noted in the change history that follows (in reverse chronological order): 2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order either statically or dynamically; added missing #include in library. 2002-03-11 lpd Corrected argument list for main(), and added int return type, in test program and T value program. 2002-02-21 lpd Added missing #include in test program. 2000-07-03 lpd Patched to eliminate warnings about "constant is unsigned in ANSI C, signed in traditional"; made test program self-checking. 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5). 1999-05-03 lpd Original version. */ #include #include #undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */ #ifdef ARCH_IS_BIG_ENDIAN # define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1) #else # define BYTE_ORDER 0 #endif #define T_MASK ((md5_word_t)~0) #define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87) #define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9) #define T3 0x242070db #define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111) #define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050) #define T6 0x4787c62a #define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec) #define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe) #define T9 0x698098d8 #define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850) #define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e) #define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841) #define T13 0x6b901122 #define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c) #define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71) #define T16 0x49b40821 #define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d) #define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf) #define T19 0x265e5a51 #define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855) #define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2) #define T22 0x02441453 #define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e) #define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437) #define T25 0x21e1cde6 #define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829) #define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278) #define T28 0x455a14ed #define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa) #define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07) #define T31 0x676f02d9 #define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375) #define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd) #define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e) #define T35 0x6d9d6122 #define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3) #define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb) #define T38 0x4bdecfa9 #define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f) #define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f) #define T41 0x289b7ec6 #define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805) #define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a) #define T44 0x04881d05 #define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6) #define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a) #define T47 0x1fa27cf8 #define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a) #define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb) #define T50 0x432aff97 #define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58) #define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6) #define T53 0x655b59c3 #define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d) #define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82) #define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e) #define T57 0x6fa87e4f #define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f) #define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb) #define T60 0x4e0811a1 #define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d) #define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca) #define T63 0x2ad7d2bb #define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e) static void md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/) { md5_word_t a = pms->abcd[0], b = pms->abcd[1], c = pms->abcd[2], d = pms->abcd[3]; md5_word_t t; #if BYTE_ORDER > 0 /* Define storage only for big-endian CPUs. */ md5_word_t X[16]; #else /* Define storage for little-endian or both types of CPUs. */ md5_word_t xbuf[16]; const md5_word_t *X; #endif { #if BYTE_ORDER == 0 /* * Determine dynamically whether this is a big-endian or * little-endian machine, since we can use a more efficient * algorithm on the latter. */ static const int w = 1; if (*((const md5_byte_t *)&w)) /* dynamic little-endian */ #endif #if BYTE_ORDER <= 0 /* little-endian */ { /* * On little-endian machines, we can process properly aligned * data without copying it. */ if (!((data - (const md5_byte_t *)0) & 3)) { /* data are properly aligned */ X = (const md5_word_t *)data; } else { /* not aligned */ memcpy(xbuf, data, 64); X = xbuf; } } #endif #if BYTE_ORDER == 0 else /* dynamic big-endian */ #endif #if BYTE_ORDER >= 0 /* big-endian */ { /* * On big-endian machines, we must arrange the bytes in the * right order. */ const md5_byte_t *xp = data; int i; # if BYTE_ORDER == 0 X = xbuf; /* (dynamic only) */ # else # define xbuf X /* (static only) */ # endif for (i = 0; i < 16; ++i, xp += 4) xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24); } #endif } #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) /* Round 1. */ /* Let [abcd k s i] denote the operation a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ #define F(x, y, z) (((x) & (y)) | (~(x) & (z))) #define SET(a, b, c, d, k, s, Ti)\ t = a + F(b,c,d) + X[k] + Ti;\ a = ROTATE_LEFT(t, s) + b /* Do the following 16 operations. */ SET(a, b, c, d, 0, 7, T1); SET(d, a, b, c, 1, 12, T2); SET(c, d, a, b, 2, 17, T3); SET(b, c, d, a, 3, 22, T4); SET(a, b, c, d, 4, 7, T5); SET(d, a, b, c, 5, 12, T6); SET(c, d, a, b, 6, 17, T7); SET(b, c, d, a, 7, 22, T8); SET(a, b, c, d, 8, 7, T9); SET(d, a, b, c, 9, 12, T10); SET(c, d, a, b, 10, 17, T11); SET(b, c, d, a, 11, 22, T12); SET(a, b, c, d, 12, 7, T13); SET(d, a, b, c, 13, 12, T14); SET(c, d, a, b, 14, 17, T15); SET(b, c, d, a, 15, 22, T16); #undef SET /* Round 2. */ /* Let [abcd k s i] denote the operation a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ #define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) #define SET(a, b, c, d, k, s, Ti)\ t = a + G(b,c,d) + X[k] + Ti;\ a = ROTATE_LEFT(t, s) + b /* Do the following 16 operations. */ SET(a, b, c, d, 1, 5, T17); SET(d, a, b, c, 6, 9, T18); SET(c, d, a, b, 11, 14, T19); SET(b, c, d, a, 0, 20, T20); SET(a, b, c, d, 5, 5, T21); SET(d, a, b, c, 10, 9, T22); SET(c, d, a, b, 15, 14, T23); SET(b, c, d, a, 4, 20, T24); SET(a, b, c, d, 9, 5, T25); SET(d, a, b, c, 14, 9, T26); SET(c, d, a, b, 3, 14, T27); SET(b, c, d, a, 8, 20, T28); SET(a, b, c, d, 13, 5, T29); SET(d, a, b, c, 2, 9, T30); SET(c, d, a, b, 7, 14, T31); SET(b, c, d, a, 12, 20, T32); #undef SET /* Round 3. */ /* Let [abcd k s t] denote the operation a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ #define H(x, y, z) ((x) ^ (y) ^ (z)) #define SET(a, b, c, d, k, s, Ti)\ t = a + H(b,c,d) + X[k] + Ti;\ a = ROTATE_LEFT(t, s) + b /* Do the following 16 operations. */ SET(a, b, c, d, 5, 4, T33); SET(d, a, b, c, 8, 11, T34); SET(c, d, a, b, 11, 16, T35); SET(b, c, d, a, 14, 23, T36); SET(a, b, c, d, 1, 4, T37); SET(d, a, b, c, 4, 11, T38); SET(c, d, a, b, 7, 16, T39); SET(b, c, d, a, 10, 23, T40); SET(a, b, c, d, 13, 4, T41); SET(d, a, b, c, 0, 11, T42); SET(c, d, a, b, 3, 16, T43); SET(b, c, d, a, 6, 23, T44); SET(a, b, c, d, 9, 4, T45); SET(d, a, b, c, 12, 11, T46); SET(c, d, a, b, 15, 16, T47); SET(b, c, d, a, 2, 23, T48); #undef SET /* Round 4. */ /* Let [abcd k s t] denote the operation a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ #define I(x, y, z) ((y) ^ ((x) | ~(z))) #define SET(a, b, c, d, k, s, Ti)\ t = a + I(b,c,d) + X[k] + Ti;\ a = ROTATE_LEFT(t, s) + b /* Do the following 16 operations. */ SET(a, b, c, d, 0, 6, T49); SET(d, a, b, c, 7, 10, T50); SET(c, d, a, b, 14, 15, T51); SET(b, c, d, a, 5, 21, T52); SET(a, b, c, d, 12, 6, T53); SET(d, a, b, c, 3, 10, T54); SET(c, d, a, b, 10, 15, T55); SET(b, c, d, a, 1, 21, T56); SET(a, b, c, d, 8, 6, T57); SET(d, a, b, c, 15, 10, T58); SET(c, d, a, b, 6, 15, T59); SET(b, c, d, a, 13, 21, T60); SET(a, b, c, d, 4, 6, T61); SET(d, a, b, c, 11, 10, T62); SET(c, d, a, b, 2, 15, T63); SET(b, c, d, a, 9, 21, T64); #undef SET /* Then perform the following additions. (That is increment each of the four registers by the value it had before this block was started.) */ pms->abcd[0] += a; pms->abcd[1] += b; pms->abcd[2] += c; pms->abcd[3] += d; } void md5_init(md5_state_t *pms) { pms->count[0] = pms->count[1] = 0; pms->abcd[0] = 0x67452301; pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476; pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301; pms->abcd[3] = 0x10325476; } void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes) { const md5_byte_t *p = data; int left = nbytes; int offset = (pms->count[0] >> 3) & 63; md5_word_t nbits = (md5_word_t)(nbytes << 3); if (nbytes <= 0) return; /* Update the message length. */ pms->count[1] += nbytes >> 29; pms->count[0] += nbits; if (pms->count[0] < nbits) pms->count[1]++; /* Process an initial partial block. */ if (offset) { int copy = (offset + nbytes > 64 ? 64 - offset : nbytes); memcpy(pms->buf + offset, p, copy); if (offset + copy < 64) return; p += copy; left -= copy; md5_process(pms, pms->buf); } /* Process full blocks. */ for (; left >= 64; p += 64, left -= 64) md5_process(pms, p); /* Process a final partial block. */ if (left) memcpy(pms->buf, p, left); } void md5_finish(md5_state_t *pms, md5_byte_t digest[16]) { static const md5_byte_t pad[64] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; md5_byte_t data[8]; int i; /* Save the length before padding. */ for (i = 0; i < 8; ++i) data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3)); /* Pad to 56 bytes mod 64. */ md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); /* Append the length. */ md5_append(pms, data, 8); for (i = 0; i < 16; ++i) digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3)); } IceE-trans-1.2.0/src/IceUtil/Time.cpp0000664000076400007640000000605210560413774016557 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 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 #ifdef _WIN32 # include # include #else # include #endif using namespace IceUtil; Time::Time() : _usec(0) { } Time IceUtil::Time::now() { #ifdef _WIN32 # if defined(_MSC_VER) struct _timeb tb; _ftime(&tb); # elif defined(__BCPLUSPLUS__) struct timeb tb; ftime(&tb); # endif return Time(static_cast(tb.time) * ICE_INT64(1000000) + tb.millitm * 1000); #else struct timeval tv; gettimeofday(&tv, 0); return Time(tv.tv_sec * ICE_INT64(1000000) + tv.tv_usec); #endif } Time IceUtil::Time::seconds(Int64 t) { return Time(t * ICE_INT64(1000000)); } Time IceUtil::Time::milliSeconds(Int64 t) { return Time(t * ICE_INT64(1000)); } Time IceUtil::Time::microSeconds(Int64 t) { return Time(t); } #ifndef _WIN32 IceUtil::Time::operator timeval() const { timeval tv; tv.tv_sec = static_cast(_usec / 1000000); tv.tv_usec = static_cast(_usec % 1000000); return tv; } #endif Int64 IceUtil::Time::toSeconds() const { return _usec / 1000000; } Int64 IceUtil::Time::toMilliSeconds() const { return _usec / 1000; } Int64 IceUtil::Time::toMicroSeconds() const { return _usec; } double IceUtil::Time::toSecondsDouble() const { return _usec / 1000000.0; } double IceUtil::Time::toMilliSecondsDouble() const { return _usec / 1000.0; } double IceUtil::Time::toMicroSecondsDouble() const { return static_cast(_usec); } std::string IceUtil::Time::toDateTime() const { time_t time = static_cast(_usec / 1000000); struct tm* t; #ifdef _WIN32 t = localtime(&time); #else struct tm tr; localtime_r(&time, &tr); t = &tr; #endif char buf[32]; strftime(buf, sizeof(buf), "%x %H:%M:%S", t); std::ostringstream os; os << buf << "."; os.fill('0'); os.width(3); os << static_cast(_usec % 1000000 / 1000); return os.str(); } std::string IceUtil::Time::toDuration() const { Int64 usecs = _usec % 1000000; Int64 secs = _usec / 1000000 % 60; Int64 mins = _usec / 1000000 / 60 % 60; Int64 hours = _usec / 1000000 / 60 / 60 % 24; Int64 days = _usec / 1000000 / 60 / 60 / 24; using namespace std; ostringstream os; if(days != 0) { os << days << "d "; } os << setfill('0') << setw(2) << hours << ":" << setw(2) << mins << ":" << setw(2) << secs; if(usecs != 0) { os << "." << setw(3) << (usecs / 1000); } return os.str(); } Time::Time(Int64 usec) : _usec(usec) { } std::ostream& IceUtil::operator<<(std::ostream& out, const Time& tm) { return out << tm.toMicroSeconds() / 1000000.0; } IceE-trans-1.2.0/src/IceUtil/StringUtil.cpp0000664000076400007640000002306510560413774017770 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 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 using namespace std; using namespace IceUtil; static string toOctalString(unsigned int n) { string s; s.resize(32); string::size_type charPos = 32; const int radix = 1 << 3; int mask = radix - 1; do { s[--charPos] = '0' + (n & mask); n >>= 3; } while(n != 0); return string(s, charPos, (32 - charPos)); } // // Write the byte b as an escape sequence if it isn't a printable ASCII // character and append the escape sequence to s. Additional characters // that should be escaped can be passed in special. If b is any of these // characters, b is preceded by a backslash in s. // static void encodeChar(string::value_type b, string& s, const string& special) { switch(b) { case '\\': { s.append("\\\\"); break; } case '\'': { s.append("\\'"); break; } case '"': { s.append("\\\""); break; } case '\b': { s.append("\\b"); break; } case '\f': { s.append("\\f"); break; } case '\n': { s.append("\\n"); break; } case '\r': { s.append("\\r"); break; } case '\t': { s.append("\\t"); break; } default: { unsigned char i = static_cast(b); if(!(i >= 32 && i <= 126)) { s.push_back('\\'); string octal = toOctalString(i); // // Add leading zeroes so that we avoid problems during // decoding. For example, consider the escaped string // \0013 (i.e., a character with value 1 followed by the // character '3'). If the leading zeroes were omitted, the // result would be incorrectly interpreted as a single // character with value 11. // for(string::size_type j = octal.size(); j < 3; j++) { s.push_back('0'); } s.append(octal); } else if(special.find(b) != string::npos) { s.push_back('\\'); s.push_back(b); } else { s.push_back(b); } break; } } } // // Add escape sequences (such as "\n", or "\007") to make a string // readable in ASCII. Any characters that appear in special are // prefixed with a backslash in the returned string. // string IceUtil::escapeString(const string& s, const string& special) { string::size_type i; for(i = 0; i < special.size(); ++i) { if(static_cast(special[i]) < 32 || static_cast(special[i]) > 126) { throw IllegalArgumentException(__FILE__, __LINE__, "special characters must be in ASCII range 32-126"); } } string result; for(i = 0; i < s.size(); ++i) { encodeChar(s[i], result, special); } return result; } static char checkChar(char c) { if(!(static_cast(c) >= 32 && static_cast(c) <= 126)) { throw IllegalArgumentException(__FILE__, __LINE__, "illegal input character"); } return c; } // // Decode the character or escape sequence starting at start and return it. // end marks the one-past-the-end position of the substring to be scanned. // nextStart is set to the index of the first character following the decoded // character or escape sequence. // static char decodeChar(const string& s, string::size_type start, string::size_type end, string::size_type& nextStart) { assert(start >= 0); assert(start < end); assert(end <= s.size()); char c; if(s[start] != '\\') { c = checkChar(s[start++]); } else { if(start + 1 == end) { throw IllegalArgumentException(__FILE__, __LINE__, "trailing backslash in argument"); } switch(s[++start]) { case '\\': case '\'': case '"': { c = s[start++]; break; } case 'b': { ++start; c = '\b'; break; } case 'f': { ++start; c = '\f'; break; } case 'n': { ++start; c = '\n'; break; } case 'r': { ++start; c = '\r'; break; } case 't': { ++start; c = '\t'; break; } case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': { int oct = 0; for(int j = 0; j < 3 && start < end; ++j) { int charVal = s[start++] - '0'; if(charVal < 0 || charVal > 7) { --start; break; } oct = oct * 8 + charVal; } if(oct > 255) { throw IllegalArgumentException(__FILE__, __LINE__, "octal value out of range"); } c = (char)oct; break; } default: { c = checkChar(s[start++]); break; } } } nextStart = start; return c; } // // Remove escape sequences from s and append the result to sb. // Return true if successful, false otherwise. // static void decodeString(const string& s, string::size_type start, string::size_type end, string& sb) { while(start < end) { sb.push_back(decodeChar(s, start, end, start)); } } // // Remove escape sequences added by escapeString. // bool IceUtil::unescapeString(const string& s, string::size_type start, string::size_type end, string& result) { if(start < 0) { throw IllegalArgumentException(__FILE__, __LINE__, "start offset must be >= 0"); } if(end > s.size()) { throw IllegalArgumentException(__FILE__, __LINE__, "end offset must be <= s.size()"); } if(start > end) { throw IllegalArgumentException(__FILE__, __LINE__, "start offset must <= end offset"); } result.reserve(end - start); try { result.clear(); decodeString(s, start, end, result); return true; } catch(...) { return false; } } // // If a single or double quotation mark is found at the start position, // then the position of the matching closing quote is returned. If no // quotation mark is found at the start position, then 0 is returned. // If no matching closing quote is found, then -1 is returned. // string::size_type IceUtil::checkQuote(const string& s, string::size_type start) { string::value_type quoteChar = s[start]; if(quoteChar == '"' || quoteChar == '\'') { start++; string::size_type pos; while(start < s.size() && (pos = s.find(quoteChar, start)) != string::npos) { if(s[pos - 1] != '\\') { return pos; } start = pos + 1; } return string::npos; // Unmatched quote. } return 0; // Not quoted. } // // Match `s' against the pattern `pat'. A * in the pattern acts // as a wildcard: it matches any non-empty sequence of characters. // We match by hand here because it's portable across platforms // (whereas regex() isn't). Only one * per pattern is supported. // bool IceUtil::match(const string& s, const string& pat, bool emptyMatch) { assert(!s.empty()); assert(!pat.empty()); // // If pattern does not contain a wildcard just compare strings. // string::size_type beginIndex = pat.find('*'); if(beginIndex == string::npos) { return s == pat; } // // Make sure start of the strings match // if(beginIndex > s.length() || s.substr(0, beginIndex) != pat.substr(0, beginIndex)) { return false; } // // Make sure there is something present in the middle to match the // wildcard. If emptyMatch is true, allow a match of "". // string::size_type endLength = pat.length() - beginIndex - 1; if(endLength > s.length()) { return false; } string::size_type endIndex = s.length() - endLength; if(endIndex < beginIndex || (!emptyMatch && endIndex == beginIndex)) { return false; } // // Make sure end of the strings match // if(s.substr(endIndex, s.length()) != pat.substr(beginIndex + 1, pat.length())) { return false; } return true; } IceE-trans-1.2.0/src/IceUtil/Random.cpp0000664000076400007640000001240410560413774017077 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 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 #ifdef _WIN32 # include #else # include # include #endif using namespace std; IceUtil::RandomGeneratorException::RandomGeneratorException(const char* file, int line, int error) : Exception(file, line), _error(error) { } const char* IceUtil::RandomGeneratorException::_name = "IceUtil::RandomGeneratorException"; // // The static mutex is required to lazy initialize the file // descriptor for /dev/urandom (Unix) or the cryptographic // context (Windows). // // Also, unfortunately on Linux (at least up to 2.6.9), concurrent // access to /dev/urandom can return the same value. Search for // "Concurrent access to /dev/urandom" in the linux-kernel mailing // list archive for additional details. Since /dev/urandom on other // platforms is usually a port from Linux, this problem could be // widespread. Therefore, we serialize access to /dev/urandom using a // static mutex. // static IceUtil::StaticMutex staticMutex = ICE_STATIC_MUTEX_INITIALIZER; #ifdef _WIN32 static HCRYPTPROV context = NULL; #else static int fd = -1; #endif namespace { // // Close fd at exit // class RandomCleanup { public: ~RandomCleanup() { #ifdef _WIN32 if(context != NULL) { CryptReleaseContext(context, 0); context = NULL; } #else if(fd != -1) { close(fd); fd = -1; } #endif } }; static RandomCleanup uuidCleanup; } string IceUtil::RandomGeneratorException::ice_name() const { return _name; } void IceUtil::RandomGeneratorException::ice_print(ostream& os) const { Exception::ice_print(os); if(_error != 0) { os << ":\nrandom generator exception: "; #ifdef _WIN32 LPVOID lpMsgBuf = 0; DWORD ok = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, _error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR)&lpMsgBuf, 0, NULL); if(ok) { LPCTSTR msg = (LPCTSTR)lpMsgBuf; assert(msg && strlen((char*)msg) > 0); os << msg; LocalFree(lpMsgBuf); } else { os << "unknown random generator error"; } #else os << strerror(_error); #endif } } IceUtil::Exception* IceUtil::RandomGeneratorException::ice_clone() const { return new RandomGeneratorException(*this); } void IceUtil::RandomGeneratorException::ice_throw() const { throw *this; } void IceUtil::generateRandom(char* buffer, int size) { #ifdef _WIN32 // // It's not clear from the Microsoft documentation if CryptGenRandom // can be called concurrently from several threads. To be on the safe // side, we also serialize calls to to CryptGenRandom with the static // mutex. // IceUtil::StaticMutex::Lock lock(staticMutex); if(context == NULL) { if(!CryptAcquireContext(&context, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { throw RandomGeneratorException(__FILE__, __LINE__, GetLastError()); } } if(!CryptGenRandom(context, size, reinterpret_cast(buffer))) { throw RandomGeneratorException(__FILE__, __LINE__, GetLastError()); } #else // // Serialize access to /dev/urandom; see comment above. // IceUtil::StaticMutex::Lock lock(staticMutex); if(fd == -1) { fd = open("/dev/urandom", O_RDONLY); if(fd == -1) { assert(0); throw RandomGeneratorException(__FILE__, __LINE__); } } // // Limit the number of attempts to 20 reads to avoid // a potential "for ever" loop // int reads = 0; size_t index = 0; while(reads <= 20 && index != static_cast(size)) { ssize_t bytesRead = read(fd, buffer + index, static_cast(size) - index); if(bytesRead == -1 && errno != EINTR) { int err = errno; cerr << "Reading /dev/urandom returned " << strerror(err) << endl; assert(0); throw RandomGeneratorException(__FILE__, __LINE__, errno); } else { index += bytesRead; reads++; } } if(index != static_cast(size)) { assert(0); throw RandomGeneratorException(__FILE__, __LINE__); } #endif } int IceUtil::random(int limit) { int r; generateRandom(reinterpret_cast(&r), static_cast(sizeof(int))); if(limit > 0) { r = r % limit; } if(r < 0) { r = -r; } return r; } IceE-trans-1.2.0/src/IceUtil/ConvertUTF.cpp0000775000076400007640000004361210560413774017666 0ustar dwaynedwayne/* * Copyright 2001-2004 Unicode, Inc. * * Disclaimer * * This source code is provided as is by Unicode, Inc. No claims are * made as to fitness for any particular purpose. No warranties of any * kind are expressed or implied. The recipient agrees to determine * applicability of information provided. If this file has been * purchased on magnetic or optical media from Unicode, Inc., the * sole remedy for any claim will be exchange of defective media * within 90 days of receipt. * * Limitations on Rights to Redistribute This Code * * Unicode, Inc. hereby grants the right to freely use the information * supplied in this file in the creation of products supporting the * Unicode Standard, and to make copies of this file in any form * for internal or external distribution as long as this notice * remains attached. */ // ********************************************************************** // // Copyright (c) 2003-2007 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. // // ********************************************************************** /* --------------------------------------------------------------------- Conversions between UTF32, UTF-16, and UTF-8. Source code file. Author: Mark E. Davis, 1994. Rev History: Rick McGowan, fixes & updates May 2001. Sept 2001: fixed const & error conditions per mods suggested by S. Parent & A. Lillich. June 2002: Tim Dodd added detection and handling of incomplete source sequences, enhanced error detection, added casts to eliminate compiler warnings. July 2003: slight mods to back out aggressive FFFE detection. Jan 2004: updated switches in from-UTF8 conversions. Oct 2004: updated to use UNI_MAX_LEGAL_UTF32 in UTF-32 conversions. See the header file "ConvertUTF.h" for complete documentation. ------------------------------------------------------------------------ */ #include #ifdef CVTUTF_DEBUG #include #endif namespace IceUtil { static const int halfShift = 10; /* used for shifting by 10 bits */ static const UTF32 halfBase = 0x0010000UL; static const UTF32 halfMask = 0x3FFUL; #define UNI_SUR_HIGH_START (UTF32)0xD800 #define UNI_SUR_HIGH_END (UTF32)0xDBFF #define UNI_SUR_LOW_START (UTF32)0xDC00 #define UNI_SUR_LOW_END (UTF32)0xDFFF // #define false 0 // #define true 1 /* --------------------------------------------------------------------- */ /* * Index into the table below with the first byte of a UTF-8 sequence to * get the number of trailing bytes that are supposed to follow it. * Note that *legal* UTF-8 values can't have 4 or 5-bytes. The table is * left as-is for anyone who may want to do such conversion, which was * allowed in earlier algorithms. */ static const char trailingBytesForUTF8[256] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 }; /* * Magic values subtracted from a buffer value during UTF8 conversion. * This table contains as many values as there might be trailing bytes * in a UTF-8 sequence. */ static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL, 0x03C82080UL, 0xFA082080UL, 0x82082080UL }; /* * Once the bits are split out into bytes of UTF-8, this is a mask OR-ed * into the first byte, depending on how many bytes follow. There are * as many entries in this table as there are UTF-8 sequence types. * (I.e., one byte sequence, two byte... etc.). Remember that sequencs * for *legal* UTF-8 will be 4 or fewer bytes total. */ static const UTF8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; /* --------------------------------------------------------------------- */ /* The interface converts a whole buffer to avoid function-call overhead. * Constants have been gathered. Loops & conditionals have been removed as * much as possible for efficiency, in favor of drop-through switches. * (See "Note A" at the bottom of the file for equivalent code.) * If your compiler supports it, the "isLegalUTF8" call can be turned * into an inline function. */ /* --------------------------------------------------------------------- */ ConversionResult ConvertUTF16toUTF8 ( const UTF16** sourceStart, const UTF16* sourceEnd, UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) { ConversionResult result = conversionOK; const UTF16* source = *sourceStart; UTF8* target = *targetStart; while (source < sourceEnd) { UTF32 ch; unsigned short bytesToWrite = 0; const UTF32 byteMask = 0xBF; const UTF32 byteMark = 0x80; const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */ ch = *source++; /* If we have a surrogate pair, convert to UTF32 first. */ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) { /* If the 16 bits following the high surrogate are in the source buffer... */ if (source < sourceEnd) { UTF32 ch2 = *source; /* If it's a low surrogate, convert to UTF32. */ if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) { ch = ((ch - UNI_SUR_HIGH_START) << halfShift) + (ch2 - UNI_SUR_LOW_START) + halfBase; ++source; } else if (flags == strictConversion) { /* it's an unpaired high surrogate */ --source; /* return to the illegal value itself */ result = sourceIllegal; break; } } else { /* We don't have the 16 bits following the high surrogate. */ --source; /* return to the high surrogate */ result = sourceExhausted; break; } } else if (flags == strictConversion) { /* UTF-16 surrogate values are illegal in UTF-32 */ if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) { --source; /* return to the illegal value itself */ result = sourceIllegal; break; } } /* Figure out how many bytes the result will require */ if (ch < (UTF32)0x80) { bytesToWrite = 1; } else if (ch < (UTF32)0x800) { bytesToWrite = 2; } else if (ch < (UTF32)0x10000) { bytesToWrite = 3; } else if (ch < (UTF32)0x110000) { bytesToWrite = 4; } else { bytesToWrite = 3; ch = UNI_REPLACEMENT_CHAR; } target += bytesToWrite; if (target > targetEnd) { source = oldSource; /* Back up source pointer! */ target -= bytesToWrite; result = targetExhausted; break; } switch (bytesToWrite) { /* note: everything falls through. */ case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; case 1: *--target = (UTF8)(ch | firstByteMark[bytesToWrite]); } target += bytesToWrite; } *sourceStart = source; *targetStart = target; return result; } /* --------------------------------------------------------------------- */ /* * Utility routine to tell whether a sequence of bytes is legal UTF-8. * This must be called with the length pre-determined by the first byte. * If not calling this from ConvertUTF8to*, then the length can be set by: * length = trailingBytesForUTF8[*source]+1; * and the sequence is illegal right away if there aren't that many bytes * available. * If presented with a length > 4, this returns false. The Unicode * definition of UTF-8 goes up to 4-byte sequences. */ static Boolean isLegalUTF8(const UTF8 *source, int length) { UTF8 a; const UTF8 *srcptr = source+length; switch (length) { default: return false; /* Everything else falls through when "true"... */ case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; case 2: if ((a = (*--srcptr)) > 0xBF) return false; switch (*source) { /* no fall-through in this inner switch */ case 0xE0: if (a < 0xA0) return false; break; case 0xED: if (a > 0x9F) return false; break; case 0xF0: if (a < 0x90) return false; break; case 0xF4: if (a > 0x8F) return false; break; default: if (a < 0x80) return false; } case 1: if (*source >= 0x80 && *source < 0xC2) return false; } if (*source > 0xF4) return false; return true; } /* --------------------------------------------------------------------- */ /* * Exported function to return whether a UTF-8 sequence is legal or not. * This is not used here; it's just exported. */ Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd) { if(source == sourceEnd) { return true; } while(true) { int length = trailingBytesForUTF8[*source]+1; // Is buffer big enough to contain character? if (source+length > sourceEnd) { return false; } // Is character legal UTF8? if(!isLegalUTF8(source, length)) { return false; } // Are we at end of buffer? source += length; if(source == sourceEnd) { return true; } } } /* --------------------------------------------------------------------- */ ConversionResult ConvertUTF8toUTF16 ( const UTF8** sourceStart, const UTF8* sourceEnd, UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) { ConversionResult result = conversionOK; const UTF8* source = *sourceStart; UTF16* target = *targetStart; while (source < sourceEnd) { UTF32 ch = 0; unsigned short extraBytesToRead = trailingBytesForUTF8[*source]; if (source + extraBytesToRead >= sourceEnd) { result = sourceExhausted; break; } /* Do this check whether lenient or strict */ if (! isLegalUTF8(source, extraBytesToRead+1)) { result = sourceIllegal; break; } /* * The cases all fall through. See "Note A" below. */ switch (extraBytesToRead) { case 5: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */ case 4: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */ case 3: ch += *source++; ch <<= 6; case 2: ch += *source++; ch <<= 6; case 1: ch += *source++; ch <<= 6; case 0: ch += *source++; } ch -= offsetsFromUTF8[extraBytesToRead]; if (target >= targetEnd) { source -= (extraBytesToRead+1); /* Back up source pointer! */ result = targetExhausted; break; } if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */ /* UTF-16 surrogate values are illegal in UTF-32 */ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { if (flags == strictConversion) { source -= (extraBytesToRead+1); /* return to the illegal value itself */ result = sourceIllegal; break; } else { *target++ = UNI_REPLACEMENT_CHAR; } } else { *target++ = (UTF16)ch; /* normal case */ } } else if (ch > UNI_MAX_UTF16) { if (flags == strictConversion) { result = sourceIllegal; source -= (extraBytesToRead+1); /* return to the start */ break; /* Bail out; shouldn't continue */ } else { *target++ = UNI_REPLACEMENT_CHAR; } } else { /* target is a character in range 0xFFFF - 0x10FFFF. */ if (target + 1 >= targetEnd) { source -= (extraBytesToRead+1); /* Back up source pointer! */ result = targetExhausted; break; } ch -= halfBase; *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START); *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START); } } *sourceStart = source; *targetStart = target; return result; } /* --------------------------------------------------------------------- */ ConversionResult ConvertUTF32toUTF8 ( const UTF32** sourceStart, const UTF32* sourceEnd, UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) { ConversionResult result = conversionOK; const UTF32* source = *sourceStart; UTF8* target = *targetStart; while (source < sourceEnd) { UTF32 ch; unsigned short bytesToWrite = 0; const UTF32 byteMask = 0xBF; const UTF32 byteMark = 0x80; ch = *source++; if (flags == strictConversion ) { /* UTF-16 surrogate values are illegal in UTF-32 */ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { --source; /* return to the illegal value itself */ result = sourceIllegal; break; } } /* * Figure out how many bytes the result will require. Turn any * illegally large UTF32 things (> Plane 17) into replacement chars. */ if (ch < (UTF32)0x80) { bytesToWrite = 1; } else if (ch < (UTF32)0x800) { bytesToWrite = 2; } else if (ch < (UTF32)0x10000) { bytesToWrite = 3; } else if (ch <= UNI_MAX_LEGAL_UTF32) { bytesToWrite = 4; } else { bytesToWrite = 3; ch = UNI_REPLACEMENT_CHAR; result = sourceIllegal; } target += bytesToWrite; if (target > targetEnd) { --source; /* Back up source pointer! */ target -= bytesToWrite; result = targetExhausted; break; } switch (bytesToWrite) { /* note: everything falls through. */ case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; case 1: *--target = (UTF8) (ch | firstByteMark[bytesToWrite]); } target += bytesToWrite; } *sourceStart = source; *targetStart = target; return result; } /* --------------------------------------------------------------------- */ ConversionResult ConvertUTF8toUTF32 ( const UTF8** sourceStart, const UTF8* sourceEnd, UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) { ConversionResult result = conversionOK; const UTF8* source = *sourceStart; UTF32* target = *targetStart; while (source < sourceEnd) { UTF32 ch = 0; unsigned short extraBytesToRead = trailingBytesForUTF8[*source]; if (source + extraBytesToRead >= sourceEnd) { result = sourceExhausted; break; } /* Do this check whether lenient or strict */ if (! isLegalUTF8(source, extraBytesToRead+1)) { result = sourceIllegal; break; } /* * The cases all fall through. See "Note A" below. */ switch (extraBytesToRead) { case 5: ch += *source++; ch <<= 6; case 4: ch += *source++; ch <<= 6; case 3: ch += *source++; ch <<= 6; case 2: ch += *source++; ch <<= 6; case 1: ch += *source++; ch <<= 6; case 0: ch += *source++; } ch -= offsetsFromUTF8[extraBytesToRead]; if (target >= targetEnd) { source -= (extraBytesToRead+1); /* Back up the source pointer! */ result = targetExhausted; break; } if (ch <= UNI_MAX_LEGAL_UTF32) { /* * UTF-16 surrogate values are illegal in UTF-32, and anything * over Plane 17 (> 0x10FFFF) is illegal. */ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { if (flags == strictConversion) { source -= (extraBytesToRead+1); /* return to the illegal value itself */ result = sourceIllegal; break; } else { *target++ = UNI_REPLACEMENT_CHAR; } } else { *target++ = ch; } } else { /* i.e., ch > UNI_MAX_LEGAL_UTF32 */ result = sourceIllegal; *target++ = UNI_REPLACEMENT_CHAR; } } *sourceStart = source; *targetStart = target; return result; } /* --------------------------------------------------------------------- Note A. The fall-through switches in UTF-8 reading code save a temp variable, some decrements & conditionals. The switches are equivalent to the following loop: { int tmpBytesToRead = extraBytesToRead+1; do { ch += *source++; --tmpBytesToRead; if (tmpBytesToRead) ch <<= 6; } while (tmpBytesToRead > 0); } In UTF-8 writing code, the switches on "bytesToWrite" are similarly unrolled loops. --------------------------------------------------------------------- */ } IceE-trans-1.2.0/src/IceUtil/Thread.cpp0000664000076400007640000002301510560413774017066 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 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 using namespace std; #ifdef _WIN32 IceUtil::ThreadControl::ThreadControl() : _handle(0), _id(GetCurrentThreadId()) { } IceUtil::ThreadControl::ThreadControl(HANDLE handle, IceUtil::ThreadControl::ID id) : _handle(handle), _id(id) { } bool IceUtil::ThreadControl::operator==(const ThreadControl& rhs) const { return _id == rhs._id; } bool IceUtil::ThreadControl::operator!=(const ThreadControl& rhs) const { return _id != rhs._id; } void IceUtil::ThreadControl::join() { if(_handle == 0) { throw BadThreadControlException(__FILE__, __LINE__); } int rc = WaitForSingleObject(_handle, INFINITE); if(rc != WAIT_OBJECT_0) { throw ThreadSyscallException(__FILE__, __LINE__, GetLastError()); } detach(); } void IceUtil::ThreadControl::detach() { if(_handle == 0) { throw BadThreadControlException(__FILE__, __LINE__); } if(CloseHandle(_handle) == 0) { throw ThreadSyscallException(__FILE__, __LINE__, GetLastError()); } } IceUtil::ThreadControl::ID IceUtil::ThreadControl::id() const { return _id; } void IceUtil::ThreadControl::sleep(const Time& timeout) { Sleep(static_cast(timeout.toMilliSeconds())); } void IceUtil::ThreadControl::yield() { // // A value of zero causes the thread to relinquish the remainder // of its time slice to any other thread of equal priority that is // ready to run. // Sleep(0); } IceUtil::Thread::Thread() : _started(false), _running(false), _handle(0), _id(0) { } IceUtil::Thread::~Thread() { } static unsigned int WINAPI startHook(void* arg) { // Ensure that the thread doesn't go away until run() has // completed. // IceUtil::ThreadPtr thread; try { IceUtil::Thread* rawThread = static_cast(arg); // // Ensure that the thread doesn't go away until run() has // completed. // thread = rawThread; #ifdef _WIN32 // // Initialize the random number generator in each thread on // Windows (the rand() seed is thread specific). // unsigned int seed = static_cast(IceUtil::Time::now().toMicroSeconds()); srand(seed ^ thread->getThreadControl().id()); #endif // // See the comment in IceUtil::Thread::start() for details. // rawThread->__decRef(); thread->run(); } catch(const IceUtil::Exception& e) { cerr << "IceUtil::Thread::run(): uncaught exception: "; cerr << e << endl; } catch(...) { cerr << "IceUtil::Thread::run(): uncaught exception" << endl; } thread->_done(); return 0; } #include IceUtil::ThreadControl IceUtil::Thread::start(size_t stackSize) { // // Keep this alive for the duration of start // IceUtil::ThreadPtr keepMe = this; IceUtil::Mutex::Lock lock(_stateMutex); if(_started) { throw ThreadStartedException(__FILE__, __LINE__); } // // It's necessary to increment the reference count since // pthread_create won't necessarily call the thread function until // later. If the user does (new MyThread)->start() then the thread // object could be deleted before the thread object takes // ownership. It's also necessary to increment the reference count // prior to calling pthread_create since the thread itself calls // __decRef(). // __incRef(); unsigned int id; _handle = reinterpret_cast( _beginthreadex(0, static_cast(stackSize), startHook, this, 0, &id)); _id = id; if(_handle == 0) { __decRef(); throw ThreadSyscallException(__FILE__, __LINE__, GetLastError()); } _started = true; _running = true; return ThreadControl(_handle, _id); } IceUtil::ThreadControl IceUtil::Thread::getThreadControl() const { IceUtil::Mutex::Lock lock(_stateMutex); if(!_started) { throw ThreadNotStartedException(__FILE__, __LINE__); } return ThreadControl(_handle, _id); } bool IceUtil::Thread::operator==(const Thread& rhs) const { return this == &rhs; } bool IceUtil::Thread::operator!=(const Thread& rhs) const { return this != &rhs; } bool IceUtil::Thread::operator<(const Thread& rhs) const { return this < &rhs; } bool IceUtil::Thread::isAlive() const { IceUtil::Mutex::Lock lock(_stateMutex); return _running; } void IceUtil::Thread::_done() { IceUtil::Mutex::Lock lock(_stateMutex); _running = false; } #else IceUtil::ThreadControl::ThreadControl(pthread_t thread) : _thread(thread), _detachable(true) { } IceUtil::ThreadControl::ThreadControl() : _thread(pthread_self()), _detachable(false) { } bool IceUtil::ThreadControl::operator==(const ThreadControl& rhs) const { return pthread_equal(_thread, rhs._thread) != 0; } bool IceUtil::ThreadControl::operator!=(const ThreadControl& rhs) const { return !operator==(rhs); } void IceUtil::ThreadControl::join() { if(!_detachable) { throw BadThreadControlException(__FILE__, __LINE__); } void* ignore = 0; int rc = pthread_join(_thread, &ignore); if(rc != 0) { throw ThreadSyscallException(__FILE__, __LINE__, rc); } } void IceUtil::ThreadControl::detach() { if(!_detachable) { throw BadThreadControlException(__FILE__, __LINE__); } int rc = pthread_detach(_thread); if(rc != 0) { throw ThreadSyscallException(__FILE__, __LINE__, rc); } } IceUtil::ThreadControl::ID IceUtil::ThreadControl::id() const { return _thread;; } void IceUtil::ThreadControl::sleep(const Time& timeout) { struct timeval tv = timeout; struct timespec ts; ts.tv_sec = tv.tv_sec; ts.tv_nsec = tv.tv_usec * 1000L; nanosleep(&ts, 0); } void IceUtil::ThreadControl::yield() { sched_yield(); } IceUtil::Thread::Thread() : _started(false), _running(false) { } IceUtil::Thread::~Thread() { } extern "C" { static void* startHook(void* arg) { // // Ensure that the thread doesn't go away until run() has // completed. // IceUtil::ThreadPtr thread; try { IceUtil::Thread* rawThread = static_cast(arg); thread = rawThread; // // See the comment in IceUtil::Thread::start() for details. // rawThread->__decRef(); thread->run(); } catch(const IceUtil::Exception& e) { cerr << "IceUtil::Thread::run(): uncaught exception: "; cerr << e << endl; } catch(...) { cerr << "IceUtil::Thread::run(): uncaught exception" << endl; } thread->_done(); return 0; } } IceUtil::ThreadControl IceUtil::Thread::start(size_t stackSize) { // // Keep this alive for the duration of start // IceUtil::ThreadPtr keepMe = this; IceUtil::Mutex::Lock lock(_stateMutex); if(_started) { throw ThreadStartedException(__FILE__, __LINE__); } // // It's necessary to increment the reference count since // pthread_create won't necessarily call the thread function until // later. If the user does (new MyThread)->start() then the thread // object could be deleted before the thread object takes // ownership. It's also necessary to increment the reference count // prior to calling pthread_create since the thread itself calls // __decRef(). // __incRef(); if(stackSize > 0) { pthread_attr_t attr; int rc = pthread_attr_init(&attr); if(rc != 0) { __decRef(); throw ThreadSyscallException(__FILE__, __LINE__, rc); } rc = pthread_attr_setstacksize(&attr, stackSize); if(rc != 0) { __decRef(); throw ThreadSyscallException(__FILE__, __LINE__, rc); } rc = pthread_create(&_thread, &attr, startHook, this); if(rc != 0) { __decRef(); throw ThreadSyscallException(__FILE__, __LINE__, rc); } } else { int rc = pthread_create(&_thread, 0, startHook, this); if(rc != 0) { __decRef(); throw ThreadSyscallException(__FILE__, __LINE__, rc); } } _started = true; _running = true; return ThreadControl(_thread); } IceUtil::ThreadControl IceUtil::Thread::getThreadControl() const { IceUtil::Mutex::Lock lock(_stateMutex); if(!_started) { throw ThreadNotStartedException(__FILE__, __LINE__); } return ThreadControl(_thread); } bool IceUtil::Thread::operator==(const Thread& rhs) const { return this == &rhs; } bool IceUtil::Thread::operator!=(const Thread& rhs) const { return this != &rhs; } bool IceUtil::Thread::operator<(const Thread& rhs) const { return this < &rhs; } bool IceUtil::Thread::isAlive() const { IceUtil::Mutex::Lock lock(_stateMutex); return _running; } void IceUtil::Thread::_done() { IceUtil::Mutex::Lock lock(_stateMutex); _running = false; } #endif IceE-trans-1.2.0/bin/0000775000076400007640000000000010620635757013601 5ustar dwaynedwayneIceE-trans-1.2.0/LICENSE0000664000076400007640000004314210524133611014023 0ustar dwaynedwayne GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. IceE-trans-1.2.0/include/0000775000076400007640000000000010620635746014452 5ustar dwaynedwayneIceE-trans-1.2.0/include/Slice/0000775000076400007640000000000010620635746015511 5ustar dwaynedwayneIceE-trans-1.2.0/include/Slice/Parser.h0000664000076400007640000007367210560413774017133 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** #ifndef SLICE_PARSER_H #define SLICE_PARSER_H #include #include #include #include #include #include #include #include #include #include #ifndef SLICE_API # ifdef SLICE_API_EXPORTS # define SLICE_API ICE_DECLSPEC_EXPORT # else # define SLICE_API ICE_DECLSPEC_IMPORT # endif #endif namespace Slice { #if defined(_WIN32) const IceUtil::Int64 Int32Max = 0x7fffffffi64; const IceUtil::Int64 Int32Min = -Int32Max - 1i64; #else # if defined(INT32_MIN) && defined(INT32_MAX) const IceUtil::Int64 Int32Max = INT32_MAX; const IceUtil::Int64 Int32Min = INT32_MIN; # else const IceUtil::Int64 Int32Max = 0x7fffffffLL; const IceUtil::Int64 Int32Min = -Int32Max - 1LL; # endif #endif const IceUtil::Int64 Int16Max = 0x7fff; const IceUtil::Int64 Int16Min = -Int16Max - 1; const IceUtil::Int64 ByteMax = 0xff; const IceUtil::Int64 ByteMin = 0x00; SLICE_API enum FeatureProfile { Ice, IceE }; class GrammarBase; class SyntaxTreeBase; class Type; class Builtin; class Contained; class Container; class Module; class Constructed; class ClassDecl; class ClassDef; class Proxy; class Exception; class Struct; class Operation; class ParamDecl; class DataMember; class Sequence; class Dictionary; class Enum; class Enumerator; class Const; class Unit; class CICompare; class DerivedToBaseCompare; class ModulePartialCompare; typedef ::IceUtil::Handle GrammarBasePtr; typedef ::IceUtil::Handle SyntaxTreeBasePtr; typedef ::IceUtil::Handle TypePtr; typedef ::IceUtil::Handle BuiltinPtr; typedef ::IceUtil::Handle ContainedPtr; typedef ::IceUtil::Handle ContainerPtr; typedef ::IceUtil::Handle ModulePtr; typedef ::IceUtil::Handle ConstructedPtr; typedef ::IceUtil::Handle ClassDeclPtr; typedef ::IceUtil::Handle ClassDefPtr; typedef ::IceUtil::Handle ProxyPtr; typedef ::IceUtil::Handle ExceptionPtr; typedef ::IceUtil::Handle StructPtr; typedef ::IceUtil::Handle OperationPtr; typedef ::IceUtil::Handle ParamDeclPtr; typedef ::IceUtil::Handle DataMemberPtr; typedef ::IceUtil::Handle SequencePtr; typedef ::IceUtil::Handle DictionaryPtr; typedef ::IceUtil::Handle EnumPtr; typedef ::IceUtil::Handle EnumeratorPtr; typedef ::IceUtil::Handle ConstPtr; typedef ::IceUtil::Handle UnitPtr; typedef std::list TypeList; typedef std::list ExceptionList; typedef std::set StringSet; typedef std::list StringList; typedef std::pair TypeString; typedef std::list TypeStringList; typedef std::list ContainedList; typedef std::list ModuleList; typedef std::list ConstructedList; typedef std::list ClassList; typedef std::list ExceptionList; typedef std::list StructList; typedef std::list SequenceList; typedef std::list DictionaryList; typedef std::list EnumList; typedef std::list OperationList; typedef std::list DataMemberList; typedef std::list ParamDeclList; typedef std::list EnumeratorList; typedef std::pair SyntaxTreeBaseString; // ---------------------------------------------------------------------- // CICompare -- function object to do case-insensitive string comparison. // ---------------------------------------------------------------------- class SLICE_API CICompare : public std::binary_function { public: bool operator()(const std::string&, const std::string&) const; }; #if defined(__SUNPRO_CC) SLICE_API bool cICompare(const std::string&, const std::string&); #endif // ---------------------------------------------------------------------- // DerivedToBaseCompare -- function object to do sort exceptions into // most-derived to least-derived order. // ---------------------------------------------------------------------- class SLICE_API DerivedToBaseCompare : public std::binary_function { public: bool operator()(const ExceptionPtr&, const ExceptionPtr&) const; }; #if defined(__SUNPRO_CC) SLICE_API bool derivedToBaseCompare(const ExceptionPtr&, const ExceptionPtr&); #endif // ---------------------------------------------------------------------- // ParserVisitor // ---------------------------------------------------------------------- class SLICE_API ParserVisitor { public: virtual ~ParserVisitor() { } virtual bool visitUnitStart(const UnitPtr&) { return true; } virtual void visitUnitEnd(const UnitPtr&) { } virtual bool visitModuleStart(const ModulePtr&) { return true; } virtual void visitModuleEnd(const ModulePtr&) { } virtual void visitClassDecl(const ClassDeclPtr&) { } virtual bool visitClassDefStart(const ClassDefPtr&) { return true; } virtual void visitClassDefEnd(const ClassDefPtr&) { } virtual bool visitExceptionStart(const ExceptionPtr&) { return true; } virtual void visitExceptionEnd(const ExceptionPtr&) { } virtual bool visitStructStart(const StructPtr&) { return true; } virtual void visitStructEnd(const StructPtr&) { } virtual void visitOperation(const OperationPtr&) { } virtual void visitParamDecl(const ParamDeclPtr&) { } virtual void visitDataMember(const DataMemberPtr&) { } virtual void visitSequence(const SequencePtr&) { } virtual void visitDictionary(const DictionaryPtr&) { } virtual void visitEnum(const EnumPtr&) { } virtual void visitConst(const ConstPtr&) { } }; // ---------------------------------------------------------------------- // DefinitionContext // ---------------------------------------------------------------------- class SLICE_API DefinitionContext : public ::IceUtil::SimpleShared { public: DefinitionContext(int, const StringList&); std::string filename() const; int includeLevel() const; bool seenDefinition() const; void setFilename(const std::string&); void setSeenDefinition(); bool hasMetaData() const; void setMetaData(const StringList&); std::string findMetaData(const std::string&) const; StringList getMetaData() const; private: int _includeLevel; StringList _metaData; std::string _filename; bool _seenDefinition; }; typedef ::IceUtil::Handle DefinitionContextPtr; // ---------------------------------------------------------------------- // GrammarBase // ---------------------------------------------------------------------- class SLICE_API GrammarBase : public ::IceUtil::SimpleShared { }; // ---------------------------------------------------------------------- // SyntaxTreeBase // ---------------------------------------------------------------------- class SLICE_API SyntaxTreeBase : public GrammarBase { public: virtual void destroy(); UnitPtr unit() const; DefinitionContextPtr definitionContext() const; // May be nil virtual void visit(ParserVisitor*, bool); protected: SyntaxTreeBase(const UnitPtr&); UnitPtr _unit; DefinitionContextPtr _definitionContext; }; // ---------------------------------------------------------------------- // Type // ---------------------------------------------------------------------- class SLICE_API Type : virtual public SyntaxTreeBase { public: virtual bool isLocal() const = 0; virtual std::string typeId() const = 0; virtual bool usesClasses() const = 0; virtual size_t minWireSize() const = 0; virtual bool isVariableLength() const = 0; protected: Type(const UnitPtr&); }; // ---------------------------------------------------------------------- // Builtin // ---------------------------------------------------------------------- class SLICE_API Builtin : virtual public Type { public: enum Kind { KindByte, KindBool, KindShort, KindInt, KindLong, KindFloat, KindDouble, KindString, KindObject, KindObjectProxy, KindLocalObject }; virtual bool isLocal() const; virtual std::string typeId() const; virtual bool usesClasses() const; virtual size_t minWireSize() const; virtual bool isVariableLength() const; Kind kind() const; std::string kindAsString() const; static const char* builtinTable[]; protected: Builtin(const UnitPtr&, Kind); friend class Unit; Kind _kind; }; // ---------------------------------------------------------------------- // Contained // ---------------------------------------------------------------------- class SLICE_API Contained : virtual public SyntaxTreeBase { public: ContainerPtr container() const; std::string name() const; std::string scoped() const; std::string scope() const; std::string flattenedScope() const; std::string file() const; std::string line() const; std::string comment() const; int includeLevel() const; void updateIncludeLevel(); bool hasMetaData(const std::string&) const; bool findMetaData(const std::string&, std::string&) const; std::list getMetaData() const; void setMetaData(const std::list&); void addMetaData(const std::string&); // TODO: remove this method once "cs:" and "vb:" are hard errors. enum ContainedType { ContainedTypeSequence, ContainedTypeDictionary, ContainedTypeEnum, ContainedTypeEnumerator, ContainedTypeModule, ContainedTypeClass, ContainedTypeException, ContainedTypeStruct, ContainedTypeOperation, ContainedTypeParamDecl, ContainedTypeDataMember, ContainedTypeConstant }; virtual ContainedType containedType() const = 0; virtual bool uses(const ContainedPtr&) const = 0; virtual std::string kindOf() const = 0; bool operator<(const Contained&) const; bool operator==(const Contained&) const; bool operator!=(const Contained&) const; protected: Contained(const ContainerPtr&, const std::string&); friend class Container; ContainerPtr _container; std::string _name; std::string _scoped; std::string _file; std::string _line; std::string _comment; int _includeLevel; std::list _metaData; }; // ---------------------------------------------------------------------- // Container // ---------------------------------------------------------------------- class SLICE_API Container : virtual public SyntaxTreeBase { public: virtual void destroy(); ModulePtr createModule(const std::string&); ClassDefPtr createClassDef(const std::string&, bool, const ClassList&, bool); ClassDeclPtr createClassDecl(const std::string&, bool, bool); ExceptionPtr createException(const std::string&, const ExceptionPtr&, bool); StructPtr createStruct(const std::string&, bool); SequencePtr createSequence(const std::string&, const TypePtr&, const StringList&, bool); DictionaryPtr createDictionary(const std::string&, const TypePtr&, const StringList&, const TypePtr&, const StringList&, bool); EnumPtr createEnum(const std::string&, bool); EnumeratorPtr createEnumerator(const std::string&); ConstPtr createConst(const std::string, const TypePtr&, const StringList&, const SyntaxTreeBasePtr&, const std::string&); TypeList lookupType(const std::string&, bool = true); TypeList lookupTypeNoBuiltin(const std::string&, bool = true); ContainedList lookupContained(const std::string&, bool = true); ExceptionPtr lookupException(const std::string&, bool = true); ModuleList modules() const; ClassList classes() const; ExceptionList exceptions() const; StructList structs() const; SequenceList sequences() const; DictionaryList dictionaries() const; EnumList enums() const; ContainedList contents() const; bool hasNonLocalClassDecls() const; bool hasNonLocalClassDefs() const; bool hasNonLocalSequences() const; bool hasNonLocalDictionaries() const; bool hasNonLocalExceptions() const; bool hasClassDecls() const; bool hasClassDefs() const; bool hasAbstractClassDefs() const; bool hasDataOnlyClasses() const; bool hasOtherConstructedOrExceptions() const; // Exceptions or constructed types other than classes. bool hasContentsWithMetaData(const std::string&) const; bool hasAsyncOps() const; std::string thisScope() const; void mergeModules(); void sort(); void sortContents(bool); virtual void visit(ParserVisitor*, bool); void containerRecDependencies(std::set&); // Internal operation, don't use directly. bool checkIntroduced(const std::string&, ContainedPtr = 0); bool nameIsLegal(const std::string&, const char *); bool checkForGlobalDef(const std::string&, const char *); protected: Container(const UnitPtr&); void checkPrefix(const std::string&) const; bool checkInterfaceAndLocal(const std::string&, bool, bool, bool, bool, bool); ContainedList _contents; std::map _introducedMap; }; // ---------------------------------------------------------------------- // Module // ---------------------------------------------------------------------- class SLICE_API Module : virtual public Container, virtual public Contained { public: virtual ContainedType containedType() const; virtual bool uses(const ContainedPtr&) const; virtual std::string kindOf() const; virtual void visit(ParserVisitor*, bool); protected: Module(const ContainerPtr&, const std::string&); friend class Container; }; // ---------------------------------------------------------------------- // Constructed // ---------------------------------------------------------------------- class SLICE_API Constructed : virtual public Type, virtual public Contained { public: virtual bool isLocal() const; virtual std::string typeId() const; virtual bool isVariableLength() const = 0; ConstructedList dependencies(); virtual void recDependencies(std::set&) = 0; // Internal operation, don't use directly. protected: Constructed(const ContainerPtr&, const std::string&, bool); bool _local; }; // ---------------------------------------------------------------------- // ClassDecl // ---------------------------------------------------------------------- class SLICE_API ClassDecl : virtual public Constructed { public: virtual void destroy(); ClassDefPtr definition() const; bool isInterface() const; virtual ContainedType containedType() const; virtual bool uses(const ContainedPtr&) const; virtual bool usesClasses() const; virtual size_t minWireSize() const; virtual bool isVariableLength() const; virtual void visit(ParserVisitor*, bool); virtual std::string kindOf() const; virtual void recDependencies(std::set&); // Internal operation, don't use directly. static void checkBasesAreLegal(const std::string&, bool, bool, const ClassList&, const UnitPtr&); protected: ClassDecl(const ContainerPtr&, const std::string&, bool, bool); friend class Container; friend class ClassDef; ClassDefPtr _definition; bool _interface; private: typedef std::list GraphPartitionList; typedef std::list StringPartitionList; static bool isInList(const GraphPartitionList&, const ClassDefPtr); static void addPartition(GraphPartitionList&, GraphPartitionList::reverse_iterator, const ClassDefPtr); static StringPartitionList toStringPartitionList(const GraphPartitionList&); static void checkPairIntersections(const StringPartitionList&, const std::string&, const UnitPtr&); }; // ---------------------------------------------------------------------- // Operation // ---------------------------------------------------------------------- class SLICE_API Operation : virtual public Contained, virtual public Container { public: // // Note: The order of definitions here *must* match the order of // definitions of ::Ice::OperationMode in slice/Ice/Current.ice! // enum Mode { Normal, Nonmutating, Idempotent }; TypePtr returnType() const; Mode mode() const; Mode sendMode() const; ParamDeclPtr createParamDecl(const std::string&, const TypePtr&, bool); ParamDeclList parameters() const; ExceptionList throws() const; void setExceptionList(const ExceptionList&); virtual ContainedType containedType() const; virtual bool uses(const ContainedPtr&) const; bool sendsClasses() const; bool returnsClasses() const; bool returnsData() const; virtual std::string kindOf() const; virtual void visit(ParserVisitor*, bool); protected: Operation(const ContainerPtr&, const std::string&, const TypePtr&, Mode); friend class ClassDef; TypePtr _returnType; ExceptionList _throws; Mode _mode; }; // ---------------------------------------------------------------------- // ClassDef // ---------------------------------------------------------------------- // // Note: For the purpose of this parser, a class definition is not // considered to be a type, but a class declaration is. And each class // definition has at least one class declaration (but not vice versa), // so if you need the class as a "constructed type", use the // declaration() operation to navigate to the class declaration. // class SLICE_API ClassDef : virtual public Container, virtual public Contained { public: virtual void destroy(); OperationPtr createOperation(const std::string&, const TypePtr&, Operation::Mode = Operation::Normal); DataMemberPtr createDataMember(const std::string&, const TypePtr&); ClassDeclPtr declaration() const; ClassList bases() const; ClassList allBases() const; OperationList operations() const; OperationList allOperations() const; DataMemberList dataMembers() const; DataMemberList allDataMembers() const; DataMemberList classDataMembers() const; DataMemberList allClassDataMembers() const; bool canBeCyclic() const; bool isAbstract() const; bool isInterface() const; bool isA(const std::string&) const; virtual bool isLocal() const; bool hasDataMembers() const; bool hasOperations() const; virtual ContainedType containedType() const; virtual bool uses(const ContainedPtr&) const; virtual std::string kindOf() const; virtual void visit(ParserVisitor*, bool); protected: ClassDef(const ContainerPtr&, const std::string&, bool, const ClassList&, bool); friend class Container; ClassDeclPtr _declaration; bool _interface; bool _hasDataMembers; bool _hasOperations; ClassList _bases; bool _local; }; // ---------------------------------------------------------------------- // Proxy // ---------------------------------------------------------------------- class SLICE_API Proxy : virtual public Type { public: virtual bool isLocal() const; virtual std::string typeId() const; virtual bool usesClasses() const; virtual size_t minWireSize() const; virtual bool isVariableLength() const; ClassDeclPtr _class() const; Proxy(const ClassDeclPtr&); protected: ClassDeclPtr __class; }; // ---------------------------------------------------------------------- // Exception // ---------------------------------------------------------------------- // No inheritance from Constructed, as this is not a Type class SLICE_API Exception : virtual public Container, virtual public Contained { public: virtual void destroy(); DataMemberPtr createDataMember(const std::string&, const TypePtr&); DataMemberList dataMembers() const; DataMemberList allDataMembers() const; DataMemberList classDataMembers() const; DataMemberList allClassDataMembers() const; ExceptionPtr base() const; ExceptionList allBases() const; virtual bool isBaseOf(const ExceptionPtr&) const; virtual bool isLocal() const; virtual ContainedType containedType() const; virtual bool uses(const ContainedPtr&) const; bool usesClasses() const; virtual std::string kindOf() const; virtual void visit(ParserVisitor*, bool); protected: Exception(const ContainerPtr&, const std::string&, const ExceptionPtr&, bool); friend class Container; ExceptionPtr _base; bool _local; }; // ---------------------------------------------------------------------- // Struct // ---------------------------------------------------------------------- class SLICE_API Struct : virtual public Container, virtual public Constructed { public: DataMemberPtr createDataMember(const std::string&, const TypePtr&); DataMemberList dataMembers() const; DataMemberList classDataMembers() const; virtual ContainedType containedType() const; virtual bool uses(const ContainedPtr&) const; virtual bool usesClasses() const; virtual size_t minWireSize() const; virtual bool isVariableLength() const; virtual std::string kindOf() const; virtual void visit(ParserVisitor*, bool); virtual void recDependencies(std::set&); // Internal operation, don't use directly. protected: Struct(const ContainerPtr&, const std::string&, bool); friend class Container; }; // ---------------------------------------------------------------------- // Sequence // ---------------------------------------------------------------------- class SLICE_API Sequence : virtual public Constructed { public: TypePtr type() const; StringList typeMetaData() const; virtual ContainedType containedType() const; virtual bool uses(const ContainedPtr&) const; virtual bool usesClasses() const; virtual size_t minWireSize() const; virtual bool isVariableLength() const; virtual std::string kindOf() const; virtual void visit(ParserVisitor*, bool); virtual void recDependencies(std::set&); // Internal operation, don't use directly. protected: Sequence(const ContainerPtr&, const std::string&, const TypePtr&, const StringList&, bool); friend class Container; TypePtr _type; StringList _typeMetaData; }; // ---------------------------------------------------------------------- // Dictionary // ---------------------------------------------------------------------- class SLICE_API Dictionary : virtual public Constructed { public: TypePtr keyType() const; TypePtr valueType() const; StringList keyMetaData() const; StringList valueMetaData() const; virtual ContainedType containedType() const; virtual bool uses(const ContainedPtr&) const; virtual bool usesClasses() const; virtual size_t minWireSize() const; virtual bool isVariableLength() const; virtual std::string kindOf() const; virtual void visit(ParserVisitor*, bool); virtual void recDependencies(std::set&); // Internal operation, don't use directly. static bool legalKeyType(const TypePtr&); protected: Dictionary(const ContainerPtr&, const std::string&, const TypePtr&, const StringList&, const TypePtr&, const StringList&, bool); friend class Container; TypePtr _keyType; TypePtr _valueType; StringList _keyMetaData; StringList _valueMetaData; }; // ---------------------------------------------------------------------- // Enum // ---------------------------------------------------------------------- class SLICE_API Enum : virtual public Constructed { public: virtual void destroy(); EnumeratorList getEnumerators(); void setEnumerators(const EnumeratorList&); virtual ContainedType containedType() const; virtual bool uses(const ContainedPtr&) const; virtual bool usesClasses() const; virtual size_t minWireSize() const; virtual bool isVariableLength() const; virtual std::string kindOf() const; virtual void visit(ParserVisitor*, bool); virtual void recDependencies(std::set&); // Internal operation, don't use directly. protected: Enum(const ContainerPtr&, const std::string&, bool); friend class Container; EnumeratorList _enumerators; }; // ---------------------------------------------------------------------- // Enumerator // ---------------------------------------------------------------------- class SLICE_API Enumerator : virtual public Contained { public: EnumPtr type() const; virtual bool uses(const ContainedPtr&) const; virtual ContainedType containedType() const; virtual std::string kindOf() const; protected: Enumerator(const ContainerPtr&, const std::string&); friend class Container; friend class Enum; EnumPtr _type; }; // ---------------------------------------------------------------------- // Const // ---------------------------------------------------------------------- class SLICE_API Const : virtual public Contained { public: TypePtr type() const; StringList typeMetaData() const; std::string value() const; virtual bool uses(const ContainedPtr&) const; virtual ContainedType containedType() const; virtual std::string kindOf() const; virtual void visit(ParserVisitor*, bool); static bool isLegalType(const std::string&, const TypePtr&, const UnitPtr&); static bool typesAreCompatible(const std::string&, const TypePtr&, const SyntaxTreeBasePtr&, const std::string&, const UnitPtr&); static bool isInRange(const std::string&, const TypePtr&, const std::string&, const UnitPtr&); protected: Const(const ContainerPtr&, const std::string&, const TypePtr&, const StringList&, const std::string&); friend class Container; TypePtr _type; StringList _typeMetaData; std::string _value; }; // ---------------------------------------------------------------------- // ParamDecl // ---------------------------------------------------------------------- class SLICE_API ParamDecl : virtual public Contained { public: TypePtr type() const; bool isOutParam() const; virtual ContainedType containedType() const; virtual bool uses(const ContainedPtr&) const; virtual std::string kindOf() const; virtual void visit(ParserVisitor*, bool); protected: ParamDecl(const ContainerPtr&, const std::string&, const TypePtr&, bool isOutParam); friend class Operation; TypePtr _type; bool _isOutParam; }; // ---------------------------------------------------------------------- // DataMember // ---------------------------------------------------------------------- class SLICE_API DataMember : virtual public Contained { public: TypePtr type() const; virtual ContainedType containedType() const; virtual bool uses(const ContainedPtr&) const; virtual std::string kindOf() const; virtual void visit(ParserVisitor*, bool); protected: DataMember(const ContainerPtr&, const std::string&, const TypePtr&); friend class ClassDef; friend class Struct; friend class Exception; TypePtr _type; }; // ---------------------------------------------------------------------- // Unit // ---------------------------------------------------------------------- class SLICE_API Unit : virtual public Container { public: static UnitPtr createUnit(bool, bool, bool, bool, const StringList& = StringList()); bool ignRedefs() const; bool allowIcePrefix() const; bool caseSensitive() const; void setComment(const std::string&); std::string currentComment(); // Not const, as this function removes the current comment. std::string currentFile() const; int currentLine() const; void nextLine(); void scanPosition(const char*); int currentIncludeLevel() const; void addGlobalMetaData(const StringList&); void setSeenDefinition(); void error(const char*); // Not const, because error count is increased. void error(const std::string&); // Ditto. void warning(const char*) const; void warning(const std::string&) const; ContainerPtr currentContainer() const; void pushContainer(const ContainerPtr&); void popContainer(); DefinitionContextPtr currentDefinitionContext() const; void pushDefinitionContext(); void popDefinitionContext(); void addContent(const ContainedPtr&); void removeContent(const ContainedPtr&); ContainedList findContents(const std::string&) const; ClassList findDerivedClasses(const ClassDefPtr&) const; ExceptionList findDerivedExceptions(const ExceptionPtr&) const; ContainedList findUsedBy(const ContainedPtr&) const; bool usesProxies() const; bool usesNonLocals() const; bool usesConsts() const; FeatureProfile profile() const; StringList includeFiles() const; int parse(FILE*, bool, FeatureProfile profile = Ice); virtual void destroy(); virtual void visit(ParserVisitor*, bool); BuiltinPtr builtin(Builtin::Kind); // Not const, as builtins are created on the fly. (Lazy initialization.) private: Unit(bool, bool, bool, bool, const StringList&); static void eraseWhiteSpace(::std::string&); bool _ignRedefs; bool _all; bool _allowIcePrefix; bool _caseSensitive; StringList _defaultGlobalMetadata; int _errors; std::string _currentComment; int _currentLine; int _currentIncludeLevel; std::string _currentFile; std::string _topLevelFile; std::stack _definitionContextStack; StringList _includeFiles; std::stack _containerStack; std::map _builtins; std::map _contentMap; FeatureProfile _featureProfile; }; extern SLICE_API Unit* unit; // The current parser for bison/flex } #endif IceE-trans-1.2.0/include/Slice/CsUtil.h0000664000076400007640000000505510560413774017070 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** #ifndef CS_UTIL_H #define CS_UTIL_H #include #include namespace Slice { class SLICE_API CsGenerator : private ::IceUtil::noncopyable { public: virtual ~CsGenerator() {}; // // Convert a dimension-less array declaration to one with a dimension. // static std::string toArrayAlloc(const std::string& decl, const std::string& sz); // // Validate all metadata in the unit with a "cs:" prefix. // static void validateMetaData(const UnitPtr&); protected: static std::string fixId(const std::string&, int = 0, bool = false); static std::string typeToString(const TypePtr&); static bool isValueType(const TypePtr&); // // Generate code to marshal or unmarshal a type // void writeMarshalUnmarshalCode(::IceUtil::Output&, const TypePtr&, const std::string&, bool, bool, bool, const std::string& = ""); void writeSequenceMarshalUnmarshalCode(::IceUtil::Output&, const SequencePtr&, const std::string&, bool, bool); private: class MetaDataVisitor : public ParserVisitor { public: MetaDataVisitor(); virtual bool visitModuleStart(const ModulePtr&); virtual void visitModuleEnd(const ModulePtr&); virtual void visitClassDecl(const ClassDeclPtr&); virtual bool visitClassDefStart(const ClassDefPtr&); virtual void visitClassDefEnd(const ClassDefPtr&); virtual bool visitExceptionStart(const ExceptionPtr&); virtual void visitExceptionEnd(const ExceptionPtr&); virtual bool visitStructStart(const StructPtr&); virtual void visitStructEnd(const StructPtr&); virtual void visitOperation(const OperationPtr&); virtual void visitParamDecl(const ParamDeclPtr&); virtual void visitDataMember(const DataMemberPtr&); virtual void visitSequence(const SequencePtr&); virtual void visitDictionary(const DictionaryPtr&); virtual void visitEnum(const EnumPtr&); virtual void visitConst(const ConstPtr&); private: void validate(const ContainedPtr&); StringSet _history; bool _globalMetaDataDone; }; }; } #endif IceE-trans-1.2.0/include/Slice/Checksum.h0000664000076400007640000000110110550516550017406 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** #ifndef SLICE_CHECKSUM_H #define SLICE_CHECKSUM_H #include namespace Slice { typedef std::map > ChecksumMap; SLICE_API ChecksumMap createChecksums(const UnitPtr&); } #endif IceE-trans-1.2.0/include/Slice/RubyUtil.h0000664000076400007640000000307110550721446017435 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** #ifndef SLICE_RUBY_UTIL_H #define SLICE_RUBY_UTIL_H #include #include namespace Slice { namespace Ruby { // // Generate Ruby code for a translation unit. // SLICE_API void generate(const Slice::UnitPtr&, bool, bool, const std::vector&, IceUtil::Output&); // // Split up a string using whitespace delimiters. // SLICE_API bool splitString(const std::string&, std::vector&, const std::string& = " \t\n\r"); // // Check the given identifier against Ruby's list of reserved words. If it matches // a reserved word, then an escaped version is returned with a leading underscore. // enum IdentStyle { IdentNormal, IdentToUpper, // Mapped identifier must begin with an upper-case letter. IdentToLower // Mapped identifier must begin with a lower-case letter. }; SLICE_API std::string fixIdent(const std::string&, IdentStyle); // // Get the fully-qualified name of the given definition. If a prefix is provided, // it is prepended to the definition's unqualified name. // SLICE_API std::string getAbsolute(const Slice::ContainedPtr&, IdentStyle, const std::string& = std::string()); // // Emit a comment header. // SLICE_API void printHeader(IceUtil::Output&); } } #endif IceE-trans-1.2.0/include/Slice/JavaUtil.h0000664000076400007640000002030410560413774017376 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** #ifndef JAVA_UTIL_H #define JAVA_UTIL_H #include #include namespace Slice { class SLICE_API JavaOutput : public ::IceUtil::Output { public: JavaOutput(); JavaOutput(std::ostream&); JavaOutput(const char*); // // Open a file to hold the source for a Java class. The first // argument is the class name (including an optional leading // package). Intermediate directories will be created as // necessary to open the file in the package. The second // argument specifies a directory prefix in which to locate // the class. // // After successfully opening the file, the function invokes // printHeader() and then emits a "package" statement if // necessary. // bool openClass(const std::string&, const std::string& = std::string()); virtual void printHeader(); }; class SLICE_API JavaGenerator : private ::IceUtil::noncopyable { public: virtual ~JavaGenerator(); // // Validate all metadata in the unit with a "java:" prefix. // static void validateMetaData(const UnitPtr&); protected: JavaGenerator(const std::string&); JavaGenerator(const std::string&, Slice::FeatureProfile profile); // // Given the fully-scoped Java class name, create any intermediate // package directories and open the class file // bool open(const std::string&); void close(); ::IceUtil::Output& output() const; // // Check a symbol against any of the Java keywords. If a // match is found, return the symbol with a leading underscore. // std::string fixKwd(const std::string&) const; // // Convert a Slice scoped name into a Java name. // std::string convertScopedName(const std::string&, const std::string& = std::string(), const std::string& = std::string()) const; // // Returns the Java package of a Contained entity. // std::string getPackage(const ContainedPtr&) const; // // Returns the Java name for a Contained entity. If the optional // package argument matches the entity's package name, then the // package is removed from the result. // std::string getAbsolute(const ContainedPtr&, const std::string& = std::string(), const std::string& = std::string(), const std::string& = std::string()) const; // // Get the Java name for a type. If an optional scope is provided, // the scope will be removed from the result if possible. // enum TypeMode { TypeModeIn, TypeModeOut, TypeModeMember, TypeModeReturn }; std::string typeToString(const TypePtr&, TypeMode, const std::string& = std::string(), const StringList& = StringList(), bool = true) const; // // Get the Java object name for a type. For primitive types, this returns the // Java class type (e.g., Integer). For all other types, this function delegates // to typeToString. // std::string typeToObjectString(const TypePtr&, TypeMode, const std::string& = std::string(), const StringList& = StringList(), bool = true) const; // // Generate code to marshal or unmarshal a type. // void writeMarshalUnmarshalCode(::IceUtil::Output&, const std::string&, const TypePtr&, const std::string&, bool, int&, bool = false, const StringList& = StringList(), const std::string& patchParams = ""); // // Generate code to marshal or unmarshal a dictionary type. // void writeDictionaryMarshalUnmarshalCode(::IceUtil::Output&, const std::string&, const DictionaryPtr&, const std::string&, bool, int&, bool, const StringList& = StringList()); // // Generate code to marshal or unmarshal a sequence type. // void writeSequenceMarshalUnmarshalCode(::IceUtil::Output&, const std::string&, const SequencePtr&, const std::string&, bool, int&, bool, const StringList& = StringList()); // // Generate code to marshal or unmarshal a type using the public stream API. // void writeStreamMarshalUnmarshalCode(::IceUtil::Output&, const std::string&, const TypePtr&, const std::string&, bool, int&, bool = false, const StringList& = StringList(), const std::string& patchParams = ""); // // Generate code to marshal or unmarshal a dictionary type using the public stream API. // void writeStreamDictionaryMarshalUnmarshalCode(::IceUtil::Output&, const std::string&, const DictionaryPtr&, const std::string&, bool, int&, bool, const StringList& = StringList()); // // Generate code to marshal or unmarshal a sequence type using the public stream API. // void writeStreamSequenceMarshalUnmarshalCode(::IceUtil::Output&, const std::string&, const SequencePtr&, const std::string&, bool, int&, bool, const StringList& = StringList()); // // Get custom type metadata. If metadata is found, the abstract and // concrete types are extracted and the function returns true. If an // abstract type is not specified, it is set to an empty string. // static bool getTypeMetaData(const StringList&, std::string&, std::string&); // // Determine whether a custom type is defined. The function checks the // metadata of the type's original definition, as well as any optional // metadata that typically represents a data member or parameter. // static bool hasTypeMetaData(const TypePtr&, const StringList& = StringList()); // // Obtain the concrete and abstract types for a dictionary or sequence type. // The functions return true if a custom type was defined and false to indicate // the default mapping was used. // bool getDictionaryTypes(const DictionaryPtr&, const std::string&, const StringList&, std::string&, std::string&) const; bool getSequenceTypes(const SequencePtr&, const std::string&, const StringList&, std::string&, std::string&) const; virtual JavaOutput* createOutput(); Slice::FeatureProfile _featureProfile; static const std::string _getSetMetaData; static const std::string _java2MetaData; static const std::string _java5MetaData; private: class MetaDataVisitor : public ParserVisitor { public: virtual bool visitModuleStart(const ModulePtr&); virtual void visitClassDecl(const ClassDeclPtr&); virtual bool visitClassDefStart(const ClassDefPtr&); virtual bool visitExceptionStart(const ExceptionPtr&); virtual bool visitStructStart(const StructPtr&); virtual void visitOperation(const OperationPtr&); virtual void visitDataMember(const DataMemberPtr&); virtual void visitSequence(const SequencePtr&); virtual void visitDictionary(const DictionaryPtr&); virtual void visitEnum(const EnumPtr&); virtual void visitConst(const ConstPtr&); private: StringList getMetaData(const ContainedPtr&); void validateType(const SyntaxTreeBasePtr&, const StringList&, const std::string&, const std::string&); void validateGetSet(const SyntaxTreeBasePtr&, const StringList&, const std::string&, const std::string&); StringSet _history; }; friend class JavaGenerator::MetaDataVisitor; std::string _dir; ::IceUtil::Output* _out; }; } #endif IceE-trans-1.2.0/include/Slice/Preprocessor.h0000664000076400007640000000243110561612463020343 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** #ifndef PREPROCESSOR_H #define PREPROCESSOR_H #include #ifdef __BCPLUSPLUS__ # include #endif #ifndef SLICE_API # ifdef SLICE_API_EXPORTS # define SLICE_API ICE_DECLSPEC_EXPORT # else # define SLICE_API ICE_DECLSPEC_IMPORT # endif #endif namespace Slice { class SLICE_API Preprocessor { public: Preprocessor(const std::string&, const std::string&, const std::string&); ~Preprocessor(); FILE* preprocess(bool); bool close(); enum Language { CPlusPlus, Java, CSharp, VisualBasic }; void printMakefileDependencies(Language); std::string getBaseName(); static std::string addQuotes(const std::string&); static std::string normalizeIncludePath(const std::string&); private: bool checkInputFile(); std::string searchIceCpp(); const std::string _path; const std::string _fileName; const std::string _args; FILE* _cppHandle; }; } #endif IceE-trans-1.2.0/include/Slice/Makefile0000664000076400007640000000135110550516550017142 0ustar dwaynedwayne# ********************************************************************** # # Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. # # This copy of Ice is licensed to you under the terms described in the # ICE_LICENSE file included in this distribution. # # ********************************************************************** top_srcdir = ../.. include $(top_srcdir)/config/Make.rules install:: @if test ! -d $(install_includedir)/Slice ; \ then \ echo "Creating $(install_includedir)/Slice..." ; \ $(call mkdir,$(install_includedir)/Slice) ; \ fi @for i in *.h ; \ do \ echo "Installing $$i" ; \ $(INSTALL_DATA) $$i $(install_includedir)/Slice/$$i ; \ chmod a+r $(install_includedir)/Slice/$$i ; \ done IceE-trans-1.2.0/include/Slice/Makefile.mak0000664000076400007640000000120610550516550017710 0ustar dwaynedwayne# ********************************************************************** # # Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. # # This copy of Ice is licensed to you under the terms described in the # ICE_LICENSE file included in this distribution. # # ********************************************************************** top_srcdir = ..\.. !include $(top_srcdir)/config/Make.rules.mak install:: @if not exist $(install_includedir)\Slice \ @echo "Creating $(install_includedir)\Slice..." & \ mkdir $(install_includedir)\Slice @for %i in ( *.h ) do \ @echo Installing %i & \ copy %i $(install_includedir)\Slice IceE-trans-1.2.0/include/Slice/PythonUtil.h0000664000076400007640000000332510550516550017775 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** #ifndef SLICE_PYTHON_UTIL_H #define SLICE_PYTHON_UTIL_H #include #include namespace Slice { namespace Python { // // Generate Python code for a translation unit. // SLICE_API void generate(const Slice::UnitPtr&, bool, bool, const std::vector&, IceUtil::Output&); // // Split up a string using whitespace delimiters. // SLICE_API bool splitString(const std::string&, std::vector&, const std::string& = " \t\n\r"); // // Convert a scoped name into a Python name. // SLICE_API std::string scopedToName(const std::string&); // // Check the given identifier against Python's list of reserved words. If it matches // a reserved word, then an escaped version is returned with a leading underscore. // SLICE_API std::string fixIdent(const std::string&); // // Return the package specified in the global metadata for the given definition, // or an empty string if no metadata was found. // SLICE_API std::string getPackageMetadata(const Slice::ContainedPtr&); // // Get the fully-qualified name of the given definition, including any package // defined via metadata. If a suffix is provided, it is prepended to the // definition's unqualified name. // SLICE_API std::string getAbsolute(const Slice::ContainedPtr&, const std::string& = std::string()); // // Emit a comment header. // SLICE_API void printHeader(IceUtil::Output&); } } #endif IceE-trans-1.2.0/include/Slice/CPlusPlusUtil.h0000664000076400007640000000502510616353751020412 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** #ifndef C_PLUS_PLUS_UTIL_H #define C_PLUS_PLUS_UTIL_H #include #include namespace Slice { SLICE_API extern FeatureProfile featureProfile; struct ToIfdef { SLICE_API char operator()(char); }; SLICE_API std::string normalizePath(const std::string&); SLICE_API std::string changeInclude(const std::string&, const std::vector&); SLICE_API void printHeader(::IceUtil::Output&); SLICE_API void printVersionCheck(::IceUtil::Output&); SLICE_API void printDllExportStuff(::IceUtil::Output&, const std::string&); SLICE_API std::string typeToString(const TypePtr&, bool, const StringList& = StringList(), bool = true); SLICE_API std::string returnTypeToString(const TypePtr&, bool, const StringList& = StringList()); SLICE_API std::string inputTypeToString(const TypePtr&, bool, const StringList& = StringList()); SLICE_API std::string outputTypeToString(const TypePtr&, bool, const StringList& = StringList()); SLICE_API std::string operationModeToString(Operation::Mode); SLICE_API std::string fixKwd(const std::string&); SLICE_API void writeMarshalUnmarshalCode(::IceUtil::Output&, const TypePtr&, const std::string&, bool, const std::string& = "", bool = true, const StringList& = StringList(), bool = false); SLICE_API void writeMarshalCode(::IceUtil::Output&, const ParamDeclList&, const TypePtr&, const StringList&, bool = false); SLICE_API void writeUnmarshalCode(::IceUtil::Output&, const ParamDeclList&, const TypePtr&, const StringList&, bool = false); SLICE_API void writeAllocateCode(::IceUtil::Output&, const ParamDeclList&, const TypePtr&, const StringList&, bool = false, bool = false); SLICE_API void writeStreamMarshalUnmarshalCode(::IceUtil::Output&, const TypePtr&, const std::string&, bool, const std::string& = "", bool = false, const StringList& = StringList()); SLICE_API std::string findMetaData(const StringList&, bool); SLICE_API bool inWstringModule(const SequencePtr&); } #endif IceE-trans-1.2.0/include/Slice/DotNetNames.h0000774000076400007640000000121010550516550020030 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** #ifndef DOTNETNAMES_H #define DOTNETNAMES_H #include namespace Slice { namespace DotNet { enum BaseType { Object=1, ICloneable=2, Exception=4, ApplicationException=8, END=16 }; extern const char * manglePrefix; std::string mangleName(const std::string&, int baseTypes = 0); } } #endif IceE-trans-1.2.0/include/Slice/VbUtil.h0000664000076400007640000000500110560413774017061 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** #ifndef CS_UTIL_H #define CS_UTIL_H #include #include namespace Slice { class SLICE_API VbGenerator : private ::IceUtil::noncopyable { public: virtual ~VbGenerator() {}; // // Convert a dimension-less array declaration to one with a dimension. // static std::string toArrayAlloc(const std::string& decl, const std::string& sz); // // Validate all metadata in the unit with a "vb:" prefix. // static void validateMetaData(const UnitPtr&); protected: static std::string fixId(const std::string&, int = 0, bool = false); static std::string typeToString(const TypePtr&); static bool isValueType(const TypePtr&); // // Generate code to marshal or unmarshal a type // void writeMarshalUnmarshalCode(::IceUtil::Output&, const TypePtr&, const std::string&, bool, bool, bool, const std::string& = ""); void writeSequenceMarshalUnmarshalCode(::IceUtil::Output&, const SequencePtr&, const std::string&, bool, bool); private: class MetaDataVisitor : public ParserVisitor { public: MetaDataVisitor(); virtual bool visitModuleStart(const ModulePtr&); virtual void visitModuleEnd(const ModulePtr&); virtual void visitClassDecl(const ClassDeclPtr&); virtual bool visitClassDefStart(const ClassDefPtr&); virtual void visitClassDefEnd(const ClassDefPtr&); virtual bool visitExceptionStart(const ExceptionPtr&); virtual void visitExceptionEnd(const ExceptionPtr&); virtual bool visitStructStart(const StructPtr&); virtual void visitStructEnd(const StructPtr&); virtual void visitOperation(const OperationPtr&); virtual void visitParamDecl(const ParamDeclPtr&); virtual void visitDataMember(const DataMemberPtr&); virtual void visitSequence(const SequencePtr&); virtual void visitDictionary(const DictionaryPtr&); virtual void visitEnum(const EnumPtr&); virtual void visitConst(const ConstPtr&); private: void validate(const ContainedPtr&); StringSet _history; bool _globalMetaDataDone; }; }; } #endif IceE-trans-1.2.0/include/Makefile0000664000076400007640000000126010550516550016102 0ustar dwaynedwayne# ********************************************************************** # # Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. # # This copy of Ice is licensed to you under the terms described in the # ICE_LICENSE file included in this distribution. # # ********************************************************************** top_srcdir = .. include $(top_srcdir)/config/Make.rules SUBDIRS = Freeze \ Glacier2 \ Ice \ IceBox \ IceGrid \ IcePatch2 \ IceSSL \ IceStorm \ IceUtil \ IceXML \ Slice $(EVERYTHING):: @for subdir in $(SUBDIRS); \ do \ echo "making $@ in $$subdir"; \ ( cd $$subdir && $(MAKE) $@ ) || exit 1; \ done IceE-trans-1.2.0/include/Makefile.mak0000664000076400007640000000127210550516550016654 0ustar dwaynedwayne# ********************************************************************** # # Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. # # This copy of Ice is licensed to you under the terms described in the # ICE_LICENSE file included in this distribution. # # ********************************************************************** top_srcdir = .. !include $(top_srcdir)/config/Make.rules.mak SUBDIRS = Freeze \ Glacier2 \ Ice \ IceBox \ IceGrid \ IcePatch2 \ IceSSL \ IceStorm \ IceUtil \ IceXML \ Slice $(EVERYTHING):: @for %i in ( $(SUBDIRS) ) do \ @echo "making $@ in %i" & \ cmd /c "cd %i & $(MAKE) -nologo -f Makefile.mak $@" || exit 1 IceE-trans-1.2.0/include/IceUtil/0000775000076400007640000000000010620635746016010 5ustar dwaynedwayneIceE-trans-1.2.0/include/IceUtil/ScopedArray.h0000664000076400007640000000230410560413774020372 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** #ifndef ICE_UTIL_SCOPED_ARRAY_H #define ICE_UTIL_SCOPED_ARRAY_H #include namespace IceUtil { template class ScopedArray : private noncopyable { public: explicit ScopedArray(T* ptr = 0) : _ptr(ptr) { } ~ScopedArray() { if(_ptr != 0) { delete[] _ptr; } } void reset(T* ptr = 0) { assert(ptr == 0 || ptr != _ptr); if(_ptr != 0) { delete[] _ptr; } _ptr = ptr; } T& operator[](size_t i) const { assert(_ptr != 0); assert(i >= 0); return _ptr[i]; } T* get() const { return _ptr; } void swap(ScopedArray& a) { T* tmp = a._ptr; a._ptr = _ptr; _ptr = tmp; } private: T* _ptr; }; } // End of namespace IceUtil #endif IceE-trans-1.2.0/include/IceUtil/Iterator.h0000664000076400007640000000161110550516550017742 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** #ifndef ICE_UTIL_ITERATOR_H #define ICE_UTIL_ITERATOR_H #include // Work-around for a limitation in the standard library provided // with the Sun C++ 5.x compilers #if defined(__SUNPRO_CC) && defined(_RWSTD_NO_CLASS_PARTIAL_SPEC) template inline typename ForwardIterator::difference_type ice_distance(ForwardIterator first, ForwardIterator last) { ForwardIterator::difference_type result = 0; std::distance(first, last, result); return result; } #else #define ice_distance(x,y) std::distance(x,y) #endif #endif IceE-trans-1.2.0/include/IceUtil/RecMutex.h0000664000076400007640000000446710560413774017726 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** #ifndef ICE_UTIL_RMUTEX_H #define ICE_UTIL_RMUTEX_H #include #include #include namespace IceUtil { // // Forward declarations for friend. // class Cond; // // Recursive Mutex implementation. // class ICE_UTIL_API RecMutex { public: // // Lock & TryLock typedefs. // typedef LockT Lock; typedef TryLockT TryLock; RecMutex(); ~RecMutex(); // // Note that lock/tryLock & unlock in general should not be used // directly. Instead use Lock & TryLock. // void lock() const; // // Returns true if the lock was acquired or was already acquired // by the calling thread, and false otherwise. // bool tryLock() const; void unlock() const; // // Returns true if the mutex will unlock when calling unlock() // (false otherwise). For non-recursive mutexes, this will always // return true. // This function is used by the Monitor implementation to know whether // the Mutex has been locked for the first time, or unlocked for the // last time (that is another thread is able to acquire the mutex). // Pre-condition: the mutex must be locked. // bool willUnlock() const; private: // noncopyable RecMutex(const RecMutex&); void operator=(const RecMutex&); // // LockState and the lock/unlock variations are for use by the // Condition variable implementation. // #ifdef _WIN32 struct LockState { int count; }; #else struct LockState { pthread_mutex_t* mutex; int count; }; #endif void unlock(LockState&) const; void lock(LockState&) const; friend class Cond; #ifdef _WIN32 # if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0400 mutable CRITICAL_SECTION _mutex; # else HANDLE _mutex; # endif #else mutable pthread_mutex_t _mutex; #endif mutable int _count; }; } // End namespace IceUtil #endif IceE-trans-1.2.0/include/IceUtil/Lock.h0000664000076400007640000000506210560413774017052 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** #ifndef ICE_UTIL_LOCK_H #define ICE_UTIL_LOCK_H #include #include namespace IceUtil { // // Forward declarations. // class Cond; // LockT and TryLockT are the preferred construct to lock/tryLock/unlock // simple and recursive mutexes. You typically allocate them on the // stack to hold a lock on a mutex. // LockT and TryLockT are not recursive: you cannot acquire several times // in a row a lock with the same Lock or TryLock object. // // We must name this LockT instead of Lock, because otherwise some // compilers (such as Sun C++ 5.4) have problems with constructs // such as: // // class Foo // { // // ... // typedef Lock Lock; // } // template class LockT { public: LockT(const T& mutex) : _mutex(mutex) { _mutex.lock(); _acquired = true; } ~LockT() { if (_acquired) { _mutex.unlock(); } } void acquire() const { if (_acquired) { throw ThreadLockedException(__FILE__, __LINE__); } _mutex.lock(); _acquired = true; } bool tryAcquire() const { if (_acquired) { throw ThreadLockedException(__FILE__, __LINE__); } _acquired = _mutex.tryLock(); return _acquired; } void release() const { if (!_acquired) { throw ThreadLockedException(__FILE__, __LINE__); } _mutex.unlock(); _acquired = false; } bool acquired() const { return _acquired; } protected: // TryLockT's contructor LockT(const T& mutex, bool) : _mutex(mutex) { _acquired = _mutex.tryLock(); } private: // Not implemented; prevents accidental use. // LockT(const LockT&); LockT& operator=(const LockT&); const T& _mutex; mutable bool _acquired; friend class Cond; }; // // Must be name TryLockT, not TryLock. See the comment for LockT for // an explanation. // template class TryLockT : public LockT { public: TryLockT(const T& mutex) : LockT(mutex, true) {} }; } // End namespace IceUtil #endif IceE-trans-1.2.0/include/IceUtil/MD5.h0000664000076400007640000000136310550516550016542 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** #ifndef ICE_UTIL_MD5_H #define ICE_UTIL_MD5_H #include extern "C" { struct md5_state_s; } namespace IceUtil { class ICE_UTIL_API MD5 { public: MD5(); MD5(const unsigned char*, int); ~MD5(); void update(const unsigned char*, int); void finish(); void getDigest(unsigned char*) const; private: md5_state_s* _state; unsigned char _digest[16]; }; } #endif IceE-trans-1.2.0/include/IceUtil/Algorithm.h0000664000076400007640000000165510550516550020107 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** #ifndef ICE_UTIL_ALGORITHM_H #define ICE_UTIL_ALGORITHM_H #include // Work-around for a limitation in the standard library provided // with the Sun C++ 5.x compilers #if defined(__SUNPRO_CC) && defined(_RWSTD_NO_CLASS_PARTIAL_SPEC) template inline typename InputIterator::difference_type ice_count_if(InputIterator first, InputIterator last, Predicate pred) { InputIterator::difference_type result = 0; std::count_if(first, last, pred, result); return result; } #else #define ice_count_if(x,y,z) std::count_if(x,y,z) #endif #endif IceE-trans-1.2.0/include/IceUtil/StringUtil.h0000664000076400007640000000277310550516550020267 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** #ifndef ICE_STRING_UTIL_H #define ICE_STRING_UTIL_H #include namespace IceUtil { // // Add escape sequences (like "\n", or "\0xxx") to make a string // readable in ASCII. // ICE_UTIL_API std::string escapeString(const std::string&, const std::string&); // // Remove escape sequences added by escapeString. // ICE_UTIL_API bool unescapeString(const std::string&, std::string::size_type, std::string::size_type, std::string&); // // If a single or double quotation mark is found at the start // position, then the position of the matching closing quote is // returned. If no quotation mark is found at the start position, then // 0 is returned. If no matching closing quote is found, then // std::string::npos is returned. // ICE_UTIL_API std::string::size_type checkQuote(const std::string&, std::string::size_type = 0); // // Match `s' against the pattern `pat'. A * in the pattern acts // as a wildcard: it matches any non-empty sequence of characters // other than a period (`.'). We match by hand here because // it's portable across platforms (whereas regex() isn't). // ICE_UTIL_API bool match(const std::string&, const std::string&, bool = false); } #endif IceE-trans-1.2.0/include/IceUtil/Cache.h0000664000076400007640000001714710560413774017174 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** #ifndef ICE_UTIL_CACHE_H #define ICE_UTIL_CACHE_H #include #include #include #include namespace IceUtil { // // An abstraction to efficiently populate a Cache, without holding // a lock while loading from a database. // template class Cache { public: // // Latch and CacheValue are implementation details; // application code should not use them. // struct Latch : public CountDownLatch { Latch() : CountDownLatch(1), useCount(0) { } int useCount; }; struct CacheValue { CacheValue(const Handle& o) : obj(o), latch(0) { } Handle obj; Latch* latch; }; typedef typename std::map::iterator Position; Handle getIfPinned(const Key&) const; void unpin(Position); bool unpin(const Key&); void clear(); size_t size() const; bool pin(const Key&, const Handle&); Handle pin(const Key&); Handle putIfAbsent(const Key&, const Handle&); protected: virtual Handle load(const Key&) = 0; virtual void pinned(const Handle&, Position) { } virtual ~Cache() { } private: Handle pinImpl(const Key&, const Handle&); typedef std::map CacheMap; Mutex _mutex; CacheMap _map; }; template Handle Cache::getIfPinned(const Key& key) const { Mutex::Lock sync(_mutex); typename CacheMap::const_iterator p = _map.find(key); if(p != _map.end()) { return (*p).second.obj; } else { return 0; } } template void Cache::unpin(typename Cache::Position p) { Mutex::Lock sync(_mutex); _map.erase(p); } template bool Cache::unpin(const Key& key) { Mutex::Lock sync(_mutex); return _map.erase(key) > 0; } template void Cache::clear() { Mutex::Lock sync(_mutex); _map.clear(); } template size_t Cache::size() const { Mutex::Lock sync(_mutex); return _map.size(); } template bool Cache::pin(const Key& key, const Handle& obj) { Mutex::Lock sync(_mutex); #if defined(_MSC_VER) && (_MSC_VER < 1300) std::pair ir = #else std::pair ir = #endif #if defined(_MSC_VER) _map.insert(CacheMap::value_type(key, CacheValue(obj))); #else _map.insert(typename CacheMap::value_type(key, CacheValue(obj))); #endif if(ir.second) { pinned(obj, ir.first); } return ir.second; } template Handle Cache::pin(const Key& key) { return pinImpl(key, 0); } template Handle Cache::putIfAbsent(const Key& key, const Handle& obj) { return pinImpl(key, obj); } template Handle Cache::pinImpl(const Key& key, const Handle& newObj) { Latch* latch = 0; Position p; for(;;) { { Mutex::Lock sync(_mutex); // // Clean up latch from previous loop // if(latch != 0) { if(--latch->useCount == 0) { delete latch; } latch = 0; } #if defined(_MSC_VER) && (_MSC_VER < 1300) std::pair ir = #else std::pair ir = #endif #if defined(_MSC_VER) || defined(__BCPLUSPLUS__) _map.insert(CacheMap::value_type(key, CacheValue(0))); #else _map.insert(typename CacheMap::value_type(key, CacheValue(0))); #endif if(ir.second == false) { CacheValue& val = ir.first->second; if(val.obj != 0) { return val.obj; } // // Otherwise wait // if(val.latch == 0) { // // The first queued thread creates the latch // val.latch = new Latch; } latch = val.latch; latch->useCount++; } p = ir.first; } if(latch != 0) { latch->await(); // // p could be stale now, e.g. some other thread pinned and unpinned the // object while we were waiting. // So start over. // continue; } else { Handle obj; try { obj = load(key); } catch(...) { { Mutex::Lock sync(_mutex); latch = p->second.latch; p->second.latch = 0; _map.erase(p); } if(latch != 0) { assert(latch->getCount() == 1); latch->countDown(); } throw; } { Mutex::Lock sync(_mutex); latch = p->second.latch; p->second.latch = 0; try { if(obj != 0) { p->second.obj = obj; pinned(obj, p); } else { if(newObj == 0) { // // pin() did not find the object // // // The waiting threads will have to call load() to see by themselves. // _map.erase(p); } else { // // putIfAbsent() inserts key/newObj // p->second.obj = newObj; pinned(newObj, p); } } } catch(...) { if(latch != 0) { assert(latch->getCount() == 1); latch->countDown(); } throw; } } if(latch != 0) { assert(latch->getCount() == 1); latch->countDown(); } return obj; } } } } #endif IceE-trans-1.2.0/include/IceUtil/UUID.h0000664000076400007640000000075410550516550016726 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** #ifndef ICE_UTIL_UUID_H #define ICE_UTIL_UUID_H #include namespace IceUtil { ICE_UTIL_API std::string generateUUID(); } #endif IceE-trans-1.2.0/include/IceUtil/CountDownLatch.h0000664000076400007640000000166310550516550021054 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** #ifndef ICE_UTIL_COUNT_DOWN_LATCH_H #define ICE_UTIL_COUNT_DOWN_LATCH_H #include namespace IceUtil { // // See java.util.concurrent.CountDownLatch in Java 1.5 // class ICE_UTIL_API CountDownLatch { public: CountDownLatch(int); ~CountDownLatch(); void await() const; void countDown(); int getCount() const; private: #ifdef _WIN32 mutable LONG _count; HANDLE _event; #else int _count; mutable pthread_mutex_t _mutex; mutable pthread_cond_t _cond; inline void lock() const; inline void unlock() const; #endif }; } #endif IceE-trans-1.2.0/include/IceUtil/Config.h0000664000076400007640000001332510620635670017366 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** #ifndef ICE_UTIL_CONFIG_H #define ICE_UTIL_CONFIG_H // // Endianness // // Most CPUs support only one endianness, with the notable exceptions // of Itanium (IA64) and MIPS. // #if defined(__i386) || defined(_M_IX86) || defined(__x86_64) || \ defined(_M_X64) || defined(_M_IA64) || defined(__alpha__) || \ defined(__MIPSEL__) # define ICE_LITTLE_ENDIAN #elif defined(__sparc) || defined(__sparc__) || defined(__hppa) || \ defined(__ppc__) || defined(__powerpc) || defined(_ARCH_COM) || \ defined(__MIPSEB__) # define ICE_BIG_ENDIAN #else # error "Unknown architecture" #endif // // 32 or 64 bit mode? // #if defined(__linux) && defined(__sparc__) // // We are a linux sparc, which forces 32 bit usr land, no matter // the architecture // # define ICE_32 #elif defined(__sun) && (defined(__sparcv9) || defined(__x86_64)) || \ defined(__linux) && defined(__x86_64) || \ defined(__hppa) && defined(__LP64__) || \ defined(_ARCH_COM) && defined(__64BIT__) || \ defined(__alpha__) || \ defined(_WIN64) # define ICE_64 #else # define ICE_32 #endif // // Compiler extensions to export and import symbols: see the documentation // for Visual C++, Sun ONE Studio 8 and HP aC++. // // TODO: more macros to support IBM Visual Age _Export syntax as well. // #if defined(__BCPLUSPLUS__) || (defined(_MSC_VER) && !defined(ICE_STATIC_LIBS)) || \ (defined(__HP_aCC) && defined(__HP_WINDLL)) # define ICE_DECLSPEC_EXPORT __declspec(dllexport) # define ICE_DECLSPEC_IMPORT __declspec(dllimport) #elif defined(__SUNPRO_CC) && (__SUNPRO_CC >= 0x550) # define ICE_DECLSPEC_EXPORT __global # define ICE_DECLSPEC_IMPORT #else # define ICE_DECLSPEC_EXPORT /**/ # define ICE_DECLSPEC_IMPORT /**/ #endif #if defined(_MSC_VER) && (_MSC_VER >= 1300) # define ICE_DEPRECATED_API __declspec(deprecated) #elif defined(__GNUC__) # define ICE_DEPRECATED_API __attribute__((deprecated)) #else # define ICE_DEPRECATED_API /**/ #endif // // Let's use these extensions with IceUtil: // #ifdef ICE_UTIL_API_EXPORTS # define ICE_UTIL_API ICE_DECLSPEC_EXPORT #else # define ICE_UTIL_API ICE_DECLSPEC_IMPORT #endif // // For STLport. If we compile in debug mode, we want to use the debug // STLport library. This is done by setting _STLP_DEBUG before any // STLport header files are included. // // TODO: figure out why IceUtil does not compile with _SLTP_DEBUG using // the Intel compiler. // #if !defined(NDEBUG) && !defined(_STLP_DEBUG) && !defined(__INTEL_COMPILER) && !defined(__BCPLUSPLUS__) # define _STLP_DEBUG #endif #if defined(_WIN32) // // Comment out the following block if you want to run on Windows 9x // or Windows NT 3.51. // # ifndef _WIN32_WINNT // // Necessary for TryEnterCriticalSection. // # define _WIN32_WINNT 0x0400 # endif # if !defined(ICE_STATIC_LIBS) && defined(_MSC_VER) && (!defined(_DLL) || !defined(_MT)) # error "Only multi-threaded DLL libraries can be used with Ice!" # endif # include # ifdef _MSC_VER // '...' : forcing value to bool 'true' or 'false' (performance warning) # pragma warning( disable : 4800 ) // ... identifier was truncated to '255' characters in the debug information # pragma warning( disable : 4786 ) // 'this' : used in base member initializer list # pragma warning( disable : 4355 ) // class ... needs to have dll-interface to be used by clients of class ... # pragma warning( disable : 4251 ) // ... : inherits ... via dominance # pragma warning( disable : 4250 ) // non dll-interface class ... used as base for dll-interface class ... # pragma warning( disable : 4275 ) // ...: decorated name length exceeded, name was truncated # pragma warning( disable : 4503 ) # endif #endif // // Some include files we need almost everywhere. // #include #include #include #ifndef _WIN32 # include # include #endif // // If we use Visual C++ 6.0, we must use STLport // #if defined(_MSC_VER) && (_MSC_VER < 1300) && !defined(_STLP_BEGIN_NAMESPACE) # error "Ice for Visual C++ 6.0 requires STLport" #endif // // By deriving from this class, other classes are made non-copyable. // namespace IceUtil { // // TODO: Constructor and destructor should not be inlined, as they are // not performance critical. // // TODO: Naming conventions? // class noncopyable { protected: noncopyable() { } ~noncopyable() { } // May not be virtual! Classes without virtual // operations also derive from noncopyable. private: noncopyable(const noncopyable&); const noncopyable& operator=(const noncopyable&); }; // // Int64 typedef // #if defined(__BCPLUSPLUS__) || defined(_MSC_VER) // // On Windows, long is always 32-bit // typedef __int64 Int64; #elif defined(ICE_64) typedef long Int64; #else typedef long long Int64; #endif } // // ICE_INT64: macro for Int64 literal values // #if defined(__BCPLUSPLUS__) || defined(_MSC_VER) # define ICE_INT64(n) n##i64 #elif defined(ICE_64) # define ICE_INT64(n) n##L #else # define ICE_INT64(n) n##LL #endif // // The Ice version. // #define ICE_STRING_VERSION "3.2.0" // "A.B.C", with A=major, B=minor, C=patch #define ICE_INT_VERSION 30200 // AABBCC, with AA=major, BB=minor, CC=patch #endif IceE-trans-1.2.0/include/IceUtil/AbstractMutex.h0000664000076400007640000000416710560413774020755 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** #ifndef ICE_UTIL_ABSTRACT_MUTEX_H #define ICE_UTIL_ABSTRACT_MUTEX_H #include #include namespace IceUtil { class AbstractMutex { public: typedef LockT Lock; typedef TryLockT TryLock; virtual ~AbstractMutex() {}; virtual void lock() const = 0; virtual void unlock() const = 0; virtual bool tryLock() const = 0; }; template class AbstractMutexI : public AbstractMutex, public T { public: #ifndef __BCPLUSPLUS__ typedef LockT Lock; typedef TryLockT TryLock; #endif virtual void lock() const { T::lock(); } virtual void unlock() const { T::unlock(); } virtual bool tryLock() const { return T::tryLock(); } virtual ~AbstractMutexI() {} }; template class AbstractMutexReadI : public AbstractMutex, public T { public: #ifndef __BCPLUSPLUS__ typedef LockT Lock; typedef TryLockT TryLock; #endif virtual void lock() const { T::readLock(); } virtual void unlock() const { T::unlock(); } virtual bool tryLock() const { return T::tryReadLock(); } virtual ~AbstractMutexReadI() {} }; template class AbstractMutexWriteI : public AbstractMutex, public T { public: #ifndef __BCPLUSPLUS__ typedef LockT Lock; typedef TryLockT TryLock; #endif virtual void lock() const { T::writeLock(); } virtual void unlock() const { T::unlock(); } virtual bool tryLock() const { return T::tryWriteLock(); } virtual ~AbstractMutexWriteI() {} }; } #endif IceE-trans-1.2.0/include/IceUtil/Base64.h0000664000076400007640000000142210616541634017201 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** #ifndef ICE_UTIL_BASE_64_H #define ICE_UTIL_BASE_64_H #include #include #include namespace IceUtil { class ICE_UTIL_API Base64 { public: static std::string encode(const std::vector&); static std::vector decode(const std::string&); static bool isBase64(char); private: static char encode(unsigned char); static unsigned char decode(char); }; } #endif IceE-trans-1.2.0/include/IceUtil/Time.h0000664000076400007640000000737510560413774017071 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** #ifndef ICE_UTIL_TIME_H #define ICE_UTIL_TIME_H #include #ifndef _WIN32 # include #endif namespace IceUtil { class ICE_UTIL_API Time { public: Time(); // No copy constructor and assignment operator necessary. The // automatically generated copy constructor and assignment // operator do the right thing. static Time now(); static Time seconds(Int64); static Time milliSeconds(Int64); static Time microSeconds(Int64); #ifndef _WIN32 operator timeval() const; #endif Int64 toSeconds() const; Int64 toMilliSeconds() const; Int64 toMicroSeconds() const; double toSecondsDouble() const; double toMilliSecondsDouble() const; double toMicroSecondsDouble() const; std::string toDateTime() const; std::string toDuration() const; Time operator-() const { return Time(-_usec); } Time operator-(const Time& rhs) const { return Time(_usec - rhs._usec); } Time operator+(const Time& rhs) const { return Time(_usec + rhs._usec); } Time& operator+=(const Time& rhs) { _usec += rhs._usec; return *this; } Time& operator-=(const Time& rhs) { _usec -= rhs._usec; return *this; } bool operator<(const Time& rhs) const { return _usec < rhs._usec; } bool operator<=(const Time& rhs) const { return _usec <= rhs._usec; } bool operator>(const Time& rhs) const { return _usec > rhs._usec; } bool operator>=(const Time& rhs) const { return _usec >= rhs._usec; } bool operator==(const Time& rhs) const { return _usec == rhs._usec; } bool operator!=(const Time& rhs) const { return _usec != rhs._usec; } double operator/(const Time& rhs) const { return (double)_usec / (double)rhs._usec; } Time& operator*=(int rhs) { _usec *= rhs; return *this; } Time operator*(int rhs) const { Time t; t._usec = _usec * rhs; return t; } Time& operator/=(int rhs) { _usec /= rhs; return *this; } Time operator/(int rhs) const { Time t; t._usec = _usec / rhs; return t; } Time& operator*=(Int64 rhs) { _usec *= rhs; return *this; } Time operator*(Int64 rhs) const { Time t; t._usec = _usec * rhs; return t; } Time& operator/=(Int64 rhs) { _usec /= rhs; return *this; } Time operator/(Int64 rhs) const { Time t; t._usec = _usec / rhs; return t; } Time& operator*=(double rhs) { _usec = static_cast(static_cast(_usec) * rhs); return *this; } Time operator*(double rhs) const { Time t; t._usec = static_cast(static_cast(_usec) * rhs); return t; } Time& operator/=(double rhs) { _usec = static_cast(static_cast(_usec) / rhs); return *this; } Time operator/(double rhs) const { Time t; t._usec = static_cast(static_cast(_usec) / rhs); return t; } private: Time(Int64); Int64 _usec; }; ICE_UTIL_API std::ostream& operator<<(std::ostream&, const Time&); } // End namespace IceUtil #endif IceE-trans-1.2.0/include/IceUtil/Thread.h0000664000076400007640000000663310560413774017376 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** #ifndef ICE_UTIL_THREAD_H #define ICE_UTIL_THREAD_H #include #include #include namespace IceUtil { class Time; class ICE_UTIL_API ThreadControl { public: // // Constructs a ThreadControl representing the current thread. // join and detach cannot be called on such ThreadControl object. // ThreadControl(); #ifdef _WIN32 ThreadControl(HANDLE, DWORD); #else explicit ThreadControl(pthread_t); #endif // // Default copy destructor, assignment operator and destructor OK // // // == and != are meaningful only before the thread is joined/detached, // or while the thread is still running. // bool operator==(const ThreadControl&) const; bool operator!=(const ThreadControl&) const; // // Wait until the controlled thread terminates. The call has POSIX // semantics. // // At most one thread can wait for the termination of a given // thread. Calling join on a thread on which another thread is // already waiting for termination results in undefined behaviour, // as does joining with a thread after having joined with it // previously, or joining with a detached thread. // void join(); // // Detach a thread. Once a thread is detached, it cannot be // detached again, nor can it be joined with. Every thread that // was created using the IceUtil::Thread class must either be // joined with or detached exactly once. Detaching a thread a // second time, or detaching a thread that was previously joined // with results in undefined behavior. // void detach(); // // id() returns the Thread ID on Windows and the underlying pthread_t // on POSIX platforms. // #ifdef _WIN32 typedef DWORD ID; #else typedef pthread_t ID; #endif ID id() const; static void sleep(const Time&); static void yield(); private: #ifdef _WIN32 HANDLE _handle; DWORD _id; #else pthread_t _thread; // // Used to prevent joining/detaching a ThreadControl constructed // with the default constructor. Only needed to enforce our // portable join/detach behavior. // bool _detachable; #endif }; class ICE_UTIL_API Thread : virtual public IceUtil::Shared { public: Thread(); virtual ~Thread(); virtual void run() = 0; ThreadControl start(size_t = 0); ThreadControl getThreadControl() const; bool operator==(const Thread&) const; bool operator!=(const Thread&) const; bool operator<(const Thread&) const; // // Check whether a thread is still alive. // bool isAlive() const; // // This function is an implementation detail; // do not call it. // void _done(); protected: Mutex _stateMutex; bool _started; bool _running; #ifdef _WIN32 HANDLE _handle; DWORD _id; #else pthread_t _thread; #endif private: Thread(const Thread&); // Copying is forbidden void operator=(const Thread&); // Assignment is forbidden }; typedef Handle ThreadPtr; } #endif IceE-trans-1.2.0/include/IceUtil/Options.h0000774000076400007640000001022510560413774017614 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** #ifndef ICE_UTIL_OPTIONS_H #define ICE_UTIL_OPTIONS_H #include #include #include #include #include #include #include #include namespace IceUtil { class ICE_UTIL_API APIException : public IceUtil::Exception { public: APIException(const char*, int, const ::std::string&); virtual ~APIException() throw(); virtual ::std::string ice_name() const; virtual void ice_print(std::ostream&) const; virtual ::IceUtil::Exception* ice_clone() const; virtual void ice_throw() const; ::std::string reason; private: static const char* _name; }; ICE_UTIL_API ::std::ostream& operator<<(::std::ostream&, const APIException&); class ICE_UTIL_API BadOptException : public IceUtil::Exception { public: BadOptException(const char*, int, const ::std::string&); virtual ~BadOptException() throw(); virtual ::std::string ice_name() const; virtual void ice_print(std::ostream&) const; virtual ::IceUtil::Exception* ice_clone() const; virtual void ice_throw() const; ::std::string reason; private: static const char* _name; }; ICE_UTIL_API ::std::ostream& operator<<(::std::ostream&, const BadOptException&); class ICE_UTIL_API Options { public: enum LengthType { ShortOpt, LongOpt }; enum RepeatType { Repeat, NoRepeat }; enum ArgType { NeedArg, NoArg }; Options(); void addOpt(const ::std::string&, const ::std::string& = "", ArgType = NoArg, ::std::string = "", RepeatType = NoRepeat); typedef ::std::vector< ::std::string> StringVector; static StringVector split(const ::std::string&); StringVector parse(const StringVector&); StringVector parse(int, const char* const []); bool isSet(const ::std::string&) const; ::std::string optArg(const ::std::string&) const; StringVector argVec(const ::std::string&) const; private: struct OptionDetails : public IceUtil::Shared { LengthType length; ArgType arg; RepeatType repeat; bool hasDefault; }; typedef IceUtil::Handle ODPtr; struct OptionValue : public IceUtil::Shared { ::std::string val; }; typedef IceUtil::Handle OValPtr; struct OptionValueVector : public IceUtil::Shared { ::std::vector< ::std::string> vals; }; typedef IceUtil::Handle OVecPtr; typedef ::std::map< ::std::string, ODPtr> ValidOpts; // Valid options and their details. typedef ::std::map< ::std::string, OValPtr> Opts; // Value of non-repeating options. typedef ::std::map< ::std::string, OVecPtr> ROpts; // Value of repeating options. typedef ::std::map< ::std::string, ::std::string> Synonyms; // Map from short to long option and vice versa. void addValidOpt(const ::std::string&, const ::std::string&, ArgType, const ::std::string&, RepeatType); ValidOpts::iterator checkOpt(const ::std::string&, LengthType); void setOpt(const ::std::string&, const ::std::string&, const ::std::string&, RepeatType); void setNonRepeatingOpt(const ::std::string&, const ::std::string&); void setRepeatingOpt(const ::std::string&, const ::std::string&); ValidOpts::const_iterator checkOptIsValid(const ::std::string&) const; ValidOpts::const_iterator checkOptHasArg(const ::std::string&) const; void updateSynonyms(const ::std::string&, const ::std::string&); ::std::string getSynonym(const ::std::string&) const; ValidOpts _validOpts; Opts _opts; ROpts _ropts; Synonyms _synonyms; bool parseCalled; RecMutex _m; Options(const Options&); // Not allowed. void operator=(const Options&); // Not allowed. static void checkArgs(const ::std::string&, const ::std::string&, bool, const ::std::string&); }; } #endif IceE-trans-1.2.0/include/IceUtil/Monitor.h0000664000076400007640000001124610560413774017612 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** #ifndef ICE_UTIL_MONITOR_H #define ICE_UTIL_MONITOR_H #include #include #include namespace IceUtil { // // This monitor implements the Mesa monitor semantics. That is any // calls to notify() or notifyAll() are delayed until the monitor is // unlocked. // template class Monitor { public: typedef LockT > Lock; typedef TryLockT > TryLock; Monitor(); ~Monitor(); // // Note that lock/tryLock & unlock in general should not be used // directly. Instead use Lock & TryLock. // void lock() const; void unlock() const; bool tryLock() const; void wait() const; bool timedWait(const Time&) const; void notify(); void notifyAll(); private: // noncopyable Monitor(const Monitor&); void operator=(const Monitor&); void notifyImpl(int) const; mutable Cond _cond; T _mutex; mutable int _nnotify; }; } // End namespace IceUtil // // Since this monitor implements the Mesa monitor semantics calls to // notify() or notifyAll() are delayed until the monitor is // unlocked. This can happen either due to a call to unlock(), or a // call to wait(). The _nnotify flag keeps track of the number of // pending notification calls. -1 indicates a broadcast, a positive // number indicates calls to notify(). The _nnotify flag is reset // upon initial acquisition of the monitor lock (either through a call // to lock(), or a return from wait(). // template inline IceUtil::Monitor::Monitor() : _nnotify(0) { } template inline IceUtil::Monitor::~Monitor() { } template inline void IceUtil::Monitor::lock() const { _mutex.lock(); if(_mutex.willUnlock()) { // // On the first mutex acquisition reset the number pending // notifications. // _nnotify = 0; } } template inline void IceUtil::Monitor::unlock() const { if(_mutex.willUnlock()) { // // Perform any pending notifications. // notifyImpl(_nnotify); } _mutex.unlock(); /* int nnotify = _nnotify; if(_mutex.unlock()) { // // Perform any pending notifications. // notifyImpl(nnotify); } */ } template inline bool IceUtil::Monitor::tryLock() const { bool result = _mutex.tryLock(); if(result && _mutex.willUnlock()) { // // On the first mutex acquisition reset the number pending // notifications. // _nnotify = 0; } return result; } template inline void IceUtil::Monitor::wait() const { // // Perform any pending notifies // notifyImpl(_nnotify); // // Wait for a notification // try { _cond.waitImpl(_mutex); // // Reset the nnotify count once wait() returns. // } catch(...) { _nnotify = 0; throw; } _nnotify = 0; } template inline bool IceUtil::Monitor::timedWait(const Time& timeout) const { // // Perform any pending notifies. // notifyImpl(_nnotify); bool rc; // // Wait for a notification. // try { rc = _cond.timedWaitImpl(_mutex, timeout); // // Reset the nnotify count once wait() returns. // } catch(...) { _nnotify = 0; throw; } _nnotify = 0; return rc; } template inline void IceUtil::Monitor::notify() { // // Increment the _nnotify flag, unless a broadcast has already // been requested. // if(_nnotify != -1) { ++_nnotify; } } template inline void IceUtil::Monitor::notifyAll() { // // -1 (indicates broadcast) // _nnotify = -1; } template inline void IceUtil::Monitor::notifyImpl(int nnotify) const { // // Zero indicates no notifies. // if(nnotify != 0) { // // -1 means notifyAll. // if(nnotify == -1) { _cond.broadcast(); return; } else { // // Otherwise notify n times. // while(nnotify > 0) { _cond.signal(); --nnotify; } } } } #endif IceE-trans-1.2.0/include/IceUtil/OutputUtil.h0000664000076400007640000001623510560413774020324 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** #ifndef ICE_UTIL_OUTPUT_UTIL_H #define ICE_UTIL_OUTPUT_UTIL_H #include #include #include #include namespace IceUtil { // ---------------------------------------------------------------------- // OutputBase // ---------------------------------------------------------------------- // // Technically it's not necessary to have print() & newline() as virtual // since the opeator<< functions are specific to each OutputBase // derivative. However, since it's possible to call print() & newline() // manually I've decided to leave them as virtual. // class ICE_UTIL_API OutputBase : private ::IceUtil::noncopyable { public: OutputBase(); OutputBase(std::ostream&); OutputBase(const char*); virtual ~OutputBase(); void setIndent(int); // What is the indent level? void setUseTab(bool); // Should we output tabs? void open(const char*); // Open output stream. bool isOpen(); // Is a file stream open? virtual void print(const char*); // Print a string. void inc(); // Increment indentation level. void dec(); // Decrement indentation level. void useCurrentPosAsIndent(); // Save the current position as indentation. void zeroIndent(); // Use zero identation. void restoreIndent(); // Restore indentation. int currIndent(); // Return current indent value. virtual void newline(); // Print newline. void separator(); // Print separator. bool operator!() const; // Check whether the output state is ok. protected: std::ofstream _fout; std::ostream& _out; int _pos; int _indent; int _indentSize; std::stack _indentSave; bool _useTab; bool _separator; }; class ICE_UTIL_API NextLine { }; extern ICE_UTIL_API NextLine nl; class ICE_UTIL_API Separator { }; extern ICE_UTIL_API Separator sp; // ---------------------------------------------------------------------- // Output // ---------------------------------------------------------------------- class ICE_UTIL_API Output : public OutputBase { public: Output(); Output(std::ostream&); Output(const char*); virtual void print(const char*); // Print a string. void setBeginBlock(const char *); // what do we use at block starts? void setEndBlock(const char *); // what do we use the block end? void sb(); // Start a block. void eb(); // End a block. void spar(); // Start a paramater list. void epar(); // End a paramater list. private: std::string _blockStart; std::string _blockEnd; int _par; // If >= 0, we are writing a parameter list. }; template inline Output& operator<<(Output& out, const T& val) { std::ostringstream s; s << val; out.print(s.str().c_str()); return out; } template inline Output& operator<<(Output& out, const std::vector& val) { for(typename std::vector::const_iterator p = val.begin(); p != val.end(); ++p) { out << *p; } return out; } #if defined(_MSC_VER) && (_MSC_VER < 1300) // // Visual C++ 6.0 needs also a version of the function above with a // non-const vector as argument. // template inline Output& operator<<(Output& out, std::vector& val) { for(typename std::vector::const_iterator p = val.begin(); p != val.end(); ++p) { out << *p; } return out; } #endif template<> inline Output& operator<<(Output& o, const NextLine&) { o.newline(); return o; } template<> inline Output& operator<<(Output& o, const Separator&) { o.separator(); return o; } class ICE_UTIL_API StartBlock { }; extern ICE_UTIL_API StartBlock sb; template<> inline Output& operator<<(Output& o, const StartBlock&) { o.sb(); return o; } class ICE_UTIL_API EndBlock { }; extern ICE_UTIL_API EndBlock eb; template<> inline Output& operator<<(Output& o, const EndBlock&) { o.eb(); return o; } class ICE_UTIL_API StartPar { }; extern ICE_UTIL_API StartPar spar; template<> inline Output& operator<<(Output& o, const StartPar&) { o.spar(); return o; } class ICE_UTIL_API EndPar { }; extern ICE_UTIL_API EndPar epar; template<> inline Output& operator<<(Output& o, const EndPar&) { o.epar(); return o; } ICE_UTIL_API Output& operator<<(Output&, std::ios_base& (*)(std::ios_base&)); // ---------------------------------------------------------------------- // XMLOutput // ---------------------------------------------------------------------- class ICE_UTIL_API XMLOutput : public OutputBase { public: XMLOutput(); XMLOutput(std::ostream&); XMLOutput(const char*); virtual void print(const char*); // Print a string. virtual void newline(); // Print newline. void startElement(const std::string&); // Start an element. void endElement(); // End an element. void attr(const std::string&, const std::string&); // Add an attribute to an element. void startEscapes(); void endEscapes(); std::string currentElement() const; private: ::std::string escape(const ::std::string&) const; std::stack _elementStack; bool _se; bool _text; bool _escape; }; template inline XMLOutput& operator<<(XMLOutput& out, const T& val) { std::ostringstream s; s << val; out.print(s.str().c_str()); return out; } template<> inline XMLOutput& operator<<(XMLOutput& o, const NextLine&) { o.newline(); return o; } template<> inline XMLOutput& operator<<(XMLOutput& o, const Separator&) { o.separator(); return o; } class ICE_UTIL_API EndElement { }; extern ICE_UTIL_API EndElement ee; template<> inline XMLOutput& operator<<(XMLOutput& o, const EndElement&) { o.endElement(); return o; } class ICE_UTIL_API StartElement { public: StartElement(const std::string&); const std::string& getName() const; private: const std::string _name; }; typedef StartElement se; template<> inline XMLOutput& operator<<(XMLOutput& o, const StartElement& e) { o.startElement(e.getName()); return o; } class ICE_UTIL_API Attribute { public: Attribute(const ::std::string&, const ::std::string&); const ::std::string& getName() const; const ::std::string& getValue() const; private: const ::std::string _name; const ::std::string _value; }; typedef Attribute attr; template<> inline XMLOutput& operator<<(XMLOutput& o, const Attribute& e) { o.attr(e.getName(), e.getValue()); return o; } class ICE_UTIL_API StartEscapes { }; extern ICE_UTIL_API StartEscapes startEscapes; class ICE_UTIL_API EndEscapes { }; extern ICE_UTIL_API EndEscapes endEscapes; template<> inline XMLOutput& operator<<(XMLOutput& o, const StartEscapes&) { o.startEscapes(); return o; } template<> inline XMLOutput& operator<<(XMLOutput& o, const EndEscapes&) { o.endEscapes(); return o; } ICE_UTIL_API XMLOutput& operator<<(XMLOutput&, std::ios_base& (*)(std::ios_base&)); } #endif IceE-trans-1.2.0/include/IceUtil/IceUtil.h0000664000076400007640000000266610600127466017522 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** #ifndef ICE_UTIL_ICE_UTIL_H #define ICE_UTIL_ICE_UTIL_H // // This file must include *all* other headers of IceUtil, except // for DisableWarnings.h. // #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #endif IceE-trans-1.2.0/include/IceUtil/Exception.h0000664000076400007640000000364610577401745020131 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** #ifndef ICE_UTIL_EXCEPTION_H #define ICE_UTIL_EXCEPTION_H #include namespace IceUtil { class ICE_UTIL_API Exception : public std::exception { public: Exception(); Exception(const char*, int); virtual ~Exception() throw(); virtual std::string ice_name() const; virtual void ice_print(std::ostream&) const; virtual const char* what() const throw(); virtual Exception* ice_clone() const; virtual void ice_throw() const; const char* ice_file() const; int ice_line() const; private: const char* _file; int _line; static const char* _name; mutable ::std::string _str; // Initialized lazily in what(). }; ICE_UTIL_API std::ostream& operator<<(std::ostream&, const Exception&); class ICE_UTIL_API NullHandleException : public Exception { public: NullHandleException(const char*, int); virtual ~NullHandleException() throw(); virtual std::string ice_name() const; virtual Exception* ice_clone() const; virtual void ice_throw() const; private: static const char* _name; }; class ICE_UTIL_API IllegalArgumentException : public Exception { public: IllegalArgumentException(const char*, int); IllegalArgumentException(const char*, int, const std::string&); virtual ~IllegalArgumentException() throw(); virtual std::string ice_name() const; virtual Exception* ice_clone() const; virtual void ice_throw() const; std::string reason; private: static const char* _name; }; ICE_UTIL_API std::ostream& operator<<(std::ostream&, const IllegalArgumentException&); } #endif IceE-trans-1.2.0/include/IceUtil/Makefile0000664000076400007640000000136310550516550017444 0ustar dwaynedwayne# ********************************************************************** # # Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. # # This copy of Ice is licensed to you under the terms described in the # ICE_LICENSE file included in this distribution. # # ********************************************************************** top_srcdir = ../.. include $(top_srcdir)/config/Make.rules install:: @if test ! -d $(install_includedir)/IceUtil ; \ then \ echo "Creating $(install_includedir)/IceUtil..." ; \ $(call mkdir,$(install_includedir)/IceUtil) ; \ fi @for i in *.h ; \ do \ echo "Installing $$i" ; \ $(INSTALL_DATA) $$i $(install_includedir)/IceUtil/$$i ; \ chmod a+r $(install_includedir)/IceUtil/$$i ; \ done IceE-trans-1.2.0/include/IceUtil/InputUtil.h0000664000076400007640000000242010560413774020112 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** #ifndef ICE_UTIL_INPUT_UTIL_H #define ICE_UTIL_INPUT_UTIL_H #include #include namespace IceUtil { // // Portable strtoll/_strtoi64 // ICE_UTIL_API Int64 strToInt64(const char*, char**, int); // // stringToInt64 converts a string into a signed 64-bit integer. // It's a simple wrapper around strToInt64. // // Semantics: // // - Ignore leading whitespace // // - If the string starts with '0', parse as octal // // - If the string starts with "0x" or "0X", parse as hexadecimal // // - Otherwise, parse as decimal // // - return value == true indicates a successful conversion and result contains the converted value // - return value == false indicates an unsuccessful conversion: // - result == 0 indicates that no digits were available for conversion // - result == "Int64 Min" or result == "Int64 Max" indicate underflow or overflow. // ICE_UTIL_API bool stringToInt64(const std::string&, Int64&); } #endif IceE-trans-1.2.0/include/IceUtil/Mutex.h0000664000076400007640000001516010560413774017264 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** #ifndef ICE_UTIL_MUTEX_H #define ICE_UTIL_MUTEX_H #include #include #include namespace IceUtil { // // Forward declaration for friend. // class Cond; // // Simple non-recursive Mutex implementation. // // Don't use noncopyable otherwise you end up with warnings like this: // // In file included from Connection.cpp:20: // ../../include/Ice/Outgoing.h:88: warning: direct base // `IceUtil::noncopyable' inaccessible in `IceInternal::Outgoing' due // to ambiguity // class Mutex { public: // // Lock & TryLock typedefs. // typedef LockT Lock; typedef TryLockT TryLock; inline Mutex(); ~Mutex(); // // Note that lock/tryLock & unlock in general should not be used // directly. Instead use Lock & TryLock. // void lock() const; // // Returns true if the lock was acquired, and false otherwise. // bool tryLock() const; void unlock() const; // // Returns true if the mutex will unlock when calling unlock() // (false otherwise). For non-recursive mutexes, this will always // return true. // This function is used by the Monitor implementation to know whether // the Mutex has been locked for the first time, or unlocked for the // last time (that is another thread is able to acquire the mutex). // Pre-condition: the mutex must be locked. // bool willUnlock() const; private: // noncopyable Mutex(const Mutex&); void operator=(const Mutex&); // // LockState and the lock/unlock variations are for use by the // Condition variable implementation. // #ifdef _WIN32 struct LockState { }; #else struct LockState { pthread_mutex_t* mutex; }; #endif void unlock(LockState&) const; void lock(LockState&) const; friend class Cond; #ifdef _WIN32 # if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0400 mutable CRITICAL_SECTION _mutex; # else mutable HANDLE _mutex; mutable int _recursionCount; # endif #else mutable pthread_mutex_t _mutex; #endif }; // // For performance reasons the following functions are inlined. // #ifdef _WIN32 # if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0400 inline Mutex::Mutex() { InitializeCriticalSection(&_mutex); } inline Mutex::~Mutex() { DeleteCriticalSection(&_mutex); } inline void Mutex::lock() const { EnterCriticalSection(&_mutex); assert(_mutex.RecursionCount == 1); } inline bool Mutex::tryLock() const { if(!TryEnterCriticalSection(&_mutex)) { return false; } if(_mutex.RecursionCount > 1) { LeaveCriticalSection(&_mutex); throw ThreadLockedException(__FILE__, __LINE__); } return true; } inline void Mutex::unlock() const { assert(_mutex.RecursionCount == 1); LeaveCriticalSection(&_mutex); } inline void Mutex::unlock(LockState&) const { LeaveCriticalSection(&_mutex); } inline void Mutex::lock(LockState&) const { EnterCriticalSection(&_mutex); } # else inline Mutex::Mutex() : _recursionCount(0) { _mutex = CreateMutex(0, false, 0); if(_mutex == 0) { throw ThreadSyscallException(__FILE__, __LINE__, GetLastError()); } } inline Mutex::~Mutex() { BOOL rc = CloseHandle(_mutex); if(rc == 0) { throw ThreadSyscallException(__FILE__, __LINE__, GetLastError()); } } inline void Mutex::lock() const { DWORD rc = WaitForSingleObject(_mutex, INFINITE); if(rc != WAIT_OBJECT_0) { if(rc == WAIT_FAILED) { throw ThreadSyscallException(__FILE__, __LINE__, GetLastError()); } else { throw ThreadSyscallException(__FILE__, __LINE__, 0); } } _recursionCount++; } inline bool Mutex::tryLock() const { DWORD rc = WaitForSingleObject(_mutex, 0); if(rc != WAIT_OBJECT_0) { return false; } else if(_recursionCount == 1) { _recursionCount++; unlock(); throw ThreadLockedException(__FILE__, __LINE__); } else { _recursionCount++; return true; } } inline void Mutex::unlock() const { _recursionCount--; BOOL rc = ReleaseMutex(_mutex); if(rc == 0) { throw ThreadSyscallException(__FILE__, __LINE__, GetLastError()); } } inline void Mutex::unlock(LockState& state) const { unlock(); } inline void Mutex::lock(LockState&) const { lock(); } # endif #else inline Mutex::Mutex() { #ifdef NDEBUG int rc = pthread_mutex_init(&_mutex, 0); #else int rc; #if defined(__linux) && !defined(__USE_UNIX98) const pthread_mutexattr_t attr = { PTHREAD_MUTEX_ERRORCHECK_NP }; #else pthread_mutexattr_t attr; rc = pthread_mutexattr_init(&attr); assert(rc == 0); rc = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK); assert(rc == 0); #endif rc = pthread_mutex_init(&_mutex, &attr); #if defined(__linux) && !defined(__USE_UNIX98) // Nothing to do #else rc = pthread_mutexattr_destroy(&attr); assert(rc == 0); #endif #endif if(rc != 0) { throw ThreadSyscallException(__FILE__, __LINE__, rc); } } inline Mutex::~Mutex() { int rc = 0; rc = pthread_mutex_destroy(&_mutex); assert(rc == 0); } inline void Mutex::lock() const { int rc = pthread_mutex_lock(&_mutex); if(rc != 0) { if(rc == EDEADLK) { throw ThreadLockedException(__FILE__, __LINE__); } else { throw ThreadSyscallException(__FILE__, __LINE__, rc); } } } inline bool Mutex::tryLock() const { int rc = pthread_mutex_trylock(&_mutex); if(rc != 0 && rc != EBUSY) { if(rc == EDEADLK) { throw ThreadLockedException(__FILE__, __LINE__); } else { throw ThreadSyscallException(__FILE__, __LINE__, rc); } } return (rc == 0); } inline void Mutex::unlock() const { int rc = pthread_mutex_unlock(&_mutex); if(rc != 0) { throw ThreadSyscallException(__FILE__, __LINE__, rc); } } inline void Mutex::unlock(LockState& state) const { state.mutex = &_mutex; } inline void Mutex::lock(LockState&) const { } #endif inline bool Mutex::willUnlock() const { return true; } } // End namespace IceUtil #endif IceE-trans-1.2.0/include/IceUtil/Functional.h0000664000076400007640000002651610560413774020273 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** #ifndef ICE_UTIL_FUNCTIONAL_H #define ICE_UTIL_FUNCTIONAL_H #include #include namespace IceUtilInternal { // ---------------------------------------------------------------------- // Various function objects that work with handles instead of plain // pointers. // ---------------------------------------------------------------------- template class MemFun : public std::unary_function { typedef R (T::*MemberFN)(void); MemberFN _mfn; public: explicit MemFun(MemberFN p) : _mfn(p) { } R operator()(H handle) const { return (handle.get() ->* _mfn)(); } }; template class MemFun1 : public std::binary_function { typedef R (T::*MemberFN)(A); MemberFN _mfn; public: explicit MemFun1(MemberFN p) : _mfn(p) { } R operator()(H handle, A arg) const { return (handle.get() ->* _mfn)(arg); } }; template class VoidMemFun : public std::unary_function { typedef void (T::*MemberFN)(void); MemberFN _mfn; public: explicit VoidMemFun(MemberFN p) : _mfn(p) { } void operator()(H handle) const { (handle.get() ->* _mfn)(); } }; template class VoidMemFun1 : public std::binary_function { typedef void (T::*MemberFN)(A); MemberFN _mfn; public: explicit VoidMemFun1(MemberFN p) : _mfn(p) { } void operator()(H handle, A arg) const { (handle.get() ->* _mfn)(arg); } }; template class SecondMemFun : public std::unary_function, R> { typedef R (T::*MemberFN)(void); MemberFN _mfn; public: explicit SecondMemFun(MemberFN p) : _mfn(p) { } R operator()(std::pair pair) const { return (pair.second.get() ->* _mfn)(); } }; template class SecondMemFun1 : public std::binary_function, A, R> { typedef R (T::*MemberFN)(A); MemberFN _mfn; public: explicit SecondMemFun1(MemberFN p) : _mfn(p) { } R operator()(std::pair pair, A arg) const { return (pair.second.get() ->* _mfn)(arg); } }; template class SecondVoidMemFun : public std::unary_function, void> { typedef void (T::*MemberFN)(void); MemberFN _mfn; public: explicit SecondVoidMemFun(MemberFN p) : _mfn(p) { } void operator()(std::pair pair) const { (pair.second.get() ->* _mfn)(); } }; template class SecondVoidMemFun1 : public std::binary_function, A, void> { typedef void (T::*MemberFN)(A); MemberFN _mfn; public: explicit SecondVoidMemFun1(MemberFN p) : _mfn(p) { } void operator()(std::pair pair, A arg) const { (pair.second.get() ->* _mfn)(arg); } }; template class ConstMemFun : public std::unary_function { typedef R (T::*MemberFN)(void) const; MemberFN _mfn; public: explicit ConstMemFun(MemberFN p) : _mfn(p) { } R operator()(H handle) const { return (handle.get() ->* _mfn)(); } }; template class ConstMemFun1 : public std::binary_function { typedef R (T::*MemberFN)(A) const; MemberFN _mfn; public: explicit ConstMemFun1(MemberFN p) : _mfn(p) { } R operator()(H handle, A arg) const { return (handle.get() ->* _mfn)(arg); } }; template class ConstVoidMemFun : public std::unary_function { typedef void (T::*MemberFN)(void) const; MemberFN _mfn; public: explicit ConstVoidMemFun(MemberFN p) : _mfn(p) { } void operator()(H handle) const { (handle.get() ->* _mfn)(); } }; template class ConstVoidMemFun1 : public std::binary_function { typedef void (T::*MemberFN)(A) const; MemberFN _mfn; public: explicit ConstVoidMemFun1(MemberFN p) : _mfn(p) { } void operator()(H handle, A arg) const { (handle.get() ->* _mfn)(arg); } }; template class SecondConstMemFun : public std::unary_function, R> { typedef R (T::*MemberFN)(void) const; MemberFN _mfn; public: explicit SecondConstMemFun(MemberFN p) : _mfn(p) { } R operator()(std::pair pair) const { return (pair.second.get() ->* _mfn)(); } }; template class SecondConstMemFun1 : public std::binary_function, A, R> { typedef R (T::*MemberFN)(A) const; MemberFN _mfn; public: explicit SecondConstMemFun1(MemberFN p) : _mfn(p) { } R operator()(std::pair pair, A arg) const { return (pair.second.get() ->* _mfn)(arg); } }; template class SecondConstVoidMemFun : public std::unary_function, void> { typedef void (T::*MemberFN)(void) const; MemberFN _mfn; public: explicit SecondConstVoidMemFun(MemberFN p) : _mfn(p) { } void operator()(std::pair pair) const { (pair.second.get() ->* _mfn)(); } }; template class SecondConstVoidMemFun1 : public std::binary_function, A, void> { typedef void (T::*MemberFN)(A) const; MemberFN _mfn; public: explicit SecondConstVoidMemFun1(MemberFN p) : _mfn(p) { } void operator()(std::pair pair, A arg) const { (pair.second.get() ->* _mfn)(arg); } }; } // ---------------------------------------------------------------------- // Inline functions that return function objects that work with // IceUtil::Handle // ---------------------------------------------------------------------- namespace IceUtil { template inline ::IceUtilInternal::MemFun > memFun(R (T::*p)(void)) { return ::IceUtilInternal::MemFun >(p); } template inline ::IceUtilInternal::MemFun1, A> memFun1(R (T::*p)(A)) { return ::IceUtilInternal::MemFun1, A>(p); } template inline ::IceUtilInternal::VoidMemFun > voidMemFun(void (T::*p)(void)) { return ::IceUtilInternal::VoidMemFun >(p); } template inline ::IceUtilInternal::VoidMemFun1, A> voidMemFun1(void (T::*p)(A)) { return ::IceUtilInternal::VoidMemFun1, A>(p); } template inline ::IceUtilInternal::SecondMemFun > secondMemFun(R (T::*p)(void)) { return ::IceUtilInternal::SecondMemFun >(p); } template inline ::IceUtilInternal::SecondMemFun1, A> secondMemFun1(R (T::*p)(A)) { return ::IceUtilInternal::SecondMemFun1, A>(p); } template inline ::IceUtilInternal::SecondVoidMemFun > secondVoidMemFun(void (T::*p)(void)) { return ::IceUtilInternal::SecondVoidMemFun >(p); } template inline ::IceUtilInternal::SecondVoidMemFun1, A> secondVoidMemFun1(void (T::*p)(A)) { return ::IceUtilInternal::SecondVoidMemFun1, A>(p); } template inline ::IceUtilInternal::ConstMemFun > constMemFun(R (T::*p)(void) const) { return ::IceUtilInternal::ConstMemFun >(p); } template inline ::IceUtilInternal::ConstMemFun1, A> constMemFun1(R (T::*p)(A) const) { return ::IceUtilInternal::ConstMemFun1, A>(p); } template inline ::IceUtilInternal::ConstVoidMemFun > constVoidMemFun(void (T::*p)(void) const) { return ::IceUtilInternal::ConstVoidMemFun >(p); } template inline ::IceUtilInternal::ConstVoidMemFun1, A> constVoidMemFun1(void (T::*p)(A) const) { return ::IceUtilInternal::ConstVoidMemFun1, A>(p); } template inline ::IceUtilInternal::SecondConstMemFun > secondConstMemFun(R (T::*p)(void) const) { return ::IceUtilInternal::SecondConstMemFun >(p); } template inline ::IceUtilInternal::SecondConstMemFun1, A> secondConstMemFun1(R (T::*p)(A) const) { return ::IceUtilInternal::SecondConstMemFun1, A>(p); } template inline ::IceUtilInternal::SecondConstVoidMemFun > secondConstVoidMemFun(void (T::*p)(void) const) { return ::IceUtilInternal::SecondConstVoidMemFun >(p); } template inline ::IceUtilInternal::SecondConstVoidMemFun1, A> secondConstVoidMemFun1(void (T::*p)(A) const) { return ::IceUtilInternal::SecondConstVoidMemFun1, A>(p); } } // ---------------------------------------------------------------------- // Extension for STLport: Special versions for bind1st and bind2nd for // operations that do not return anything (i.e., return void). Needed // for broken compilers, such as Visual C++ 6.0. // ---------------------------------------------------------------------- #ifdef _STLP_BEGIN_NAMESPACE _STLP_BEGIN_NAMESPACE template class voidbinder1st : public unary_function { protected: _Operation _M_op; typename _Operation::first_argument_type _M_value; public: voidbinder1st(const _Operation& __x, const typename _Operation::first_argument_type& __y) : _M_op(__x), _M_value(__y) {} typename _Operation::result_type operator()(const typename _Operation::second_argument_type& __x) const { _M_op(_M_value, __x); } }; template inline voidbinder1st<_Operation> voidbind1st(const _Operation& __fn, const _Tp& __x) { typedef typename _Operation::first_argument_type _Arg1_type; return voidbinder1st<_Operation>(__fn, _Arg1_type(__x)); } template class voidbinder2nd : public unary_function { protected: _Operation _M_op; typename _Operation::second_argument_type value; public: voidbinder2nd(const _Operation& __x, const typename _Operation::second_argument_type& __y) : _M_op(__x), value(__y) {} typename _Operation::result_type operator()(const typename _Operation::first_argument_type& __x) const { _M_op(__x, value); } }; template inline voidbinder2nd<_Operation> voidbind2nd(const _Operation& __fn, const _Tp& __x) { typedef typename _Operation::second_argument_type _Arg2_type; return voidbinder2nd<_Operation>(__fn, _Arg2_type(__x)); } _STLP_END_NAMESPACE #endif #endif IceE-trans-1.2.0/include/IceUtil/CtrlCHandler.h0000664000076400007640000000434410550516550020464 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** #ifndef ICE_UTIL_CTRL_C_HANDLER_H #define ICE_UTIL_CTRL_C_HANDLER_H #include #include namespace IceUtil { // The CtrlCHandler provides a portable way to handle CTRL+C and // CTRL+C like signals // On Unix/POSIX, the CtrlCHandler handles SIGHUP, SIGINT and SIGTERM. // On Windows, it is essentially a wrapper for SetConsoleCtrlHandler(). // // In a process, only one CtrlCHandler can exist at a given time: // the CtrlCHandler constructor raises CtrlCHandlerException if // you attempt to create a second CtrlCHandler. // On Unix/POSIX, it is essential to create the CtrlCHandler before // creating any thread, as the CtrlCHandler constructor masks // SIGHUP, SIGINT and SIGTERM; by default, threads created later will // inherit this signal mask. // // When a CTRL+C or CTRL+C like signal is sent to the process, the // user-registered callback is called in a separate thread; it is // given the signal number. The callback must not raise exceptions. // On Unix/POSIX, the callback is NOT a signal handler and can call // functions that are not async-signal safe. // // The CtrCHandler destructor "unregisters" the callback. However // on Unix/POSIX it does not restore the old signal mask in any // thread, so SIGHUP, SIGINT and SIGTERM are then ignored. // // TODO: Maybe the behavior on Windows should be the same? Now we // just restore the default behavior (TerminateProcess). typedef void (*CtrlCHandlerCallback)(int); class ICE_UTIL_API CtrlCHandler { public: CtrlCHandler(CtrlCHandlerCallback = 0); ~CtrlCHandler(); void setCallback(CtrlCHandlerCallback); CtrlCHandlerCallback getCallback() const; }; class ICE_UTIL_API CtrlCHandlerException : public Exception { public: CtrlCHandlerException(const char*, int); virtual std::string ice_name() const; virtual Exception* ice_clone() const; virtual void ice_throw() const; }; } #endif IceE-trans-1.2.0/include/IceUtil/Makefile.mak0000664000076400007640000000121610550516550020210 0ustar dwaynedwayne# ********************************************************************** # # Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. # # This copy of Ice is licensed to you under the terms described in the # ICE_LICENSE file included in this distribution. # # ********************************************************************** top_srcdir = ..\.. !include $(top_srcdir)/config/Make.rules.mak install:: @if not exist $(install_includedir)\IceUtil \ @echo "Creating $(install_includedir)\IceUtil..." & \ mkdir $(install_includedir)\IceUtil @for %i in ( *.h ) do \ @echo Installing %i & \ copy %i $(install_includedir)\IceUtil IceE-trans-1.2.0/include/IceUtil/Shared.h0000664000076400007640000001330610560413774017370 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** #ifndef ICE_UTIL_SHARED_H #define ICE_UTIL_SHARED_H #include #if defined(ICE_USE_MUTEX_SHARED) # include #elif (defined(__linux) || defined(__FreeBSD__)) && (defined(__i386) || defined(__x86_64)) && !defined(__ICC) # define ICE_HAS_ATOMIC_FUNCTIONS // __ICC: The inline assembler causes problems with shared libraries. // // Linux only. Unfortunately, asm/atomic.h builds non-SMP safe code // with non-SMP kernels. This means that executables compiled with a // non-SMP kernel would fail randomly due to concurrency errors with // reference counting on SMP hosts. Therefore the relevent pieces of // atomic.h are more-or-less duplicated. // /* * Make sure gcc doesn't try to be clever and move things around * on us. We need to use _exactly_ the address the user gave us, * not some alias that contains the same information. */ struct ice_atomic_t { volatile int counter; }; /* * ice_atomic_set - set ice_atomic variable * @v: pointer of type ice_atomic_t * @i: required value * * Atomically sets the value of @v to @i. Note that the guaranteed * useful range of an ice_atomic_t is only 24 bits. */ inline void ice_atomic_set(ice_atomic_t* v, int i) { v->counter = i; } /* * ice_atomic_inc - increment ice_atomic variable * @v: pointer of type ice_atomic_t * * Atomically increments @v by 1. Note that the guaranteed useful * range of an ice_atomic_t is only 24 bits. * * Inlined because this operation is performance critical. */ inline void ice_atomic_inc(ice_atomic_t *v) { __asm__ __volatile__( "lock ; incl %0" :"=m" (v->counter) :"m" (v->counter)); } /** * ice_atomic_dec_and_test - decrement and test * @v: pointer of type ice_atomic_t * * Atomically decrements @v by 1 and returns true if the result is 0, * or false for all other cases. Note that the guaranteed useful * range of an ice_atomic_t is only 24 bits. * * Inlined because this operation is performance critical. */ inline int ice_atomic_dec_and_test(ice_atomic_t *v) { unsigned char c; __asm__ __volatile__( "lock ; decl %0; sete %1" :"=m" (v->counter), "=qm" (c) :"m" (v->counter) : "memory"); return c != 0; } /** * ice_atomic_exchange_add - same as InterlockedExchangeAdd. This * didn't come from atomic.h (the code was derived from similar code * in /usr/include/asm/rwsem.h) * * Inlined because this operation is performance critical. */ inline int ice_atomic_exchange_add(int i, ice_atomic_t* v) { int tmp = i; __asm__ __volatile__( "lock ; xadd %0,(%2)" :"+r"(tmp), "=m"(v->counter) :"r"(v), "m"(v->counter) : "memory"); return tmp + i; } #elif defined(_WIN32) // Nothing to include #else // Use a simple mutex # include #endif // // Base classes for reference counted types. The IceUtil::Handle // template can be used for smart pointers to types derived from these // bases. // // IceUtil::SimpleShared // ===================== // // A non thread-safe base class for reference-counted types. // // IceUtil::Shared // =============== // // A thread-safe base class for reference-counted types. // namespace IceUtil { class ICE_UTIL_API SimpleShared { public: SimpleShared(); SimpleShared(const SimpleShared&); virtual ~SimpleShared() { } SimpleShared& operator=(const SimpleShared&) { return *this; } void __incRef() { assert(_ref >= 0); ++_ref; } void __decRef() { assert(_ref > 0); if(--_ref == 0) { if(!_noDelete) { _noDelete = true; delete this; } } } int __getRef() const { return _ref; } void __setNoDelete(bool b) { _noDelete = b; } private: int _ref; bool _noDelete; }; class ICE_UTIL_API Shared { public: Shared(); Shared(const Shared&); virtual ~Shared() { } Shared& operator=(const Shared&) { return *this; } void __incRef() { #if defined(_WIN32) assert(InterlockedExchangeAdd(&_ref, 0) >= 0); InterlockedIncrement(&_ref); #elif defined(ICE_HAS_ATOMIC_FUNCTIONS) assert(ice_atomic_exchange_add(0, &_ref) >= 0); ice_atomic_inc(&_ref); #else _mutex.lock(); assert(_ref >= 0); ++_ref; _mutex.unlock(); #endif } void __decRef() { #if defined(_WIN32) assert(InterlockedExchangeAdd(&_ref, 0) > 0); if(InterlockedDecrement(&_ref) == 0 && !_noDelete) { _noDelete = true; delete this; } #elif defined(ICE_HAS_ATOMIC_FUNCTIONS) assert(ice_atomic_exchange_add(0, &_ref) > 0); if(ice_atomic_dec_and_test(&_ref) && !_noDelete) { _noDelete = true; delete this; } #else _mutex.lock(); bool doDelete = false; assert(_ref > 0); if(--_ref == 0) { doDelete = !_noDelete; _noDelete = true; } _mutex.unlock(); if(doDelete) { delete this; } #endif } int __getRef() const; void __setNoDelete(bool); protected: #if defined(_WIN32) LONG _ref; #elif defined(ICE_HAS_ATOMIC_FUNCTIONS) ice_atomic_t _ref; #else int _ref; Mutex _mutex; #endif bool _noDelete; }; } #endif IceE-trans-1.2.0/include/IceUtil/RWRecMutex.h0000664000076400007640000001714710560413774020176 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** #ifndef ICE_UTIL_RW_REC_MUTEX_H #define ICE_UTIL_RW_REC_MUTEX_H #include #include #include namespace IceUtil { class ICE_UTIL_API DeadlockException : public Exception { public: DeadlockException(const char*, int); virtual std::string ice_name() const; virtual Exception* ice_clone() const; virtual void ice_throw() const; private: static const char* _name; }; template class RLockT { public: RLockT(const T& mutex) : _mutex(mutex) { _mutex.readLock(); _acquired = true; } ~RLockT() { if (_acquired) { _mutex.unlock(); } } void acquire() const { if (_acquired) { throw ThreadLockedException(__FILE__, __LINE__); } _mutex.readLock(); _acquired = true; } bool tryAcquire() const { if (_acquired) { throw ThreadLockedException(__FILE__, __LINE__); } _acquired = _mutex.tryReadLock(); return _acquired; } bool timedAcquire(const Time& timeout) const { if (_acquired) { throw ThreadLockedException(__FILE__, __LINE__); } _acquired = _mutex.timedReadLock(timeout); return _acquired; } void release() const { if (!_acquired) { throw ThreadLockedException(__FILE__, __LINE__); } _mutex.unlock(); _acquired = false; } bool acquired() const { return _acquired; } void upgrade() const { _mutex.upgrade(); } bool timedUpgrade(const Time& timeout) const { return _mutex.timedUpgrade(timeout); } void downgrade() const { _mutex.downgrade(); } protected: // TryRLockT's constructors RLockT(const T& mutex, bool) : _mutex(mutex) { _acquired = _mutex.tryReadLock(); } RLockT(const T& mutex, const Time& timeout) : _mutex(mutex) { _acquired = _mutex.timedReadLock(timeout); } private: // Not implemented; prevents accidental use. // RLockT(const RLockT&); RLockT& operator=(const RLockT&); const T& _mutex; mutable bool _acquired; }; template class TryRLockT : public RLockT { public: TryRLockT(const T& mutex) : RLockT(mutex, true) { } TryRLockT(const T& mutex, const Time& timeout) : RLockT(mutex, timeout) { } }; template class WLockT { public: WLockT(const T& mutex) : _mutex(mutex) { _mutex.writeLock(); _acquired = true; } ~WLockT() { if (_acquired) { _mutex.unlock(); } } void acquire() const { if (_acquired) { throw ThreadLockedException(__FILE__, __LINE__); } _mutex.writeLock(); _acquired = true; } bool tryAcquire() const { if (_acquired) { throw ThreadLockedException(__FILE__, __LINE__); } _acquired = _mutex.tryWriteLock(); return _acquired; } bool timedAcquire(const Time& timeout) const { if (_acquired) { throw ThreadLockedException(__FILE__, __LINE__); } _acquired = _mutex.timedWriteLock(timeout); return _acquired; } void release() const { if (!_acquired) { throw ThreadLockedException(__FILE__, __LINE__); } _mutex.unlock(); _acquired = false; } bool acquired() const { return _acquired; } protected: // TryWLockT's constructor WLockT(const T& mutex, bool) : _mutex(mutex) { _acquired = _mutex.tryWriteLock(); } WLockT(const T& mutex, const Time& timeout) : _mutex(mutex) { _acquired = _mutex.timedWriteLock(timeout); } private: // Not implemented; prevents accidental use. // WLockT(const WLockT&); WLockT& operator=(const WLockT&); const T& _mutex; mutable bool _acquired; }; template class TryWLockT : public WLockT { public: TryWLockT(const T& mutex) : WLockT(mutex, true) { } TryWLockT(const T& mutex, const Time& timeout) : WLockT(mutex, timeout) { } }; // // Concurrency primitive that allows many readers & one writer access // to a data structure. Writers have priority over readers. The // structure is not strictly fair in that there is no absolute queue // of waiting writers - that is managed by a condition variable. // // Both Reader & Writer mutexes can be recursively locked. Calling // upgrade() or timedUpgrade() while holding a read lock promotes // the reader to a writer lock. // class ICE_UTIL_API RWRecMutex { public: // // RLock (reader) & WLock (writer) typedefs. // typedef RLockT RLock; typedef TryRLockT TryRLock; typedef WLockT WLock; typedef TryWLockT TryWLock; RWRecMutex(); ~RWRecMutex(); // // Note that readLock/writeLock & unlock in general should not be // used directly. Instead use RLock & WLock. // // // Acquire a read lock. // void readLock() const; // // Try to acquire a read lock. // bool tryReadLock() const; // // Try to acquire a read lock for upto the given timeout. // bool timedReadLock(const Time&) const; // // Acquire a write lock. // void writeLock() const; // // Acquire a write lock. // bool tryWriteLock() const; // // Acquire a write lock for up to the given timeout. // bool timedWriteLock(const Time&) const; // // Unlock the reader/writer lock. // void unlock() const; // // Upgrade the read lock to a writer lock. Note that this method // can only be called if the reader lock is not held recursively. // void upgrade() const; // // Upgrade the read lock to a writer lock for up to the given // timeout Note that this method can only be called if the reader // lock is not held recursively. // bool timedUpgrade(const Time&) const; // // Downgrade a write lock to a read lock. // void downgrade() const; private: // noncopyable RWRecMutex(const RWRecMutex&); void operator=(const RWRecMutex&); // // Number of readers holding the lock. A positive number indicates // readers are active. A negative number means that a writer is // active and indicates the number of times writeLock() was called. // mutable int _count; // // If there is an active writer this is the ID of the writer thread. // mutable ThreadControl _writerId; // // Number of waiting writers (including any upgrader). // mutable unsigned int _waitingWriters; // // True if an upgrader wants the lock. // mutable bool _upgrading; // // Internal mutex. // Mutex _mutex; // // Condition variables for waiting readers, writers, and upgrader. // mutable Cond _readers; mutable Cond _writers; mutable Cond _upgrader; }; } // End namespace IceUtil #endif IceE-trans-1.2.0/include/IceUtil/Cond.h0000664000076400007640000001255110560413774017046 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** #ifndef ICE_UTIL_COND_H #define ICE_UTIL_COND_H #include #include #include #ifdef _WIN32 # include #endif namespace IceUtil { // // Forward declaration (for friend declarations). // template class Monitor; class RecMutex; class Mutex; #ifdef _WIN32 // // Needed for implementation. // class Semaphore { public: Semaphore(long = 0); ICE_UTIL_API ~Semaphore(); void wait() const; bool timedWait(const Time&) const; void post(int = 1) const; private: mutable HANDLE _sem; }; #endif // // Condition variable implementation. Conforms to the same semantics // as a POSIX threads condition variable. // class Cond : private noncopyable { public: ICE_UTIL_API Cond(); ICE_UTIL_API ~Cond(); // // signal restarts one of the threads that are waiting on the // condition variable cond. If no threads are waiting on cond, // nothing happens. If several threads are waiting on cond, // exactly one is restarted, but it is not specified which. // ICE_UTIL_API void signal(); // // broadcast restarts all the threads that are waiting on the // condition variable cond. Nothing happens if no threads are // waiting on cond. // ICE_UTIL_API void broadcast(); // // MSVC doesn't support out-of-class definitions of member // templates. See KB Article Q241949 for details. // // // wait atomically unlocks the mutex and waits for the condition // variable to be signaled. Before returning to the calling thread // the mutex is reaquired. // template inline void wait(const Lock& lock) const { if(!lock.acquired()) { throw ThreadLockedException(__FILE__, __LINE__); } waitImpl(lock._mutex); } // // wait atomically unlocks the mutex and waits for the condition // variable to be signaled for up to the given timeout. Before // returning to the calling thread the mutex is reaquired. Returns // true if the condition variable was signaled, false on a // timeout. // template inline bool timedWait(const Lock& lock, const Time& timeout) const { if(!lock.acquired()) { throw ThreadLockedException(__FILE__, __LINE__); } return timedWaitImpl(lock._mutex, timeout); } private: friend class Monitor; friend class Monitor; // // The Monitor implementation uses waitImpl & timedWaitImpl. // #ifdef _WIN32 template void waitImpl(const M& mutex) const { preWait(); typedef typename M::LockState LockState; LockState state; mutex.unlock(state); try { dowait(); mutex.lock(state); } catch(...) { mutex.lock(state); throw; } } template bool timedWaitImpl(const M& mutex, const Time& timeout) const { preWait(); typedef typename M::LockState LockState; LockState state; mutex.unlock(state); try { bool rc = timedDowait(timeout); mutex.lock(state); return rc; } catch(...) { mutex.lock(state); throw; } } #else template void waitImpl(const M&) const; template bool timedWaitImpl(const M&, const Time&) const; #endif #ifdef _WIN32 ICE_UTIL_API void wake(bool); ICE_UTIL_API void preWait() const; ICE_UTIL_API void postWait(bool) const; ICE_UTIL_API bool timedDowait(const Time&) const; ICE_UTIL_API void dowait() const; Mutex _internal; Semaphore _gate; Semaphore _queue; mutable long _blocked; mutable long _unblocked; mutable long _toUnblock; #else mutable pthread_cond_t _cond; #endif }; #ifndef _WIN32 template inline void Cond::waitImpl(const M& mutex) const { typedef typename M::LockState LockState; LockState state; mutex.unlock(state); int rc = pthread_cond_wait(&_cond, state.mutex); mutex.lock(state); if(rc != 0) { throw ThreadSyscallException(__FILE__, __LINE__, rc); } } template inline bool Cond::timedWaitImpl(const M& mutex, const Time& timeout) const { typedef typename M::LockState LockState; LockState state; mutex.unlock(state); timeval tv = Time::now() + timeout; timespec ts; ts.tv_sec = tv.tv_sec; ts.tv_nsec = tv.tv_usec * 1000; int rc = pthread_cond_timedwait(&_cond, state.mutex, &ts); mutex.lock(state); if(rc != 0) { // // pthread_cond_timedwait returns ETIMEOUT in the event of a // timeout. // if(rc != ETIMEDOUT) { throw ThreadSyscallException(__FILE__, __LINE__, rc); } return false; } return true; } #endif } // End namespace IceUtil #endif IceE-trans-1.2.0/include/IceUtil/Handle.h0000664000076400007640000001254010601001131017324 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** #ifndef ICE_UTIL_HANDLE_H #define ICE_UTIL_HANDLE_H #include #include // // "Handle" or "smart pointer" class for classes derived from // IceUtil::Shared, IceUtil::SimpleShared, or Ice::GCShared. // namespace IceUtil { template class HandleBase { public: typedef T element_type; T* get() const { return _ptr; } T* operator->() const { if(!_ptr) { // // We don't throw directly NullHandleException here to // keep the code size of this method to a minimun (the // assembly code for throwing an exception is much bigger // than just a function call). This maximises the chances // of inlining by compiler optimization. // throwNullHandleException(__FILE__, __LINE__); } return _ptr; } T& operator*() const { if(!_ptr) { // // We don't throw directly NullHandleException here to // keep the code size of this method to a minimun (the // assembly code for throwing an exception is much bigger // than just a function call). This maximises the chances // of inlining by compiler optimization. // throwNullHandleException(__FILE__, __LINE__); } return *_ptr; } operator bool() const { return _ptr ? true : false; } void swap(HandleBase& other) { std::swap(_ptr, other._ptr); } T* _ptr; private: void throwNullHandleException(const char *, int) const; }; template inline void HandleBase::throwNullHandleException(const char* file, int line) const { throw NullHandleException(file, line); } template inline bool operator==(const HandleBase& lhs, const HandleBase& rhs) { T* l = lhs.get(); U* r = rhs.get(); if(l && r) { return *l == *r; } else { return !l && !r; } } template inline bool operator!=(const HandleBase& lhs, const HandleBase& rhs) { return !operator==(lhs, rhs); } template inline bool operator<(const HandleBase& lhs, const HandleBase& rhs) { T* l = lhs.get(); U* r = rhs.get(); if(l && r) { return *l < *r; } else { return !l && r; } } template inline bool operator<=(const HandleBase& lhs, const HandleBase& rhs) { return lhs < rhs || lhs == rhs; } template inline bool operator>(const HandleBase& lhs, const HandleBase& rhs) { return !(lhs < rhs || lhs == rhs); } template inline bool operator>=(const HandleBase& lhs, const HandleBase& rhs) { return !(lhs < rhs); } template class Handle : public HandleBase { public: Handle(T* p = 0) { this->_ptr = p; if(this->_ptr) { this->_ptr->__incRef(); } } template Handle(const Handle& r) { this->_ptr = r._ptr; if(this->_ptr) { this->_ptr->__incRef(); } } Handle(const Handle& r) { this->_ptr = r._ptr; if(this->_ptr) { this->_ptr->__incRef(); } } ~Handle() { if(this->_ptr) { this->_ptr->__decRef(); } } Handle& operator=(T* p) { if(this->_ptr != p) { if(p) { p->__incRef(); } T* ptr = this->_ptr; this->_ptr = p; if(ptr) { ptr->__decRef(); } } return *this; } template Handle& operator=(const Handle& r) { if(this->_ptr != r._ptr) { if(r._ptr) { r._ptr->__incRef(); } T* ptr = this->_ptr; this->_ptr = r._ptr; if(ptr) { ptr->__decRef(); } } return *this; } Handle& operator=(const Handle& r) { if(this->_ptr != r._ptr) { if(r._ptr) { r._ptr->__incRef(); } T* ptr = this->_ptr; this->_ptr = r._ptr; if(ptr) { ptr->__decRef(); } } return *this; } template static Handle dynamicCast(const HandleBase& r) { #ifdef __BCPLUSPLUS__ return Handle(dynamic_cast(r._ptr)); #else return Handle(dynamic_cast(r._ptr)); #endif } template static Handle dynamicCast(Y* p) { #ifdef __BCPLUSPLUS__ return Handle(dynamic_cast(p)); #else return Handle(dynamic_cast(p)); #endif } }; } #endif IceE-trans-1.2.0/include/IceUtil/ThreadException.h0000664000076400007640000000372610550516550021250 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** #ifndef ICE_UTIL_THREAD_EXCEPTION_H #define ICE_UTIL_THREAD_EXCEPTION_H #include namespace IceUtil { class ICE_UTIL_API ThreadSyscallException : public Exception { public: ThreadSyscallException(const char*, int, int); virtual std::string ice_name() const; virtual void ice_print(std::ostream&) const; virtual Exception* ice_clone() const; virtual void ice_throw() const; int error() const; private: const int _error; static const char* _name; }; class ICE_UTIL_API ThreadLockedException : public Exception { public: ThreadLockedException(const char*, int); virtual std::string ice_name() const; virtual Exception* ice_clone() const; virtual void ice_throw() const; private: static const char* _name; }; class ICE_UTIL_API ThreadStartedException : public Exception { public: ThreadStartedException(const char*, int); virtual std::string ice_name() const; virtual Exception* ice_clone() const; virtual void ice_throw() const; private: static const char* _name; }; class ICE_UTIL_API ThreadNotStartedException : public Exception { public: ThreadNotStartedException(const char*, int); virtual std::string ice_name() const; virtual Exception* ice_clone() const; virtual void ice_throw() const; private: static const char* _name; }; class ICE_UTIL_API BadThreadControlException : public Exception { public: BadThreadControlException(const char*, int); virtual std::string ice_name() const; virtual Exception* ice_clone() const; virtual void ice_throw() const; private: static const char* _name; }; } #endif IceE-trans-1.2.0/include/IceUtil/Random.h0000664000076400007640000000170110550516550017371 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** #ifndef ICE_UTIL_RANDOM_H #define ICE_UTIL_RANDOM_H #include #include namespace IceUtil { class ICE_UTIL_API RandomGeneratorException : public Exception { public: RandomGeneratorException(const char*, int, int = 0); virtual std::string ice_name() const; virtual void ice_print(std::ostream&) const; virtual Exception* ice_clone() const; virtual void ice_throw() const; int error() const; private: const int _error; static const char* _name; }; ICE_UTIL_API void generateRandom(char*, int); ICE_UTIL_API int random(int = 0); } #endif IceE-trans-1.2.0/include/IceUtil/Unicode.h0000664000076400007640000001045410560413774017551 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** #ifndef ICE_UTIL_UNICODE_H #define ICE_UTIL_UNICODE_H #include #include namespace IceUtil { #if defined(_MSC_VER) && (_MSC_VER >= 1300) // // With Visual C++ 7.x, wchar_t is either a typedef unsigned short or a // native type (when /Zc:wchar_t is used). // Since wstring is a typedef basic_string, its type is also // different depending on whether /Zc:wchar_t is used or not. // // With Visual C++ 7.x, the default is typedef; with Visual C++ 8.0, // the default is native type. // // Ice is always built with the default, but provides wstringToString() // and stringToWstring() implementations for both flavors of wstring. // # if defined(_NATIVE_WCHAR_T_DEFINED) ICE_UTIL_API std::string wstringToString(const std::wstring&); # if _MSC_VER >= 1400 // // Building or using with VC8 // ICE_UTIL_API std::wstring stringToWstring(const std::string&); ICE_UTIL_API std::string wstringToString(const std::basic_string&); ICE_UTIL_API std::basic_string stringToTypedefWstring(const std::string&); # else // // Using a VC7.x build with the non-default /Zc // ICE_UTIL_API std::wstring stringToNativeWstring(const std::string&); inline std::wstring stringToWstring(const std::string& str) { return stringToNativeWstring(str); } # endif # else ICE_UTIL_API std::string wstringToString(const std::wstring&); # if _MSC_VER < 1400 // // Building or using with VC7.x // ICE_UTIL_API std::wstring stringToWstring(const std::string&); ICE_UTIL_API std::string wstringToString(const std::basic_string<__wchar_t>&); ICE_UTIL_API std::basic_string<__wchar_t> stringToNativeWstring(const std::string&); # else // // Using a VC8.x build the non-default /Zc // ICE_UTIL_API std::wstring stringToTypedefWstring(const std::string&); inline std::wstring stringToWstring(const std::string& str) { return stringToTypedefWstring(str); } # endif # endif #else ICE_UTIL_API std::string wstringToString(const std::wstring&); ICE_UTIL_API std::wstring stringToWstring(const std::string&); #endif // // Converts UTF-8 byte-sequences to and from UTF-16 or UTF-32 (with native // endianness) depending on sizeof(wchar_t). // // These are thin wrappers over the UTF8/16/32 converters provided by // unicode.org // // // TODO: provide the same support for /Zc:wchar_t as the functions above // enum ConversionResult { conversionOK, /* conversion successful */ sourceExhausted, /* partial character in source, but hit end */ targetExhausted, /* insuff. room in target for conversion */ sourceIllegal /* source sequence is illegal/malformed */ }; enum ConversionFlags { strictConversion = 0, lenientConversion }; typedef unsigned char Byte; ICE_UTIL_API bool isLegalUTF8Sequence(const Byte* source, const Byte* end); ICE_UTIL_API ConversionResult convertUTFWstringToUTF8(const wchar_t*& sourceStart, const wchar_t* sourceEnd, Byte*& targetStart, Byte* targetEnd, ConversionFlags flags); ICE_UTIL_API ConversionResult convertUTF8ToUTFWstring(const Byte*& sourceStart, const Byte* sourceEnd, wchar_t*& targetStart, wchar_t* targetEnd, ConversionFlags flags); ICE_UTIL_API ConversionResult convertUTF8ToUTFWstring(const Byte*& sourceStart, const Byte* sourceEnd, std::wstring& target, ConversionFlags flags); // // UTFConversionException is raised by wstringToString() or stringToWstring() // to report a conversion error // class ICE_UTIL_API UTFConversionException : public Exception { public: UTFConversionException(const char*, int, ConversionResult); virtual std::string ice_name() const; virtual void ice_print(std::ostream&) const; virtual Exception* ice_clone() const; virtual void ice_throw() const; ConversionResult conversionResult() const; private: const ConversionResult _conversionResult; static const char* _name; }; } #endif IceE-trans-1.2.0/include/IceUtil/ArgVector.h0000664000076400007640000000170210562516516020053 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** #ifndef ICE_UTIL_ARGVECTOR_H #define ICE_UTIL_ARGVECTOR_H #include #include #include namespace IceUtil { class ICE_UTIL_API ArgVector { public: ArgVector(int argc, char* argv[]); ArgVector(const ::std::vector< ::std::string>&); ArgVector(const ArgVector&); ArgVector& operator=(const ArgVector&); ~ArgVector(); void setNoDelete(); int argc; char** argv; private: int _origArgc; bool _noDelete; void copyVec(int, int, char**); void copyVec(const ::std::vector< ::std::string>&); void swap(ArgVector&) throw(); }; } #endif IceE-trans-1.2.0/include/IceUtil/StaticMutex.h0000664000076400007640000001454210560413774020437 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** #ifndef ICE_UTIL_STATIC_MUTEX_H #define ICE_UTIL_STATIC_MUTEX_H #include #include #include #if defined(_MSC_VER) && (_MSC_VER < 1300) // // Old versions of the Platform SDK don't have InterlockedCompareExchangePointer // # ifndef InterlockedCompareExchangePointer # define InterlockedCompareExchangePointer(Destination, ExChange, Comperand) \ InterlockedCompareExchange(Destination, ExChange, Comperand) # endif #endif namespace IceUtil { // // Forward declaration for friend. // class Cond; // // Simple non-recursive Mutex implementation. // These mutexes are POD types (see ISO C++ 9(4) and 8.5.1) and must be // initialized statically using ICE_STATIC_MUTEX_INITIALIZER. // // class StaticMutex { public: // // Lock & TryLock typedefs. // typedef LockT Lock; typedef TryLockT TryLock; // // Note that lock/tryLock & unlock in general should not be used // directly. Instead use Lock & TryLock. // void lock() const; // // Returns true if the lock was acquired, and false otherwise. // bool tryLock() const; void unlock() const; #ifdef _WIN32 # if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0400 mutable CRITICAL_SECTION* _mutex; # else mutable HANDLE _mutex; mutable int _recursionCount; # endif #else mutable pthread_mutex_t _mutex; #endif #if !defined(_MSC_VER) && !defined(__BCPLUSPLUS__) // COMPILERBUG // VC++ BC++ considers that aggregates should not have private members ... // even if it's just functions. private: #endif // // LockState and the lock/unlock variations are for use by the // Condition variable implementation. // #ifdef _WIN32 struct LockState { }; #else struct LockState { pthread_mutex_t* mutex; }; #endif void unlock(LockState&) const; void lock(LockState&) const; #ifdef _WIN32 inline bool initialized() const; ICE_UTIL_API void initialize() const; #endif #ifndef _MSC_VER friend class Cond; #endif }; #ifdef _WIN32 # define ICE_STATIC_MUTEX_INITIALIZER { 0 } #else # define ICE_STATIC_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER } #endif // A "shared" global mutex that can be used for very simple tasks // which should not lock any other mutexes. // extern ICE_UTIL_API StaticMutex globalMutex; // // For performance reasons the following functions are inlined. // #ifdef _WIN32 inline bool StaticMutex::initialized() const { // // Read mutex and then inserts a memory barrier to ensure we can't // see tmp != 0 before we see the initialized object // void* tmp = _mutex; return InterlockedCompareExchangePointer(reinterpret_cast(&tmp), 0, 0) != 0; } # if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0400 inline void StaticMutex::lock() const { if(!initialized()) { initialize(); } EnterCriticalSection(_mutex); assert(_mutex->RecursionCount == 1); } inline bool StaticMutex::tryLock() const { if(!initialized()) { initialize(); } if(!TryEnterCriticalSection(_mutex)) { return false; } if(_mutex->RecursionCount > 1) { LeaveCriticalSection(_mutex); throw ThreadLockedException(__FILE__, __LINE__); } return true; } inline void StaticMutex::unlock() const { assert(_mutex != 0); assert(_mutex->RecursionCount == 1); LeaveCriticalSection(_mutex); } inline void StaticMutex::unlock(LockState&) const { assert(_mutex != 0); assert(_mutex->RecursionCount == 1); LeaveCriticalSection(_mutex); } inline void StaticMutex::lock(LockState&) const { if(!initialized()) { initialize(); } EnterCriticalSection(_mutex); } # else inline void StaticMutex::lock() const { if(!initialized()) { initialize(); } DWORD rc = WaitForSingleObject(_mutex, INFINITE); if(rc != WAIT_OBJECT_0) { if(rc == WAIT_FAILED) { throw ThreadSyscallException(__FILE__, __LINE__, GetLastError()); } else { throw ThreadSyscallException(__FILE__, __LINE__, 0); } } _recursionCount++; assert(_recursionCount == 1); } inline bool StaticMutex::tryLock() const { if(!initialized()) { initialize(); } DWORD rc = WaitForSingleObject(_mutex, 0); if(rc != WAIT_OBJECT_0) { return false; } else if(_recursionCount == 1) { _recursionCount++; unlock(); throw ThreadLockedException(__FILE__, __LINE__); } else { _recursionCount++; return true; } } inline void StaticMutex::unlock() const { _recursionCount--; BOOL rc = ReleaseMutex(_mutex); if(rc == 0) { throw ThreadSyscallException(__FILE__, __LINE__, GetLastError()); } } inline void StaticMutex::unlock(LockState& state) const { unlock(); } inline void StaticMutex::lock(LockState&) const { lock(); } # endif #else inline void StaticMutex::lock() const { int rc = pthread_mutex_lock(&_mutex); if(rc != 0) { if(rc == EDEADLK) { throw ThreadLockedException(__FILE__, __LINE__); } else { throw ThreadSyscallException(__FILE__, __LINE__, rc); } } } inline bool StaticMutex::tryLock() const { int rc = pthread_mutex_trylock(&_mutex); if(rc != 0 && rc != EBUSY) { if(rc == EDEADLK) { throw ThreadLockedException(__FILE__, __LINE__); } else { throw ThreadSyscallException(__FILE__, __LINE__, rc); } } return (rc == 0); } inline void StaticMutex::unlock() const { int rc = pthread_mutex_unlock(&_mutex); if(rc != 0) { throw ThreadSyscallException(__FILE__, __LINE__, rc); } } inline void StaticMutex::unlock(LockState& state) const { state.mutex = &_mutex; } inline void StaticMutex::lock(LockState&) const { } #endif } // End namespace IceUtil #endif IceE-trans-1.2.0/include/IceUtil/DisableWarnings.h0000664000076400007640000000205310560413774021233 0ustar dwaynedwayne// ********************************************************************** // // Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** #ifndef ICE_UTIL_DISABLEWARNINGS_H #define ICE_UTIL_DISABLEWARNINGS_H // // This header file disables various annoying compiler warnings that // we don't want. // // IMPORTANT: Do *not* include this header file in another public header file! // Doing this may potentially disable the warnings in the source // code of our customers, which would be bad. Only include this // header file in Ice *source* files! // #if defined(_MSC_VER) && _MSC_VER >= 1400 # define _CRT_SECURE_NO_DEPRECATE 1 // C4996 '' was declared deprecated/ #endif #if defined(_MSC_VER) && _MSC_VER >= 1300 # pragma warning( 4 : 4996 ) // C4996 'std::' was declared deprecated #endif #endif IceE-trans-1.2.0/Makefile0000664000076400007640000000317510620635757014477 0ustar dwaynedwayne# ********************************************************************** # # Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. # # This copy of Ice is licensed to you under the terms described in the # ICE_LICENSE file included in this distribution. # # ********************************************************************** top_srcdir = . include $(top_srcdir)/config/Make.rules SUBDIRS = src INSTALL_SUBDIRS = $(install_bindir) $(install_libdir) install:: @if test ! -d $(prefix) ; \ then \ echo "Creating $(prefix)..." ; \ $(call mkdir,$(prefix)) ; \ fi ifneq ($(embedded_runpath_prefix),) @if test -h $(embedded_runpath_prefix) ; \ then \ if `\rm -f $(embedded_runpath_prefix) 2>/dev/null`; \ then echo "Removed symbolic link $(embedded_runpath_prefix)"; fi \ fi @if `ln -s $(prefix) $(embedded_runpath_prefix) 2>/dev/null`;\ then echo "Created symbolic link $(embedded_runpath_prefix) --> $(prefix)"; fi endif @for subdir in $(INSTALL_SUBDIRS); \ do \ if test ! -d $$subdir ; \ then \ echo "Creating $$subdir..." ; \ mkdir -p $$subdir ; \ chmod a+rx $$subdir ; \ fi ; \ done $(EVERYTHING):: @for subdir in $(SUBDIRS); \ do \ echo "making $@ in $$subdir"; \ ( cd $$subdir && $(MAKE) $@ ) || exit 1; \ done doc:: @( cd doc && $(MAKE) ) || exit 1 install:: @if test -d doc ; \ then \ ( cd doc && $(MAKE) install ) || exit 1 ; \ fi $(call installdata,ICE_LICENSE,$(prefix)) $(call installdata,LICENSE,$(prefix)) clean:: @if test -d doc ; \ then \ ( cd doc && $(MAKE) clean ) || exit 1 ; \ fi test:: @python $(top_srcdir)/allTests.py IceE-trans-1.2.0/Makefile.mak0000664000076400007640000000166110620635757015244 0ustar dwaynedwayne# ********************************************************************** # # Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. # # This copy of Ice is licensed to you under the terms described in the # ICE_LICENSE file included in this distribution. # # ********************************************************************** top_srcdir = . !include $(top_srcdir)/config/Make.rules.mak SUBDIRS = src INSTALL_SUBDIRS = $(install_bindir) $(install_libdir) install:: createdir createdir:: @if not exist $(prefix) \ @echo "Creating $(prefix)..." & \ mkdir $(prefix) @for %i in ( $(INSTALL_SUBDIRS) ) do \ @if not exist %i \ @echo "Creating %i..." & \ mkdir %i $(EVERYTHING):: @for %i in ( $(SUBDIRS) ) do \ @echo "making $@ in %i" & \ cmd /c "cd %i & $(MAKE) -nologo -f Makefile.mak $@" || exit 1 install:: copy ICE_LICENSE $(prefix) copy LICENSE $(prefix) test:: @python $(top_srcdir)/allTests.py IceE-trans-1.2.0/INSTALL.WINDOWS0000664000076400007640000000272310620635757015217 0ustar dwaynedwayne====================================================================== Requirements ====================================================================== Windows version --------------- The Ice-E translators have been extensively tested on: - Windows XP x86 - Windows Vista x86 C++ compiler ------------ The following Microsoft Visual C++ compilers are supported: - Microsoft Visual C++ 2005 (both Professional and Express editions) Visual C++ 2005 Express is available for download from: http://msdn.microsoft.com/vstudio/express/visualc/ ====================================================================== Compilation ====================================================================== Using your favorite Zip tool, unzip the Ice source archive anywhere you like. Open a command prompt and change the working directory to IceE-trans-1.2.0. For example: > cd C:\IceE-trans-1.2.0 Edit config\Make.rules.mak to establish your build configuration. The comments in the file provide more information. In particular, you must set CPP_COMPILER to the appropriate compiler. Now you're ready to build the Ice-E translators: > nmake /f Makefile.mak ====================================================================== Installation ====================================================================== Simply run "nmake /f Makefile.mak install". This will install the Ice-E translators in the directory specified by the "prefix" variable in config\Make.rules.mak. IceE-trans-1.2.0/ICE_LICENSE0000664000076400007640000000136110620635757014517 0ustar dwaynedwayneCopyright (c) 2003-2007 ZeroC, Inc. All rights reserved. This copy of the Ice-E translators is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. Ice is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. The GNU General Public License is often shipped with GNU software, and is generally kept in a file called COPYING or LICENSE. If you do not have a copy of the license, write to the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. IceE-trans-1.2.0/config/0000775000076400007640000000000010620635757014276 5ustar dwaynedwayneIceE-trans-1.2.0/config/Make.rules.mak0000664000076400007640000000434210620635757017001 0ustar dwaynedwayne# ********************************************************************** # # Copyright (c) 2003-2007 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. # # ********************************************************************** # # Select an installation base directory. The directory will be created # if it does not exist. # prefix = C:\IceE-1.2.0 # # Define OPTIMIZE as yes if you want to build with # optimization. Otherwise build with debug information. # OPTIMIZE = yes # # Specify your C++ compiler. Supported values are: # VC80, VC80_EXPRESS # !if "$(CPP_COMPILER)" == "" CPP_COMPILER = VC80 !endif # # For VC80 and VC80 Express it is necessary to set the location of the # manifest tool. This must be the 6.x version of mt.exe, not the 5.x # version! # # For VC80 Express mt.exe 6.x is provided by the Windows Platform SDK. # It is necessary to set the location of the Platform SDK through the # PDK_HOME environment variable (see INSTALL.WINDOWS for details). # !if "$(CPP_COMPILER)" == "VC80" MT = "$(VS80COMNTOOLS)bin\mt.exe" !elseif "$(CPP_COMPILER)" == "VC80_EXPRESS" MT = "$(PDK_HOME)\bin\mt.exe" !endif # ---------------------------------------------------------------------- # Don't change anything below this line! # ---------------------------------------------------------------------- STATICLIBS = yes SHELL = /bin/sh bindir = $(top_srcdir)\bin libdir = $(top_srcdir)\lib includedir = $(top_srcdir)\include slicedir = $(top_srcdir)\slice install_bindir = $(prefix)\bin OBJEXT = .obj SETARGV = setargv.obj !include $(top_srcdir)/config/Make.rules.msvc libsubdir = lib !if "$(OPTIMIZE)" != "yes" LIBSUFFIX = $(LIBSUFFIX)d !endif CPPFLAGS = $(CPPFLAGS) -I$(includedir) LDFLAGS = $(LDFLAGS) $(LDPLATFORMFLAGS) $(CXXFLAGS) SLICEPARSERLIB = $(libdir)\slice$(LIBSUFFIX).lib EVERYTHING = all clean install .SUFFIXES: .SUFFIXES: .ice .cpp .c .obj .cpp.obj:: $(CXX) /c $(CPPFLAGS) $(CXXFLAGS) $< .c.obj: $(CC) /c $(CPPFLAGS) $(CFLAGS) $< all:: $(SRCS) $(TARGETS) !if "$(TARGETS)" != "" clean:: -del /q $(TARGETS) !endif clean:: -del /q *.obj *.bak *.ilk *.exp *.pdb *.tds install:: IceE-trans-1.2.0/config/Make.rules0000664000076400007640000000613110620635757016230 0ustar dwaynedwayne# ********************************************************************** # # Copyright (c) 2003-2007 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. # # ********************************************************************** # # Select an installation base directory. The directory will be created # if it does not exist. # prefix ?= /opt/IceE-1.2.0 # # Define OPTIMIZE as yes if you want to build with # optimization. Otherwise build with debug information. # OPTIMIZE = yes # # Define LP64 as yes or no if you want force a 32 or 64 bit. The # default is platform-dependent # #LP64 ?= yes # ---------------------------------------------------------------------- # Don't change anything below this line! # ---------------------------------------------------------------------- STATICLIBS = yes SHELL = /bin/sh bindir = $(top_srcdir)/bin libdir = $(top_srcdir)/lib includedir = $(top_srcdir)/include install_bindir = $(prefix)/bin INSTALL = cp -fp INSTALL_PROGRAM = ${INSTALL} INSTALL_LIBRARY = ${INSTALL} INSTALL_DATA = ${INSTALL} OBJEXT = .o UNAME := $(shell uname) # # Platform specific definitions # include $(top_srcdir)/config/Make.rules.$(UNAME) CPPFLAGS = -I$(includedir) $(STLPORT_FLAGS) LDFLAGS = $(LDPLATFORMFLAGS) $(CXXFLAGS) -L$(libdir) ifeq ($(FLEX_NOLINE),yes) FLEXFLAGS := -L else FLEXFLAGS := endif ifeq ($(BISON_NOLINE),yes) BISONFLAGS := -dvtl else BISONFLAGS := -dvt endif # # Default functions for shared library names # ifeq ($(mklibname),) ifeq ($(STATICLIBS),yes) mklibname = lib$(1).a else mklibname = lib$(1).so endif endif ifndef mklibtargets ifeq ($(STATICLIBS),yes) mklibtargets = $(3) else mklibtargets = $(1) $(2) $(3) endif endif ifeq ($(installdata),) installdata = $(INSTALL_DATA) $(1) $(2); \ chmod a+r $(2)/$(notdir $(1)) endif ifeq ($(installprogram),) installprogram = $(INSTALL_PROGRAM) $(1) $(2); \ chmod a+rx $(2)/$(notdir $(1)) endif ifeq ($(mkdir),) mkdir = mkdir $(1) ; \ chmod a+rx $(1) endif EVERYTHING = all depend clean install .SUFFIXES: .SUFFIXES: .cpp .c .o .cpp.o: $(CXX) -c $(CPPFLAGS) $(CXXFLAGS) $< .c.o: $(CC) -c $(CPPFLAGS) $(CFLAGS) $< #%.h %.cpp: %.y # rm -f $(*F).h $(*F).cpp # bison $(BISONFLAGS) $< # mv $(*F).tab.c $(*F).cpp # mv $(*F).tab.h $(*F).h # rm -f $(*F).output #%.cpp: %.l # flex $(FLEXFLAGS) $< # rm -f $@ # echo '#include ' > $@ # cat lex.yy.c >> $@ # rm -f lex.yy.c all:: $(SRCS) $(TARGETS) depend:: $(SRCS) -rm -f .depend if test -n "$(SRCS)" ; then \ $(CXX) -DMAKEDEPEND -M $(CXXFLAGS) $(CPPFLAGS) $(SRCS) | \ $(top_srcdir)/config/makedepend.py >> .depend; \ fi if test -n "$(SLICE_SRCS)" ; then \ $(SLICE2CPP) --depend $(SLICE2CPPFLAGS) $(SLICE_SRCS) | \ $(top_srcdir)/config/makedepend.py >> .depend; \ fi clean:: -rm -f $(TARGETS) -rm -f core *.o *.bak ifneq ($(TEMPLATE_REPOSITORY),) clean:: rm -fr $(TEMPLATE_REPOSITORY) endif install:: IceE-trans-1.2.0/config/Make.rules.msvc0000775000076400007640000000411510620635670017174 0ustar dwaynedwayne# ********************************************************************** # # Copyright (c) 2003-2007 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. # # ********************************************************************** # # This file is included by Make.rules.mak when using Borland C++Builder. # CXX = cl.exe CC = cl.exe LINK = link.exe AR = lib.exe RC = rc.exe PREOUT = /out: PRELIBS = !if "$(THIRDPARTY_HOME)" != "" CPPFLAGS = -I"$(THIRDPARTY_HOME)\include" LDFLAGS = /LIBPATH:"$(THIRDPARTY_HOME)\lib" !if "$(CPP_COMPILER)" == "VC60" CPPFLAGS = -I"$(THIRDPARTY_HOME)\include\stlport" $(CPPFLAGS) !endif !endif # # ICE_DIR should only be set with demo tarball build, and if we are # building the demo tarball with VC60 then STLPort include must be set # properly. # !if "$(CPP_COMPILER)" == "VC60" & "$(ICE_DIR)" != "" CPPFLAGS = -I"$(ICE_DIR)\include\stlport" $(CPPFLAGS) !endif CPPFLAGS = $(CPPFLAGS) -nologo -W3 -WX -GR -EHsc -FD -D_CONSOLE !if "$(OPTIMIZE)" == "yes" CPPFLAGS = $(CPPFLAGS) -O2 -DNDEBUG !if "$(STATICLIBS)" == "yes" CPPFLAGS = $(CPPFLAGS) -MT !else CPPFLAGS = $(CPPFLAGS) -MD !endif !else CPPFLAGS = $(CPPFLAGS) -Zi -Gm -Od -D_DEBUG !if "$(STATICLIBS)" == "yes" CPPFLAGS = $(CPPFLAGS) -MTd !else CPPFLAGS = $(CPPFLAGS) -MDd !endif !if "$(CPP_COMPILER)" == "VC60" | "$(CPP_COMPILER)" == "VC71" CPPFLAGS = $(CPPFLAGS) -GZ !else CPPFLAGS = $(CPPFLAGS) -RTC1 !endif !endif !if "$(STATICLIBS)" == "yes" CPPFLAGS = $(CPPFLAGS) -DICE_STATIC_LIBS !endif LDFLAGS = $(LDFLAGS) /LIBPATH:"$(libdir)" /nologo /FIXED:no !if "$(OPTIMIZE)" != "yes" LDFLAGS = $(LDFLAGS) /debug /incremental:yes !else LDFLAGS = $(LDFLAGS) /pdb:none /OPT:REF !endif LD_DLLFLAGS = $(LDFLAGS) /dll LD_EXEFLAGS = $(LDFLAGS) ICE_OS_LIBS = rpcrt4.lib advapi32.lib BASELIBS = iceutil$(LIBSUFFIX).lib $(ICE_OS_LIBS) LIBS = ice$(LIBSUFFIX).lib $(BASELIBS) BZIP2_LIBS = libbz2$(LIBSUFFIX).lib DB_LIBS = libdb45$(LIBSUFFIX).lib IceE-trans-1.2.0/config/Make.rules.Linux0000664000076400007640000001074610552721165017326 0ustar dwaynedwayne# ********************************************************************** # # Copyright (c) 2003-2007 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. # # ********************************************************************** # # This file is included by Make.rules when uname is Linux. # USE_SPARC_ASM = irrelevant MACHINE = $(shell uname -m) # # Default compiler is c++ (aka g++). # ifeq ($(CXX),) CXX = c++ endif ifeq ($(CXX),g++) CXX = c++ endif # # icecpp is built with a C compiler # CFLAGS = -O2 ifeq ($(MACHINE),x86_64) ifeq ($(LP64),) LP64 = yes endif ifeq ($(LP64),yes) CFLAGS += -m64 else CFLAGS += -m32 endif endif ifeq ($(CXX),c++) ifeq ($(MACHINE),sparc64) # # We are an ultra, at least, and so have the atomic instructions # $(warning ===================================================================) $(warning Linux on SPARC is currently unsupported. The Ice team does not) $(warning maintain SPARC specific portions of the source code or build) $(warning system. Contact sales@zeroc.com if you wish to sponsor official) $(warning support.) $(warning ===================================================================) USE_SPARC_ASM = yes CXXARCHFLAGS = -mcpu=ultrasparc -pipe -Wno-deprecated -DUSE_SPARC_ASM endif ifeq ($(MACHINE),sparc) # # We are a sun4m or sun4c # On sun4m, there is a bug in some CPU/kernel/gcc configurations which # prevent us from using '-mcpu=v8' # $(warning ===================================================================) $(warning Linux on SPARC is currently unsupported. The Ice team does not) $(warning maintain SPARC specific portions of the source code or build) $(warning system. Contact sales@zeroc.com if you wish to sponsor official) $(warning support.) $(warning ===================================================================) USE_SPARC_ASM = no CXXARCHFLAGS = -mtune=v8 -pipe -Wno-deprecated -DICE_USE_MUTEX_SHARED endif ifeq ($(MACHINE),x86_64) ifeq ($(LP64),yes) CXXARCHFLAGS += -m64 else CXXARCHFLAGS += -m32 endif lp64suffix = 64 endif CXXFLAGS = $(CXXARCHFLAGS) -ftemplate-depth-128 -Wall -D_REENTRANT ifeq ($(STATICLIBS),) CXXFLAGS += -fPIC endif ifeq ($(OPTIMIZE),yes) CXXFLAGS += -O2 -DNDEBUG else CXXFLAGS += -g endif ifeq ($(USE_SPARC_ASM),yes) CFLAGS = -O2 -mcpu=ultrasparc -pipe -DNDEBUG -DUSE_SPARC_ASM ifeq ($(STATICLIBS),) CFLAGS += -fPIC endif endif ifeq ($(USE_SPARC_ASM),no) CFLAGS = -O2 -mcpu=v8 -pipe -DNDEBUG -DICE_USE_MUTEX_SHARED ifeq ($(STATICLIBS),) CFLAGS += -fPIC endif endif # # C++ run-time libraries, necessary for linking some shared libraries. # CXXLIBS = mkshlib = $(CXX) -shared $(LDFLAGS) -o $(1) -Wl,-h,$(2) $(3) $(4) -lpthread mklib = ar cr $(1) $(2) rpathlink = -Wl,-rpath-link,$(1) ifneq ($(embedded_runpath_prefix),) LDPLATFORMFLAGS = -Wl,--enable-new-dtags -Wl,-rpath,$(runpath_libdir) else LDPLATFORMFLAGS = -Wl,--enable-new-dtags endif endif ifeq ($(CXX),icpc) $(warning ===================================================================) $(warning Intel C++ is currently not supported. The Ice team does not) $(warning maintain Intel C++ specific portions of the source code or build) $(warning system. Contact sales@zeroc.com if you wish to sponsor official) $(warning support.) $(warning ===================================================================) CXXFLAGS = -D_REENTRANT ifeq ($(STATICLIBS),) CXXFLAGS += -fPIC endif ifeq ($(OPTIMIZE),yes) CXXFLAGS += -O2 -DNDEBUG else CXXFLAGS += -g endif # # C++ run-time libraries, necessary for linking some shared libraries. # CXXLIBS = mkshlib = $(CXX) -shared $(LDFLAGS) -o $(1) -Wl,-h,$(2) $(3) $(4) -lpthread mklib = ar cr $(1) $(2) rpathlink = -Wl,-rpath-link,$(1) endif BASELIBS = -lIceUtil $(STLPORT_LIBS) -lpthread LIBS = $(BZIP2_RPATH_LINK) -lIce $(BASELIBS) ICEUTIL_OS_LIBS = ICE_OS_LIBS = -ldl PLATFORM_HAS_READLINE = yes export LD_LIBRARY_PATH := $(libdir):$(LD_LIBRARY_PATH) IceE-trans-1.2.0/README0000664000076400007640000000022710620635757013712 0ustar dwaynedwayneThis archive contains the source code for the Ice-E translators. For installation instructions, please refer to the INSTALL.* file for your plaftorm.