Back to index

php5  5.3.10
zend_constants.c
Go to the documentation of this file.
00001 /*
00002    +----------------------------------------------------------------------+
00003    | Zend Engine                                                          |
00004    +----------------------------------------------------------------------+
00005    | Copyright (c) 1998-2012 Zend Technologies Ltd. (http://www.zend.com) |
00006    +----------------------------------------------------------------------+
00007    | This source file is subject to version 2.00 of the Zend license,     |
00008    | that is bundled with this package in the file LICENSE, and is        | 
00009    | available through the world-wide-web at the following url:           |
00010    | http://www.zend.com/license/2_00.txt.                                |
00011    | If you did not receive a copy of the Zend license and are unable to  |
00012    | obtain it through the world-wide-web, please send a note to          |
00013    | license@zend.com so we can mail you a copy immediately.              |
00014    +----------------------------------------------------------------------+
00015    | Authors: Andi Gutmans <andi@zend.com>                                |
00016    |          Zeev Suraski <zeev@zend.com>                                |
00017    +----------------------------------------------------------------------+
00018 */
00019 
00020 /* $Id: zend_constants.c 321634 2012-01-01 13:15:04Z felipe $ */
00021 
00022 #include "zend.h"
00023 #include "zend_constants.h"
00024 #include "zend_execute.h"
00025 #include "zend_variables.h"
00026 #include "zend_operators.h"
00027 #include "zend_globals.h"
00028 
00029 
00030 void free_zend_constant(zend_constant *c)
00031 {
00032        if (!(c->flags & CONST_PERSISTENT)) {
00033               zval_dtor(&c->value);
00034        }
00035        free(c->name);
00036 }
00037 
00038 
00039 void copy_zend_constant(zend_constant *c)
00040 {
00041        c->name = zend_strndup(c->name, c->name_len - 1);
00042        if (!(c->flags & CONST_PERSISTENT)) {
00043               zval_copy_ctor(&c->value);
00044        }
00045 }
00046 
00047 
00048 void zend_copy_constants(HashTable *target, HashTable *source)
00049 {
00050        zend_constant tmp_constant;
00051 
00052        zend_hash_copy(target, source, (copy_ctor_func_t) copy_zend_constant, &tmp_constant, sizeof(zend_constant));
00053 }
00054 
00055 
00056 static int clean_non_persistent_constant(const zend_constant *c TSRMLS_DC)
00057 {
00058        return (c->flags & CONST_PERSISTENT) ? ZEND_HASH_APPLY_STOP : ZEND_HASH_APPLY_REMOVE;
00059 }
00060 
00061 
00062 static int clean_non_persistent_constant_full(const zend_constant *c TSRMLS_DC)
00063 {
00064        return (c->flags & CONST_PERSISTENT) ? 0 : 1;
00065 }
00066 
00067 
00068 static int clean_module_constant(const zend_constant *c, int *module_number TSRMLS_DC)
00069 {
00070        if (c->module_number == *module_number) {
00071               return 1;
00072        } else {
00073               return 0;
00074        }
00075 }
00076 
00077 
00078 void clean_module_constants(int module_number TSRMLS_DC)
00079 {
00080        zend_hash_apply_with_argument(EG(zend_constants), (apply_func_arg_t) clean_module_constant, (void *) &module_number TSRMLS_CC);
00081 }
00082 
00083 
00084 int zend_startup_constants(TSRMLS_D)
00085 {
00086        EG(zend_constants) = (HashTable *) malloc(sizeof(HashTable));
00087 
00088        if (zend_hash_init(EG(zend_constants), 20, NULL, ZEND_CONSTANT_DTOR, 1)==FAILURE) {
00089               return FAILURE;
00090        }
00091        return SUCCESS;
00092 }
00093 
00094 
00095 
00096 void zend_register_standard_constants(TSRMLS_D)
00097 {
00098        REGISTER_MAIN_LONG_CONSTANT("E_ERROR", E_ERROR, CONST_PERSISTENT | CONST_CS);
00099        REGISTER_MAIN_LONG_CONSTANT("E_RECOVERABLE_ERROR", E_RECOVERABLE_ERROR, CONST_PERSISTENT | CONST_CS);
00100        REGISTER_MAIN_LONG_CONSTANT("E_WARNING", E_WARNING, CONST_PERSISTENT | CONST_CS);
00101        REGISTER_MAIN_LONG_CONSTANT("E_PARSE", E_PARSE, CONST_PERSISTENT | CONST_CS);
00102        REGISTER_MAIN_LONG_CONSTANT("E_NOTICE", E_NOTICE, CONST_PERSISTENT | CONST_CS);
00103        REGISTER_MAIN_LONG_CONSTANT("E_STRICT", E_STRICT, CONST_PERSISTENT | CONST_CS);
00104        REGISTER_MAIN_LONG_CONSTANT("E_DEPRECATED", E_DEPRECATED, CONST_PERSISTENT | CONST_CS);
00105        REGISTER_MAIN_LONG_CONSTANT("E_CORE_ERROR", E_CORE_ERROR, CONST_PERSISTENT | CONST_CS);
00106        REGISTER_MAIN_LONG_CONSTANT("E_CORE_WARNING", E_CORE_WARNING, CONST_PERSISTENT | CONST_CS);
00107        REGISTER_MAIN_LONG_CONSTANT("E_COMPILE_ERROR", E_COMPILE_ERROR, CONST_PERSISTENT | CONST_CS);
00108        REGISTER_MAIN_LONG_CONSTANT("E_COMPILE_WARNING", E_COMPILE_WARNING, CONST_PERSISTENT | CONST_CS);
00109        REGISTER_MAIN_LONG_CONSTANT("E_USER_ERROR", E_USER_ERROR, CONST_PERSISTENT | CONST_CS);
00110        REGISTER_MAIN_LONG_CONSTANT("E_USER_WARNING", E_USER_WARNING, CONST_PERSISTENT | CONST_CS);
00111        REGISTER_MAIN_LONG_CONSTANT("E_USER_NOTICE", E_USER_NOTICE, CONST_PERSISTENT | CONST_CS);
00112        REGISTER_MAIN_LONG_CONSTANT("E_USER_DEPRECATED", E_USER_DEPRECATED, CONST_PERSISTENT | CONST_CS);
00113 
00114        REGISTER_MAIN_LONG_CONSTANT("E_ALL", E_ALL, CONST_PERSISTENT | CONST_CS);
00115 
00116        REGISTER_MAIN_LONG_CONSTANT("DEBUG_BACKTRACE_PROVIDE_OBJECT", DEBUG_BACKTRACE_PROVIDE_OBJECT, CONST_PERSISTENT | CONST_CS);
00117        REGISTER_MAIN_LONG_CONSTANT("DEBUG_BACKTRACE_IGNORE_ARGS", DEBUG_BACKTRACE_IGNORE_ARGS, CONST_PERSISTENT | CONST_CS);
00118        /* true/false constants */
00119        {
00120               zend_constant c;
00121        
00122               c.flags = CONST_PERSISTENT | CONST_CT_SUBST;
00123               c.module_number = 0;
00124 
00125               c.name = zend_strndup(ZEND_STRL("TRUE"));
00126               c.name_len = sizeof("TRUE");
00127               c.value.value.lval = 1;
00128               c.value.type = IS_BOOL;
00129               zend_register_constant(&c TSRMLS_CC);
00130               
00131               c.name = zend_strndup(ZEND_STRL("FALSE"));
00132               c.name_len = sizeof("FALSE");
00133               c.value.value.lval = 0;
00134               c.value.type = IS_BOOL;
00135               zend_register_constant(&c TSRMLS_CC);
00136 
00137               c.name = zend_strndup(ZEND_STRL("NULL"));
00138               c.name_len = sizeof("NULL");
00139               c.value.type = IS_NULL;
00140               zend_register_constant(&c TSRMLS_CC);
00141 
00142               c.flags = CONST_PERSISTENT;
00143 
00144               c.name = zend_strndup(ZEND_STRL("ZEND_THREAD_SAFE"));
00145               c.name_len = sizeof("ZEND_THREAD_SAFE");
00146               c.value.value.lval = ZTS_V;
00147               c.value.type = IS_BOOL;
00148               zend_register_constant(&c TSRMLS_CC);
00149 
00150               c.name = zend_strndup(ZEND_STRL("ZEND_DEBUG_BUILD"));
00151               c.name_len = sizeof("ZEND_DEBUG_BUILD");
00152               c.value.value.lval = ZEND_DEBUG;
00153               c.value.type = IS_BOOL;
00154               zend_register_constant(&c TSRMLS_CC);
00155        }
00156 }
00157 
00158 
00159 int zend_shutdown_constants(TSRMLS_D)
00160 {
00161        zend_hash_destroy(EG(zend_constants));
00162        free(EG(zend_constants));
00163        return SUCCESS;
00164 }
00165 
00166 
00167 void clean_non_persistent_constants(TSRMLS_D)
00168 {
00169        if (EG(full_tables_cleanup)) {
00170               zend_hash_apply(EG(zend_constants), (apply_func_t) clean_non_persistent_constant_full TSRMLS_CC);
00171        } else {
00172               zend_hash_reverse_apply(EG(zend_constants), (apply_func_t) clean_non_persistent_constant TSRMLS_CC);
00173        }
00174 }
00175 
00176 
00177 ZEND_API void zend_register_long_constant(const char *name, uint name_len, long lval, int flags, int module_number TSRMLS_DC)
00178 {
00179        zend_constant c;
00180        
00181        c.value.type = IS_LONG;
00182        c.value.value.lval = lval;
00183        c.flags = flags;
00184        c.name = zend_strndup(name, name_len-1);
00185        c.name_len = name_len;
00186        c.module_number = module_number;
00187        zend_register_constant(&c TSRMLS_CC);
00188 }
00189 
00190 
00191 ZEND_API void zend_register_double_constant(const char *name, uint name_len, double dval, int flags, int module_number TSRMLS_DC)
00192 {
00193        zend_constant c;
00194        
00195        c.value.type = IS_DOUBLE;
00196        c.value.value.dval = dval;
00197        c.flags = flags;
00198        c.name = zend_strndup(name, name_len-1);
00199        c.name_len = name_len;
00200        c.module_number = module_number;
00201        zend_register_constant(&c TSRMLS_CC);
00202 }
00203 
00204 
00205 ZEND_API void zend_register_stringl_constant(const char *name, uint name_len, char *strval, uint strlen, int flags, int module_number TSRMLS_DC)
00206 {
00207        zend_constant c;
00208        
00209        c.value.type = IS_STRING;
00210        c.value.value.str.val = strval;
00211        c.value.value.str.len = strlen;
00212        c.flags = flags;
00213        c.name = zend_strndup(name, name_len-1);
00214        c.name_len = name_len;
00215        c.module_number = module_number;
00216        zend_register_constant(&c TSRMLS_CC);
00217 }
00218 
00219 
00220 ZEND_API void zend_register_string_constant(const char *name, uint name_len, char *strval, int flags, int module_number TSRMLS_DC)
00221 {
00222        zend_register_stringl_constant(name, name_len, strval, strlen(strval), flags, module_number TSRMLS_CC);
00223 }
00224 
00225 
00226 ZEND_API int zend_get_constant(const char *name, uint name_len, zval *result TSRMLS_DC)
00227 {
00228        zend_constant *c;
00229        int retval = 1;
00230        char *lookup_name;
00231 
00232        if (zend_hash_find(EG(zend_constants), name, name_len+1, (void **) &c) == FAILURE) {
00233               lookup_name = zend_str_tolower_dup(name, name_len);
00234 
00235               if (zend_hash_find(EG(zend_constants), lookup_name, name_len+1, (void **) &c)==SUCCESS) {
00236                      if (c->flags & CONST_CS) {
00237                             retval=0;
00238                      }
00239               } else {
00240                      static char haltoff[] = "__COMPILER_HALT_OFFSET__";
00241 
00242                      if (!EG(in_execution)) {
00243                             retval = 0;
00244                      } else if (name_len == sizeof("__COMPILER_HALT_OFFSET__")-1 &&
00245                                !memcmp(name, "__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__")-1)) {
00246                             char *cfilename, *haltname;
00247                             int len, clen;
00248 
00249                             cfilename = zend_get_executed_filename(TSRMLS_C);
00250                             clen = strlen(cfilename);
00251                             /* check for __COMPILER_HALT_OFFSET__ */
00252                             zend_mangle_property_name(&haltname, &len, haltoff,
00253                                    sizeof("__COMPILER_HALT_OFFSET__") - 1, cfilename, clen, 0);
00254                             if (zend_hash_find(EG(zend_constants), haltname, len+1, (void **) &c) == SUCCESS) {
00255                                    retval = 1;
00256                             } else {
00257                                    retval=0;
00258                             }
00259                             pefree(haltname, 0);
00260                      } else {
00261                             retval=0;
00262                      }
00263               }
00264               efree(lookup_name);
00265        }
00266 
00267        if (retval) {
00268               *result = c->value;
00269               zval_copy_ctor(result);
00270               Z_SET_REFCOUNT_P(result, 1);
00271               Z_UNSET_ISREF_P(result);
00272        }
00273 
00274        return retval;
00275 }
00276 
00277 ZEND_API int zend_get_constant_ex(const char *name, uint name_len, zval *result, zend_class_entry *scope, ulong flags TSRMLS_DC)
00278 {
00279        zend_constant *c;
00280        int retval = 1;
00281        char *colon;
00282        zend_class_entry *ce = NULL;
00283        char *class_name;
00284        zval **ret_constant;
00285 
00286        /* Skip leading \\ */
00287        if (name[0] == '\\') {
00288               name += 1;
00289               name_len -= 1;
00290        }
00291 
00292 
00293        if ((colon = zend_memrchr(name, ':', name_len)) &&
00294            colon > name && (*(colon - 1) == ':')) {
00295               int class_name_len = colon - name - 1;
00296               int const_name_len = name_len - class_name_len - 2;
00297               char *constant_name = colon + 1;
00298               char *lcname;
00299 
00300               class_name = estrndup(name, class_name_len);
00301               lcname = zend_str_tolower_dup(class_name, class_name_len);
00302               if (!scope) {
00303                      if (EG(in_execution)) {
00304                             scope = EG(scope);
00305                      } else {
00306                             scope = CG(active_class_entry);
00307                      }
00308               }
00309 
00310               if (class_name_len == sizeof("self")-1 &&
00311                   !memcmp(lcname, "self", sizeof("self")-1)) {
00312                      if (scope) {
00313                             ce = scope;
00314                      } else {
00315                             zend_error(E_ERROR, "Cannot access self:: when no class scope is active");
00316                             retval = 0;
00317                      }
00318                      efree(lcname);
00319               } else if (class_name_len == sizeof("parent")-1 &&
00320                          !memcmp(lcname, "parent", sizeof("parent")-1)) {
00321                      if (!scope) {
00322                             zend_error(E_ERROR, "Cannot access parent:: when no class scope is active");
00323                      } else if (!scope->parent) {
00324                             zend_error(E_ERROR, "Cannot access parent:: when current class scope has no parent");
00325                      } else {
00326                             ce = scope->parent;
00327                      }
00328                      efree(lcname);
00329               } else if (class_name_len == sizeof("static")-1 &&
00330                          !memcmp(lcname, "static", sizeof("static")-1)) {
00331                      if (EG(called_scope)) {
00332                             ce = EG(called_scope);
00333                      } else {
00334                             zend_error(E_ERROR, "Cannot access static:: when no class scope is active");
00335                      }
00336                      efree(lcname);
00337               } else {
00338                      efree(lcname);
00339                      ce = zend_fetch_class(class_name, class_name_len, flags TSRMLS_CC);
00340               }
00341               if (retval && ce) {
00342                      if (zend_hash_find(&ce->constants_table, constant_name, const_name_len+1, (void **) &ret_constant) != SUCCESS) {
00343                             retval = 0;
00344                             if ((flags & ZEND_FETCH_CLASS_SILENT) == 0) {
00345                                    zend_error(E_ERROR, "Undefined class constant '%s::%s'", class_name, constant_name);
00346                             }
00347                      }
00348               } else if (!ce) {
00349                      retval = 0;
00350               }
00351               efree(class_name);
00352               goto finish;
00353        }
00354 
00355        /* non-class constant */
00356        if ((colon = zend_memrchr(name, '\\', name_len)) != NULL) {
00357               /* compound constant name */
00358               int prefix_len = colon - name;
00359               int const_name_len = name_len - prefix_len - 1;
00360               char *constant_name = colon + 1;
00361               char *lcname;
00362               int found_const = 0;
00363 
00364               lcname = zend_str_tolower_dup(name, prefix_len);
00365               /* Check for namespace constant */
00366 
00367               /* Concatenate lowercase namespace name and constant name */
00368               lcname = erealloc(lcname, prefix_len + 1 + const_name_len + 1);
00369               lcname[prefix_len] = '\\';
00370               memcpy(lcname + prefix_len + 1, constant_name, const_name_len + 1);
00371 
00372               if (zend_hash_find(EG(zend_constants), lcname, prefix_len + 1 + const_name_len + 1, (void **) &c) == SUCCESS) {
00373                      found_const = 1;
00374               } else {
00375                      /* try lowercase */
00376                      zend_str_tolower(lcname + prefix_len + 1, const_name_len);
00377                      if (zend_hash_find(EG(zend_constants), lcname, prefix_len + 1 + const_name_len + 1, (void **) &c) == SUCCESS) {
00378                             if ((c->flags & CONST_CS) == 0) {
00379                                    found_const = 1;
00380                             }
00381                      }
00382               }
00383               efree(lcname);
00384               if(found_const) {
00385                      *result = c->value;
00386                      zval_update_constant_ex(&result, (void*)1, NULL TSRMLS_CC);
00387                      zval_copy_ctor(result);
00388                      Z_SET_REFCOUNT_P(result, 1);
00389                      Z_UNSET_ISREF_P(result);
00390                      return 1;
00391               }
00392               /* name requires runtime resolution, need to check non-namespaced name */
00393               if ((flags & IS_CONSTANT_UNQUALIFIED) != 0) {
00394                      name = constant_name;
00395                      name_len = const_name_len;
00396                      return zend_get_constant(name, name_len, result TSRMLS_CC);
00397               }
00398               retval = 0;
00399 finish:
00400               if (retval) {
00401                      zval_update_constant_ex(ret_constant, (void*)1, ce TSRMLS_CC);
00402                      *result = **ret_constant;
00403                      zval_copy_ctor(result);
00404                      INIT_PZVAL(result);
00405               }
00406 
00407               return retval;
00408        }
00409 
00410        return zend_get_constant(name, name_len, result TSRMLS_CC);
00411 }
00412 
00413 ZEND_API int zend_register_constant(zend_constant *c TSRMLS_DC)
00414 {
00415        char *lowercase_name = NULL;
00416        char *name;
00417        int ret = SUCCESS;
00418 
00419 #if 0
00420        printf("Registering constant for module %d\n", c->module_number);
00421 #endif
00422 
00423        if (!(c->flags & CONST_CS)) {
00424               /* keep in mind that c->name_len already contains the '\0' */
00425               lowercase_name = estrndup(c->name, c->name_len-1);
00426               zend_str_tolower(lowercase_name, c->name_len-1);
00427               name = lowercase_name;
00428        } else {
00429               char *slash = strrchr(c->name, '\\');
00430               if(slash) {
00431                      lowercase_name = estrndup(c->name, c->name_len-1);
00432                      zend_str_tolower(lowercase_name, slash-c->name);
00433                      name = lowercase_name;
00434               } else {
00435                      name = c->name;
00436               }
00437        }
00438 
00439        /* Check if the user is trying to define the internal pseudo constant name __COMPILER_HALT_OFFSET__ */
00440        if ((c->name_len == sizeof("__COMPILER_HALT_OFFSET__")
00441               && !memcmp(name, "__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__")-1))
00442               || zend_hash_add(EG(zend_constants), name, c->name_len, (void *) c, sizeof(zend_constant), NULL)==FAILURE) {
00443               
00444               /* The internal __COMPILER_HALT_OFFSET__ is prefixed by NULL byte */
00445               if (c->name[0] == '\0' && c->name_len > sizeof("\0__COMPILER_HALT_OFFSET__")
00446                      && memcmp(name, "\0__COMPILER_HALT_OFFSET__", sizeof("\0__COMPILER_HALT_OFFSET__")) == 0) {
00447                      name++;
00448               }
00449               zend_error(E_NOTICE,"Constant %s already defined", name);
00450               free(c->name);
00451               if (!(c->flags & CONST_PERSISTENT)) {
00452                      zval_dtor(&c->value);
00453               }
00454               ret = FAILURE;
00455        }
00456        if (lowercase_name) {
00457               efree(lowercase_name);
00458        }
00459        return ret;
00460 }
00461 
00462 
00463 /*
00464  * Local variables:
00465  * tab-width: 4
00466  * c-basic-offset: 4
00467  * indent-tabs-mode: t
00468  * End:
00469  */