PageRenderTime 26ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/hphp/runtime/base/builtin-functions.h

https://github.com/tstarling/hiphop-php
C Header | 376 lines | 225 code | 53 blank | 98 comment | 4 complexity | 77498f0f1d138217eecb42cb0108285f MD5 | raw file
  1. /*
  2. +----------------------------------------------------------------------+
  3. | HipHop for PHP |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 2010-2014 Facebook, Inc. (http://www.facebook.com) |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 3.01 of the PHP license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available through the world-wide-web at the following url: |
  10. | http://www.php.net/license/3_01.txt |
  11. | If you did not receive a copy of the PHP license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@php.net so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. */
  16. #ifndef incl_HPHP_BUILTIN_FUNCTIONS_H_
  17. #define incl_HPHP_BUILTIN_FUNCTIONS_H_
  18. #include "hphp/runtime/base/execution-context.h"
  19. #include "hphp/runtime/base/request-event-handler.h"
  20. #include "hphp/runtime/base/types.h"
  21. #include "hphp/runtime/base/complex-types.h"
  22. #include "hphp/runtime/base/intercept.h"
  23. #include "hphp/runtime/base/runtime-error.h"
  24. #include "hphp/runtime/base/runtime-option.h"
  25. #include "hphp/runtime/base/variable-unserializer.h"
  26. #include "hphp/runtime/base/request-local.h"
  27. #include "hphp/runtime/base/strings.h"
  28. #include "hphp/util/functional.h"
  29. #include "hphp/runtime/base/type-conversions.h"
  30. #if defined(__APPLE__) || defined(__USE_BSD)
  31. /**
  32. * We don't actually use param.h in this file,
  33. * but other files which use us do, and we want
  34. * to enforce clearing of the isset macro from
  35. * that header by handling the header now
  36. * and wiping it out.
  37. */
  38. # include <sys/param.h>
  39. #include <algorithm>
  40. # ifdef isset
  41. # undef isset
  42. # endif
  43. #endif
  44. /**
  45. * This file contains a list of functions that HPHP generates to wrap
  46. * around different expressions to maintain semantics. If we read
  47. * through all types of expressions in
  48. * compiler/expression/expression.h, we can find most of them can be
  49. * directly transformed into C/C++ counterpart without too much
  50. * syntactical changes. The functions in this file happen to be the
  51. * ones that are somewhat special.
  52. *
  53. * Another way to think about this file is that this file has a list of C-style
  54. * functions, and the rest of run-time has object/classes for other tasks,
  55. * although we do have some global functions defined in other files as well,
  56. * when they are closer to the classes/objects in the same files.
  57. */
  58. namespace HPHP {
  59. ///////////////////////////////////////////////////////////////////////////////
  60. extern const StaticString s_self;
  61. extern const StaticString s_parent;
  62. extern const StaticString s_static;
  63. ///////////////////////////////////////////////////////////////////////////////
  64. // operators
  65. inline String concat(const String& s1, const String& s2) {
  66. return s1 + s2;
  67. }
  68. String concat3(const String& s1, const String& s2, const String& s3);
  69. String concat4(const String& s1, const String& s2, const String& s3,
  70. const String& s4);
  71. ///////////////////////////////////////////////////////////////////////////////
  72. // output functions
  73. inline void echo(const char *s) {
  74. g_context->write(s);
  75. }
  76. inline void echo(const char *s, int len) {
  77. g_context->write(s, len);
  78. }
  79. inline void echo(const String& s) {
  80. g_context->write(s);
  81. }
  82. void NEVER_INLINE throw_invalid_property_name(const String& name)
  83. ATTRIBUTE_NORETURN;
  84. void NEVER_INLINE throw_null_object_prop();
  85. void NEVER_INLINE throw_null_get_object_prop();
  86. void NEVER_INLINE raise_null_object_prop();
  87. void throw_exception(const Object& e);
  88. ///////////////////////////////////////////////////////////////////////////////
  89. // type testing
  90. inline bool is_null(const Variant& v) { return v.isNull();}
  91. inline bool is_not_null(const Variant& v) { return !v.isNull();}
  92. inline bool is_bool(const Variant& v) { return v.is(KindOfBoolean);}
  93. inline bool is_int(const Variant& v) { return v.isInteger();}
  94. inline bool is_double(const Variant& v) { return v.is(KindOfDouble);}
  95. inline bool is_string(const Variant& v) { return v.isString();}
  96. inline bool is_array(const Variant& v) { return v.is(KindOfArray);}
  97. inline bool is_object(const Variant& var) { return var.is(KindOfObject); }
  98. inline bool is_empty_string(const Variant& v) {
  99. return v.isString() && v.getStringData()->empty();
  100. }
  101. ///////////////////////////////////////////////////////////////////////////////
  102. // misc functions
  103. bool array_is_valid_callback(const Array& arr);
  104. Variant f_call_user_func_array(const Variant& function, const Array& params,
  105. bool bound = false);
  106. const HPHP::Func*
  107. vm_decode_function(const Variant& function,
  108. ActRec* ar,
  109. bool forwarding,
  110. ObjectData*& this_,
  111. HPHP::Class*& cls,
  112. StringData*& invName,
  113. bool warn = true);
  114. inline void
  115. vm_decode_function(const Variant& function,
  116. ActRec* ar,
  117. bool forwarding,
  118. CallCtx& ctx,
  119. bool warn = true) {
  120. ctx.func = vm_decode_function(function, ar, forwarding, ctx.this_, ctx.cls,
  121. ctx.invName, warn);
  122. }
  123. ActRec* vm_get_previous_frame();
  124. Variant vm_call_user_func(const Variant& function, const Variant& params,
  125. bool forwarding = false);
  126. /**
  127. * Invoking an arbitrary static method.
  128. */
  129. Variant invoke_static_method(const String& s, const String& method,
  130. const Variant& params, bool fatal = true);
  131. /**
  132. * Fallback when a dynamic function call fails to find a user function
  133. * matching the name. If no handlers are able to
  134. * invoke the function, throw an InvalidFunctionCallException.
  135. */
  136. Variant invoke_failed(const char *func,
  137. bool fatal = true);
  138. Variant invoke_failed(const Variant& func,
  139. bool fatal = true);
  140. Variant o_invoke_failed(const char *cls, const char *meth,
  141. bool fatal = true);
  142. /**
  143. * When fatal coding errors are transformed to this function call.
  144. */
  145. inline Variant throw_fatal(const char *msg, void *dummy = nullptr) {
  146. throw FatalErrorException(msg);
  147. }
  148. inline Variant throw_missing_class(const char *cls) {
  149. throw ClassNotFoundException((std::string("unknown class ") + cls).c_str());
  150. }
  151. inline Variant throw_missing_file(const char *file) {
  152. if (file[0] == '\0') {
  153. throw NoFileSpecifiedException();
  154. }
  155. throw PhpFileDoesNotExistException(file);
  156. }
  157. void throw_instance_method_fatal(const char *name);
  158. void throw_iterator_not_valid() ATTRIBUTE_NORETURN;
  159. void throw_collection_modified() ATTRIBUTE_NORETURN;
  160. void throw_collection_property_exception() ATTRIBUTE_NORETURN;
  161. void throw_collection_compare_exception() ATTRIBUTE_NORETURN;
  162. void throw_param_is_not_container() ATTRIBUTE_NORETURN;
  163. void throw_cannot_modify_immutable_object(const char* className)
  164. ATTRIBUTE_NORETURN;
  165. void warn_cannot_modify_immutable_object(const char* className);
  166. void check_collection_compare(ObjectData* obj);
  167. void check_collection_compare(ObjectData* obj1, ObjectData* obj2);
  168. void check_collection_cast_to_array();
  169. Object create_object_only(const String& s);
  170. Object create_object(const String& s, const Array &params, bool init = true);
  171. /**
  172. * Argument count handling.
  173. * - When level is 2, it's from constructors that turn these into fatals
  174. * - When level is 1, it's from system funcs that turn both into warnings
  175. * - When level is 0, it's from user funcs that turn missing arg in warnings
  176. */
  177. void throw_missing_arguments_nr(const char *fn, int expected, int got,
  178. int level = 0, TypedValue *rv = nullptr)
  179. __attribute__((cold));
  180. void throw_toomany_arguments_nr(const char *fn, int num, int level = 0,
  181. TypedValue *rv = nullptr)
  182. __attribute__((cold));
  183. void throw_wrong_arguments_nr(const char *fn, int count, int cmin, int cmax,
  184. int level = 0, TypedValue *rv = nullptr)
  185. __attribute__((cold));
  186. /**
  187. * Handler for exceptions thrown from user functions that we don't
  188. * allow exception propagation from. E.g., object destructors or
  189. * certain callback hooks (user profiler). Implemented in
  190. * program-functions.cpp.
  191. */
  192. void handle_destructor_exception(const char* situation = "Destructor");
  193. /**
  194. * If RuntimeOption::ThrowBadTypeExceptions is on, we are running in
  195. * a restrictive mode that's not compatible with PHP, and this will throw.
  196. * If RuntimeOption::ThrowBadTypeExceptions is off, we will log a
  197. * warning and swallow the error.
  198. */
  199. void throw_bad_type_exception(const char *fmt, ...) ATTRIBUTE_PRINTF(1,2);
  200. void throw_expected_array_exception();
  201. void throw_expected_array_or_collection_exception();
  202. /**
  203. * If RuntimeOption::ThrowInvalidArguments is on, we are running in
  204. * a restrictive mode that's not compatible with PHP, and this will throw.
  205. * If RuntimeOption::ThrowInvalidArguments is off, we will log a
  206. * warning and swallow the error.
  207. */
  208. void throw_invalid_argument(const char *fmt, ...) ATTRIBUTE_PRINTF(1,2);
  209. /**
  210. * Unsetting ClassName::StaticProperty.
  211. */
  212. Variant throw_fatal_unset_static_property(const char *s, const char *prop);
  213. /**
  214. * Exceptions injected code throws
  215. */
  216. Exception* generate_request_timeout_exception();
  217. Exception* generate_memory_exceeded_exception();
  218. // unserializable default value arguments such as TimeStamp::Current()
  219. // are serialized as "\x01"
  220. char const kUnserializableString[] = "\x01";
  221. /**
  222. * Serialize/unserialize a variant into/from a string. We need these
  223. * two functions in runtime/base, as there are functions in
  224. * runtime/base that depend on these two functions.
  225. */
  226. String f_serialize(const Variant& value);
  227. Variant unserialize_ex(const String& str,
  228. VariableUnserializer::Type type,
  229. const Array& class_whitelist = null_array);
  230. Variant unserialize_ex(const char* str, int len,
  231. VariableUnserializer::Type type,
  232. const Array& class_whitelist = null_array);
  233. inline Variant unserialize_from_buffer(const char* str, int len,
  234. const Array& class_whitelist = null_array) {
  235. return unserialize_ex(str, len,
  236. VariableUnserializer::Type::Serialize,
  237. class_whitelist);
  238. }
  239. inline Variant unserialize_from_string(const String& str,
  240. const Array& class_whitelist = null_array) {
  241. return unserialize_from_buffer(str.data(), str.size(), class_whitelist);
  242. }
  243. String resolve_include(const String& file, const char* currentDir,
  244. bool (*tryFile)(const String& file, void* ctx),
  245. void* ctx);
  246. Variant include(const String& file, bool once = false,
  247. const char *currentDir = "",
  248. bool raiseNotice = true);
  249. Variant require(const String& file, bool once = false,
  250. const char *currentDir = "",
  251. bool raiseNotice = true);
  252. Variant include_impl_invoke(const String& file, bool once = false,
  253. const char *currentDir = "");
  254. Variant invoke_file(const String& file, bool once = false,
  255. const char *currentDir = nullptr);
  256. bool invoke_file_impl(Variant &res, const String& path, bool once,
  257. const char *currentDir);
  258. bool function_exists(const String& function_name);
  259. /**
  260. * For autoload support
  261. */
  262. class AutoloadHandler final : public RequestEventHandler {
  263. enum Result {
  264. Failure,
  265. Success,
  266. StopAutoloading,
  267. ContinueAutoloading
  268. };
  269. struct HandlerBundle {
  270. HandlerBundle() = delete;
  271. HandlerBundle(const Variant& handler,
  272. smart::unique_ptr<CufIter>& cufIter) :
  273. m_handler(handler) {
  274. m_cufIter = std::move(cufIter);
  275. }
  276. Variant m_handler; // used to respond to f_spl_autoload_functions
  277. smart::unique_ptr<CufIter> m_cufIter; // used to invoke handlers
  278. };
  279. class CompareBundles {
  280. public:
  281. explicit CompareBundles(CufIter* cufIter) : m_cufIter(cufIter) { }
  282. bool operator()(const HandlerBundle& hb);
  283. private:
  284. CufIter* m_cufIter;
  285. };
  286. public:
  287. AutoloadHandler() { }
  288. ~AutoloadHandler() {
  289. m_map.detach();
  290. m_map_root.detach();
  291. // m_handlers won't run a destructor so nothing to do here
  292. m_loading.detach();
  293. }
  294. virtual void requestInit();
  295. virtual void requestShutdown();
  296. Array getHandlers();
  297. bool addHandler(const Variant& handler, bool prepend);
  298. void removeHandler(const Variant& handler);
  299. void removeAllHandlers();
  300. bool isRunning();
  301. bool invokeHandler(const String& className, bool forceSplStack = false);
  302. bool autoloadFunc(StringData* name);
  303. bool autoloadConstant(StringData* name);
  304. bool autoloadType(const String& name);
  305. bool setMap(const Array& map, const String& root);
  306. DECLARE_STATIC_REQUEST_LOCAL(AutoloadHandler, s_instance);
  307. private:
  308. template <class T>
  309. Result loadFromMap(const String& name, const String& kind, bool toLower,
  310. const T &checkExists);
  311. static String getSignature(const Variant& handler);
  312. Array m_map;
  313. String m_map_root;
  314. bool m_spl_stack_inited;
  315. union {
  316. smart::deque<HandlerBundle> m_handlers;
  317. };
  318. Array m_loading;
  319. };
  320. #define CALL_USER_FUNC_FEW_ARGS_COUNT 6
  321. ///////////////////////////////////////////////////////////////////////////////
  322. }
  323. #endif // incl_HPHP_BUILTIN_FUNCTIONS_H_