diff options
author | Mark Spruiell <mes@zeroc.com> | 2009-06-23 17:47:58 -0700 |
---|---|---|
committer | Mark Spruiell <mes@zeroc.com> | 2009-06-23 17:47:58 -0700 |
commit | a2e794a1366fcd71f04496c206869ffa158547ac (patch) | |
tree | 4c9d6554f3dc658aeaa76892aeecfc3d7eb56b61 /cpp/src/slice2php | |
parent | Add x64 configurations to C++ projects (diff) | |
download | ice-a2e794a1366fcd71f04496c206869ffa158547ac.tar.bz2 ice-a2e794a1366fcd71f04496c206869ffa158547ac.tar.xz ice-a2e794a1366fcd71f04496c206869ffa158547ac.zip |
PHP changes:
- static translation
- more traditional language mapping (multiple communicators, etc.)
- support for registered (persistent) communicators
- support for PHP namespaces (PHP 5.3 or later)
Diffstat (limited to 'cpp/src/slice2php')
-rw-r--r-- | cpp/src/slice2php/.depend | 1 | ||||
-rw-r--r-- | cpp/src/slice2php/Main.cpp | 1677 | ||||
-rw-r--r-- | cpp/src/slice2php/Makefile | 31 | ||||
-rw-r--r-- | cpp/src/slice2php/Makefile.mak | 60 | ||||
-rw-r--r-- | cpp/src/slice2php/Slice2PHP.rc | 34 |
5 files changed, 1803 insertions, 0 deletions
diff --git a/cpp/src/slice2php/.depend b/cpp/src/slice2php/.depend new file mode 100644 index 00000000000..4e49f990dad --- /dev/null +++ b/cpp/src/slice2php/.depend @@ -0,0 +1 @@ +Main$(OBJEXT): Main.cpp $(includedir)/IceUtil/DisableWarnings.h $(includedir)/IceUtil/CtrlCHandler.h $(includedir)/IceUtil/Config.h $(includedir)/IceUtil/Exception.h $(includedir)/IceUtil/IceUtil.h $(includedir)/IceUtil/AbstractMutex.h $(includedir)/IceUtil/Lock.h $(includedir)/IceUtil/ThreadException.h $(includedir)/IceUtil/Time.h $(includedir)/IceUtil/Cache.h $(includedir)/IceUtil/Handle.h $(includedir)/IceUtil/Mutex.h $(includedir)/IceUtil/CountDownLatch.h $(includedir)/IceUtil/Cond.h $(includedir)/IceUtil/Functional.h $(includedir)/IceUtil/Monitor.h $(includedir)/IceUtil/RWRecMutex.h $(includedir)/IceUtil/Thread.h $(includedir)/IceUtil/Shared.h $(includedir)/IceUtil/RecMutex.h $(includedir)/IceUtil/StaticMutex.h $(includedir)/IceUtil/Timer.h $(includedir)/IceUtil/UUID.h $(includedir)/IceUtil/Unicode.h $(includedir)/IceUtil/InputUtil.h $(includedir)/IceUtil/Options.h $(includedir)/IceUtil/OutputUtil.h $(includedir)/IceUtil/StringUtil.h $(includedir)/Slice/Checksum.h $(includedir)/Slice/Parser.h $(includedir)/Slice/Preprocessor.h $(includedir)/Slice/FileTracker.h $(includedir)/Slice/PHPUtil.h $(includedir)/Slice/Util.h diff --git a/cpp/src/slice2php/Main.cpp b/cpp/src/slice2php/Main.cpp new file mode 100644 index 00000000000..9ad5e42935e --- /dev/null +++ b/cpp/src/slice2php/Main.cpp @@ -0,0 +1,1677 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2009 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 <IceUtil/DisableWarnings.h> +#include <IceUtil/CtrlCHandler.h> +#include <IceUtil/IceUtil.h> +#include <IceUtil/InputUtil.h> +#include <IceUtil/Options.h> +#include <IceUtil/OutputUtil.h> +#include <IceUtil/StringUtil.h> +#include <IceUtil/StaticMutex.h> +#include <Slice/Checksum.h> +#include <Slice/Preprocessor.h> +#include <Slice/FileTracker.h> +#include <Slice/PHPUtil.h> +#include <Slice/Util.h> +#include <cstring> +#include <climits> + +#include <sys/types.h> +#include <sys/stat.h> + +#ifdef _WIN32 +#include <direct.h> +#endif + +#ifndef _WIN32 +#include <unistd.h> +#endif + +using namespace std; +using namespace Slice; +using namespace Slice::PHP; +using namespace IceUtil; +using namespace IceUtilInternal; + +// +// CodeVisitor generates the PHP mapping for a translation unit. +// +class CodeVisitor : public ParserVisitor +{ +public: + + CodeVisitor(IceUtilInternal::Output&, bool); + + 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: + + void startNamespace(const ContainedPtr&); + void endNamespace(); + + // + // Return the PHP name for the given Slice type. When using namespaces, + // this name is a relative (unqualified) name, otherwise this name is the + // flattened absolute name. + // + string getName(const ContainedPtr&, const string& = string()); + + // + // Return the PHP variable for the given object's type. + // + string getTypeVar(const ContainedPtr&, const string& = string()); + + // + // Emit the array for a Slice type. + // + void writeType(const TypePtr&); + + // + // Write a default value for a given type. + // + void writeDefaultValue(const TypePtr&); + + struct MemberInfo + { + string fixedName; + TypePtr type; + bool inherited; + StringList metaData; + }; + typedef list<MemberInfo> MemberInfoList; + + // + // Write a member assignment statement for a constructor. + // + void writeAssign(const MemberInfo&); + + // + // Convert an operation mode into a string. + // + string getOperationMode(Slice::Operation::Mode, bool); + + void collectClassMembers(const ClassDefPtr&, MemberInfoList&, bool); + void collectExceptionMembers(const ExceptionPtr&, MemberInfoList&, bool); + + Output& _out; + bool _ns; // Using namespaces? + list<string> _moduleStack; // TODO: Necessary? + set<string> _classHistory; // TODO: Necessary? +}; + +// +// CodeVisitor implementation. +// +CodeVisitor::CodeVisitor(Output& out, bool ns) : + _out(out), _ns(ns) +{ +} + +void +CodeVisitor::visitClassDecl(const ClassDeclPtr& p) +{ + // + // Handle forward declarations. + // + string scoped = p->scoped(); + string abs = getAbsolute(p, _ns); + if(_classHistory.count(scoped) == 0) + { + startNamespace(p); + + string type = getTypeVar(p); + _out << sp << nl << "if(!isset(" << type << "))"; + _out << sb; + _out << nl << type << " = IcePHP_declareClass('" << scoped << "');"; + if(!p->isLocal()) + { + _out << nl << type << "Prx = IcePHP_defineProxy(" << type << ");"; + } + _out << eb; + + endNamespace(); + + _classHistory.insert(scoped); // Avoid redundant declarations. + } +} + +bool +CodeVisitor::visitClassDefStart(const ClassDefPtr& p) +{ + string scoped = p->scoped(); + string name = getName(p); + string type = getTypeVar(p); + string abs = getAbsolute(p, _ns); + string prxName = getName(p, "Prx"); + string prxType = getTypeVar(p, "Prx"); + string prxAbs = getAbsolute(p, _ns, "", "Prx"); + ClassList bases = p->bases(); + ClassDefPtr base; + OperationList ops = p->operations(); + OperationList::iterator oli; + DataMemberList members = p->dataMembers(); + bool isInterface = p->isInterface(); + bool isAbstract = isInterface || p->allOperations().size() > 0; // Don't use isAbstract() - see bug 3739 + + startNamespace(p); + + // + // Define the class. + // + if(isInterface) + { + _out << sp << nl << "if(!interface_exists('" << escapeName(abs) << "'))"; + _out << sb; + _out << nl << "interface " << name; + if(!bases.empty()) + { + _out << " extends "; + for(ClassList::const_iterator q = bases.begin(); q != bases.end(); ++q) + { + if(q != bases.begin()) + { + _out << ", "; + } + _out << getAbsolute(*q, _ns); + } + } + _out << sb; + for(oli = ops.begin(); oli != ops.end(); ++oli) + { + _out << nl << "public function " << fixIdent((*oli)->name()) << '('; + ParamDeclList params = (*oli)->parameters(); + for(ParamDeclList::iterator q = params.begin(); q != params.end(); ++q) + { + if(q != params.begin()) + { + _out << ", "; + } + _out << '$' << fixIdent((*q)->name()); + } + _out << ");"; + } + _out << eb; + } + else + { + _out << sp << nl << "if(!class_exists('" << escapeName(abs) << "'))"; + _out << sb; + _out << nl; + if(isAbstract) + { + _out << "abstract "; + } + _out << "class " << name; + if(!bases.empty() && !bases.front()->isInterface()) + { + base = bases.front(); + bases.pop_front(); + } + if(base) + { + _out << " extends " << getAbsolute(base, _ns); + } + else + { + if(!p->isLocal()) + { + _out << " extends " << scopedToName("::Ice::ObjectImpl", _ns); + } + } + if(!bases.empty()) + { + _out << " implements "; + for(ClassList::const_iterator q = bases.begin(); q != bases.end(); ++q) + { + if(q != bases.begin()) + { + _out << ", "; + } + _out << getAbsolute(*q, _ns); + } + } + + _out << sb; + + // + // __construct + // + _out << nl << "public function __construct("; + MemberInfoList allMembers; + collectClassMembers(p, allMembers, false); + if(!allMembers.empty()) + { + for(MemberInfoList::iterator q = allMembers.begin(); q != allMembers.end(); ++q) + { + if(q != allMembers.begin()) + { + _out << ", "; + } + _out << '$' << q->fixedName << '='; + writeDefaultValue(q->type); + } + } + _out << ")"; + _out << sb; + if(base) + { + _out << nl << "parent::__construct("; + int count = 0; + for(MemberInfoList::iterator q = allMembers.begin(); q != allMembers.end(); ++q) + { + if(q->inherited) + { + if(count) + { + _out << ", "; + } + _out << '$' << q->fixedName; + ++count; + } + } + _out << ");"; + } + { + for(MemberInfoList::iterator q = allMembers.begin(); q != allMembers.end(); ++q) + { + if(!q->inherited) + { + writeAssign(*q); + } + } + } + _out << eb; + + if(!ops.empty()) + { + _out << sp; + for(oli = ops.begin(); oli != ops.end(); ++oli) + { + _out << nl << "abstract public function " << fixIdent((*oli)->name()) << '('; + ParamDeclList params = (*oli)->parameters(); + for(ParamDeclList::iterator q = params.begin(); q != params.end(); ++q) + { + if(q != params.begin()) + { + _out << ", "; + } + _out << '$' << fixIdent((*q)->name()); + } + _out << ");"; + } + } + + if(!p->isLocal()) + { + // + // ice_staticId + // + _out << sp << nl << "public static function ice_staticId()"; + _out << sb; + _out << nl << "return '" << scoped << "';"; + _out << eb; + } + + // + // __toString + // + _out << sp << nl << "public function __toString()"; + _out << sb; + _out << nl << "global " << type << ';'; + _out << nl << "return IcePHP_stringify($this, " << type << ");"; + _out << eb; + + if(!members.empty()) + { + _out << sp; + bool isProtected = p->hasMetaData("protected"); + for(DataMemberList::iterator q = members.begin(); q != members.end(); ++q) + { + _out << nl; + if(isProtected || (*q)->hasMetaData("protected")) + { + _out << "protected "; + } + else + { + _out << "public "; + } + _out << "$" << fixIdent((*q)->name()) << ";"; + } + } + + _out << eb; // End of class. + } + + // + // Define the proxy class. + // + if(!p->isLocal()) + { + _out << sp << nl << "class " << prxName << "Helper"; + _out << sb; + + _out << sp << nl << "public static function checkedCast($proxy, $facetOrCtx=null, $ctx=null)"; + _out << sb; + _out << nl << "return $proxy->ice_checkedCast('" << scoped << "', $facetOrCtx, $ctx);"; + _out << eb; + + _out << sp << nl << "public static function uncheckedCast($proxy, $facet=null)"; + _out << sb; + _out << nl << "return $proxy->ice_uncheckedCast('" << scoped << "', $facet);"; + _out << eb; + + _out << eb; + } + + 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 << type << " = IcePHP_declareClass('" << scoped << "');"; + } + + // + // Emit the type information. + // + _out << sp << nl << type << " = IcePHP_defineClass('" << scoped << "', '" << escapeName(abs) << "', " + << (isAbstract ? "true" : "false") << ", "; + if(!base) + { + _out << "$Ice__t_Object"; + } + else + { + _out << getTypeVar(base); + } + _out << ", "; + // + // Interfaces + // + if(!bases.empty()) + { + _out << "array("; + for(ClassList::const_iterator q = bases.begin(); q != bases.end(); ++q) + { + if(q != bases.begin()) + { + _out << ", "; + } + _out << getTypeVar(*q); + } + _out << ')'; + } + else + { + _out << "null"; + } + _out << ", "; + // + // 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. + // + if(!members.empty()) + { + _out << "array("; + for(DataMemberList::iterator q = members.begin(); q != members.end(); ++q) + { + if(q != members.begin()) + { + _out << ',' << nl; + } + _out.inc(); + _out << nl << "array('" << fixIdent((*q)->name()) << "', "; + writeType((*q)->type()); + _out << ')'; + _out.dec(); + } + _out << ')'; + } + else + { + _out << "null"; + } + _out << ");"; + + if(!p->isLocal()) + { + _out << sp << nl << prxType << " = IcePHP_defineProxy(" << type << ");"; + + // + // Define each operation. The arguments to IcePHP_defineOperation are: + // + // $ClassType, 'opName', Mode, SendMode, (InParams), (OutParams), ReturnType, (Exceptions) + // + // where InParams and OutParams are arrays of type descriptions, and Exceptions + // is an array of exception type ids. + // + if(!ops.empty()) + { + _out << sp; + for(oli = ops.begin(); oli != ops.end(); ++oli) + { + ParamDeclList params = (*oli)->parameters(); + ParamDeclList::iterator t; + int count; + + _out << nl << "IcePHP_defineOperation(" << type << ", '" << (*oli)->name() << "', " + << getOperationMode((*oli)->mode(), _ns) << ", " << getOperationMode((*oli)->sendMode(), _ns) + << ", "; + for(t = params.begin(), count = 0; t != params.end(); ++t) + { + if(!(*t)->isOutParam()) + { + if(count == 0) + { + _out << "array("; + } + else if(count > 0) + { + _out << ", "; + } + writeType((*t)->type()); + ++count; + } + } + if(count > 0) + { + _out << ')'; + } + else + { + _out << "null"; + } + _out << ", "; + for(t = params.begin(), count = 0; t != params.end(); ++t) + { + if((*t)->isOutParam()) + { + if(count == 0) + { + _out << "array("; + } + else if(count > 0) + { + _out << ", "; + } + writeType((*t)->type()); + ++count; + } + } + if(count > 0) + { + _out << ')'; + } + else + { + _out << "null"; + } + _out << ", "; + TypePtr returnType = (*oli)->returnType(); + if(returnType) + { + writeType(returnType); + } + else + { + _out << "null"; + } + _out << ", "; + ExceptionList exceptions = (*oli)->throws(); + if(!exceptions.empty()) + { + _out << "array("; + for(ExceptionList::iterator u = exceptions.begin(); u != exceptions.end(); ++u) + { + if(u != exceptions.begin()) + { + _out << ", "; + } + _out << getTypeVar(*u); + } + _out << ')'; + } + else + { + _out << "null"; + } + _out << ");"; + } + } + } + + _out << eb; + + endNamespace(); + + if(_classHistory.count(scoped) == 0) + { + _classHistory.insert(scoped); // Avoid redundant declarations. + } + + return false; +} + +bool +CodeVisitor::visitExceptionStart(const ExceptionPtr& p) +{ + string scoped = p->scoped(); + string name = getName(p); + string type = getTypeVar(p); + string abs = getAbsolute(p, _ns); + + startNamespace(p); + + _out << sp << nl << "if(!class_exists('" << escapeName(abs) << "'))"; + _out << sb; + _out << nl << "class " << name << " extends "; + ExceptionPtr base = p->base(); + string baseName; + if(base) + { + baseName = getAbsolute(base, _ns); + _out << baseName; + } + else if(p->isLocal()) + { + _out << scopedToName("::Ice::LocalException", _ns); + } + else + { + _out << scopedToName("::Ice::UserException", _ns); + } + _out << sb; + + DataMemberList members = p->dataMembers(); + DataMemberList::iterator dmli; + + // + // __construct + // + _out << nl << "public function __construct("; + MemberInfoList allMembers; + collectExceptionMembers(p, allMembers, false); + if(!allMembers.empty()) + { + for(MemberInfoList::iterator q = allMembers.begin(); q != allMembers.end(); ++q) + { + if(q != allMembers.begin()) + { + _out << ", "; + } + _out << '$' << q->fixedName << '='; + writeDefaultValue(q->type); + } + } + _out << ")"; + _out << sb; + if(base) + { + _out << nl << "parent::__construct("; + int count = 0; + for(MemberInfoList::iterator q = allMembers.begin(); q != allMembers.end(); ++q) + { + if(q->inherited) + { + if(count) + { + _out << ", "; + } + _out << '$' << q->fixedName; + ++count; + } + } + _out << ");"; + } + for(MemberInfoList::iterator q = allMembers.begin(); q != allMembers.end(); ++q) + { + if(!q->inherited) + { + writeAssign(*q); + } + } + _out << eb; + + // + // ice_name + // + _out << sp << nl << "public function ice_name()"; + _out << sb; + _out << nl << "return '" << scoped.substr(2) << "';"; + _out << eb; + + // + // __toString + // + _out << sp << nl << "public function __toString()"; + _out << sb; + _out << nl << "global " << type << ';'; + _out << nl << "return IcePHP_stringifyException($this, " << type << ");"; + _out << eb; + + if(!members.empty()) + { + _out << sp; + for(dmli = members.begin(); dmli != members.end(); ++dmli) + { + _out << nl << "public $" << fixIdent((*dmli)->name()) << ";"; + } + } + + _out << eb; + + // + // Emit the type information. + // + _out << sp << nl << type << " = IcePHP_defineException('" << scoped << "', '" << escapeName(abs) << "', "; + if(!base) + { + _out << "null"; + } + else + { + _out << getTypeVar(base); + } + _out << ", "; + // + // 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(!members.empty()) + { + _out << "array("; + for(dmli = members.begin(); dmli != members.end(); ++dmli) + { + if(dmli != members.begin()) + { + _out << ',' << nl; + } + _out.inc(); + _out << nl << "array('" << fixIdent((*dmli)->name()) << "', "; + writeType((*dmli)->type()); + _out << ')'; + _out.dec(); + } + _out << ')'; + } + else + { + _out << "null"; + } + _out << ");"; + + _out << eb; + + endNamespace(); + + return false; +} + +bool +CodeVisitor::visitStructStart(const StructPtr& p) +{ + string scoped = p->scoped(); + string name = getName(p); + string type = getTypeVar(p); + string abs = getAbsolute(p, _ns); + 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(); + } + } + + startNamespace(p); + + _out << sp << nl << "if(!class_exists('" << escapeName(abs) << "'))"; + _out << sb; + + _out << nl << "class " << name; + _out << sb; + _out << nl << "public function __construct("; + for(r = memberList.begin(); r != memberList.end(); ++r) + { + if(r != memberList.begin()) + { + _out << ", "; + } + _out << '$' << r->fixedName << '='; + writeDefaultValue(r->type); + } + _out << ")"; + _out << sb; + for(r = memberList.begin(); r != memberList.end(); ++r) + { + writeAssign(*r); + } + _out << eb; + + // + // __toString + // + _out << sp << nl << "public function __toString()"; + _out << sb; + _out << nl << "global " << type << ';'; + _out << nl << "return IcePHP_stringify($this, " << type << ");"; + _out << eb; + + if(!memberList.empty()) + { + _out << sp; + for(r = memberList.begin(); r != memberList.end(); ++r) + { + _out << nl << "public $" << r->fixedName << ';'; + } + } + + _out << eb; + + // + // Emit the type information. + // + _out << sp << nl << type << " = IcePHP_defineStruct('" << scoped << "', '" << escapeName(abs) << "', array("; + // + // 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(r = memberList.begin(); r != memberList.end(); ++r) + { + if(r != memberList.begin()) + { + _out << ", "; + } + _out.inc(); + _out << nl << "array('" << r->fixedName << "', "; + writeType(r->type); + _out << ')'; + _out.dec(); + } + _out << "));"; + + _out << eb; + + endNamespace(); + + return false; +} + +void +CodeVisitor::visitSequence(const SequencePtr& p) +{ + string type = getTypeVar(p); + TypePtr content = p->type(); + + startNamespace(p); + + // + // Emit the type information. + // + string scoped = p->scoped(); + _out << sp << nl << "if(!isset(" << type << "))"; + _out << sb; + _out << nl << type << " = IcePHP_defineSequence('" << scoped << "', "; + writeType(content); + _out << ", "; + if(content->isVariableLength()) + { + _out << "true"; + } + else + { + _out << "false"; + } + _out << ", " << content->minWireSize() << ");"; + _out << eb; + + endNamespace(); +} + +void +CodeVisitor::visitDictionary(const DictionaryPtr& p) +{ + string type = getTypeVar(p); + + startNamespace(p); + + // + // Emit the type information. + // + string scoped = p->scoped(); + _out << sp << nl << "if(!isset(" << type << "))"; + _out << sb; + _out << nl << type << " = IcePHP_defineDictionary('" << scoped << "', "; + writeType(p->keyType()); + _out << ", "; + writeType(p->valueType()); + _out << ");"; + _out << eb; + + endNamespace(); +} + +void +CodeVisitor::visitEnum(const EnumPtr& p) +{ + string scoped = p->scoped(); + string name = getName(p); + string type = getTypeVar(p); + string abs = getAbsolute(p, _ns); + EnumeratorList enums = p->getEnumerators(); + EnumeratorList::iterator q; + long i; + + startNamespace(p); + + _out << sp << nl << "if(!class_exists('" << escapeName(abs) << "'))"; + _out << sb; + _out << nl << "class " << name; + _out << sb; + + for(q = enums.begin(), i = 0; q != enums.end(); ++q, ++i) + { + string fixedEnum = fixIdent((*q)->name()); + ostringstream idx; + idx << i; + _out << nl << "const " << fixedEnum << " = " << idx.str() << ';'; + } + + _out << eb; + + // + // Emit the type information. + // + _out << sp << nl << type << " = IcePHP_defineEnum('" << scoped << "', array("; + for(q = enums.begin(); q != enums.end(); ++q) + { + if(q != enums.begin()) + { + _out << ", "; + } + _out << "'" << (*q)->name() << "'"; + } + _out << "));"; + + _out << eb; + + endNamespace(); +} + +void +CodeVisitor::visitConst(const ConstPtr& p) +{ + string name = getName(p); + string type = getTypeVar(p); + string abs = getAbsolute(p, _ns); + string value = p->value(); + Slice::TypePtr valueType = p->type(); + + startNamespace(p); + + _out << sp << nl << "if(!defined('" << escapeName(abs) << "'))"; + _out << sb; + _out << sp << nl << "define('" << name << "', "; + + Slice::BuiltinPtr b = Slice::BuiltinPtr::dynamicCast(valueType); + Slice::EnumPtr en = Slice::EnumPtr::dynamicCast(valueType); + if(b) + { + switch(b->kind()) + { + case Slice::Builtin::KindBool: + 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; + IceUtilInternal::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<char> 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 '\\': + { + _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<unsigned>(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::size_type colon = value.rfind(':'); + if(colon != string::npos) + { + value = value.substr(colon + 1); + } + Slice::EnumeratorList l = en->getEnumerators(); + Slice::EnumeratorList::iterator q; + for(q = l.begin(); q != l.end(); ++q) + { + if((*q)->name() == value) + { + _out << getAbsolute(en, _ns) << "::" << fixIdent(value); + break; + } + } + } + else + { + assert(false); // Unknown const type. + } + + _out << ");"; + _out << eb; + + endNamespace(); +} + +void +CodeVisitor::startNamespace(const ContainedPtr& cont) +{ + if(_ns) + { + string scope = cont->scope(); + scope = scope.substr(2); // Removing leading '::' + scope = scope.substr(0, scope.length() - 2); // Removing trailing '::' + _out << sp << nl << "namespace " << scopedToName(scope, true); + _out << sb; + } +} + +void +CodeVisitor::endNamespace() +{ + if(_ns) + { + _out << eb; + } +} + +string +CodeVisitor::getTypeVar(const ContainedPtr& p, const string& suffix) +{ + return "$" + getAbsolute(p, false, "_t_", suffix); +} + +string +CodeVisitor::getName(const ContainedPtr& p, const string& suffix) +{ + if(_ns) + { + return fixIdent(p->name() + suffix); + } + else + { + return getAbsolute(p, false, "", suffix); + } +} + +void +CodeVisitor::writeType(const TypePtr& p) +{ + BuiltinPtr builtin = BuiltinPtr::dynamicCast(p); + if(builtin) + { + switch(builtin->kind()) + { + case Builtin::KindBool: + { + _out << "$IcePHP__t_bool"; + break; + } + case Builtin::KindByte: + { + _out << "$IcePHP__t_byte"; + break; + } + case Builtin::KindShort: + { + _out << "$IcePHP__t_short"; + break; + } + case Builtin::KindInt: + { + _out << "$IcePHP__t_int"; + break; + } + case Builtin::KindLong: + { + _out << "$IcePHP__t_long"; + break; + } + case Builtin::KindFloat: + { + _out << "$IcePHP__t_float"; + break; + } + case Builtin::KindDouble: + { + _out << "$IcePHP__t_double"; + break; + } + case Builtin::KindString: + { + _out << "$IcePHP__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 << getTypeVar(prx->_class(), "Prx"); + return; + } + + ContainedPtr cont = ContainedPtr::dynamicCast(p); + assert(cont); + _out << getTypeVar(cont); +} + +void +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 << "null"; + break; + } + } + return; + } + + EnumPtr en = EnumPtr::dynamicCast(p); + if(en) + { + EnumeratorList enums = en->getEnumerators(); + _out << getAbsolute(en, _ns) << "::" << fixIdent(enums.front()->name()); + return; + } + + // + // PHP does not allow the following construct: + // + // function foo($theStruct=new MyStructType) + // + // Instead we use null as the default value and allocate an instance in + // the constructor. + // + StructPtr st = StructPtr::dynamicCast(p); + if(st) + { + _out << "null"; + return; + } + + _out << "null"; +} + +void +CodeVisitor::writeAssign(const MemberInfo& info) +{ + StructPtr st = StructPtr::dynamicCast(info.type); + if(st) + { + _out << nl << "$this->" << info.fixedName << " = is_null($" << info.fixedName << ") ? new " + << getAbsolute(st, _ns) << " : $" << info.fixedName << ';'; + } + else + { + _out << nl << "$this->" << info.fixedName << " = $" << info.fixedName << ';'; + } +} + +string +CodeVisitor::getOperationMode(Slice::Operation::Mode mode, bool ns) +{ + ostringstream ostr; + ostr << static_cast<int>(mode); + return ostr.str(); +} + +void +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 +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 void +generate(const UnitPtr& un, bool all, bool checksum, bool ns, const vector<string>& includePaths, Output& out) +{ + if(!all) + { + vector<string> paths = includePaths; + for(vector<string>::iterator p = paths.begin(); p != paths.end(); ++p) + { + *p = fullPath(*p); + } + + StringList includes = un->includeFiles(); + if(!includes.empty()) + { + if(ns) + { + out << sp; + out << nl << "namespace"; + out << sb; + } + for(StringList::const_iterator q = includes.begin(); q != includes.end(); ++q) + { + string file = changeInclude(*q, paths); + out << nl << "require '" << file << ".php';"; + } + if(ns) + { + out << eb; + } + } + } + + CodeVisitor codeVisitor(out, ns); + un->visit(&codeVisitor, false); + + if(checksum) + { + ChecksumMap checksums = createChecksums(un); + if(!checksums.empty()) + { + out << sp; + if(ns) + { + out << "namespace"; // Global namespace. + out << sb; + } + 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<unsigned char>::const_iterator q = p->second.begin(); q != p->second.end(); ++q) + { + str << (int)(*q); + } + out << str.str() << "\";"; + } + if(ns) + { + out << eb; + } + } + } + + out << nl; // Trailing newline. +} + +static void +printHeader(IceUtilInternal::Output& out) +{ + static const char* header = +"// **********************************************************************\n" +"//\n" +"// Copyright (c) 2003-2009 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; +} + +static IceUtil::StaticMutex _mutex = ICE_STATIC_MUTEX_INITIALIZER; +static bool _interrupted = false; + +void +interruptedCallback(int signal) +{ + IceUtil::StaticMutex::Lock lock(_mutex); + + _interrupted = true; +} + +void +usage(const char* n) +{ + cerr << "Usage: " << n << " [options] slice-files...\n"; + cerr << + "Options:\n" + "-h, --help Show this message.\n" + "-v, --version Display the Ice version.\n" + "-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" + "-d, --debug Print debug messages.\n" + "--ice Permit `Ice' prefix (for building Ice source code only)\n" + "--all Generate code for Slice definitions in included files.\n" + "--checksum Generate checksums for Slice definitions.\n" + "-n, --namespace Use PHP namespaces (requires PHP 5.3.0 or later).\n" + ; +} + +int +main(int argc, char* argv[]) +{ + IceUtilInternal::Options opts; + opts.addOpt("h", "help"); + opts.addOpt("v", "version"); + opts.addOpt("D", "", IceUtilInternal::Options::NeedArg, "", IceUtilInternal::Options::Repeat); + opts.addOpt("U", "", IceUtilInternal::Options::NeedArg, "", IceUtilInternal::Options::Repeat); + opts.addOpt("I", "", IceUtilInternal::Options::NeedArg, "", IceUtilInternal::Options::Repeat); + opts.addOpt("E"); + opts.addOpt("", "output-dir", IceUtilInternal::Options::NeedArg); + opts.addOpt("d", "debug"); + opts.addOpt("", "ice"); + opts.addOpt("", "all"); + opts.addOpt("", "checksum"); + opts.addOpt("n", "namespace"); + + vector<string> args; + try + { +#if defined(__BCPLUSPLUS__) && (__BCPLUSPLUS__ >= 0x0600) + IceUtil::DummyBCC dummy; +#endif + args = opts.parse(argc, (const char**)argv); + } + catch(const IceUtilInternal::BadOptException& e) + { + cerr << argv[0] << ": error: " << e.reason << endl; + usage(argv[0]); + return EXIT_FAILURE; + } + + if(opts.isSet("help")) + { + usage(argv[0]); + return EXIT_SUCCESS; + } + + if(opts.isSet("version")) + { + cerr << ICE_STRING_VERSION << endl; + return EXIT_SUCCESS; + } + + vector<string> cppArgs; + vector<string> optargs = opts.argVec("D"); + vector<string>::const_iterator i; + for(i = optargs.begin(); i != optargs.end(); ++i) + { + cppArgs.push_back("-D" + *i); + } + + optargs = opts.argVec("U"); + for(i = optargs.begin(); i != optargs.end(); ++i) + { + cppArgs.push_back("-U" + *i); + } + + vector<string> includePaths = opts.argVec("I"); + for(i = includePaths.begin(); i != includePaths.end(); ++i) + { + cppArgs.push_back("-I" + Preprocessor::normalizeIncludePath(*i)); + } + + bool preprocess = opts.isSet("E"); + + string output = opts.optArg("output-dir"); + + bool debug = opts.isSet("debug"); + + bool ice = opts.isSet("ice"); + + bool all = opts.isSet("all"); + + bool checksum = opts.isSet("checksum"); + + bool ns = opts.isSet("namespace"); + + if(args.empty()) + { + getErrorStream() << argv[0] << ": error: no input file" << endl; + usage(argv[0]); + return EXIT_FAILURE; + } + + int status = EXIT_SUCCESS; + + IceUtil::CtrlCHandler ctrlCHandler; + ctrlCHandler.setCallback(interruptedCallback); + + for(i = args.begin(); i != args.end(); ++i) + { + 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<int>(sizeof(buf)), cppHandle) != NULL) + { + if(fputs(buf, stdout) == EOF) + { + return EXIT_FAILURE; + } + } + if(!icecpp.close()) + { + return EXIT_FAILURE; + } + } + else + { + UnitPtr u = Unit::createUnit(false, all, ice); + int parseStatus = u->parse(*i, cppHandle, debug); + + if(!icecpp.close()) + { + u->destroy(); + return EXIT_FAILURE; + } + + if(parseStatus == EXIT_FAILURE) + { + status = EXIT_FAILURE; + } + else + { + string base = icecpp.getBaseName(); + string::size_type pos = base.find_last_of("/\\"); + if(pos != string::npos) + { + base.erase(0, pos + 1); + } + + string file = base + ".php"; + if(!output.empty()) + { + file = output + '/' + file; + } + + try + { + IceUtilInternal::Output out; + out.open(file.c_str()); + if(!out) + { + ostringstream os; + os << "cannot open`" << file << "': " << strerror(errno); + throw FileException(__FILE__, __LINE__, os.str()); + } + FileTracker::instance()->addFile(file); + + out << "<?php\n"; + printHeader(out); + out << "\n// Generated from file `" << base << ".ice'\n"; + + // + // Generate the PHP mapping. + // + generate(u, all, checksum, ns, includePaths, out); + + out << "?>\n"; + out.close(); + } + catch(const Slice::FileException& ex) + { + // If a file could not be created, then cleanup any + // created files. + FileTracker::instance()->cleanup(); + u->destroy(); + getErrorStream() << argv[0] << ": error: " << ex.reason() << endl; + return EXIT_FAILURE; + } + catch(const string& err) + { + FileTracker::instance()->cleanup(); + getErrorStream() << argv[0] << ": error: " << err << endl; + status = EXIT_FAILURE; + } + } + + u->destroy(); + } + + { + IceUtil::StaticMutex::Lock lock(_mutex); + + if(_interrupted) + { + FileTracker::instance()->cleanup(); + return EXIT_FAILURE; + } + } + } + + return status; +} diff --git a/cpp/src/slice2php/Makefile b/cpp/src/slice2php/Makefile new file mode 100644 index 00000000000..5c7d5cdffb5 --- /dev/null +++ b/cpp/src/slice2php/Makefile @@ -0,0 +1,31 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2009 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/slice2php + +TARGETS = $(NAME) + +OBJS = Main.o + +SRCS = $(OBJS:.o=.cpp) + +include $(top_srcdir)/config/Make.rules + +CPPFLAGS := -I. $(CPPFLAGS) + +$(NAME): $(OBJS) + rm -f $@ + $(CXX) $(LDFLAGS) -o $@ $(OBJS) -lSlice $(BASELIBS) $(MCPP_RPATH_LINK) + +install:: all + $(call installprogram,$(NAME),$(install_bindir)) + +include .depend diff --git a/cpp/src/slice2php/Makefile.mak b/cpp/src/slice2php/Makefile.mak new file mode 100644 index 00000000000..3f1d6bf9be1 --- /dev/null +++ b/cpp/src/slice2php/Makefile.mak @@ -0,0 +1,60 @@ +# **********************************************************************
+#
+# Copyright (c) 2003-2009 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\slice2php.exe
+
+TARGETS = $(NAME)
+
+OBJS = Main.obj
+
+SRCS = $(OBJS:.obj=.cpp)
+
+!include $(top_srcdir)/config/Make.rules.mak
+
+CPPFLAGS = -I. $(CPPFLAGS) -DWIN32_LEAN_AND_MEAN
+
+!if "$(GENERATE_PDB)" == "yes"
+PDBFLAGS = /pdb:$(NAME:.exe=.pdb)
+!endif
+
+!if "$(BCPLUSPLUS)" == "yes"
+RES_FILE = ,, Slice2PHP.res
+!else
+RES_FILE = Slice2PHP.res
+!endif
+
+$(NAME): $(OBJS) Slice2PHP.res
+ $(LINK) $(LD_EXEFLAGS) $(PDBFLAGS) $(OBJS) $(SETARGV) $(PREOUT)$@ $(PRELIBS)slice$(LIBSUFFIX).lib \
+ $(BASELIBS) $(RES_FILE)
+ @if exist $@.manifest echo ^ ^ ^ Embedding manifest using $(MT) && \
+ $(MT) -nologo -manifest $@.manifest -outputresource:$@;#1 && del /q $@.manifest
+
+clean::
+ del /q $(NAME:.exe=.*)
+ del /q Slice2PHP.res
+
+install:: all
+ copy $(NAME) $(install_bindir)
+
+
+!if "$(BCPLUSPLUS)" == "yes" && "$(OPTIMIZE)" != "yes"
+
+install:: all
+ copy $(NAME:.exe=.tds) $(install_bindir)
+
+!elseif "$(GENERATE_PDB)" == "yes"
+
+install:: all
+ copy $(NAME:.exe=.pdb) $(install_bindir)
+
+!endif
+
+!include .depend
diff --git a/cpp/src/slice2php/Slice2PHP.rc b/cpp/src/slice2php/Slice2PHP.rc new file mode 100644 index 00000000000..31db7dfc054 --- /dev/null +++ b/cpp/src/slice2php/Slice2PHP.rc @@ -0,0 +1,34 @@ +#include "winver.h"
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 3,3,1,0
+ PRODUCTVERSION 3,3,1,0
+ FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
+#ifdef _DEBUG
+ FILEFLAGS VS_FF_DEBUG
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE VFT_APP
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904e4"
+ BEGIN
+ VALUE "CompanyName", "ZeroC, Inc.\0"
+ VALUE "FileDescription", "Slice To Python Translator\0"
+ VALUE "FileVersion", "3.3.1\0"
+ VALUE "InternalName", "slice2py\0"
+ VALUE "LegalCopyright", "Copyright (c) 2003-2009 ZeroC, Inc. All rights reserved.\0"
+ VALUE "OriginalFilename", "slice2py.exe\0"
+ VALUE "ProductName", "Ice\0"
+ VALUE "ProductVersion", "3.3.1\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1252
+ END
+END
|