PageRenderTime 57ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/hphp/runtime/ext_zend_compat/php-src/Zend/zend_API.cpp

http://github.com/facebook/hiphop-php
C++ | 1688 lines | 1280 code | 276 blank | 132 comment | 222 complexity | a9e5bb4a3105735f03f0030a0e819e50 MD5 | raw file
Possible License(s): LGPL-2.1, BSD-2-Clause, BSD-3-Clause, MPL-2.0-no-copyleft-exception, MIT, LGPL-2.0, Apache-2.0
  1. /*
  2. +----------------------------------------------------------------------+
  3. | Zend Engine |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1998-2013 Zend Technologies Ltd. (http://www.zend.com) |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 2.00 of the Zend 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.zend.com/license/2_00.txt. |
  11. | If you did not receive a copy of the Zend license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@zend.com so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Authors: Andi Gutmans <andi@zend.com> |
  16. | Zeev Suraski <zeev@zend.com> |
  17. | Andrei Zmievski <andrei@php.net> |
  18. +----------------------------------------------------------------------+
  19. */
  20. /* $Id$ */
  21. // has to be before zend_API since that defines getThis()
  22. #include "zend_API.h"
  23. #include "hphp/runtime/ext/std/ext_std_function.h"
  24. #include "zend_constants.h"
  25. #include "hphp/runtime/base/builtin-functions.h"
  26. #include "hphp/runtime/base/zend-printf.h"
  27. #include "hphp/util/thread-local.h"
  28. #include "hphp/runtime/ext_zend_compat/hhvm/zend-class-entry.h"
  29. #include "hphp/runtime/ext_zend_compat/hhvm/zend-execution-stack.h"
  30. #include "hphp/runtime/ext_zend_compat/hhvm/zval-helpers.h"
  31. #include "hphp/runtime/vm/jit/translator-inline.h"
  32. #include "hphp/runtime/vm/native.h"
  33. namespace {
  34. void releaseZval(zval* v) {
  35. if (v->zRefcount() > 1) {
  36. v->zDelRef();
  37. } else {
  38. FREE_ZVAL(v);
  39. }
  40. }
  41. }
  42. ZEND_API const char *zend_get_type_by_const(int type) {
  43. return HPHP::getDataTypeString((HPHP::DataType)type).data();
  44. }
  45. ZEND_API const char *zend_zval_type_name(const zval *arg) {
  46. return zend_get_type_by_const(Z_TYPE_P(arg));
  47. }
  48. ZEND_API zend_class_entry *zend_get_class_entry(const zval *zobject TSRMLS_DC) {
  49. auto* hphp_class = Z_OBJVAL_P(zobject)->getVMClass();
  50. return HPHP::zend_hphp_class_to_class_entry(hphp_class);
  51. }
  52. static int parse_arg_object_to_string(zval **arg, const char **p, int *pl, int type TSRMLS_DC) {
  53. HPHP::StringData *sd = tvCastToString((*arg)->tv());
  54. *p = sd->data();
  55. *pl = sd->size();
  56. return sd->empty();
  57. }
  58. static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, const char **spec, char **error, int *severity TSRMLS_DC) {
  59. const char *spec_walk = *spec;
  60. char c = *spec_walk++;
  61. int check_null = 0;
  62. /* scan through modifiers */
  63. while (1) {
  64. if (*spec_walk == '/') {
  65. SEPARATE_ZVAL_IF_NOT_REF(arg);
  66. } else if (*spec_walk == '!') {
  67. check_null = 1;
  68. } else {
  69. break;
  70. }
  71. spec_walk++;
  72. }
  73. switch (c) {
  74. case 'l':
  75. case 'L':
  76. {
  77. long *p = va_arg(*va, long *);
  78. if (check_null) {
  79. zend_bool *p = va_arg(*va, zend_bool *);
  80. *p = (Z_TYPE_PP(arg) == IS_NULL);
  81. }
  82. switch (Z_TYPE_PP(arg)) {
  83. case IS_STRING:
  84. {
  85. double d;
  86. int type;
  87. if ((type = is_numeric_string(Z_STRVAL_PP(arg), Z_STRLEN_PP(arg), p, &d, -1)) == 0) {
  88. return "long";
  89. } else if (type == IS_DOUBLE) {
  90. if (c == 'L') {
  91. if (d > LONG_MAX) {
  92. *p = LONG_MAX;
  93. break;
  94. } else if (d < LONG_MIN) {
  95. *p = LONG_MIN;
  96. break;
  97. }
  98. }
  99. *p = zend_dval_to_lval(d);
  100. }
  101. }
  102. break;
  103. case IS_DOUBLE:
  104. if (c == 'L') {
  105. if (Z_DVAL_PP(arg) > LONG_MAX) {
  106. *p = LONG_MAX;
  107. break;
  108. } else if (Z_DVAL_PP(arg) < LONG_MIN) {
  109. *p = LONG_MIN;
  110. break;
  111. }
  112. }
  113. case IS_NULL:
  114. case IS_LONG:
  115. case IS_BOOL:
  116. convert_to_long_ex(arg);
  117. *p = Z_LVAL_PP(arg);
  118. break;
  119. case IS_ARRAY:
  120. case IS_OBJECT:
  121. case IS_RESOURCE:
  122. default:
  123. return "long";
  124. }
  125. }
  126. break;
  127. case 'd':
  128. {
  129. double *p = va_arg(*va, double *);
  130. if (check_null) {
  131. zend_bool *p = va_arg(*va, zend_bool *);
  132. *p = (Z_TYPE_PP(arg) == IS_NULL);
  133. }
  134. switch (Z_TYPE_PP(arg)) {
  135. case IS_STRING:
  136. {
  137. long l;
  138. int type;
  139. if ((type = is_numeric_string(Z_STRVAL_PP(arg), Z_STRLEN_PP(arg), &l, p, -1)) == 0) {
  140. return "double";
  141. } else if (type == IS_LONG) {
  142. *p = (double) l;
  143. }
  144. }
  145. break;
  146. case IS_NULL:
  147. case IS_LONG:
  148. case IS_DOUBLE:
  149. case IS_BOOL:
  150. convert_to_double_ex(arg);
  151. *p = Z_DVAL_PP(arg);
  152. break;
  153. case IS_ARRAY:
  154. case IS_OBJECT:
  155. case IS_RESOURCE:
  156. default:
  157. return "double";
  158. }
  159. }
  160. break;
  161. case 'p':
  162. case 's':
  163. {
  164. const char **p = va_arg(*va, const char **);
  165. int *pl = va_arg(*va, int *);
  166. switch (Z_TYPE_PP(arg)) {
  167. case IS_NULL:
  168. if (check_null) {
  169. *p = NULL;
  170. *pl = 0;
  171. break;
  172. }
  173. /* break omitted intentionally */
  174. case IS_STRING:
  175. case IS_LONG:
  176. case IS_DOUBLE:
  177. case IS_BOOL:
  178. convert_to_string_ex(arg);
  179. if (UNEXPECTED(Z_ISREF_PP(arg) != 0)) {
  180. /* it's dangerous to return pointers to string
  181. buffer of referenced variable, because it can
  182. be clobbered throug magic callbacks */
  183. SEPARATE_ZVAL(arg);
  184. }
  185. *p = Z_STRVAL_PP(arg);
  186. *pl = Z_STRLEN_PP(arg);
  187. if (c == 'p' && CHECK_ZVAL_NULL_PATH(*arg)) {
  188. return "a valid path";
  189. }
  190. break;
  191. case IS_OBJECT:
  192. if (parse_arg_object_to_string(arg, p, pl, IS_STRING TSRMLS_CC) == SUCCESS) {
  193. if (c == 'p' && CHECK_ZVAL_NULL_PATH(*arg)) {
  194. return "a valid path";
  195. }
  196. break;
  197. }
  198. case IS_ARRAY:
  199. case IS_RESOURCE:
  200. default:
  201. return c == 's' ? "string" : "a valid path";
  202. }
  203. }
  204. break;
  205. case 'b':
  206. {
  207. zend_bool *p = va_arg(*va, zend_bool *);
  208. if (check_null) {
  209. zend_bool *p = va_arg(*va, zend_bool *);
  210. *p = (Z_TYPE_PP(arg) == IS_NULL);
  211. }
  212. switch (Z_TYPE_PP(arg)) {
  213. case IS_NULL:
  214. case IS_STRING:
  215. case IS_LONG:
  216. case IS_DOUBLE:
  217. case IS_BOOL:
  218. convert_to_boolean_ex(arg);
  219. *p = Z_BVAL_PP(arg);
  220. break;
  221. case IS_ARRAY:
  222. case IS_OBJECT:
  223. case IS_RESOURCE:
  224. default:
  225. return "boolean";
  226. }
  227. }
  228. break;
  229. case 'r':
  230. {
  231. zval **p = va_arg(*va, zval **);
  232. if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
  233. *p = NULL;
  234. break;
  235. }
  236. if (Z_TYPE_PP(arg) == IS_RESOURCE) {
  237. *p = *arg;
  238. } else {
  239. return "resource";
  240. }
  241. }
  242. break;
  243. case 'A':
  244. case 'a':
  245. {
  246. zval **p = va_arg(*va, zval **);
  247. if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
  248. *p = NULL;
  249. break;
  250. }
  251. if (Z_TYPE_PP(arg) == IS_ARRAY || (c == 'A' && Z_TYPE_PP(arg) == IS_OBJECT)) {
  252. *p = *arg;
  253. } else {
  254. return "array";
  255. }
  256. }
  257. break;
  258. case 'H':
  259. case 'h':
  260. {
  261. HashTable **p = va_arg(*va, HashTable **);
  262. if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
  263. *p = NULL;
  264. break;
  265. }
  266. if (Z_TYPE_PP(arg) == IS_ARRAY) {
  267. *p = Z_ARRVAL_PP(arg);
  268. } else if(c == 'H' && Z_TYPE_PP(arg) == IS_OBJECT) {
  269. *p = HASH_OF(*arg);
  270. if(*p == NULL) {
  271. return "array";
  272. }
  273. } else {
  274. return "array";
  275. }
  276. }
  277. break;
  278. case 'o':
  279. {
  280. zval **p = va_arg(*va, zval **);
  281. if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
  282. *p = NULL;
  283. break;
  284. }
  285. if (Z_TYPE_PP(arg) == IS_OBJECT) {
  286. *p = *arg;
  287. } else {
  288. return "object";
  289. }
  290. }
  291. break;
  292. case 'O':
  293. {
  294. zval **p = va_arg(*va, zval **);
  295. zend_class_entry *ce = va_arg(*va, zend_class_entry *);
  296. if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
  297. *p = NULL;
  298. break;
  299. }
  300. if (Z_TYPE_PP(arg) == IS_OBJECT &&
  301. (!ce || instanceof_function(Z_OBJCE_PP(arg), ce TSRMLS_CC))) {
  302. *p = *arg;
  303. } else {
  304. if (ce) {
  305. return ce->name;
  306. } else {
  307. return "object";
  308. }
  309. }
  310. }
  311. break;
  312. case 'C':
  313. {
  314. zend_class_entry **lookup, **pce = va_arg(*va, zend_class_entry **);
  315. zend_class_entry *ce_base = *pce;
  316. if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
  317. *pce = NULL;
  318. break;
  319. }
  320. convert_to_string_ex(arg);
  321. if (zend_lookup_class(Z_STRVAL_PP(arg), Z_STRLEN_PP(arg), &lookup TSRMLS_CC) == FAILURE) {
  322. *pce = NULL;
  323. } else {
  324. *pce = *lookup;
  325. }
  326. if (ce_base) {
  327. if ((!*pce || !instanceof_function(*pce, ce_base TSRMLS_CC))) {
  328. HPHP::spprintf(error, 0, "to be a class name derived from %s, '%s' given",
  329. ce_base->name, Z_STRVAL_PP(arg));
  330. *pce = NULL;
  331. return "";
  332. }
  333. }
  334. if (!*pce) {
  335. HPHP::spprintf(error, 0, "to be a valid class name, '%s' given",
  336. Z_STRVAL_PP(arg));
  337. return "";
  338. }
  339. break;
  340. }
  341. break;
  342. case 'f':
  343. {
  344. zend_fcall_info *fci = va_arg(*va, zend_fcall_info *);
  345. zend_fcall_info_cache *fcc = va_arg(*va, zend_fcall_info_cache *);
  346. char *is_callable_error = NULL;
  347. if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
  348. fci->size = 0;
  349. fcc->initialized = 0;
  350. break;
  351. }
  352. if (zend_fcall_info_init(*arg, 0, fci, fcc, NULL, &is_callable_error TSRMLS_CC) == SUCCESS) {
  353. if (is_callable_error) {
  354. *severity = E_STRICT;
  355. HPHP::spprintf(error, 0, "to be a valid callback, %s", is_callable_error);
  356. efree(is_callable_error);
  357. *spec = spec_walk;
  358. return "";
  359. }
  360. break;
  361. } else {
  362. if (is_callable_error) {
  363. *severity = E_WARNING;
  364. HPHP::spprintf(error, 0, "to be a valid callback, %s", is_callable_error);
  365. efree(is_callable_error);
  366. return "";
  367. } else {
  368. return "valid callback";
  369. }
  370. }
  371. }
  372. case 'z':
  373. {
  374. zval **p = va_arg(*va, zval **);
  375. if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
  376. *p = NULL;
  377. } else {
  378. *p = *arg;
  379. }
  380. }
  381. break;
  382. case 'Z':
  383. {
  384. zval ***p = va_arg(*va, zval ***);
  385. if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
  386. *p = NULL;
  387. } else {
  388. *p = arg;
  389. }
  390. }
  391. break;
  392. default:
  393. return "unknown";
  394. }
  395. *spec = spec_walk;
  396. return NULL;
  397. }
  398. static int zend_parse_arg(int arg_num, zval **arg, va_list *va, const char **spec, int quiet TSRMLS_DC) {
  399. const char *expected_type = NULL;
  400. char *error = NULL;
  401. int severity = E_WARNING;
  402. expected_type = zend_parse_arg_impl(arg_num, arg, va, spec, &error, &severity TSRMLS_CC);
  403. if (expected_type) {
  404. if (!quiet && (*expected_type || error)) {
  405. const char *space;
  406. const char *class_name = get_active_class_name(&space TSRMLS_CC);
  407. if (error) {
  408. zend_error(severity, "%s%s%s() expects parameter %d %s",
  409. class_name, space, get_active_function_name(TSRMLS_C), arg_num, error);
  410. efree(error);
  411. } else {
  412. zend_error(severity, "%s%s%s() expects parameter %d to be %s, %s given",
  413. class_name, space, get_active_function_name(TSRMLS_C), arg_num, expected_type,
  414. zend_zval_type_name(*arg));
  415. }
  416. }
  417. if (severity != E_STRICT) {
  418. return FAILURE;
  419. }
  420. }
  421. return SUCCESS;
  422. }
  423. static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va, int flags TSRMLS_DC) {
  424. const char *spec_walk;
  425. int c, i;
  426. int min_num_args = -1;
  427. int max_num_args = 0;
  428. int post_varargs = 0;
  429. zval **arg;
  430. int arg_count;
  431. int quiet = flags & ZEND_PARSE_PARAMS_QUIET;
  432. zend_bool have_varargs = 0;
  433. zval ****varargs = NULL;
  434. int *n_varargs = NULL;
  435. HPHP::VMRegAnchor _;
  436. for (spec_walk = type_spec; *spec_walk; spec_walk++) {
  437. c = *spec_walk;
  438. switch (c) {
  439. case 'l': case 'd':
  440. case 's': case 'b':
  441. case 'r': case 'a':
  442. case 'o': case 'O':
  443. case 'z': case 'Z':
  444. case 'C': case 'h':
  445. case 'f': case 'A':
  446. case 'H': case 'p':
  447. max_num_args++;
  448. break;
  449. case '|':
  450. min_num_args = max_num_args;
  451. break;
  452. case '/':
  453. case '!':
  454. /* Pass */
  455. break;
  456. case '*':
  457. case '+':
  458. if (have_varargs) {
  459. if (!quiet) {
  460. zend_error(E_WARNING, "%s(): only one varargs specifier (* or +) is permitted",
  461. get_active_function_name(TSRMLS_C));
  462. }
  463. return FAILURE;
  464. }
  465. have_varargs = 1;
  466. /* we expect at least one parameter in varargs */
  467. if (c == '+') {
  468. max_num_args++;
  469. }
  470. /* mark the beginning of varargs */
  471. post_varargs = max_num_args;
  472. break;
  473. default:
  474. if (!quiet) {
  475. zend_error(E_WARNING, "%s(): bad type specifier while parsing parameters",
  476. get_active_function_name(TSRMLS_C));
  477. }
  478. return FAILURE;
  479. }
  480. }
  481. if (min_num_args < 0) {
  482. min_num_args = max_num_args;
  483. }
  484. if (have_varargs) {
  485. /* calculate how many required args are at the end of the specifier list */
  486. post_varargs = max_num_args - post_varargs;
  487. max_num_args = -1;
  488. }
  489. if (num_args < min_num_args || (num_args > max_num_args && max_num_args > 0)) {
  490. if (!quiet) {
  491. zend_error(E_WARNING, "%s() expects %s %d parameter%s, %d given",
  492. get_active_function_name(TSRMLS_C),
  493. min_num_args == max_num_args ? "exactly" : num_args < min_num_args ? "at least" : "at most",
  494. num_args < min_num_args ? min_num_args : max_num_args,
  495. (num_args < min_num_args ? min_num_args : max_num_args) == 1 ? "" : "s",
  496. num_args);
  497. }
  498. return FAILURE;
  499. }
  500. arg_count = HPHP::ZendExecutionStack::numArgs();
  501. if (num_args > arg_count) {
  502. zend_error(E_WARNING, "%s(): could not obtain parameters for parsing",
  503. get_active_function_name(TSRMLS_C));
  504. return FAILURE;
  505. }
  506. i = 0;
  507. while (num_args-- > 0) {
  508. if (*type_spec == '|') {
  509. type_spec++;
  510. }
  511. if (*type_spec == '*' || *type_spec == '+') {
  512. int num_varargs = num_args + 1 - post_varargs;
  513. /* eat up the passed in storage even if it won't be filled in with varargs */
  514. varargs = va_arg(*va, zval ****);
  515. n_varargs = va_arg(*va, int *);
  516. type_spec++;
  517. if (num_varargs > 0) {
  518. int iv = 0;
  519. *n_varargs = num_varargs;
  520. /* Allocate space for the args. We need to allocate it in such a way
  521. * that a single efree(varargs) in the caller will free all relevant
  522. * memory.
  523. */
  524. *varargs = (zval***)safe_emalloc(num_varargs, sizeof(void*), 0);
  525. for (iv = 0; iv < num_varargs; iv++) {
  526. (*varargs)[iv] = HPHP::ZendExecutionStack::getArg(i + iv);
  527. }
  528. /* adjust how many args we have left and restart loop */
  529. num_args = num_args + 1 - iv;
  530. i += iv;
  531. continue;
  532. } else {
  533. *varargs = NULL;
  534. *n_varargs = 0;
  535. }
  536. }
  537. arg = HPHP::ZendExecutionStack::getArg(i);
  538. if (zend_parse_arg(i+1, arg, va, &type_spec, quiet TSRMLS_CC) == FAILURE) {
  539. /* clean up varargs array if it was used */
  540. if (varargs && *varargs) {
  541. efree(*varargs);
  542. *varargs = NULL;
  543. }
  544. return FAILURE;
  545. }
  546. i++;
  547. }
  548. return SUCCESS;
  549. }
  550. #define RETURN_IF_ZERO_ARGS(num_args, type_spec, quiet) { \
  551. int __num_args = (num_args); \
  552. \
  553. if (0 == (type_spec)[0] && 0 != __num_args && !(quiet)) { \
  554. const char *__space; \
  555. const char * __class_name = get_active_class_name(&__space TSRMLS_CC); \
  556. zend_error(E_WARNING, "%s%s%s() expects exactly 0 parameters, %d given", \
  557. __class_name, __space, \
  558. get_active_function_name(TSRMLS_C), __num_args); \
  559. return FAILURE; \
  560. }\
  561. }
  562. ZEND_API int zend_parse_parameters_ex(int flags, int num_args TSRMLS_DC, const char *type_spec, ...) {
  563. va_list va;
  564. int retval;
  565. RETURN_IF_ZERO_ARGS(num_args, type_spec, flags & ZEND_PARSE_PARAMS_QUIET);
  566. va_start(va, type_spec);
  567. retval = zend_parse_va_args(num_args, type_spec, &va, flags TSRMLS_CC);
  568. va_end(va);
  569. return retval;
  570. }
  571. ZEND_API int zend_parse_parameters(int num_args TSRMLS_DC, const char *type_spec, ...) {
  572. va_list va;
  573. int retval;
  574. RETURN_IF_ZERO_ARGS(num_args, type_spec, 0);
  575. va_start(va, type_spec);
  576. retval = zend_parse_va_args(num_args, type_spec, &va, 0 TSRMLS_CC);
  577. va_end(va);
  578. return retval;
  579. }
  580. ZEND_API int zend_parse_method_parameters(int num_args TSRMLS_DC, zval *this_ptr, const char *type_spec, ...) /* {{{ */
  581. {
  582. va_list va;
  583. int retval;
  584. const char *p = type_spec;
  585. zval **object;
  586. zend_class_entry *ce;
  587. if (!this_ptr) {
  588. RETURN_IF_ZERO_ARGS(num_args, p, 0);
  589. va_start(va, type_spec);
  590. retval = zend_parse_va_args(num_args, type_spec, &va, 0 TSRMLS_CC);
  591. va_end(va);
  592. } else {
  593. p++;
  594. RETURN_IF_ZERO_ARGS(num_args, p, 0);
  595. va_start(va, type_spec);
  596. object = va_arg(va, zval **);
  597. ce = va_arg(va, zend_class_entry *);
  598. *object = this_ptr;
  599. if (ce && !instanceof_function(Z_OBJCE_P(this_ptr), ce TSRMLS_CC)) {
  600. zend_error(E_CORE_ERROR, "%s::%s() must be derived from %s::%s",
  601. ce->name, get_active_function_name(TSRMLS_C), Z_OBJCE_P(this_ptr)->name, get_active_function_name(TSRMLS_C));
  602. }
  603. retval = zend_parse_va_args(num_args, p, &va, 0 TSRMLS_CC);
  604. va_end(va);
  605. }
  606. return retval;
  607. }
  608. /* }}} */
  609. ZEND_API int zend_parse_method_parameters_ex(int flags, int num_args TSRMLS_DC, zval *this_ptr, const char *type_spec, ...) /* {{{ */
  610. {
  611. va_list va;
  612. int retval;
  613. const char *p = type_spec;
  614. zval **object;
  615. zend_class_entry *ce;
  616. int quiet = flags & ZEND_PARSE_PARAMS_QUIET;
  617. if (!this_ptr) {
  618. RETURN_IF_ZERO_ARGS(num_args, p, quiet);
  619. va_start(va, type_spec);
  620. retval = zend_parse_va_args(num_args, type_spec, &va, flags TSRMLS_CC);
  621. va_end(va);
  622. } else {
  623. p++;
  624. RETURN_IF_ZERO_ARGS(num_args, p, quiet);
  625. va_start(va, type_spec);
  626. object = va_arg(va, zval **);
  627. ce = va_arg(va, zend_class_entry *);
  628. *object = this_ptr;
  629. if (ce && !instanceof_function(Z_OBJCE_P(this_ptr), ce TSRMLS_CC)) {
  630. if (!quiet) {
  631. zend_error(E_CORE_ERROR, "%s::%s() must be derived from %s::%s",
  632. ce->name, get_active_function_name(TSRMLS_C), Z_OBJCE_P(this_ptr)->name, get_active_function_name(TSRMLS_C));
  633. }
  634. va_end(va);
  635. return FAILURE;
  636. }
  637. retval = zend_parse_va_args(num_args, p, &va, flags TSRMLS_CC);
  638. va_end(va);
  639. }
  640. return retval;
  641. }
  642. /* }}} */
  643. ZEND_API int add_assoc_long_ex(zval *arg, const char *key, uint key_len, long n) /* {{{ */
  644. {
  645. zval *tmp;
  646. MAKE_STD_ZVAL(tmp);
  647. ZVAL_LONG(tmp, n);
  648. return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, &tmp, sizeof(zval *), NULL);
  649. }
  650. /* }}} */
  651. ZEND_API int add_assoc_null_ex(zval *arg, const char *key, uint key_len) /* {{{ */
  652. {
  653. zval *tmp;
  654. MAKE_STD_ZVAL(tmp);
  655. ZVAL_NULL(tmp);
  656. return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, &tmp, sizeof(zval *), NULL);
  657. }
  658. /* }}} */
  659. ZEND_API int add_assoc_bool_ex(zval *arg, const char *key, uint key_len, int b) /* {{{ */
  660. {
  661. zval *tmp;
  662. MAKE_STD_ZVAL(tmp);
  663. ZVAL_BOOL(tmp, b);
  664. return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, &tmp, sizeof(zval *), NULL);
  665. }
  666. /* }}} */
  667. ZEND_API int add_assoc_resource_ex(zval *arg, const char *key, uint key_len, int r) /* {{{ */
  668. {
  669. zval *tmp;
  670. MAKE_STD_ZVAL(tmp);
  671. ZVAL_RESOURCE(tmp, r);
  672. return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, &tmp, sizeof(zval *), NULL);
  673. }
  674. /* }}} */
  675. ZEND_API int add_assoc_double_ex(zval *arg, const char *key, uint key_len, double d) /* {{{ */
  676. {
  677. zval *tmp;
  678. MAKE_STD_ZVAL(tmp);
  679. ZVAL_DOUBLE(tmp, d);
  680. return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, &tmp, sizeof(zval *), NULL);
  681. }
  682. /* }}} */
  683. ZEND_API int add_assoc_string_ex(zval *arg, const char *key, uint key_len, const char *str, int duplicate) /* {{{ */
  684. {
  685. zval *tmp;
  686. MAKE_STD_ZVAL(tmp);
  687. ZVAL_STRING(tmp, str, duplicate);
  688. return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, &tmp, sizeof(zval *), NULL);
  689. }
  690. /* }}} */
  691. ZEND_API int add_assoc_stringl_ex(zval *arg, const char *key, uint key_len, const char *str, uint length, int duplicate) /* {{{ */
  692. {
  693. zval *tmp;
  694. MAKE_STD_ZVAL(tmp);
  695. ZVAL_STRINGL(tmp, str, length, duplicate);
  696. return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, &tmp, sizeof(zval *), NULL);
  697. }
  698. /* }}} */
  699. ZEND_API int add_assoc_zval_ex(zval *arg, const char *key, uint key_len, zval *value) /* {{{ */
  700. {
  701. return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, &value, sizeof(zval *), NULL);
  702. }
  703. /* }}} */
  704. ZEND_API int add_index_long(zval *arg, ulong index, long n) /* {{{ */
  705. {
  706. zval *tmp;
  707. MAKE_STD_ZVAL(tmp);
  708. ZVAL_LONG(tmp, n);
  709. return zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp, sizeof(zval *), NULL);
  710. }
  711. /* }}} */
  712. ZEND_API int add_index_null(zval *arg, ulong index) /* {{{ */
  713. {
  714. zval *tmp;
  715. MAKE_STD_ZVAL(tmp);
  716. ZVAL_NULL(tmp);
  717. return zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp, sizeof(zval *), NULL);
  718. }
  719. /* }}} */
  720. ZEND_API int add_index_bool(zval *arg, ulong index, int b) /* {{{ */
  721. {
  722. zval *tmp;
  723. MAKE_STD_ZVAL(tmp);
  724. ZVAL_BOOL(tmp, b);
  725. return zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp, sizeof(zval *), NULL);
  726. }
  727. /* }}} */
  728. ZEND_API int add_index_resource(zval *arg, ulong index, int r) /* {{{ */
  729. {
  730. zval *tmp;
  731. MAKE_STD_ZVAL(tmp);
  732. ZVAL_RESOURCE(tmp, r);
  733. return zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp, sizeof(zval *), NULL);
  734. }
  735. /* }}} */
  736. ZEND_API int add_index_double(zval *arg, ulong index, double d) /* {{{ */
  737. {
  738. zval *tmp;
  739. MAKE_STD_ZVAL(tmp);
  740. ZVAL_DOUBLE(tmp, d);
  741. return zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp, sizeof(zval *), NULL);
  742. }
  743. /* }}} */
  744. ZEND_API int add_index_string(zval *arg, ulong index, const char *str, int duplicate) /* {{{ */
  745. {
  746. zval *tmp;
  747. MAKE_STD_ZVAL(tmp);
  748. ZVAL_STRING(tmp, str, duplicate);
  749. return zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp, sizeof(zval *), NULL);
  750. }
  751. /* }}} */
  752. ZEND_API int add_index_stringl(zval *arg, ulong index, const char *str, uint length, int duplicate) /* {{{ */
  753. {
  754. zval *tmp;
  755. MAKE_STD_ZVAL(tmp);
  756. ZVAL_STRINGL(tmp, str, length, duplicate);
  757. return zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp, sizeof(zval *), NULL);
  758. }
  759. /* }}} */
  760. ZEND_API int add_index_zval(zval *arg, ulong index, zval *value) /* {{{ */
  761. {
  762. return zend_hash_index_update(Z_ARRVAL_P(arg), index, &value, sizeof(zval *), NULL);
  763. }
  764. /* }}} */
  765. ZEND_API int add_next_index_long(zval *arg, long n) /* {{{ */
  766. {
  767. zval *tmp;
  768. MAKE_STD_ZVAL(tmp);
  769. ZVAL_LONG(tmp, n);
  770. return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL);
  771. }
  772. /* }}} */
  773. ZEND_API int add_next_index_null(zval *arg) /* {{{ */
  774. {
  775. zval *tmp;
  776. MAKE_STD_ZVAL(tmp);
  777. ZVAL_NULL(tmp);
  778. return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL);
  779. }
  780. /* }}} */
  781. ZEND_API int add_next_index_bool(zval *arg, int b) /* {{{ */
  782. {
  783. zval *tmp;
  784. MAKE_STD_ZVAL(tmp);
  785. ZVAL_BOOL(tmp, b);
  786. return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL);
  787. }
  788. /* }}} */
  789. ZEND_API int add_next_index_resource(zval *arg, int r) /* {{{ */
  790. {
  791. zval *tmp;
  792. MAKE_STD_ZVAL(tmp);
  793. ZVAL_RESOURCE(tmp, r);
  794. return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL);
  795. }
  796. /* }}} */
  797. ZEND_API int add_next_index_double(zval *arg, double d) /* {{{ */
  798. {
  799. zval *tmp;
  800. MAKE_STD_ZVAL(tmp);
  801. ZVAL_DOUBLE(tmp, d);
  802. return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL);
  803. }
  804. /* }}} */
  805. ZEND_API int add_next_index_string(zval *arg, const char *str, int duplicate) /* {{{ */
  806. {
  807. zval *tmp;
  808. MAKE_STD_ZVAL(tmp);
  809. ZVAL_STRING(tmp, str, duplicate);
  810. return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL);
  811. }
  812. /* }}} */
  813. ZEND_API int add_next_index_stringl(zval *arg, const char *str, uint length, int duplicate) /* {{{ */
  814. {
  815. zval *tmp;
  816. MAKE_STD_ZVAL(tmp);
  817. ZVAL_STRINGL(tmp, str, length, duplicate);
  818. return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL);
  819. }
  820. /* }}} */
  821. ZEND_API int add_next_index_zval(zval *arg, zval *value) /* {{{ */
  822. {
  823. return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &value, sizeof(zval *), NULL);
  824. }
  825. /* }}} */
  826. ZEND_API int add_get_assoc_string_ex(zval *arg, const char *key, uint key_len, const char *str, void **dest, int duplicate) /* {{{ */
  827. {
  828. zval *tmp;
  829. MAKE_STD_ZVAL(tmp);
  830. ZVAL_STRING(tmp, str, duplicate);
  831. return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, &tmp, sizeof(zval *), dest);
  832. }
  833. /* }}} */
  834. ZEND_API int add_get_assoc_stringl_ex(zval *arg, const char *key, uint key_len, const char *str, uint length, void **dest, int duplicate) /* {{{ */
  835. {
  836. zval *tmp;
  837. MAKE_STD_ZVAL(tmp);
  838. ZVAL_STRINGL(tmp, str, length, duplicate);
  839. return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, &tmp, sizeof(zval *), dest);
  840. }
  841. /* }}} */
  842. ZEND_API int add_get_index_long(zval *arg, ulong index, long l, void **dest) /* {{{ */
  843. {
  844. zval *tmp;
  845. MAKE_STD_ZVAL(tmp);
  846. ZVAL_LONG(tmp, l);
  847. return zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp, sizeof(zval *), dest);
  848. }
  849. /* }}} */
  850. ZEND_API int add_get_index_double(zval *arg, ulong index, double d, void **dest) /* {{{ */
  851. {
  852. zval *tmp;
  853. MAKE_STD_ZVAL(tmp);
  854. ZVAL_DOUBLE(tmp, d);
  855. return zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp, sizeof(zval *), dest);
  856. }
  857. /* }}} */
  858. ZEND_API int add_get_index_string(zval *arg, ulong index, const char *str, void **dest, int duplicate) /* {{{ */
  859. {
  860. zval *tmp;
  861. MAKE_STD_ZVAL(tmp);
  862. ZVAL_STRING(tmp, str, duplicate);
  863. return zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp, sizeof(zval *), dest);
  864. }
  865. /* }}} */
  866. ZEND_API int add_get_index_stringl(zval *arg, ulong index, const char *str, uint length, void **dest, int duplicate) /* {{{ */
  867. {
  868. zval *tmp;
  869. MAKE_STD_ZVAL(tmp);
  870. ZVAL_STRINGL(tmp, str, length, duplicate);
  871. return zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp, sizeof(zval *), dest);
  872. }
  873. /* }}} */
  874. ZEND_API int array_set_zval_key(HashTable *ht, zval *key, zval *value) /* {{{ */
  875. {
  876. int result;
  877. switch (Z_TYPE_P(key)) {
  878. case IS_STRING:
  879. result = zend_symtable_update(ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, &value, sizeof(zval *), NULL);
  880. break;
  881. case IS_NULL:
  882. result = zend_symtable_update(ht, "", 1, &value, sizeof(zval *), NULL);
  883. break;
  884. case IS_RESOURCE:
  885. zend_error(E_STRICT, "Resource ID#%ld used as offset, casting to integer (%ld)", Z_LVAL_P(key), Z_LVAL_P(key));
  886. /* break missing intentionally */
  887. case IS_BOOL:
  888. case IS_LONG:
  889. result = zend_hash_index_update(ht, Z_LVAL_P(key), &value, sizeof(zval *), NULL);
  890. break;
  891. case IS_DOUBLE:
  892. result = zend_hash_index_update(ht, zend_dval_to_lval(Z_DVAL_P(key)), &value, sizeof(zval *), NULL);
  893. break;
  894. default:
  895. zend_error(E_WARNING, "Illegal offset type");
  896. result = FAILURE;
  897. }
  898. if (result == SUCCESS) {
  899. Z_ADDREF_P(value);
  900. }
  901. return result;
  902. }
  903. /* }}} */
  904. ZEND_API zend_bool zend_is_callable_ex(zval *callable, zval *object_ptr, uint check_flags, char **callable_name, int *callable_name_len, zend_fcall_info_cache *fcc, char **error TSRMLS_DC) /* {{{ */
  905. {
  906. HPHP::Variant name;
  907. HPHP::RefData* nameRef = nullptr;
  908. int callable_name_len_local;
  909. zend_fcall_info_cache fcc_local;
  910. if (callable_name) {
  911. *callable_name = NULL;
  912. tvBox(name.asTypedValue());
  913. nameRef = name.asTypedValue()->m_data.pref;
  914. }
  915. if (callable_name_len == NULL) {
  916. callable_name_len = &callable_name_len_local;
  917. }
  918. if (fcc == NULL) {
  919. fcc = &fcc_local;
  920. }
  921. fcc->initialized = 0;
  922. fcc->calling_scope = NULL;
  923. fcc->called_scope = NULL;
  924. fcc->function_handler = NULL;
  925. fcc->calling_scope = NULL;
  926. fcc->object_ptr = NULL;
  927. bool b = is_callable(
  928. tvAsVariant(callable->tv()),
  929. check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY,
  930. nameRef);
  931. if (b) {
  932. if (callable_name) {
  933. HPHP::StringData *sd = name.getStringData();
  934. *callable_name = (char*) emalloc(sd->size() + 1);
  935. memcpy(*callable_name, sd->data(), sd->size() + 1);
  936. *callable_name_len = sd->size();
  937. }
  938. // This is mostly a lie -- we don't use zend_fcall_info_cache, so don't set
  939. // its members. Callers depending on fields of this structure will probably
  940. // fail.
  941. fcc->initialized = 1;
  942. }
  943. return b;
  944. }
  945. ZEND_API zend_bool zend_is_callable(zval *callable, uint check_flags, char **callable_name TSRMLS_DC) {
  946. return zend_is_callable_ex(callable, NULL, check_flags, callable_name, NULL, NULL, NULL TSRMLS_CC);
  947. }
  948. ZEND_API int zend_fcall_info_init(zval *callable, uint check_flags, zend_fcall_info *fci, zend_fcall_info_cache *fcc, char **callable_name, char **error TSRMLS_DC) /* {{{ */
  949. {
  950. if (!zend_is_callable_ex(callable, NULL, check_flags, callable_name, NULL, fcc, error TSRMLS_CC)) {
  951. return FAILURE;
  952. }
  953. fci->size = sizeof(*fci);
  954. // In Zend, object_ptr would be set to the Callable object, but here, all the
  955. // magic is in callable, so we just set this to NULL as if it were a global
  956. // function, and hope nobody will notice.
  957. fci->object_ptr = NULL;
  958. fci->function_name = callable;
  959. fci->retval_ptr_ptr = NULL;
  960. fci->param_count = 0;
  961. fci->params = NULL;
  962. fci->no_separation = 1;
  963. fci->symbol_table = NULL;
  964. return SUCCESS;
  965. }
  966. /* }}} */
  967. ZEND_API void zend_fcall_info_args_clear(zend_fcall_info *fci, int free_mem) /* {{{ */
  968. {
  969. if (fci->params) {
  970. if (free_mem) {
  971. efree(fci->params);
  972. fci->params = nullptr;
  973. }
  974. }
  975. fci->param_count = 0;
  976. }
  977. /* }}} */
  978. ZEND_API void zend_fcall_info_args_save(zend_fcall_info *fci, int *param_count, zval ****params) /* {{{ */
  979. {
  980. *param_count = fci->param_count;
  981. *params = fci->params;
  982. fci->param_count = 0;
  983. fci->params = nullptr;
  984. }
  985. /* }}} */
  986. ZEND_API void zend_fcall_info_args_restore(zend_fcall_info *fci, int param_count, zval ***params) /* {{{ */
  987. {
  988. zend_fcall_info_args_clear(fci, 1);
  989. fci->param_count = param_count;
  990. fci->params = params;
  991. }
  992. /* }}} */
  993. ZEND_API int zend_fcall_info_args(zend_fcall_info *fci, zval *args TSRMLS_DC) /* {{{ */
  994. {
  995. HashPosition pos;
  996. zval **arg, ***params;
  997. zend_fcall_info_args_clear(fci, !args);
  998. if (!args) {
  999. return SUCCESS;
  1000. }
  1001. if (Z_TYPE_P(args) != IS_ARRAY) {
  1002. return FAILURE;
  1003. }
  1004. fci->param_count = zend_hash_num_elements(Z_ARRVAL_P(args));
  1005. fci->params = params =
  1006. (zval ***) erealloc(fci->params, fci->param_count * sizeof(zval **));
  1007. zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(args), &pos);
  1008. while (zend_hash_get_current_data_ex(Z_ARRVAL_P(args),
  1009. (void **) &arg, &pos) == SUCCESS) {
  1010. *params++ = arg;
  1011. zend_hash_move_forward_ex(Z_ARRVAL_P(args), &pos);
  1012. }
  1013. return SUCCESS;
  1014. }
  1015. /* }}} */
  1016. ZEND_API int zend_fcall_info_call(zend_fcall_info *fci, zend_fcall_info_cache *fcc, zval **retval_ptr_ptr, zval *args TSRMLS_DC) /* {{{ */
  1017. {
  1018. zval *retval, ***org_params = NULL;
  1019. int result, org_count = 0;
  1020. fci->retval_ptr_ptr = retval_ptr_ptr ? retval_ptr_ptr : &retval;
  1021. if (args) {
  1022. zend_fcall_info_args_save(fci, &org_count, &org_params);
  1023. zend_fcall_info_args(fci, args TSRMLS_CC);
  1024. }
  1025. result = zend_call_function(fci, fcc TSRMLS_CC);
  1026. if (!retval_ptr_ptr && retval) {
  1027. zval_ptr_dtor(&retval);
  1028. }
  1029. if (args) {
  1030. zend_fcall_info_args_restore(fci, org_count, org_params);
  1031. }
  1032. return result;
  1033. }
  1034. /* }}} */
  1035. ZEND_API int _array_init(zval *arg, uint size ZEND_FILE_LINE_DC) {
  1036. ALLOC_HASHTABLE(Z_ARRVAL_P(arg));
  1037. _zend_hash_init(Z_ARRVAL_P(arg), size, NULL, ZVAL_PTR_DTOR, 0 ZEND_FILE_LINE_RELAY_CC);
  1038. Z_TYPE_P(arg) = IS_ARRAY;
  1039. return SUCCESS;
  1040. }
  1041. /* returns 1 if you need to copy result, 0 if it's already a copy */
  1042. ZEND_API int zend_get_object_classname(const zval *object, const char **class_name, zend_uint *class_name_len TSRMLS_DC) {
  1043. zend_class_entry* ce = zend_get_class_entry(object TSRMLS_CC);
  1044. *class_name_len = ce->name_length;
  1045. *class_name = estrndup(ce->name, *class_name_len);
  1046. return 0;
  1047. }
  1048. ZEND_API void zend_update_property_null(zend_class_entry *scope, zval *object, const char *name, int name_length TSRMLS_DC) /* {{{ */
  1049. {
  1050. zval *tmp;
  1051. ALLOC_ZVAL(tmp);
  1052. Z_UNSET_ISREF_P(tmp);
  1053. ZVAL_NULL(tmp);
  1054. SCOPE_EXIT { releaseZval(tmp); };
  1055. zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC);
  1056. }
  1057. /* }}} */
  1058. ZEND_API void zend_update_property_bool(zend_class_entry *scope, zval *object, const char *name, int name_length, long value TSRMLS_DC) /* {{{ */
  1059. {
  1060. zval *tmp;
  1061. ALLOC_ZVAL(tmp);
  1062. Z_UNSET_ISREF_P(tmp);
  1063. ZVAL_BOOL(tmp, value);
  1064. SCOPE_EXIT { releaseZval(tmp); };
  1065. zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC);
  1066. }
  1067. /* }}} */
  1068. ZEND_API void zend_update_property_long(zend_class_entry *scope, zval *object, const char *name, int name_length, long value TSRMLS_DC) /* {{{ */
  1069. {
  1070. zval *tmp;
  1071. ALLOC_ZVAL(tmp);
  1072. Z_UNSET_ISREF_P(tmp);
  1073. ZVAL_LONG(tmp, value);
  1074. SCOPE_EXIT { releaseZval(tmp); };
  1075. zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC);
  1076. }
  1077. /* }}} */
  1078. ZEND_API void zend_update_property_double(zend_class_entry *scope, zval *object, const char *name, int name_length, double value TSRMLS_DC) /* {{{ */
  1079. {
  1080. zval *tmp;
  1081. ALLOC_ZVAL(tmp);
  1082. Z_UNSET_ISREF_P(tmp);
  1083. ZVAL_DOUBLE(tmp, value);
  1084. SCOPE_EXIT { releaseZval(tmp); };
  1085. zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC);
  1086. }
  1087. /* }}} */
  1088. ZEND_API void zend_update_property_string(zend_class_entry *scope, zval *object, const char *name, int name_length, const char *value TSRMLS_DC) /* {{{ */
  1089. {
  1090. zval *tmp;
  1091. ALLOC_ZVAL(tmp);
  1092. Z_UNSET_ISREF_P(tmp);
  1093. ZVAL_STRING(tmp, value, 1);
  1094. SCOPE_EXIT { releaseZval(tmp); };
  1095. zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC);
  1096. }
  1097. /* }}} */
  1098. ZEND_API void zend_update_property_stringl(zend_class_entry *scope, zval *object, const char *name, int name_length, const char *value, int value_len TSRMLS_DC) /* {{{ */
  1099. {
  1100. zval *tmp;
  1101. ALLOC_ZVAL(tmp);
  1102. Z_UNSET_ISREF_P(tmp);
  1103. ZVAL_STRINGL(tmp, value, value_len, 1);
  1104. SCOPE_EXIT { releaseZval(tmp); };
  1105. zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC);
  1106. }
  1107. /* }}} */
  1108. ZEND_API int _object_init_ex(zval *arg, zend_class_entry *class_type ZEND_FILE_LINE_DC TSRMLS_DC) /* {{{ */
  1109. {
  1110. return _object_and_properties_init(arg, class_type, 0 ZEND_FILE_LINE_RELAY_CC TSRMLS_CC);
  1111. }
  1112. /* }}} */
  1113. ZEND_API int _object_init(zval *arg ZEND_FILE_LINE_DC TSRMLS_DC) /* {{{ */
  1114. {
  1115. return _object_init_ex(arg, get_zend_standard_class_def() ZEND_FILE_LINE_RELAY_CC TSRMLS_CC);
  1116. }
  1117. /* }}} */
  1118. ZEND_API int zend_declare_property(zend_class_entry *ce, const char *name, int name_length, zval *property, int access_type TSRMLS_DC) /* {{{ */
  1119. {
  1120. // Done by our system library
  1121. return SUCCESS;
  1122. }
  1123. /* }}} */
  1124. ZEND_API int zend_declare_property_null(zend_class_entry *ce, const char *name, int name_length, int access_type TSRMLS_DC) /* {{{ */
  1125. {
  1126. // Done by our system library
  1127. return SUCCESS;
  1128. }
  1129. /* }}} */
  1130. ZEND_API int zend_declare_property_bool(zend_class_entry *ce, const char *name, int name_length, long value, int access_type TSRMLS_DC) /* {{{ */
  1131. {
  1132. // Done by our system library
  1133. return SUCCESS;
  1134. }
  1135. /* }}} */
  1136. ZEND_API int zend_declare_property_long(zend_class_entry *ce, const char *name, int name_length, long value, int access_type TSRMLS_DC) /* {{{ */
  1137. {
  1138. // Done by our system library
  1139. return SUCCESS;
  1140. }
  1141. /* }}} */
  1142. ZEND_API int zend_declare_property_double(zend_class_entry *ce, const char *name, int name_length, double value, int access_type TSRMLS_DC) /* {{{ */
  1143. {
  1144. // Done by our system library
  1145. return SUCCESS;
  1146. }
  1147. /* }}} */
  1148. ZEND_API int zend_declare_property_string(zend_class_entry *ce, const char *name, int name_length, const char *value, int access_type TSRMLS_DC) /* {{{ */
  1149. {
  1150. // Done by our system library
  1151. return SUCCESS;
  1152. }
  1153. /* }}} */
  1154. ZEND_API int zend_declare_property_stringl(zend_class_entry *ce, const char *name, int name_length, const char *value, int value_len, int access_type TSRMLS_DC) /* {{{ */
  1155. {
  1156. // Done by our system library
  1157. return SUCCESS;
  1158. }
  1159. /* }}} */
  1160. ZEND_API int zend_declare_class_constant(zend_class_entry *ce,
  1161. const char *name, size_t name_length, zval *value TSRMLS_DC) /* {{{ */
  1162. {
  1163. using namespace HPHP;
  1164. Native::registerClassConstant(
  1165. makeStaticString(ce->name, ce->name_length),
  1166. makeStaticString(name, name_length),
  1167. *value->tv());
  1168. return SUCCESS;
  1169. }
  1170. /* }}} */
  1171. ZEND_API int zend_declare_class_constant_null(zend_class_entry *ce,
  1172. const char *name, size_t name_length TSRMLS_DC) /* {{{ */
  1173. {
  1174. using namespace HPHP;
  1175. Native::registerClassConstant(
  1176. makeStaticString(ce->name, ce->name_length),
  1177. makeStaticString(name, name_length),
  1178. make_tv<KindOfNull>());
  1179. return SUCCESS;
  1180. }
  1181. /* }}} */
  1182. ZEND_API int zend_declare_class_constant_long(zend_class_entry *ce,
  1183. const char *name, size_t name_length, long value TSRMLS_DC) /* {{{ */
  1184. {
  1185. using namespace HPHP;
  1186. Native::registerClassConstant(
  1187. makeStaticString(ce->name, ce->name_length),
  1188. makeStaticString(name, name_length),
  1189. make_tv<KindOfInt64>(value));
  1190. return SUCCESS;
  1191. }
  1192. /* }}} */
  1193. ZEND_API int zend_declare_class_constant_bool(zend_class_entry *ce,
  1194. const char *name, size_t name_length, zend_bool value TSRMLS_DC) /* {{{ */
  1195. {
  1196. using namespace HPHP;
  1197. Native::registerClassConstant(
  1198. makeStaticString(ce->name, ce->name_length),
  1199. makeStaticString(name, name_length),
  1200. make_tv<KindOfBoolean>((bool)value));
  1201. return SUCCESS;
  1202. }
  1203. /* }}} */
  1204. ZEND_API int zend_declare_class_constant_double(zend_class_entry *ce,
  1205. const char *name, size_t name_length, double value TSRMLS_DC) /* {{{ */
  1206. {
  1207. using namespace HPHP;
  1208. Native::registerClassConstant(
  1209. makeStaticString(ce->name, ce->name_length),
  1210. makeStaticString(name, name_length),
  1211. make_tv<KindOfDouble>(value));
  1212. return SUCCESS;
  1213. }
  1214. /* }}} */
  1215. ZEND_API int zend_declare_class_constant_stringl(zend_class_entry *ce,
  1216. const char *name, size_t name_length,
  1217. const char *value, size_t value_length TSRMLS_DC) /* {{{ */
  1218. {
  1219. using namespace HPHP;
  1220. Native::registerClassConstant(
  1221. makeStaticString(ce->name, ce->name_length),
  1222. makeStaticString(name, name_length),
  1223. make_tv<KindOfPersistentString>(
  1224. makeStaticString(value, value_length)));
  1225. return SUCCESS;
  1226. }
  1227. /* }}} */
  1228. ZEND_API int zend_declare_class_constant_string(zend_class_entry *ce,
  1229. const char *name, size_t name_length, const char *value TSRMLS_DC) /* {{{ */
  1230. {
  1231. using namespace HPHP;
  1232. Native::registerClassConstant(
  1233. makeStaticString(ce->name, ce->name_length),
  1234. makeStaticString(name, name_length),
  1235. make_tv<KindOfPersistentString>(makeStaticString(value)));
  1236. return SUCCESS;
  1237. }
  1238. /* }}} */
  1239. ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, const char *name, int name_length, zval *value TSRMLS_DC) {
  1240. HPHP::String key(name, name_length, HPHP::CopyString);
  1241. HPHP::String context(scope->name);
  1242. Z_OBJVAL_P(object)->o_set(key, tvAsVariant(value->tv()), context);
  1243. }
  1244. ZEND_API int zend_update_static_property(zend_class_entry *scope, const char *name, int name_length, zval *value TSRMLS_DC) {
  1245. HPHP::Class * cls = HPHP::zend_hphp_class_entry_to_class(scope);
  1246. if (!cls) {
  1247. return FAILURE;
  1248. }
  1249. HPHP::String sname(name, name_length, HPHP::CopyString);
  1250. auto const lookup = cls->getSProp(cls, sname.get());
  1251. if (!lookup.prop) return FAILURE;
  1252. HPHP::tvSetZval(value, lookup.prop);
  1253. return SUCCESS;
  1254. }
  1255. ZEND_API int zend_update_static_property_null(zend_class_entry *scope, const char *name, int name_length TSRMLS_DC) /* {{{ */
  1256. {
  1257. zval *tmp;
  1258. ALLOC_ZVAL(tmp);
  1259. Z_UNSET_ISREF_P(tmp);
  1260. ZVAL_NULL(tmp);
  1261. SCOPE_EXIT { releaseZval(tmp); };
  1262. return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC);
  1263. }
  1264. /* }}} */
  1265. ZEND_API int zend_update_static_property_bool(zend_class_entry *scope, const char *name, int name_length, long value TSRMLS_DC) /* {{{ */
  1266. {
  1267. zval *tmp;
  1268. ALLOC_ZVAL(tmp);
  1269. Z_UNSET_ISREF_P(tmp);
  1270. ZVAL_BOOL(tmp, value);
  1271. SCOPE_EXIT { releaseZval(tmp); };
  1272. return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC);
  1273. }
  1274. /* }}} */
  1275. ZEND_API int zend_update_static_property_long(zend_class_entry *scope, const char *name, int name_length, long value TSRMLS_DC) /* {{{ */
  1276. {
  1277. zval *tmp;
  1278. ALLOC_ZVAL(tmp);
  1279. Z_UNSET_ISREF_P(tmp);
  1280. ZVAL_LONG(tmp, value);
  1281. SCOPE_EXIT { releaseZval(tmp); };
  1282. return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC);
  1283. }
  1284. /* }}} */
  1285. ZEND_API int zend_update_static_property_double(zend_class_entry *scope, const char *name, int name_length, double value TSRMLS_DC) /* {{{ */
  1286. {
  1287. zval *tmp;
  1288. ALLOC_ZVAL(tmp);
  1289. Z_UNSET_ISREF_P(tmp);
  1290. ZVAL_DOUBLE(tmp, value);
  1291. SCOPE_EXIT { releaseZval(tmp); };
  1292. return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC);
  1293. }
  1294. /* }}} */
  1295. ZEND_API int zend_update_static_property_string(zend_class_entry *scope, const char *name, int name_length, const char *value TSRMLS_DC) /* {{{ */
  1296. {
  1297. zval *tmp;
  1298. ALLOC_ZVAL(tmp);
  1299. Z_UNSET_ISREF_P(tmp);
  1300. ZVAL_STRING(tmp, value, 1);
  1301. SCOPE_EXIT { releaseZval(tmp); };
  1302. return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC);
  1303. }
  1304. /* }}} */
  1305. ZEND_API int zend_update_static_property_stringl(zend_class_entry *scope, const char *name, int name_length, const char *value, int value_len TSRMLS_DC) /* {{{ */
  1306. {
  1307. zval *tmp;
  1308. ALLOC_ZVAL(tmp);
  1309. Z_UNSET_ISREF_P(tmp);
  1310. ZVAL_STRINGL(tmp, value, value_len, 1);
  1311. SCOPE_EXIT { releaseZval(tmp); };
  1312. return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC);
  1313. }
  1314. /* }}} */
  1315. ZEND_API zend_class_entry *zend_register_internal_class(zend_class_entry *orig_class_entry TSRMLS_DC) {
  1316. // Create the class entry and associate it with an HPHP::Class if possible
  1317. zend_class_entry * ce;
  1318. zend_class_entry * oce = orig_class_entry;
  1319. HPHP::StringData * sd = HPHP::makeStaticString(oce->name, oce->name_length);
  1320. HPHP::Class * cls = HPHP::Unit::lookupClass(sd);
  1321. if (cls) {
  1322. ce = HPHP::zend_hphp_class_to_class_entry(cls);
  1323. } else {
  1324. // System library not loaded yet -- defer initialisation of ce->hphp_class
  1325. ce = HPHP::zend_hphp_register_internal_class_entry(sd);
  1326. }
  1327. ce->create_object = oce->create_object;
  1328. // Register functions
  1329. const zend_function_entry * fe = oce->info.internal.builtin_functions;
  1330. if (fe) {
  1331. while (fe->fname) {
  1332. if (!fe->handler) {
  1333. // This is allowed for abstract functions
  1334. continue;
  1335. }
  1336. HPHP::String name(sd);
  1337. if (fe->flags & ZEND_ACC_STATIC) {
  1338. name += "::";
  1339. } else {
  1340. name += "->";
  1341. }
  1342. name += fe->fname;
  1343. HPHP::Native::registerBuiltinZendFunction(name, fe->handler);
  1344. fe++;
  1345. }
  1346. }
  1347. return ce;
  1348. }
  1349. ZEND_API void zend_class_implements(zend_class_entry *class_entry TSRMLS_DC, int num_interfaces, ...) {
  1350. // Done by the system library
  1351. }
  1352. ZEND_API void object_properties_init(zend_object *object, zend_class_entry *class_type) {
  1353. }
  1354. /* This function requires 'properties' to contain all props declared in the
  1355. * class and all props being public. If only a subset is given or the class
  1356. * has protected members then you need to merge the properties separately by
  1357. * calling zend_merge_properties(). */
  1358. ZEND_API int _object_and_properties_init(zval *arg, zend_class_entry *class_type, HashTable *properties ZEND_FILE_LINE_DC TSRMLS_DC) {
  1359. assert(properties == 0);
  1360. // Why is there no ZVAL_OBJVAL?
  1361. HPHP::Class * cls = HPHP::zend_hphp_class_entry_to_class(class_type);
  1362. if (!cls) {
  1363. // You can't call this function from MINIT, sorry
  1364. HPHP::raise_error("cannot create object of class %s. "
  1365. "Is the system library not loaded yet?", class_type->name);
  1366. return FAILURE;
  1367. }
  1368. Z_OBJVAL_P(arg) = HPHP::Object{cls}.detach();
  1369. Z_TYPE_P(arg) = IS_OBJECT;
  1370. return SUCCESS;
  1371. }
  1372. ZEND_API zval *zend_read_property(zend_class_entry *scope, zval *object, const char *name, int name_length, zend_bool silent TSRMLS_DC) {
  1373. HPHP::String prop_name(name, name_length, HPHP::CopyString);
  1374. HPHP::String scope_name(scope->name, scope->name_length, HPHP::CopyString);
  1375. HPHP::Class* ctx = nullptr;
  1376. if (!scope_name.empty()) {
  1377. ctx = HPHP::Unit::lookupClass(scope_name.get());
  1378. }
  1379. auto const lookup = Z_OBJVAL_P(object)->getProp(ctx, prop_name.get());
  1380. auto const prop = lookup.prop;
  1381. if (!lookup.accessible || prop->m_type == HPHP::KindOfUninit) return nullptr;
  1382. if (prop->m_type != HPHP::KindOfRef) {
  1383. tvBox(prop);
  1384. }
  1385. return prop->m_data.pref;
  1386. }
  1387. ZEND_API zval *zend_read_static_property(zend_class_entry *scope, const char *name, int name_length, zend_bool silent TSRMLS_DC) {
  1388. auto const cls = HPHP::zend_hphp_class_entry_to_class(scope);
  1389. if (!cls) {
  1390. // You can't call this function from MINIT, sorry
  1391. HPHP::raise_error("cannot read property of class %s. "
  1392. "Is the system library not loaded yet?", scope->name);
  1393. return nullptr;
  1394. }
  1395. HPHP::String sname(name, name_length, HPHP::CopyString);
  1396. auto const lookup = cls->getSProp(cls, sname.get());
  1397. auto const prop = lookup.prop;
  1398. // Static properties should never be Uninit.
  1399. assert(!prop || prop->m_type != HPHP::KindOfUninit);
  1400. if (!prop || !lookup.accessible) return nullptr;
  1401. if (prop->m_type != HPHP::KindOfRef) {
  1402. tvBox(prop);
  1403. }
  1404. return prop->m_data.pref;
  1405. }
  1406. ZEND_API zend_class_entry *zend_register_internal_class_ex(zend_class_entry *class_entry, zend_class_entry *parent_ce, char *parent_name TSRMLS_DC) {
  1407. auto ret = zend_register_internal_class(class_entry TSRMLS_CC);
  1408. if (parent_ce) {
  1409. ret->create_object = parent_ce->create_object;
  1410. }
  1411. return ret;
  1412. }