PageRenderTime 110ms CodeModel.GetById 48ms RepoModel.GetById 1ms app.codeStats 0ms

/Zend/zend_constants.c

http://github.com/infusion/PHP
C | 450 lines | 342 code | 70 blank | 38 comment | 83 complexity | d9c7454cab53685827d7a9316f7746e0 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, LGPL-2.1, BSD-3-Clause
  1. /*
  2. +----------------------------------------------------------------------+
  3. | Zend Engine |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1998-2011 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. +----------------------------------------------------------------------+
  18. */
  19. /* $Id: zend_constants.c 307522 2011-01-16 20:39:22Z stas $ */
  20. #include "zend.h"
  21. #include "zend_constants.h"
  22. #include "zend_execute.h"
  23. #include "zend_variables.h"
  24. #include "zend_operators.h"
  25. #include "zend_globals.h"
  26. void free_zend_constant(zend_constant *c)
  27. {
  28. if (!(c->flags & CONST_PERSISTENT)) {
  29. zval_dtor(&c->value);
  30. }
  31. free(c->name);
  32. }
  33. void copy_zend_constant(zend_constant *c)
  34. {
  35. c->name = zend_strndup(c->name, c->name_len - 1);
  36. if (!(c->flags & CONST_PERSISTENT)) {
  37. zval_copy_ctor(&c->value);
  38. }
  39. }
  40. void zend_copy_constants(HashTable *target, HashTable *source)
  41. {
  42. zend_constant tmp_constant;
  43. zend_hash_copy(target, source, (copy_ctor_func_t) copy_zend_constant, &tmp_constant, sizeof(zend_constant));
  44. }
  45. static int clean_non_persistent_constant(const zend_constant *c TSRMLS_DC)
  46. {
  47. return (c->flags & CONST_PERSISTENT) ? ZEND_HASH_APPLY_STOP : ZEND_HASH_APPLY_REMOVE;
  48. }
  49. static int clean_non_persistent_constant_full(const zend_constant *c TSRMLS_DC)
  50. {
  51. return (c->flags & CONST_PERSISTENT) ? 0 : 1;
  52. }
  53. static int clean_module_constant(const zend_constant *c, int *module_number TSRMLS_DC)
  54. {
  55. if (c->module_number == *module_number) {
  56. return 1;
  57. } else {
  58. return 0;
  59. }
  60. }
  61. void clean_module_constants(int module_number TSRMLS_DC)
  62. {
  63. zend_hash_apply_with_argument(EG(zend_constants), (apply_func_arg_t) clean_module_constant, (void *) &module_number TSRMLS_CC);
  64. }
  65. int zend_startup_constants(TSRMLS_D)
  66. {
  67. EG(zend_constants) = (HashTable *) malloc(sizeof(HashTable));
  68. if (zend_hash_init(EG(zend_constants), 20, NULL, ZEND_CONSTANT_DTOR, 1)==FAILURE) {
  69. return FAILURE;
  70. }
  71. return SUCCESS;
  72. }
  73. void zend_register_standard_constants(TSRMLS_D)
  74. {
  75. REGISTER_MAIN_LONG_CONSTANT("E_ERROR", E_ERROR, CONST_PERSISTENT | CONST_CS);
  76. REGISTER_MAIN_LONG_CONSTANT("E_RECOVERABLE_ERROR", E_RECOVERABLE_ERROR, CONST_PERSISTENT | CONST_CS);
  77. REGISTER_MAIN_LONG_CONSTANT("E_WARNING", E_WARNING, CONST_PERSISTENT | CONST_CS);
  78. REGISTER_MAIN_LONG_CONSTANT("E_PARSE", E_PARSE, CONST_PERSISTENT | CONST_CS);
  79. REGISTER_MAIN_LONG_CONSTANT("E_NOTICE", E_NOTICE, CONST_PERSISTENT | CONST_CS);
  80. REGISTER_MAIN_LONG_CONSTANT("E_STRICT", E_STRICT, CONST_PERSISTENT | CONST_CS);
  81. REGISTER_MAIN_LONG_CONSTANT("E_DEPRECATED", E_DEPRECATED, CONST_PERSISTENT | CONST_CS);
  82. REGISTER_MAIN_LONG_CONSTANT("E_CORE_ERROR", E_CORE_ERROR, CONST_PERSISTENT | CONST_CS);
  83. REGISTER_MAIN_LONG_CONSTANT("E_CORE_WARNING", E_CORE_WARNING, CONST_PERSISTENT | CONST_CS);
  84. REGISTER_MAIN_LONG_CONSTANT("E_COMPILE_ERROR", E_COMPILE_ERROR, CONST_PERSISTENT | CONST_CS);
  85. REGISTER_MAIN_LONG_CONSTANT("E_COMPILE_WARNING", E_COMPILE_WARNING, CONST_PERSISTENT | CONST_CS);
  86. REGISTER_MAIN_LONG_CONSTANT("E_USER_ERROR", E_USER_ERROR, CONST_PERSISTENT | CONST_CS);
  87. REGISTER_MAIN_LONG_CONSTANT("E_USER_WARNING", E_USER_WARNING, CONST_PERSISTENT | CONST_CS);
  88. REGISTER_MAIN_LONG_CONSTANT("E_USER_NOTICE", E_USER_NOTICE, CONST_PERSISTENT | CONST_CS);
  89. REGISTER_MAIN_LONG_CONSTANT("E_USER_DEPRECATED", E_USER_DEPRECATED, CONST_PERSISTENT | CONST_CS);
  90. REGISTER_MAIN_LONG_CONSTANT("E_ALL", E_ALL, CONST_PERSISTENT | CONST_CS);
  91. REGISTER_MAIN_LONG_CONSTANT("DEBUG_BACKTRACE_PROVIDE_OBJECT", DEBUG_BACKTRACE_PROVIDE_OBJECT, CONST_PERSISTENT | CONST_CS);
  92. REGISTER_MAIN_LONG_CONSTANT("DEBUG_BACKTRACE_IGNORE_ARGS", DEBUG_BACKTRACE_IGNORE_ARGS, CONST_PERSISTENT | CONST_CS);
  93. /* true/false constants */
  94. {
  95. zend_constant c;
  96. c.module_number = 0;
  97. c.flags = CONST_PERSISTENT;
  98. c.name = zend_strndup(ZEND_STRL("ZEND_THREAD_SAFE"));
  99. c.name_len = sizeof("ZEND_THREAD_SAFE");
  100. c.value.value.lval = ZTS_V;
  101. c.value.type = IS_BOOL;
  102. zend_register_constant(&c TSRMLS_CC);
  103. c.name = zend_strndup(ZEND_STRL("ZEND_DEBUG_BUILD"));
  104. c.name_len = sizeof("ZEND_DEBUG_BUILD");
  105. c.value.value.lval = ZEND_DEBUG;
  106. c.value.type = IS_BOOL;
  107. zend_register_constant(&c TSRMLS_CC);
  108. }
  109. }
  110. int zend_shutdown_constants(TSRMLS_D)
  111. {
  112. zend_hash_destroy(EG(zend_constants));
  113. free(EG(zend_constants));
  114. return SUCCESS;
  115. }
  116. void clean_non_persistent_constants(TSRMLS_D)
  117. {
  118. if (EG(full_tables_cleanup)) {
  119. zend_hash_apply(EG(zend_constants), (apply_func_t) clean_non_persistent_constant_full TSRMLS_CC);
  120. } else {
  121. zend_hash_reverse_apply(EG(zend_constants), (apply_func_t) clean_non_persistent_constant TSRMLS_CC);
  122. }
  123. }
  124. ZEND_API void zend_register_long_constant(const char *name, uint name_len, long lval, int flags, int module_number TSRMLS_DC)
  125. {
  126. zend_constant c;
  127. c.value.type = IS_LONG;
  128. c.value.value.lval = lval;
  129. c.flags = flags;
  130. c.name = zend_strndup(name, name_len-1);
  131. c.name_len = name_len;
  132. c.module_number = module_number;
  133. zend_register_constant(&c TSRMLS_CC);
  134. }
  135. ZEND_API void zend_register_double_constant(const char *name, uint name_len, double dval, int flags, int module_number TSRMLS_DC)
  136. {
  137. zend_constant c;
  138. c.value.type = IS_DOUBLE;
  139. c.value.value.dval = dval;
  140. c.flags = flags;
  141. c.name = zend_strndup(name, name_len-1);
  142. c.name_len = name_len;
  143. c.module_number = module_number;
  144. zend_register_constant(&c TSRMLS_CC);
  145. }
  146. ZEND_API void zend_register_stringl_constant(const char *name, uint name_len, char *strval, uint strlen, int flags, int module_number TSRMLS_DC)
  147. {
  148. zend_constant c;
  149. c.value.type = IS_STRING;
  150. c.value.value.str.val = strval;
  151. c.value.value.str.len = strlen;
  152. c.flags = flags;
  153. c.name = zend_strndup(name, name_len-1);
  154. c.name_len = name_len;
  155. c.module_number = module_number;
  156. zend_register_constant(&c TSRMLS_CC);
  157. }
  158. ZEND_API void zend_register_string_constant(const char *name, uint name_len, char *strval, int flags, int module_number TSRMLS_DC)
  159. {
  160. zend_register_stringl_constant(name, name_len, strval, strlen(strval), flags, module_number TSRMLS_CC);
  161. }
  162. ZEND_API int zend_get_constant(const char *name, uint name_len, zval *result TSRMLS_DC)
  163. {
  164. zend_constant *c;
  165. int retval = 1;
  166. char *lookup_name;
  167. if (zend_hash_find(EG(zend_constants), name, name_len+1, (void **) &c) == FAILURE) {
  168. lookup_name = zend_str_tolower_dup(name, name_len);
  169. if (zend_hash_find(EG(zend_constants), lookup_name, name_len+1, (void **) &c)==SUCCESS) {
  170. if (c->flags & CONST_CS) {
  171. retval=0;
  172. }
  173. } else {
  174. static char haltoff[] = "__COMPILER_HALT_OFFSET__";
  175. if (!EG(in_execution)) {
  176. retval = 0;
  177. } else if (name_len == sizeof("__COMPILER_HALT_OFFSET__")-1 &&
  178. !memcmp(name, "__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__")-1)) {
  179. char *cfilename, *haltname;
  180. int len, clen;
  181. cfilename = zend_get_executed_filename(TSRMLS_C);
  182. clen = strlen(cfilename);
  183. /* check for __COMPILER_HALT_OFFSET__ */
  184. zend_mangle_property_name(&haltname, &len, haltoff,
  185. sizeof("__COMPILER_HALT_OFFSET__") - 1, cfilename, clen, 0);
  186. if (zend_hash_find(EG(zend_constants), haltname, len+1, (void **) &c) == SUCCESS) {
  187. retval = 1;
  188. } else {
  189. retval=0;
  190. }
  191. pefree(haltname, 0);
  192. } else {
  193. retval=0;
  194. }
  195. }
  196. efree(lookup_name);
  197. }
  198. if (retval) {
  199. *result = c->value;
  200. zval_copy_ctor(result);
  201. Z_SET_REFCOUNT_P(result, 1);
  202. Z_UNSET_ISREF_P(result);
  203. }
  204. return retval;
  205. }
  206. ZEND_API int zend_get_constant_ex(const char *name, uint name_len, zval *result, zend_class_entry *scope, ulong flags TSRMLS_DC)
  207. {
  208. zend_constant *c;
  209. int retval = 1;
  210. char *colon;
  211. zend_class_entry *ce = NULL;
  212. char *class_name;
  213. zval **ret_constant;
  214. /* Skip leading \\ */
  215. if (name[0] == '\\') {
  216. name += 1;
  217. name_len -= 1;
  218. }
  219. if ((colon = zend_memrchr(name, ':', name_len)) &&
  220. colon > name && (*(colon - 1) == ':')) {
  221. int class_name_len = colon - name - 1;
  222. int const_name_len = name_len - class_name_len - 2;
  223. char *constant_name = colon + 1;
  224. char *lcname;
  225. class_name = estrndup(name, class_name_len);
  226. lcname = zend_str_tolower_dup(class_name, class_name_len);
  227. if (!scope) {
  228. if (EG(in_execution)) {
  229. scope = EG(scope);
  230. } else {
  231. scope = CG(active_class_entry);
  232. }
  233. }
  234. if (class_name_len == sizeof("self")-1 &&
  235. !memcmp(lcname, "self", sizeof("self")-1)) {
  236. if (scope) {
  237. ce = scope;
  238. } else {
  239. zend_error(E_ERROR, "Cannot access self:: when no class scope is active");
  240. retval = 0;
  241. }
  242. efree(lcname);
  243. } else if (class_name_len == sizeof("parent")-1 &&
  244. !memcmp(lcname, "parent", sizeof("parent")-1)) {
  245. if (!scope) {
  246. zend_error(E_ERROR, "Cannot access parent:: when no class scope is active");
  247. } else if (!scope->parent) {
  248. zend_error(E_ERROR, "Cannot access parent:: when current class scope has no parent");
  249. } else {
  250. ce = scope->parent;
  251. }
  252. efree(lcname);
  253. } else if (class_name_len == sizeof("static")-1 &&
  254. !memcmp(lcname, "static", sizeof("static")-1)) {
  255. if (EG(called_scope)) {
  256. ce = EG(called_scope);
  257. } else {
  258. zend_error(E_ERROR, "Cannot access static:: when no class scope is active");
  259. }
  260. efree(lcname);
  261. } else {
  262. efree(lcname);
  263. ce = zend_fetch_class(class_name, class_name_len, flags TSRMLS_CC);
  264. }
  265. if (retval && ce) {
  266. if (zend_hash_find(&ce->constants_table, constant_name, const_name_len+1, (void **) &ret_constant) != SUCCESS) {
  267. retval = 0;
  268. if ((flags & ZEND_FETCH_CLASS_SILENT) == 0) {
  269. zend_error(E_ERROR, "Undefined class constant '%s::%s'", class_name, constant_name);
  270. }
  271. }
  272. } else if (!ce) {
  273. retval = 0;
  274. }
  275. efree(class_name);
  276. goto finish;
  277. }
  278. /* non-class constant */
  279. if ((colon = zend_memrchr(name, '\\', name_len)) != NULL) {
  280. /* compound constant name */
  281. int prefix_len = colon - name;
  282. int const_name_len = name_len - prefix_len - 1;
  283. char *constant_name = colon + 1;
  284. char *lcname;
  285. int found_const = 0;
  286. lcname = zend_str_tolower_dup(name, prefix_len);
  287. /* Check for namespace constant */
  288. /* Concatenate lowercase namespace name and constant name */
  289. lcname = erealloc(lcname, prefix_len + 1 + const_name_len + 1);
  290. lcname[prefix_len] = '\\';
  291. memcpy(lcname + prefix_len + 1, constant_name, const_name_len + 1);
  292. if (zend_hash_find(EG(zend_constants), lcname, prefix_len + 1 + const_name_len + 1, (void **) &c) == SUCCESS) {
  293. found_const = 1;
  294. } else {
  295. /* try lowercase */
  296. zend_str_tolower(lcname + prefix_len + 1, const_name_len);
  297. if (zend_hash_find(EG(zend_constants), lcname, prefix_len + 1 + const_name_len + 1, (void **) &c) == SUCCESS) {
  298. if ((c->flags & CONST_CS) == 0) {
  299. found_const = 1;
  300. }
  301. }
  302. }
  303. efree(lcname);
  304. if(found_const) {
  305. *result = c->value;
  306. zval_update_constant_ex(&result, (void*)1, NULL TSRMLS_CC);
  307. zval_copy_ctor(result);
  308. Z_SET_REFCOUNT_P(result, 1);
  309. Z_UNSET_ISREF_P(result);
  310. return 1;
  311. }
  312. /* name requires runtime resolution, need to check non-namespaced name */
  313. if ((flags & IS_CONSTANT_UNQUALIFIED) != 0) {
  314. name = constant_name;
  315. name_len = const_name_len;
  316. return zend_get_constant(name, name_len, result TSRMLS_CC);
  317. }
  318. retval = 0;
  319. finish:
  320. if (retval) {
  321. zval_update_constant_ex(ret_constant, (void*)1, ce TSRMLS_CC);
  322. *result = **ret_constant;
  323. zval_copy_ctor(result);
  324. INIT_PZVAL(result);
  325. }
  326. return retval;
  327. }
  328. return zend_get_constant(name, name_len, result TSRMLS_CC);
  329. }
  330. ZEND_API int zend_register_constant(zend_constant *c TSRMLS_DC)
  331. {
  332. char *lowercase_name = NULL;
  333. char *name;
  334. int ret = SUCCESS;
  335. #if 0
  336. printf("Registering constant for module %d\n", c->module_number);
  337. #endif
  338. if (!(c->flags & CONST_CS)) {
  339. /* keep in mind that c->name_len already contains the '\0' */
  340. lowercase_name = estrndup(c->name, c->name_len-1);
  341. zend_str_tolower(lowercase_name, c->name_len-1);
  342. name = lowercase_name;
  343. } else {
  344. char *slash = strrchr(c->name, '\\');
  345. if(slash) {
  346. lowercase_name = estrndup(c->name, c->name_len-1);
  347. zend_str_tolower(lowercase_name, slash-c->name);
  348. name = lowercase_name;
  349. } else {
  350. name = c->name;
  351. }
  352. }
  353. /* Check if the user is trying to define the internal pseudo constant name __COMPILER_HALT_OFFSET__ */
  354. if ((c->name_len == sizeof("__COMPILER_HALT_OFFSET__")
  355. && !memcmp(name, "__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__")-1))
  356. || zend_hash_add(EG(zend_constants), name, c->name_len, (void *) c, sizeof(zend_constant), NULL)==FAILURE) {
  357. /* The internal __COMPILER_HALT_OFFSET__ is prefixed by NULL byte */
  358. if (c->name[0] == '\0' && c->name_len > sizeof("\0__COMPILER_HALT_OFFSET__")
  359. && memcmp(name, "\0__COMPILER_HALT_OFFSET__", sizeof("\0__COMPILER_HALT_OFFSET__")) == 0) {
  360. name++;
  361. }
  362. zend_error(E_NOTICE,"Constant %s already defined", name);
  363. free(c->name);
  364. if (!(c->flags & CONST_PERSISTENT)) {
  365. zval_dtor(&c->value);
  366. }
  367. ret = FAILURE;
  368. }
  369. if (lowercase_name) {
  370. efree(lowercase_name);
  371. }
  372. return ret;
  373. }
  374. /*
  375. * Local variables:
  376. * tab-width: 4
  377. * c-basic-offset: 4
  378. * indent-tabs-mode: t
  379. * End:
  380. */