diff options
Diffstat (limited to 'php/src/IcePHP/Profile.cpp')
-rw-r--r-- | php/src/IcePHP/Profile.cpp | 1617 |
1 files changed, 0 insertions, 1617 deletions
diff --git a/php/src/IcePHP/Profile.cpp b/php/src/IcePHP/Profile.cpp deleted file mode 100644 index 3e79ae26d8f..00000000000 --- a/php/src/IcePHP/Profile.cpp +++ /dev/null @@ -1,1617 +0,0 @@ -// ********************************************************************** -// -// 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 <Profile.h> -#include <Util.h> - -#include <Slice/Preprocessor.h> -#include <IceUtil/Options.h> -#include <IceUtil/InputUtil.h> -#include <fstream> - -using namespace std; -using namespace IcePHP; - -ZEND_EXTERN_MODULE_GLOBALS(ice) - -// -// The name we give to the default profile. -// -static const char* _defaultProfileName = "__default__"; - -// -// The table of profiles. -// -static map<string, Profile*> _profiles; - -namespace IcePHP -{ - -// -// CodeVisitor descends the Slice parse tree and generates PHP code for certain Slice types. -// -class CodeVisitor : public Slice::ParserVisitor -{ -public: - CodeVisitor(ostream&, Profile::ClassMap&, bool TSRMLS_DC); - - virtual void visitClassDecl(const Slice::ClassDeclPtr&); - virtual bool visitClassDefStart(const Slice::ClassDefPtr&); - virtual void visitClassDefEnd(const Slice::ClassDefPtr&); - virtual bool visitExceptionStart(const Slice::ExceptionPtr&); - virtual void visitExceptionEnd(const Slice::ExceptionPtr&); - virtual bool visitStructStart(const Slice::StructPtr&); - virtual void visitStructEnd(const Slice::StructPtr&); - virtual void visitOperation(const Slice::OperationPtr&); - virtual void visitDataMember(const Slice::DataMemberPtr&); - virtual void visitDictionary(const Slice::DictionaryPtr&); - virtual void visitEnum(const Slice::EnumPtr&); - virtual void visitConst(const Slice::ConstPtr&); - -private: - - string getTypeHint(const Slice::TypePtr&); - string getDefaultValue(const Slice::TypePtr&); - void writeConstructorParameter(const Slice::DataMemberPtr&); - void writeConstructorAssignment(const Slice::DataMemberPtr&); - - ostream& _out; - Profile::ClassMap& _classes; - bool _suppressWarnings; -#ifdef ZTS - TSRMLS_D; -#endif -}; - -} // End of namespace IcePHP - -// -// This PHP code defines the core types we need. We supply a few of the common -// local exception subclasses; all other local exceptions are mapped to -// UnknownLocalException. We don't define Ice::Identity here because it's -// possible the user will have included its definition (see createProfile). -// -// NOTE: If a local exception is added or removed here, then changes are also -// necessary to IcePHP::throwException. -// -static const char* _coreTypes = - "abstract class Ice_Exception extends Exception\n" - "{\n" - " function __construct($message = '')\n" - " {\n" - " Exception::__construct($message);\n" - " }\n" - "}\n" - "\n" - "abstract class Ice_LocalException extends Ice_Exception\n" - "{\n" - " function __construct($message = '')\n" - " {\n" - " Ice_Exception::__construct($message);\n" - " }\n" - "}\n" - "\n" - "class Ice_TwowayOnlyException extends Ice_LocalException\n" - "{\n" - " function __construct($message = '')\n" - " {\n" - " Ice_LocalException::__construct($message);\n" - " }\n" - "\n" - " function __toString()\n" - " {\n" - " return get_class($this) . \"\\n\" .\n" - " \" operation: \" . $this->operation;\n" - " }\n" - "\n" - " public $operation;\n" - "}\n" - "\n" - "class Ice_UnknownException extends Ice_LocalException\n" - "{\n" - " function __construct($message = '')\n" - " {\n" - " Ice_LocalException::__construct($message);\n" - " }\n" - "\n" - " function __toString()\n" - " {\n" - " return get_class($this) . \"\\n\" .\n" - " $this->unknown;\n" - " }\n" - "\n" - " public $unknown;\n" - "}\n" - "\n" - "class Ice_UnknownLocalException extends Ice_UnknownException\n" - "{\n" - " function __construct($message = '')\n" - " {\n" - " Ice_UnknownException::__construct($message);\n" - " }\n" - "}\n" - "\n" - "class Ice_UnknownUserException extends Ice_UnknownException\n" - "{\n" - " function __construct($message = '')\n" - " {\n" - " Ice_UnknownException::__construct($message);\n" - " }\n" - "}\n" - "\n" - "class Ice_RequestFailedException extends Ice_LocalException\n" - "{\n" - " function __construct($message = '')\n" - " {\n" - " Ice_LocalException::__construct($message);\n" - " }\n" - "\n" - " function __toString()\n" - " {\n" - " return get_class($this) . \"\\n\" .\n" - " \" identity: \" . Ice_identityToString($this->id) . \"\\n\" .\n" - " \" facet: \" . $this->facet . \"\\n\" .\n" - " \" operation: \" . $this->operation;\n" - " }\n" - "\n" - " public $id;\n" - " public $facet;\n" - " public $operation;\n" - "}\n" - "\n" - "class Ice_ObjectNotExistException extends Ice_RequestFailedException\n" - "{\n" - " function __construct($message = '')\n" - " {\n" - " Ice_RequestFailedException::__construct($message);\n" - " }\n" - "}\n" - "\n" - "class Ice_FacetNotExistException extends Ice_RequestFailedException\n" - "{\n" - " function __construct($message = '')\n" - " {\n" - " Ice_RequestFailedException::__construct($message);\n" - " }\n" - "}\n" - "\n" - "class Ice_OperationNotExistException extends Ice_RequestFailedException\n" - "{\n" - " function __construct($message = '')\n" - " {\n" - " Ice_RequestFailedException::__construct($message);\n" - " }\n" - "}\n" - "\n" - "class Ice_ProtocolException extends Ice_LocalException\n" - "{\n" - " function __construct($message = '')\n" - " {\n" - " Ice_LocalException::__construct($message);\n" - " }\n" - "\n" - " function __toString()\n" - " {\n" - " return get_class($this) . \"\\n\" .\n" - " \" reason: \" . $this->reason;\n" - " }\n" - "\n" - " public $reason;\n" - "}\n" - "\n" - "class Ice_MarshalException extends Ice_ProtocolException\n" - "{\n" - " function __construct($message = '')\n" - " {\n" - " Ice_ProtocolException::__construct($message);\n" - " }\n" - "}\n" - "\n" - "class Ice_NoObjectFactoryException extends Ice_MarshalException\n" - "{\n" - " function __construct($message = '')\n" - " {\n" - " Ice_MarshalException::__construct($message);\n" - " }\n" - "\n" - " function __toString()\n" - " {\n" - " return get_class($this) . \"\\n\" .\n" - " \" reason: \" . $this->reason . \"\\n\" .\n" - " \" type: \" . $this->type;\n" - " }\n" - "\n" - " public $type;\n" - "}\n" - "\n" - "class Ice_UnexpectedObjectException extends Ice_MarshalException\n" - "{\n" - " function __construct($message = '')\n" - " {\n" - " Ice_MarshalException::__construct($message);\n" - " }\n" - "\n" - " function __toString()\n" - " {\n" - " return get_class($this) . \"\\n\" .\n" - " \" reason: \" . $this->reason . \"\\n\" .\n" - " \" type: \" . $this->type . \"\\n\" .\n" - " \" expectedType: \" . $this->expectedType;\n" - " }\n" - "\n" - " public $type;\n" - "}\n" - "\n" - "class Ice_ProfileAlreadyLoadedException extends Ice_LocalException\n" - "{\n" - " function __construct($message = '')\n" - " {\n" - " Ice_LocalException::__construct($message);\n" - " }\n" - "}\n" - "\n" - "class Ice_ProfileNotFoundException extends Ice_LocalException\n" - "{\n" - " function __construct($message = '')\n" - " {\n" - " Ice_LocalException::__construct($message);\n" - " }\n" - "\n" - " function __toString()\n" - " {\n" - " return get_class($this) . \"\\n\" .\n" - " \" name: \" . $this->name;\n" - " }\n" - "\n" - " public $name;\n" - "}\n" - "\n" - "abstract class Ice_UserException extends Ice_Exception\n" - "{\n" - " function __construct($message = '')\n" - " {\n" - " Ice_Exception::__construct($message);\n" - " }\n" - "}\n" - "\n" - "interface Ice_LocalObject\n" - "{\n" - "}\n" - "\n" - "class Ice_LocalObjectImpl implements Ice_LocalObject\n" - "{\n" - "}\n" - "\n" - "interface Ice_Object\n" - "{\n" - " function ice_preMarshal();\n" - " function ice_postUnmarshal();\n" - "}\n" - "\n" - "abstract class Ice_ObjectImpl implements Ice_Object\n" - "{\n" - " function ice_preMarshal()\n" - " {\n" - " }\n" - "\n" - " function ice_postUnmarshal()\n" - " {\n" - " }\n" - "}\n" - "\n" - "interface Ice_ObjectFactory\n" - "{\n" - " function create($id);\n" - " function destroy();\n" - "}\n" -; - -// -// Parse the Slice files that define the types and operations available to a PHP script. -// -static bool -parseSlice(const string& argStr, vector<Slice::UnitPtr>& units, bool& suppressWarnings TSRMLS_DC) -{ - vector<string> args; - try - { - args = IceUtilInternal::Options::split(argStr); - } - catch(const IceUtil::Exception& ex) - { - ostringstream ostr; - ex.ice_print(ostr); - string msg = ostr.str(); - php_error_docref(0 TSRMLS_CC, E_ERROR, "error occurred while parsing Slice options in `%s':\n%s", - argStr.c_str(), msg.c_str()); - return false; - } - - IceUtilInternal::Options opts; - 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("d", "debug"); - opts.addOpt("", "ice"); - opts.addOpt("w"); - - vector<string> files; - try - { - args.insert(args.begin(), ""); // dummy argv[0] - files = opts.parse(args); - if(files.empty() && !argStr.empty()) - { - php_error_docref(0 TSRMLS_CC, E_ERROR, "no Slice files specified in `%s'", argStr.c_str()); - return false; - } - } - catch(const IceUtil::Exception& ex) - { - ostringstream ostr; - ex.ice_print(ostr); - string msg = ostr.str(); - php_error_docref(0 TSRMLS_CC, E_ERROR, "error occurred while parsing Slice options in `%s':\n%s", - argStr.c_str(), msg.c_str()); - return false; - } - - vector<string> cppArgs; - bool debug = false; - bool ice = true; // This must be true so that we can create Ice::Identity when necessary. - if(opts.isSet("D")) - { - vector<string> optargs = opts.argVec("D"); - for(vector<string>::const_iterator i = optargs.begin(); i != optargs.end(); ++i) - { - cppArgs.push_back("-D" + *i); - } - } - if(opts.isSet("U")) - { - vector<string> optargs = opts.argVec("U"); - for(vector<string>::const_iterator i = optargs.begin(); i != optargs.end(); ++i) - { - cppArgs.push_back("-U" + *i); - } - } - if(opts.isSet("I")) - { - vector<string> optargs = opts.argVec("I"); - for(vector<string>::const_iterator i = optargs.begin(); i != optargs.end(); ++i) - { - cppArgs.push_back("-I" + *i); - } - } - debug = opts.isSet("d") || opts.isSet("debug"); - suppressWarnings = opts.isSet("w"); - - bool ignoreRedefs = false; - bool all = true; - - for(vector<string>::iterator p = files.begin(); p != files.end(); ++p) - { - Slice::UnitPtr unit = Slice::Unit::createUnit(ignoreRedefs, all, ice); - Slice::Preprocessor icecpp("icecpp", *p, cppArgs); - FILE* cppHandle = icecpp.preprocess(false); - - if(cppHandle == 0) - { - return false; - } - - int parseStatus = unit->parse(*p, cppHandle, debug); - - if(!icecpp.close()) - { - return false; - } - - if(parseStatus == EXIT_FAILURE) - { - return false; - } - - units.push_back(unit); - } - - return true; -} - -static bool -createProfile(const string& name, const string& config, const string& options, const string& slice TSRMLS_DC) -{ - map<string, Profile*>::iterator p = _profiles.find(name); - if(p != _profiles.end()) - { - php_error_docref(0 TSRMLS_CC, E_ERROR, "profile `%s' already exists", name.c_str()); - return false; - } - - Ice::PropertiesPtr properties = Ice::createProperties(); - - if(!config.empty()) - { - try - { - properties->load(config); - } - catch(const IceUtil::Exception& ex) - { - ostringstream ostr; - ex.ice_print(ostr); - php_error_docref(0 TSRMLS_CC, E_ERROR, "unable to load Ice configuration file %s:\n%s", config.c_str(), - ostr.str().c_str()); - return false; - } - } - - if(!options.empty()) - { - vector<string> args; - try - { - args = IceUtilInternal::Options::split(options); - } - catch(const IceUtil::Exception& ex) - { - ostringstream ostr; - ex.ice_print(ostr); - string msg = ostr.str(); - php_error_docref(0 TSRMLS_CC, E_ERROR, "error occurred while parsing the options `%s':\n%s", - options.c_str(), msg.c_str()); - return false; - } - properties->parseCommandLineOptions("", args); - } - - // - // We create a Unit for each Slice file. - // - vector<Slice::UnitPtr> units; - - // - // Even if the profile specifies no Slice files, we still need to obtain builtin - // types as well as create types such as Ice::Identity. - // - { - Slice::UnitPtr unit = Slice::Unit::createUnit(false, false, true); - - // - // Create the Slice definition for Ice::Identity if it doesn't exist. The PHP class will - // be created automatically by CodeVisitor. - // - string scoped = "::Ice::Identity"; - Slice::TypeList l = unit->lookupTypeNoBuiltin(scoped, false); - if(l.empty()) - { - Slice::ContainedList c = unit->lookupContained("Ice", false); - Slice::ModulePtr module; - if(c.empty()) - { - module = unit->createModule("Ice"); - } - else - { - module = Slice::ModulePtr::dynamicCast(c.front()); - if(!module) - { - php_error_docref(0 TSRMLS_CC, E_ERROR, - "the symbol `::Ice' is defined in Slice but is not a module"); - return false; - } - } - Slice::StructPtr identity = module->createStruct("Identity", false); - Slice::TypePtr str = unit->builtin(Slice::Builtin::KindString); - identity->createDataMember("category", str); - identity->createDataMember("name", str); - } - - // - // Create the Slice definition for Ice::EndpointSelectionType if it doesn't exist. The PHP class will - // be created automatically by CodeVisitor. - // - scoped = "::Ice::EndpointSelectionType"; - l = unit->lookupTypeNoBuiltin(scoped, false); - if(l.empty()) - { - Slice::ContainedList c = unit->lookupContained("Ice", false); - Slice::ModulePtr module; - if(c.empty()) - { - module = unit->createModule("Ice"); - } - else - { - module = Slice::ModulePtr::dynamicCast(c.front()); - if(!module) - { - php_error_docref(0 TSRMLS_CC, E_ERROR, - "the symbol `::Ice' is defined in Slice but is not a module"); - return false; - } - } - Slice::EnumPtr en = module->createEnum("EndpointSelectionType", false); - Slice::EnumeratorList el; - el.push_back(module->createEnumerator("Random")); - el.push_back(module->createEnumerator("Ordered")); - en->setEnumerators(el); - } - - units.push_back(unit); - } - - bool suppressWarnings = false; - if(!slice.empty() && !parseSlice(slice, units, suppressWarnings TSRMLS_CC)) - { - return false; - } - - // - // Descend the parse trees to generate PHP code. - // - ostringstream out; - Profile::ClassMap classes; - for(vector<Slice::UnitPtr>::const_iterator q = units.begin(); q != units.end(); ++ q) - { - CodeVisitor visitor(out, classes, suppressWarnings TSRMLS_CC); - (*q)->visit(&visitor, false); - } - - _profiles[name] = new Profile(name, units, out.str(), classes, properties); - - return true; -} - -bool -IcePHP::profileInit(TSRMLS_D) -{ - // - // The default profile is configured using ice.config, ice.options and ice.slice. Named profiles - // are contained in a separate INI file, whose name is defined by ice.profiles. - // - const char* config = INI_STR("ice.config"); - const char* options = INI_STR("ice.options"); - const char* profiles = INI_STR("ice.profiles"); - const char* slice = INI_STR("ice.slice"); - - if(!createProfile(_defaultProfileName, config, options, slice TSRMLS_CC)) - { - return false; - } - - if(strlen(profiles) > 0) - { - // - // The Zend engine doesn't export a function for loading an INI file, so we - // have to do it ourselves. The format is: - // - // [profile-name] - // ice.config = config-file - // ice.options = args - // ice.slice = slice-args - // - ifstream in(profiles); - if(!in) - { - php_error_docref(0 TSRMLS_CC, E_ERROR, "unable to open Ice profiles in %s", profiles); - return false; - } - - string currentName, currentConfig, currentOptions, currentSlice; - char line[1024]; - while(in.getline(line, 1024)) - { - const string delim = " \t\r\n"; - string s = line; - - string::size_type idx = s.find(';'); - if(idx != string::npos) - { - s.erase(idx); - } - - idx = s.find_last_not_of(delim); - if(idx != string::npos && idx + 1 < s.length()) - { - s.erase(idx + 1); - } - - string::size_type beg = s.find_first_not_of(delim); - if(beg == string::npos) - { - continue; - } - - if(s[beg] == '[') - { - beg++; - string::size_type end = s.find_first_of(" \t]", beg); - if(end == string::npos || s[s.length() - 1] != ']') - { - php_error_docref(0 TSRMLS_CC, E_ERROR, "invalid profile section in file %s:\n%s\n", profiles, - line); - return false; - } - - if(!currentName.empty()) - { - if(!createProfile(currentName, currentConfig, currentOptions, currentSlice TSRMLS_CC)) - { - return false; - } - currentConfig.clear(); - currentOptions.clear(); - currentSlice.clear(); - } - - currentName = s.substr(beg, end - beg); - } - else - { - string::size_type end = s.find_first_of(delim + "=", beg); - assert(end != string::npos); - - string key = s.substr(beg, end - beg); - - end = s.find('=', end); - if(end == string::npos) - { - php_error_docref(0 TSRMLS_CC, E_ERROR, "invalid profile entry in file %s:\n%s\n", profiles, - line); - return false; - } - ++end; - - string value; - beg = s.find_first_not_of(delim, end); - if(beg != string::npos) - { - end = s.length(); - value = s.substr(beg, end - beg); - } - - if(key == "config" || key == "ice.config") - { - currentConfig = value; - } - else if(key == "options" || key == "ice.options") - { - currentOptions = value; - } - else if(key == "slice" || key == "ice.slice") - { - currentSlice = value; - } - else - { - php_error_docref(0 TSRMLS_CC, E_ERROR, "unknown profile entry in file %s:\n%s\n", profiles, - line); - return false; - } - - if(currentName.empty()) - { - php_error_docref(0 TSRMLS_CC, E_ERROR, "no section for profile entry in file %s:\n%s\n", - profiles, line); - return false; - } - } - } - - if(!currentName.empty() && !createProfile(currentName, currentConfig, currentOptions, currentSlice TSRMLS_CC)) - { - return false; - } - } - - return true; -} - -bool -IcePHP::profileShutdown(TSRMLS_D) -{ - for(map<string, Profile*>::iterator p = _profiles.begin(); p != _profiles.end(); ++p) - { - p->second->destroy(TSRMLS_C); - delete p->second; - } - - _profiles.clear(); - - return true; -} - -IcePHP::Profile::Profile(const string& name, const vector<Slice::UnitPtr>& units, const string& code, - const ClassMap& classes, const Ice::PropertiesPtr& properties) : - _name(name), _units(units), _code(code), _classes(classes), _properties(properties) -{ -} - -string -IcePHP::Profile::name() const -{ - return _name; -} - -string -IcePHP::Profile::code() const -{ - return _code; -} - -const IcePHP::Profile::ClassMap& -IcePHP::Profile::classes() const -{ - return _classes; -} - -Ice::PropertiesPtr -IcePHP::Profile::properties() const -{ - return _properties; -} - -Slice::TypePtr -IcePHP::Profile::lookupType(const string& id) const -{ - for(vector<Slice::UnitPtr>::const_iterator p = _units.begin(); p != _units.end(); ++p) - { - Slice::TypeList l = (*p)->lookupType(id, false); - if(!l.empty()) - { - return l.front(); - } - } - - return 0; -} - -Slice::ExceptionPtr -IcePHP::Profile::lookupException(const string& id) const -{ - for(vector<Slice::UnitPtr>::const_iterator p = _units.begin(); p != _units.end(); ++p) - { - Slice::ExceptionPtr ex = (*p)->lookupException(id, false); - if(ex) - { - return ex; - } - } - - return 0; -} - -void -IcePHP::Profile::destroy(TSRMLS_D) -{ - for(vector<Slice::UnitPtr>::iterator p = _units.begin(); p != _units.end(); ++p) - { - try - { - (*p)->destroy(); - } - catch(const IceUtil::Exception& ex) - { - ostringstream ostr; - ex.ice_print(ostr); - php_error_docref(0 TSRMLS_CC, E_ERROR, "error while destroying Slice parse tree:\n%s\n", - ostr.str().c_str()); - } - } -} - -static bool -do_load(const string& name, const Ice::StringSeq& args TSRMLS_DC) -{ - Profile* profile = static_cast<Profile*>(ICE_G(profile)); - - if(profile) - { - // - // A profile has already been loaded; raise Ice_ProfileAlreadyLoadedException. - // - zend_class_entry* cls = findClass("Ice_ProfileAlreadyLoadedException" TSRMLS_CC); - assert(cls); - - zval* zex; - MAKE_STD_ZVAL(zex); - if(object_init_ex(zex, cls) != SUCCESS) - { - php_error_docref(0 TSRMLS_CC, E_ERROR, "unable to create exception %s", cls->name); - return false; - } - - zend_throw_exception_object(zex TSRMLS_CC); - return false; - } - - string profileName = name; - if(profileName.empty()) - { - profileName = _defaultProfileName; - } - - // - // Compile the core types if necessary. We do this now so that the exceptions - // are available. - // - if(!findClass("Ice_Exception" TSRMLS_CC)) - { - if(zend_eval_string(const_cast<char*>(_coreTypes), 0, "__core" TSRMLS_CC) == FAILURE) - { - php_error_docref(0 TSRMLS_CC, E_ERROR, "unable to create core types:\n%s\n", _coreTypes); - return false; - } - } - - map<string, Profile*>::iterator p = _profiles.find(profileName); - if(p == _profiles.end()) - { - zend_class_entry* cls = findClass("Ice_ProfileNotFoundException" TSRMLS_CC); - assert(cls); - - zval* zex; - MAKE_STD_ZVAL(zex); - if(object_init_ex(zex, cls) != SUCCESS) - { - php_error_docref(0 TSRMLS_CC, E_ERROR, "unable to create exception %s", cls->name); - return false; - } - - // - // Set the name member. - // - zend_update_property_string(cls, zex, "name", sizeof("name") - 1, - const_cast<char*>(profileName.c_str()) TSRMLS_CC); - - zend_throw_exception_object(zex TSRMLS_CC); - return false; - } - profile = p->second; - - // - // Compile the user-defined types. - // - if(zend_eval_string(const_cast<char*>(profile->code().c_str()), 0, "__slice" TSRMLS_CC) == FAILURE) - { - php_error_docref(0 TSRMLS_CC, E_ERROR, "unable to create Slice types:\n%s\n", profile->code().c_str()); - return false; - } - - // - // Make a copy of the profile's properties, and include any command-line arguments. - // - Ice::PropertiesPtr properties = Ice::createProperties(); - properties->parseCommandLineOptions("", profile->properties()->getCommandLineOptions()); - properties->parseCommandLineOptions("", args); - ICE_G(properties) = new Ice::PropertiesPtr(properties); - - ICE_G(profile) = profile; - return true; -} - -ZEND_FUNCTION(Ice_stringVersion) -{ - if(ZEND_NUM_ARGS() != 0) - { - WRONG_PARAM_COUNT; - } - - string s = ICE_STRING_VERSION; - RETURN_STRINGL(const_cast<char*>(s.c_str()), s.length(), 1); -} - -ZEND_FUNCTION(Ice_intVersion) -{ - if(ZEND_NUM_ARGS() != 0) - { - WRONG_PARAM_COUNT; - } - - RETURN_LONG(ICE_INT_VERSION); -} - -ZEND_FUNCTION(Ice_loadProfile) -{ - if(ZEND_NUM_ARGS() > 1) - { - WRONG_PARAM_COUNT; - } - - char* name = ""; - int len; - - if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &name, &len) == FAILURE) - { - return; - } - - Ice::StringSeq args; - do_load(name, args TSRMLS_CC); -} - -ZEND_FUNCTION(Ice_loadProfileWithArgs) -{ - if(ZEND_NUM_ARGS() > 2) - { - WRONG_PARAM_COUNT; - } - - zval* zv; - char* name = ""; - int len; - - if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|s", &zv, &name, &len) == FAILURE) - { - return; - } - - // - // Extract the command-line arguments from the array. - // - Ice::StringSeq args; - HashTable* arr = Z_ARRVAL_P(zv); - void* data; - HashPosition pos; - zend_hash_internal_pointer_reset_ex(arr, &pos); - while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE) - { - zval** val = reinterpret_cast<zval**>(data); - if(Z_TYPE_PP(val) != IS_STRING) - { - php_error_docref(0 TSRMLS_CC, E_ERROR, "argument array must contain strings"); - return; - } - args.push_back(Z_STRVAL_PP(val)); - zend_hash_move_forward_ex(arr, &pos); - } - - do_load(name, args TSRMLS_CC); -} - -ZEND_FUNCTION(Ice_dumpProfile) -{ - Profile* profile = static_cast<Profile*>(ICE_G(profile)); - Ice::PropertiesPtr* properties = static_cast<Ice::PropertiesPtr*>(ICE_G(properties)); - - if(!profile) - { - php_error_docref(0 TSRMLS_CC, E_ERROR, "no profile has been loaded"); - return; - } - - ostringstream out; - out << "Ice profile: " << profile->name() << endl; - - Ice::PropertyDict props = (*properties)->getPropertiesForPrefix(""); - if(!props.empty()) - { - out << endl << "Ice configuration properties:" << endl << endl; - for(Ice::PropertyDict::iterator p = props.begin(); p != props.end(); ++p) - { - out << p->first << "=" << p->second << endl; - } - } - else - { - out << endl << "Ice configuration properties: <none>" << endl; - } - - string code = profile->code(); - if(!code.empty()) - { - out << endl << "PHP code for Slice types:" << endl << endl; - out << code; - } - else - { - out << endl << "PHP code for Slice types: <none>" << endl; - } - - string s = out.str(); - PUTS(s.c_str()); -} - -IcePHP::CodeVisitor::CodeVisitor(ostream& out, map<string, Slice::ClassDefPtr>& classes, bool suppressWarnings - TSRMLS_DC) : - _out(out), _classes(classes), _suppressWarnings(suppressWarnings) -{ -#ifdef ZTS - this->TSRMLS_C = TSRMLS_C; -#endif -} - -void -IcePHP::CodeVisitor::visitClassDecl(const Slice::ClassDeclPtr& p) -{ - Slice::ClassDefPtr def = p->definition(); - if(!def && !_suppressWarnings) - { - string scoped = p->scoped(); - php_error_docref(0 TSRMLS_CC, E_WARNING, "%s %s declared but not defined", - p->isInterface() ? "interface" : "class", scoped.c_str()); - } -} - -bool -IcePHP::CodeVisitor::visitClassDefStart(const Slice::ClassDefPtr& p) -{ - string flat = flatten(p->scoped()); - - _classes[flat] = p; - - Slice::ClassList bases = p->bases(); - Slice::ClassDefPtr base; - - if(p->isInterface()) - { - _out << "if(!interface_exists(\"" << flat << "\"))" << endl; - _out << "{" << endl; - _out << "interface " << flat; - if(!bases.empty()) - { - _out << " extends "; - for(Slice::ClassList::iterator q = bases.begin(); q != bases.end(); ++q) - { - if(q != bases.begin()) - { - _out << ","; - } - _out << flatten((*q)->scoped()); - } - } - else if(!p->isLocal()) - { - _out << " extends Ice_Object"; - } - } - else - { - _out << "if(!class_exists(\"" << flat << "\"))" << endl; - _out << "{" << endl; - if(p->isAbstract()) - { - _out << "abstract "; - } - _out << "class " << flat; - if(!bases.empty() && !bases.front()->isInterface()) - { - _out << " extends " << flatten(bases.front()->scoped()); - base = bases.front(); - bases.pop_front(); - } - else if(!p->isLocal()) - { - _out << " extends Ice_ObjectImpl"; - } - if(!bases.empty()) - { - _out << " implements "; - for(Slice::ClassList::iterator q = bases.begin(); q != bases.end(); ++q) - { - if(q != bases.begin()) - { - _out << ","; - } - _out << flatten((*q)->scoped()); - } - } - } - - _out << endl << '{' << endl; - - if(!p->isInterface()) - { - Slice::DataMemberList baseMembers; - if(base) - { - baseMembers = base->allDataMembers(); - } - - Slice::DataMemberList members = p->dataMembers(); - Slice::DataMemberList::const_iterator q; - - // - // Generate a constructor. - // - _out << "function __construct("; - for(q = baseMembers.begin(); q != baseMembers.end(); ++q) - { - if(q != baseMembers.begin()) - { - _out << ", "; - } - writeConstructorParameter(*q); - } - for(q = members.begin(); q != members.end(); ++q) - { - if(!baseMembers.empty() || q != members.begin()) - { - _out << ", "; - } - writeConstructorParameter(*q); - } - _out << ')' << endl; - _out << '{' << endl; - if(base) - { - _out << " parent::__construct("; - for(q = baseMembers.begin(); q != baseMembers.end(); ++q) - { - if(q != baseMembers.begin()) - { - _out << ", "; - } - _out << '$' << fixIdent((*q)->name()); - } - _out << ");" << endl; - } - for(q = members.begin(); q != members.end(); ++q) - { - writeConstructorAssignment(*q); - } - _out << "}" << endl; - } - - return true; -} - -void -IcePHP::CodeVisitor::visitClassDefEnd(const Slice::ClassDefPtr& p) -{ - _out << '}' << endl; - _out << '}' << endl; // interface_exists/class_exists -} - -bool -IcePHP::CodeVisitor::visitExceptionStart(const Slice::ExceptionPtr& p) -{ - string flat = flatten(p->scoped()); - Slice::ExceptionPtr base = p->base(); - - _out << "if(!class_exists(\"" << flat << "\"))" << endl; - _out << "{" << endl; - _out << "class " << flat << " extends "; - string baseName; - if(!base) - { - if(p->isLocal()) - { - baseName = "Ice_LocalException"; - } - else - { - baseName = "Ice_UserException"; - } - } - else - { - baseName = flatten(base->scoped()); - } - - _out << baseName << endl << '{' << endl; - - Slice::DataMemberList baseMembers; - if(base) - { - baseMembers = base->allDataMembers(); - } - - Slice::DataMemberList members = p->dataMembers(); - Slice::DataMemberList::const_iterator q; - - // - // Generate a constructor. - // - _out << "function __construct($_message=''"; - for(q = baseMembers.begin(); q != baseMembers.end(); ++q) - { - _out << ", "; - writeConstructorParameter(*q); - } - for(q = members.begin(); q != members.end(); ++q) - { - _out << ", "; - writeConstructorParameter(*q); - } - _out << ')' << endl; - _out << '{' << endl; - _out << " " << baseName << "::__construct($_message"; - for(q = baseMembers.begin(); q != baseMembers.end(); ++q) - { - _out << ", $" << fixIdent((*q)->name()); - } - _out << ");" << endl; - for(q = members.begin(); q != members.end(); ++q) - { - writeConstructorAssignment(*q); - } - _out << "}" << endl; - - return true; -} - -void -IcePHP::CodeVisitor::visitExceptionEnd(const Slice::ExceptionPtr& p) -{ - _out << '}' << endl; - _out << '}' << endl; // class_exists -} - -bool -IcePHP::CodeVisitor::visitStructStart(const Slice::StructPtr& p) -{ - string flat = flatten(p->scoped()); - - _out << "if(!class_exists(\"" << flat << "\"))" << endl; - _out << "{" << endl; - _out << "class " << flatten(p->scoped()) << endl; - _out << '{' << endl; - - // - // Generate a constructor. - // - Slice::DataMemberList members = p->dataMembers(); - Slice::DataMemberList::const_iterator q; - _out << "function __construct("; - for(q = members.begin(); q != members.end(); ++q) - { - if(q != members.begin()) - { - _out << ", "; - } - writeConstructorParameter(*q); - } - _out << ')' << endl; - _out << '{' << endl; - for(q = members.begin(); q != members.end(); ++q) - { - writeConstructorAssignment(*q); - } - _out << '}' << endl; - - return true; -} - -void -IcePHP::CodeVisitor::visitStructEnd(const Slice::StructPtr& p) -{ - _out << '}' << endl; - _out << '}' << endl; // class_exists -} - -void -IcePHP::CodeVisitor::visitOperation(const Slice::OperationPtr& p) -{ - string name = fixIdent(p->name()); - - Slice::ParamDeclList params = p->parameters(); - - Slice::ClassDefPtr cl = Slice::ClassDefPtr::dynamicCast(p->container()); - assert(cl); - - if(!cl->isInterface()) - { - _out << "abstract "; - } - _out << "function " << name << '('; - for(Slice::ParamDeclList::const_iterator q = params.begin(); q != params.end(); ++q) - { - Slice::ParamDeclPtr param = *q; - if(q != params.begin()) - { - _out << ", "; - } - if(param->isOutParam()) - { - _out << '&'; - } - else - { - string hint = getTypeHint(param->type()); - if(!hint.empty()) - { - _out << hint << ' '; - } - } - _out << '$' << fixIdent(param->name()); - } - _out << ");" << endl; -} - -void -IcePHP::CodeVisitor::visitDataMember(const Slice::DataMemberPtr& p) -{ - Slice::ContainedPtr cont = Slice::ContainedPtr::dynamicCast(p->container()); - assert(cont); - if(Slice::ClassDefPtr::dynamicCast(cont) && (cont->hasMetaData("protected") || p->hasMetaData("protected"))) - { - _out << "protected $" << fixIdent(p->name()) << ';' << endl; - } - else - { - _out << "public $" << fixIdent(p->name()) << ';' << endl; - } -} - -void -IcePHP::CodeVisitor::visitDictionary(const Slice::DictionaryPtr& p) -{ - Slice::TypePtr keyType = p->keyType(); - if(!isNativeKey(keyType) && !_suppressWarnings) - { - // - // TODO: Generate class. - // - string scoped = p->scoped(); - php_error_docref(0 TSRMLS_CC, E_WARNING, "skipping dictionary %s - unsupported key type", scoped.c_str()); - } -} - -void -IcePHP::CodeVisitor::visitEnum(const Slice::EnumPtr& p) -{ - string flat = flatten(p->scoped()); - - _out << "if(!class_exists(\"" << flat << "\"))" << endl; - _out << "{" << endl; - _out << "class " << flat << endl; - _out << '{' << endl; - - // - // Create a class constant for each enumerator. - // - Slice::EnumeratorList l = p->getEnumerators(); - Slice::EnumeratorList::const_iterator q; - long i; - for(q = l.begin(), i = 0; q != l.end(); ++q, ++i) - { - string name = fixIdent((*q)->name()); - _out << " const " << fixIdent((*q)->name()) << " = " << i << ';' << endl; - } - - _out << '}' << endl; - _out << '}' << endl; // class_exists -} - -void -IcePHP::CodeVisitor::visitConst(const Slice::ConstPtr& p) -{ - string flat = flatten(p->scoped()); - Slice::TypePtr type = p->type(); - string value = p->value(); - - _out << "if(!defined(\"" << flat << "\"))" << endl; - _out << "{" << endl; - _out << "define(\"" << flat << "\", "; - - Slice::BuiltinPtr b = Slice::BuiltinPtr::dynamicCast(type); - Slice::EnumPtr en = Slice::EnumPtr::dynamicCast(type); - 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" - "_{}[]#()<>%:;,?*+=/^&|~!=,\\' \t"; - static const set<char> charSet(basicSourceChars.begin(), basicSourceChars.end()); - - _out << "\""; // Opening " - - ios_base::fmtflags originalFlags = _out.flags(); // Save stream state - streamsize originalWidth = _out.width(); - ostream::char_type originalFill = _out.fill(); - - for(string::const_iterator c = value.begin(); c != value.end(); ++c) - { - if(*c == '$') - { - _out << "\\$"; - } - else if(*c == '"') - { - _out << "\\\""; - } - else if(charSet.find(*c) == charSet.end()) - { - unsigned char uc = *c; // char may be signed, so make it positive - _out << "\\"; // Print as octal if not in basic source character set - _out.flags(ios_base::oct); - _out.width(3); - _out.fill('0'); - _out << static_cast<unsigned>(uc); - } - else - { - _out << *c; // Print normally if in basic source character set - } - } - - _out.fill(originalFill); // Restore stream state - _out.width(originalWidth); - _out.flags(originalFlags); - - _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 << flatten(en->scoped()) << "::" << fixIdent(value); - break; - } - } - } - - _out << ");" << endl; - _out << "}" << endl; // defined -} - -string -IcePHP::CodeVisitor::getTypeHint(const Slice::TypePtr& type) -{ - // - // Currently, the Zend engine does not allow an argument with a type hint to have - // a value of null, therefore we can only use type hints for structs. - // - Slice::StructPtr st = Slice::StructPtr::dynamicCast(type); - if(st) - { - return flatten(st->scoped()); - } - - return string(); -} - -string -IcePHP::CodeVisitor::getDefaultValue(const Slice::TypePtr& type) -{ - Slice::BuiltinPtr builtin = Slice::BuiltinPtr::dynamicCast(type); - if(builtin) - { - switch(builtin->kind()) - { - case Slice::Builtin::KindByte: - case Slice::Builtin::KindShort: - case Slice::Builtin::KindInt: - case Slice::Builtin::KindLong: - return "0"; - - case Slice::Builtin::KindBool: - return "false"; - - case Slice::Builtin::KindFloat: - case Slice::Builtin::KindDouble: - return "0.0"; - - case Slice::Builtin::KindString: - return "''"; - - case Slice::Builtin::KindObject: - case Slice::Builtin::KindObjectProxy: - case Slice::Builtin::KindLocalObject: - return "null"; - } - } - - Slice::EnumPtr en = Slice::EnumPtr::dynamicCast(type); - if(en) - { - // - // Use the first enumerator. - // - string flat = flatten(en->scoped()); - Slice::EnumeratorList l = en->getEnumerators(); - string name = fixIdent(l.front()->name()); - return flat + "::" + name; - } - - Slice::StructPtr str = Slice::StructPtr::dynamicCast(type); - if(str) - { - return "new " + flatten(str->scoped()) + "()"; - } - - return "null"; -} - -void -IcePHP::CodeVisitor::writeConstructorParameter(const Slice::DataMemberPtr& member) -{ - _out << '$' << fixIdent(member->name()) << '='; - // - // Structure types must be handled specially. - // - if(Slice::StructPtr::dynamicCast(member->type())) - { - // - // If a data member is a structure, we want to initialize it to a new instance of the - // structure type. However, PHP does not allow a call to "new" in the default value of - // a function argument, so we assign a marker value now and create the instance in the - // constructor body. - // - _out << "-1"; - } - else - { - _out << getDefaultValue(member->type()); - } -} - -void -IcePHP::CodeVisitor::writeConstructorAssignment(const Slice::DataMemberPtr& member) -{ - // - // Structure types are instantiated in the constructor body. - // - string name = fixIdent(member->name()); - if(Slice::StructPtr::dynamicCast(member->type())) - { - _out << " $this->" << name << " = $" << name << " == -1 ? " << getDefaultValue(member->type()) - << " : $" << name << ';' << endl; - } - else - { - _out << " $this->" << name << " = $" << name << ';' << endl; - } -} |