Back to index

php5  5.3.10
zend_API.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    |          Andrei Zmievski <andrei@php.net>                            |
00018    +----------------------------------------------------------------------+
00019 */
00020 
00021 /* $Id: zend_API.c 321634 2012-01-01 13:15:04Z felipe $ */
00022 
00023 #include "zend.h"
00024 #include "zend_execute.h"
00025 #include "zend_API.h"
00026 #include "zend_modules.h"
00027 #include "zend_constants.h"
00028 #include "zend_exceptions.h"
00029 #include "zend_closures.h"
00030 
00031 #ifdef HAVE_STDARG_H
00032 #include <stdarg.h>
00033 #endif
00034 
00035 /* these variables are true statics/globals, and have to be mutex'ed on every access */
00036 static int module_count=0;
00037 ZEND_API HashTable module_registry;
00038 
00039 /* this function doesn't check for too many parameters */
00040 ZEND_API int zend_get_parameters(int ht, int param_count, ...) /* {{{ */
00041 {
00042        void **p;
00043        int arg_count;
00044        va_list ptr;
00045        zval **param, *param_ptr;
00046        TSRMLS_FETCH();
00047 
00048        p = zend_vm_stack_top(TSRMLS_C) - 1;
00049        arg_count = (int)(zend_uintptr_t) *p;
00050 
00051        if (param_count>arg_count) {
00052               return FAILURE;
00053        }
00054 
00055        va_start(ptr, param_count);
00056 
00057        while (param_count-->0) {
00058               param = va_arg(ptr, zval **);
00059               param_ptr = *(p-arg_count);
00060               if (!PZVAL_IS_REF(param_ptr) && Z_REFCOUNT_P(param_ptr) > 1) {
00061                      zval *new_tmp;
00062 
00063                      ALLOC_ZVAL(new_tmp);
00064                      *new_tmp = *param_ptr;
00065                      zval_copy_ctor(new_tmp);
00066                      INIT_PZVAL(new_tmp);
00067                      param_ptr = new_tmp;
00068                      Z_DELREF_P((zval *) *(p-arg_count));
00069                      *(p-arg_count) = param_ptr;
00070               }
00071               *param = param_ptr;
00072               arg_count--;
00073        }
00074        va_end(ptr);
00075 
00076        return SUCCESS;
00077 }
00078 /* }}} */
00079 
00080 ZEND_API int _zend_get_parameters_array(int ht, int param_count, zval **argument_array TSRMLS_DC) /* {{{ */
00081 {
00082        void **p;
00083        int arg_count;
00084        zval *param_ptr;
00085 
00086        p = zend_vm_stack_top(TSRMLS_C) - 1;
00087        arg_count = (int)(zend_uintptr_t) *p;
00088 
00089        if (param_count>arg_count) {
00090               return FAILURE;
00091        }
00092 
00093        while (param_count-->0) {
00094               param_ptr = *(p-arg_count);
00095               if (!PZVAL_IS_REF(param_ptr) && Z_REFCOUNT_P(param_ptr) > 1) {
00096                      zval *new_tmp;
00097 
00098                      ALLOC_ZVAL(new_tmp);
00099                      *new_tmp = *param_ptr;
00100                      zval_copy_ctor(new_tmp);
00101                      INIT_PZVAL(new_tmp);
00102                      param_ptr = new_tmp;
00103                      Z_DELREF_P((zval *) *(p-arg_count));
00104                      *(p-arg_count) = param_ptr;
00105               }
00106               *(argument_array++) = param_ptr;
00107               arg_count--;
00108        }
00109 
00110        return SUCCESS;
00111 }
00112 /* }}} */
00113 
00114 /* Zend-optimized Extended functions */
00115 /* this function doesn't check for too many parameters */
00116 ZEND_API int zend_get_parameters_ex(int param_count, ...) /* {{{ */
00117 {
00118        void **p;
00119        int arg_count;
00120        va_list ptr;
00121        zval ***param;
00122        TSRMLS_FETCH();
00123 
00124        p = zend_vm_stack_top(TSRMLS_C) - 1;
00125        arg_count = (int)(zend_uintptr_t) *p;
00126 
00127        if (param_count>arg_count) {
00128               return FAILURE;
00129        }
00130 
00131        va_start(ptr, param_count);
00132        while (param_count-->0) {
00133               param = va_arg(ptr, zval ***);
00134               *param = (zval **) p-(arg_count--);
00135        }
00136        va_end(ptr);
00137 
00138        return SUCCESS;
00139 }
00140 /* }}} */
00141 
00142 ZEND_API int _zend_get_parameters_array_ex(int param_count, zval ***argument_array TSRMLS_DC) /* {{{ */
00143 {
00144        void **p;
00145        int arg_count;
00146 
00147        p = zend_vm_stack_top(TSRMLS_C) - 1;
00148        arg_count = (int)(zend_uintptr_t) *p;
00149 
00150        if (param_count>arg_count) {
00151               return FAILURE;
00152        }
00153 
00154        while (param_count-->0) {
00155               zval **value = (zval**)(p-arg_count);
00156 
00157               *(argument_array++) = value;
00158               arg_count--;
00159        }
00160 
00161        return SUCCESS;
00162 }
00163 /* }}} */
00164 
00165 ZEND_API int zend_copy_parameters_array(int param_count, zval *argument_array TSRMLS_DC) /* {{{ */
00166 {
00167        void **p;
00168        int arg_count;
00169 
00170        p = zend_vm_stack_top(TSRMLS_C) - 1;
00171        arg_count = (int)(zend_uintptr_t) *p;
00172 
00173        if (param_count>arg_count) {
00174               return FAILURE;
00175        }
00176 
00177        while (param_count-->0) {
00178               zval **param = (zval **) p-(arg_count--);
00179               zval_add_ref(param);
00180               add_next_index_zval(argument_array, *param);
00181        }
00182 
00183        return SUCCESS;
00184 }
00185 /* }}} */
00186 
00187 ZEND_API void zend_wrong_param_count(TSRMLS_D) /* {{{ */
00188 {
00189        char *space;
00190        char *class_name = get_active_class_name(&space TSRMLS_CC);
00191 
00192        zend_error(E_WARNING, "Wrong parameter count for %s%s%s()", class_name, space, get_active_function_name(TSRMLS_C));
00193 }
00194 /* }}} */
00195 
00196 /* Argument parsing API -- andrei */
00197 ZEND_API char *zend_get_type_by_const(int type) /* {{{ */
00198 {
00199        switch(type) {
00200               case IS_BOOL:
00201                      return "boolean";
00202               case IS_LONG:
00203                      return "integer";
00204               case IS_DOUBLE:
00205                      return "double";
00206               case IS_STRING:
00207                      return "string";
00208               case IS_OBJECT:
00209                      return "object";
00210               case IS_RESOURCE:
00211                      return "resource";
00212               case IS_NULL:
00213                      return "null";
00214               case IS_ARRAY:
00215                      return "array";
00216               default:
00217                      return "unknown";
00218        }
00219 }
00220 /* }}} */
00221 
00222 ZEND_API char *zend_zval_type_name(const zval *arg) /* {{{ */
00223 {
00224        return zend_get_type_by_const(Z_TYPE_P(arg));
00225 }
00226 /* }}} */
00227 
00228 ZEND_API zend_class_entry *zend_get_class_entry(const zval *zobject TSRMLS_DC) /* {{{ */
00229 {
00230        if (Z_OBJ_HT_P(zobject)->get_class_entry) {
00231               return Z_OBJ_HT_P(zobject)->get_class_entry(zobject TSRMLS_CC);
00232        } else {
00233               zend_error(E_ERROR, "Class entry requested for an object without PHP class");
00234               return NULL;
00235        }
00236 }
00237 /* }}} */
00238 
00239 /* returns 1 if you need to copy result, 0 if it's already a copy */
00240 ZEND_API int zend_get_object_classname(const zval *object, char **class_name, zend_uint *class_name_len TSRMLS_DC) /* {{{ */
00241 {
00242        if (Z_OBJ_HT_P(object)->get_class_name == NULL ||
00243               Z_OBJ_HT_P(object)->get_class_name(object, class_name, class_name_len, 0 TSRMLS_CC) != SUCCESS) {
00244               zend_class_entry *ce = Z_OBJCE_P(object);
00245 
00246               *class_name = ce->name;
00247               *class_name_len = ce->name_length;
00248               return 1;
00249        }
00250        return 0;
00251 }
00252 /* }}} */
00253 
00254 static int parse_arg_object_to_string(zval **arg TSRMLS_DC) /* {{{ */
00255 {
00256        if (Z_OBJ_HANDLER_PP(arg, cast_object)) {
00257               SEPARATE_ZVAL_IF_NOT_REF(arg);
00258               if (Z_OBJ_HANDLER_PP(arg, cast_object)(*arg, *arg, IS_STRING TSRMLS_CC) == SUCCESS) {
00259                      return SUCCESS;
00260               }
00261        }
00262        /* Standard PHP objects */
00263        if (Z_OBJ_HT_PP(arg) == &std_object_handlers || !Z_OBJ_HANDLER_PP(arg, cast_object)) {
00264               SEPARATE_ZVAL_IF_NOT_REF(arg);
00265               if (zend_std_cast_object_tostring(*arg, *arg, IS_STRING TSRMLS_CC) == SUCCESS) {
00266                      return SUCCESS;
00267               }
00268        }
00269        if (!Z_OBJ_HANDLER_PP(arg, cast_object) && Z_OBJ_HANDLER_PP(arg, get)) {
00270               int use_copy;
00271               zval *z = Z_OBJ_HANDLER_PP(arg, get)(*arg TSRMLS_CC);
00272               Z_ADDREF_P(z);
00273               if(Z_TYPE_P(z) != IS_OBJECT) {
00274                      zval_dtor(*arg);
00275                      Z_TYPE_P(*arg) = IS_NULL;
00276                      zend_make_printable_zval(z, *arg, &use_copy);
00277                      if (!use_copy) {
00278                             ZVAL_ZVAL(*arg, z, 1, 1);
00279                      }
00280                      return SUCCESS;
00281               }
00282               zval_ptr_dtor(&z);
00283        }
00284        return FAILURE;
00285 }
00286 /* }}} */
00287 
00288 static char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, char **spec, char **error, int *severity TSRMLS_DC) /* {{{ */
00289 {
00290        char *spec_walk = *spec;
00291        char c = *spec_walk++;
00292        int return_null = 0;
00293 
00294        /* scan through modifiers */
00295        while (1) {
00296               if (*spec_walk == '/') {
00297                      SEPARATE_ZVAL_IF_NOT_REF(arg);
00298               } else if (*spec_walk == '!') {
00299                      if (Z_TYPE_PP(arg) == IS_NULL) {
00300                             return_null = 1;
00301                      }
00302               } else {
00303                      break;
00304               }
00305               spec_walk++;
00306        }
00307 
00308        switch (c) {
00309               case 'l':
00310               case 'L':
00311                      {
00312                             long *p = va_arg(*va, long *);
00313                             switch (Z_TYPE_PP(arg)) {
00314                                    case IS_STRING:
00315                                           {
00316                                                  double d;
00317                                                  int type;
00318 
00319                                                  if ((type = is_numeric_string(Z_STRVAL_PP(arg), Z_STRLEN_PP(arg), p, &d, -1)) == 0) {
00320                                                         return "long";
00321                                                  } else if (type == IS_DOUBLE) {
00322                                                         if (c == 'L') {
00323                                                                if (d > LONG_MAX) {
00324                                                                       *p = LONG_MAX;
00325                                                                       break;
00326                                                                } else if (d < LONG_MIN) {
00327                                                                       *p = LONG_MIN;
00328                                                                       break;
00329                                                                }
00330                                                         }
00331 
00332                                                         *p = zend_dval_to_lval(d);
00333                                                  }
00334                                           }
00335                                           break;
00336 
00337                                    case IS_DOUBLE:
00338                                           if (c == 'L') {
00339                                                  if (Z_DVAL_PP(arg) > LONG_MAX) {
00340                                                         *p = LONG_MAX;
00341                                                         break;
00342                                                  } else if (Z_DVAL_PP(arg) < LONG_MIN) {
00343                                                         *p = LONG_MIN;
00344                                                         break;
00345                                                  }
00346                                           }
00347                                    case IS_NULL:
00348                                    case IS_LONG:
00349                                    case IS_BOOL:
00350                                           convert_to_long_ex(arg);
00351                                           *p = Z_LVAL_PP(arg);
00352                                           break;
00353 
00354                                    case IS_ARRAY:
00355                                    case IS_OBJECT:
00356                                    case IS_RESOURCE:
00357                                    default:
00358                                           return "long";
00359                             }
00360                      }
00361                      break;
00362 
00363               case 'd':
00364                      {
00365                             double *p = va_arg(*va, double *);
00366                             switch (Z_TYPE_PP(arg)) {
00367                                    case IS_STRING:
00368                                           {
00369                                                  long l;
00370                                                  int type;
00371 
00372                                                  if ((type = is_numeric_string(Z_STRVAL_PP(arg), Z_STRLEN_PP(arg), &l, p, -1)) == 0) {
00373                                                         return "double";
00374                                                  } else if (type == IS_LONG) {
00375                                                         *p = (double) l;
00376                                                  }
00377                                           }
00378                                           break;
00379 
00380                                    case IS_NULL:
00381                                    case IS_LONG:
00382                                    case IS_DOUBLE:
00383                                    case IS_BOOL:
00384                                           convert_to_double_ex(arg);
00385                                           *p = Z_DVAL_PP(arg);
00386                                           break;
00387 
00388                                    case IS_ARRAY:
00389                                    case IS_OBJECT:
00390                                    case IS_RESOURCE:
00391                                    default:
00392                                           return "double";
00393                             }
00394                      }
00395                      break;
00396 
00397               case 's':
00398                      {
00399                             char **p = va_arg(*va, char **);
00400                             int *pl = va_arg(*va, int *);
00401                             switch (Z_TYPE_PP(arg)) {
00402                                    case IS_NULL:
00403                                           if (return_null) {
00404                                                  *p = NULL;
00405                                                  *pl = 0;
00406                                                  break;
00407                                           }
00408                                           /* break omitted intentionally */
00409 
00410                                    case IS_STRING:
00411                                    case IS_LONG:
00412                                    case IS_DOUBLE:
00413                                    case IS_BOOL:
00414                                           convert_to_string_ex(arg);
00415                                           if (UNEXPECTED(Z_ISREF_PP(arg) != 0)) {
00416                                                  /* it's dangerous to return pointers to string
00417                                                     buffer of referenced variable, because it can
00418                                                     be clobbered throug magic callbacks */
00419                                                  SEPARATE_ZVAL(arg);
00420                                           }
00421                                           *p = Z_STRVAL_PP(arg);
00422                                           *pl = Z_STRLEN_PP(arg);
00423                                           break;
00424 
00425                                    case IS_OBJECT:
00426                                    case IS_ARRAY:
00427                                    case IS_RESOURCE:
00428                                    default:
00429                                           return "string";
00430                             }
00431                      }
00432                      break;
00433 
00434               case 'b':
00435                      {
00436                             zend_bool *p = va_arg(*va, zend_bool *);
00437                             switch (Z_TYPE_PP(arg)) {
00438                                    case IS_NULL:
00439                                    case IS_STRING:
00440                                    case IS_LONG:
00441                                    case IS_DOUBLE:
00442                                    case IS_BOOL:
00443                                           convert_to_boolean_ex(arg);
00444                                           *p = Z_BVAL_PP(arg);
00445                                           break;
00446 
00447                                    case IS_ARRAY:
00448                                    case IS_OBJECT:
00449                                    case IS_RESOURCE:
00450                                    default:
00451                                           return "boolean";
00452                             }
00453                      }
00454                      break;
00455 
00456               case 'r':
00457                      {
00458                             zval **p = va_arg(*va, zval **);
00459                             if (return_null) {
00460                                    *p = NULL;
00461                                    break;
00462                             }
00463                             if (Z_TYPE_PP(arg) == IS_RESOURCE) {
00464                                    *p = *arg;
00465                             } else {
00466                                    return "resource";
00467                             }
00468                      }
00469                      break;
00470               case 'A':
00471               case 'a':
00472                      {
00473                             zval **p = va_arg(*va, zval **);
00474                             if (return_null) {
00475                                    *p = NULL;
00476                                    break;
00477                             }
00478                             if (Z_TYPE_PP(arg) == IS_ARRAY || (c == 'A' && Z_TYPE_PP(arg) == IS_OBJECT)) {
00479                                    *p = *arg;
00480                             } else {
00481                                    return "array";
00482                             }
00483                      }
00484                      break;
00485               case 'H':
00486               case 'h':
00487                      {
00488                             HashTable **p = va_arg(*va, HashTable **);
00489                             if (return_null) {
00490                                    *p = NULL;
00491                                    break;
00492                             }
00493                             if (Z_TYPE_PP(arg) == IS_ARRAY) {
00494                                    *p = Z_ARRVAL_PP(arg);
00495                             } else if(c == 'H' && Z_TYPE_PP(arg) == IS_OBJECT) {
00496                                    *p = HASH_OF(*arg);
00497                                    if(*p == NULL) {
00498                                           return "array";
00499                                    }
00500                             } else {
00501                                    return "array";
00502                             }
00503                      }
00504                      break;
00505 
00506               case 'o':
00507                      {
00508                             zval **p = va_arg(*va, zval **);
00509                             if (return_null) {
00510                                    *p = NULL;
00511                                    break;
00512                             }
00513                             if (Z_TYPE_PP(arg) == IS_OBJECT) {
00514                                    *p = *arg;
00515                             } else {
00516                                    return "object";
00517                             }
00518                      }
00519                      break;
00520 
00521               case 'O':
00522                      {
00523                             zval **p = va_arg(*va, zval **);
00524                             zend_class_entry *ce = va_arg(*va, zend_class_entry *);
00525 
00526                             if (return_null) {
00527                                    *p = NULL;
00528                                    break;
00529                             }
00530                             if (Z_TYPE_PP(arg) == IS_OBJECT &&
00531                                           (!ce || instanceof_function(Z_OBJCE_PP(arg), ce TSRMLS_CC))) {
00532                                    *p = *arg;
00533                             } else {
00534                                    if (ce) {
00535                                           return ce->name;
00536                                    } else {
00537                                           return "object";
00538                                    }
00539                             }
00540                      }
00541                      break;
00542 
00543               case 'C':
00544                      {
00545                             zend_class_entry **lookup, **pce = va_arg(*va, zend_class_entry **);
00546                             zend_class_entry *ce_base = *pce;
00547 
00548                             if (return_null) {
00549                                    *pce = NULL;
00550                                    break;
00551                             }
00552                             convert_to_string_ex(arg);
00553                             if (zend_lookup_class(Z_STRVAL_PP(arg), Z_STRLEN_PP(arg), &lookup TSRMLS_CC) == FAILURE) {
00554                                    *pce = NULL;
00555                             } else {
00556                                    *pce = *lookup;
00557                             }
00558                             if (ce_base) {
00559                                    if ((!*pce || !instanceof_function(*pce, ce_base TSRMLS_CC))) {
00560                                           zend_spprintf(error, 0, "to be a class name derived from %s, '%s' given",
00561                                                  ce_base->name, Z_STRVAL_PP(arg));
00562                                           *pce = NULL;
00563                                           return "";
00564                                    }
00565                             }
00566                             if (!*pce) {
00567                                    zend_spprintf(error, 0, "to be a valid class name, '%s' given",
00568                                           Z_STRVAL_PP(arg));
00569                                    return "";
00570                             }
00571                             break;
00572 
00573                      }
00574                      break;
00575 
00576               case 'f':
00577                      {
00578                             zend_fcall_info *fci = va_arg(*va, zend_fcall_info *);
00579                             zend_fcall_info_cache *fcc = va_arg(*va, zend_fcall_info_cache *);
00580                             char *is_callable_error = NULL;
00581 
00582                             if (return_null) {
00583                                    fci->size = 0;
00584                                    fcc->initialized = 0;
00585                                    break;
00586                             }
00587 
00588                             if (zend_fcall_info_init(*arg, 0, fci, fcc, NULL, &is_callable_error TSRMLS_CC) == SUCCESS) {
00589                                    if (is_callable_error) {
00590                                           *severity = E_STRICT;
00591                                           zend_spprintf(error, 0, "to be a valid callback, %s", is_callable_error);
00592                                           efree(is_callable_error);
00593                                           *spec = spec_walk;
00594                                           return "";
00595                                    }
00596                                    break;
00597                             } else {
00598                                    if (is_callable_error) {
00599                                           *severity = E_WARNING;
00600                                           zend_spprintf(error, 0, "to be a valid callback, %s", is_callable_error);
00601                                           efree(is_callable_error);
00602                                           return "";
00603                                    } else {
00604                                           return "valid callback";
00605                                    }
00606                             }
00607                      }
00608 
00609               case 'z':
00610                      {
00611                             zval **p = va_arg(*va, zval **);
00612                             if (return_null) {
00613                                    *p = NULL;
00614                             } else {
00615                                    *p = *arg;
00616                             }
00617                      }
00618                      break;
00619 
00620               case 'Z':
00621                      {
00622                             zval ***p = va_arg(*va, zval ***);
00623                             if (return_null) {
00624                                    *p = NULL;
00625                             } else {
00626                                    *p = arg;
00627                             }
00628                      }
00629                      break;
00630 
00631               default:
00632                      return "unknown";
00633        }
00634 
00635        *spec = spec_walk;
00636 
00637        return NULL;
00638 }
00639 /* }}} */
00640 
00641 static int zend_parse_arg(int arg_num, zval **arg, va_list *va, char **spec, int quiet TSRMLS_DC) /* {{{ */
00642 {
00643        char *expected_type = NULL, *error = NULL;
00644        int severity = E_WARNING;
00645 
00646        expected_type = zend_parse_arg_impl(arg_num, arg, va, spec, &error, &severity TSRMLS_CC);
00647        if (expected_type) {
00648               if (!quiet && (*expected_type || error)) {
00649                      char *space;
00650                      char *class_name = get_active_class_name(&space TSRMLS_CC);
00651 
00652                      if (error) {
00653                             zend_error(severity, "%s%s%s() expects parameter %d %s",
00654                                           class_name, space, get_active_function_name(TSRMLS_C), arg_num, error);
00655                             efree(error);
00656                      } else {
00657                             zend_error(severity, "%s%s%s() expects parameter %d to be %s, %s given",
00658                                           class_name, space, get_active_function_name(TSRMLS_C), arg_num, expected_type,
00659                                           zend_zval_type_name(*arg));
00660                      }
00661               }
00662               if (severity != E_STRICT) {
00663                      return FAILURE;
00664               }
00665        }
00666 
00667        return SUCCESS;
00668 }
00669 /* }}} */
00670 
00671 static int zend_parse_va_args(int num_args, char *type_spec, va_list *va, int flags TSRMLS_DC) /* {{{ */
00672 {
00673        char *spec_walk;
00674        int c, i;
00675        int min_num_args = -1;
00676        int max_num_args = 0;
00677        int post_varargs = 0;
00678        zval **arg;
00679        int arg_count = (int)(zend_uintptr_t) *(zend_vm_stack_top(TSRMLS_C) - 1);
00680        int quiet = flags & ZEND_PARSE_PARAMS_QUIET;
00681        zend_bool have_varargs = 0;
00682        zval ****varargs = NULL;
00683        int *n_varargs = NULL;
00684 
00685        for (spec_walk = type_spec; *spec_walk; spec_walk++) {
00686               c = *spec_walk;
00687               switch (c) {
00688                      case 's':
00689                             if (max_num_args < arg_count) {
00690                                    arg = (zval **) (zend_vm_stack_top(TSRMLS_C) - 1 - (arg_count - max_num_args));
00691                                    if (Z_TYPE_PP(arg) == IS_OBJECT) {
00692                                           parse_arg_object_to_string(arg TSRMLS_CC);
00693                                    }
00694                             }
00695                             /* break missing intentionally */
00696                      case 'l': case 'd':
00697                      case 'H': case 'b':
00698                      case 'r': case 'a':
00699                      case 'o': case 'O':
00700                      case 'z': case 'Z':
00701                      case 'C': case 'h':
00702                      case 'f': case 'A':
00703                             max_num_args++;
00704                             break;
00705 
00706                      case '|':
00707                             min_num_args = max_num_args;
00708                             break;
00709 
00710                      case '/':
00711                      case '!':
00712                             /* Pass */
00713                             break;
00714 
00715                      case '*':
00716                      case '+':
00717                             if (have_varargs) {
00718                                    if (!quiet) {
00719                                           zend_function *active_function = EG(current_execute_data)->function_state.function;
00720                                           char *class_name = active_function->common.scope ? active_function->common.scope->name : "";
00721                                           zend_error(E_WARNING, "%s%s%s(): only one varargs specifier (* or +) is permitted",
00722                                                         class_name,
00723                                                         class_name[0] ? "::" : "",
00724                                                         active_function->common.function_name);
00725                                    }
00726                                    return FAILURE;
00727                             }
00728                             have_varargs = 1;
00729                             /* we expect at least one parameter in varargs */
00730                             if (c == '+') {
00731                                    max_num_args++;
00732                             }
00733                             /* mark the beginning of varargs */
00734                             post_varargs = max_num_args;
00735                             break;
00736 
00737                      default:
00738                             if (!quiet) {
00739                                    zend_function *active_function = EG(current_execute_data)->function_state.function;
00740                                    char *class_name = active_function->common.scope ? active_function->common.scope->name : "";
00741                                    zend_error(E_WARNING, "%s%s%s(): bad type specifier while parsing parameters",
00742                                                  class_name,
00743                                                  class_name[0] ? "::" : "",
00744                                                  active_function->common.function_name);
00745                             }
00746                             return FAILURE;
00747               }
00748        }
00749 
00750        if (min_num_args < 0) {
00751               min_num_args = max_num_args;
00752        }
00753 
00754        if (have_varargs) {
00755               /* calculate how many required args are at the end of the specifier list */
00756               post_varargs = max_num_args - post_varargs;
00757               max_num_args = -1;
00758        }
00759 
00760        if (num_args < min_num_args || (num_args > max_num_args && max_num_args > 0)) {
00761               if (!quiet) {
00762                      zend_function *active_function = EG(current_execute_data)->function_state.function;
00763                      char *class_name = active_function->common.scope ? active_function->common.scope->name : "";
00764                      zend_error(E_WARNING, "%s%s%s() expects %s %d parameter%s, %d given",
00765                                    class_name,
00766                                    class_name[0] ? "::" : "",
00767                                    active_function->common.function_name,
00768                                    min_num_args == max_num_args ? "exactly" : num_args < min_num_args ? "at least" : "at most",
00769                                    num_args < min_num_args ? min_num_args : max_num_args,
00770                                    (num_args < min_num_args ? min_num_args : max_num_args) == 1 ? "" : "s",
00771                                    num_args);
00772               }
00773               return FAILURE;
00774        }
00775 
00776        if (num_args > arg_count) {
00777               zend_error(E_WARNING, "%s(): could not obtain parameters for parsing",
00778                      get_active_function_name(TSRMLS_C));
00779               return FAILURE;
00780        }
00781 
00782        i = 0;
00783        while (num_args-- > 0) {
00784               if (*type_spec == '|') {
00785                      type_spec++;
00786               }
00787 
00788               if (*type_spec == '*' || *type_spec == '+') {
00789                      int num_varargs = num_args + 1 - post_varargs;
00790 
00791                      /* eat up the passed in storage even if it won't be filled in with varargs */
00792                      varargs = va_arg(*va, zval ****);
00793                      n_varargs = va_arg(*va, int *);
00794                      type_spec++;
00795 
00796                      if (num_varargs > 0) {
00797                             int iv = 0;
00798                             zval **p = (zval **) (zend_vm_stack_top(TSRMLS_C) - 1 - (arg_count - i));
00799 
00800                             *n_varargs = num_varargs;
00801 
00802                             /* allocate space for array and store args */
00803                             *varargs = safe_emalloc(num_varargs, sizeof(zval **), 0);
00804                             while (num_varargs-- > 0) {
00805                                    (*varargs)[iv++] = p++;
00806                             }
00807 
00808                             /* adjust how many args we have left and restart loop */
00809                             num_args = num_args + 1 - iv;
00810                             i += iv;
00811                             continue;
00812                      } else {
00813                             *varargs = NULL;
00814                             *n_varargs = 0;
00815                      }
00816               }
00817 
00818               arg = (zval **) (zend_vm_stack_top(TSRMLS_C) - 1 - (arg_count-i));
00819 
00820               if (zend_parse_arg(i+1, arg, va, &type_spec, quiet TSRMLS_CC) == FAILURE) {
00821                      /* clean up varargs array if it was used */
00822                      if (varargs && *varargs) {
00823                             efree(*varargs);
00824                             *varargs = NULL;
00825                      }
00826                      return FAILURE;
00827               }
00828               i++;
00829        }
00830 
00831        return SUCCESS;
00832 }
00833 /* }}} */
00834 
00835 #define RETURN_IF_ZERO_ARGS(num_args, type_spec, quiet) { \
00836        int __num_args = (num_args); \
00837        \
00838        if (0 == (type_spec)[0] && 0 != __num_args && !(quiet)) { \
00839               char *__space; \
00840               char * __class_name = get_active_class_name(&__space TSRMLS_CC); \
00841               zend_error(E_WARNING, "%s%s%s() expects exactly 0 parameters, %d given", \
00842                      __class_name, __space, \
00843                      get_active_function_name(TSRMLS_C), __num_args); \
00844               return FAILURE; \
00845        }\
00846 }
00847 
00848 ZEND_API int zend_parse_parameters_ex(int flags, int num_args TSRMLS_DC, char *type_spec, ...) /* {{{ */
00849 {
00850        va_list va;
00851        int retval;
00852 
00853        RETURN_IF_ZERO_ARGS(num_args, type_spec, flags & ZEND_PARSE_PARAMS_QUIET);
00854 
00855        va_start(va, type_spec);
00856        retval = zend_parse_va_args(num_args, type_spec, &va, flags TSRMLS_CC);
00857        va_end(va);
00858 
00859        return retval;
00860 }
00861 /* }}} */
00862 
00863 ZEND_API int zend_parse_parameters(int num_args TSRMLS_DC, char *type_spec, ...) /* {{{ */
00864 {
00865        va_list va;
00866        int retval;
00867 
00868        RETURN_IF_ZERO_ARGS(num_args, type_spec, 0);
00869 
00870        va_start(va, type_spec);
00871        retval = zend_parse_va_args(num_args, type_spec, &va, 0 TSRMLS_CC);
00872        va_end(va);
00873 
00874        return retval;
00875 }
00876 /* }}} */
00877 
00878 ZEND_API int zend_parse_method_parameters(int num_args TSRMLS_DC, zval *this_ptr, char *type_spec, ...) /* {{{ */
00879 {
00880        va_list va;
00881        int retval;
00882        char *p = type_spec;
00883        zval **object;
00884        zend_class_entry *ce;
00885 
00886        if (!this_ptr) {
00887               RETURN_IF_ZERO_ARGS(num_args, p, 0);
00888 
00889               va_start(va, type_spec);
00890               retval = zend_parse_va_args(num_args, type_spec, &va, 0 TSRMLS_CC);
00891               va_end(va);
00892        } else {
00893               p++;
00894               RETURN_IF_ZERO_ARGS(num_args, p, 0);
00895 
00896               va_start(va, type_spec);
00897 
00898               object = va_arg(va, zval **);
00899               ce = va_arg(va, zend_class_entry *);
00900               *object = this_ptr;
00901 
00902               if (ce && !instanceof_function(Z_OBJCE_P(this_ptr), ce TSRMLS_CC)) {
00903                      zend_error(E_CORE_ERROR, "%s::%s() must be derived from %s::%s",
00904                             ce->name, get_active_function_name(TSRMLS_C), Z_OBJCE_P(this_ptr)->name, get_active_function_name(TSRMLS_C));
00905               }
00906 
00907               retval = zend_parse_va_args(num_args, p, &va, 0 TSRMLS_CC);
00908               va_end(va);
00909        }
00910        return retval;
00911 }
00912 /* }}} */
00913 
00914 ZEND_API int zend_parse_method_parameters_ex(int flags, int num_args TSRMLS_DC, zval *this_ptr, char *type_spec, ...) /* {{{ */
00915 {
00916        va_list va;
00917        int retval;
00918        char *p = type_spec;
00919        zval **object;
00920        zend_class_entry *ce;
00921        int quiet = flags & ZEND_PARSE_PARAMS_QUIET;
00922 
00923        if (!this_ptr) {
00924               RETURN_IF_ZERO_ARGS(num_args, p, quiet);
00925 
00926               va_start(va, type_spec);
00927               retval = zend_parse_va_args(num_args, type_spec, &va, flags TSRMLS_CC);
00928               va_end(va);
00929        } else {
00930               p++;
00931               RETURN_IF_ZERO_ARGS(num_args, p, quiet);
00932 
00933               va_start(va, type_spec);
00934 
00935               object = va_arg(va, zval **);
00936               ce = va_arg(va, zend_class_entry *);
00937               *object = this_ptr;
00938 
00939               if (ce && !instanceof_function(Z_OBJCE_P(this_ptr), ce TSRMLS_CC)) {
00940                      if (!quiet) {
00941                             zend_error(E_CORE_ERROR, "%s::%s() must be derived from %s::%s",
00942                                    ce->name, get_active_function_name(TSRMLS_C), Z_OBJCE_P(this_ptr)->name, get_active_function_name(TSRMLS_C));
00943                      }
00944                      va_end(va);
00945                      return FAILURE;
00946               }
00947 
00948               retval = zend_parse_va_args(num_args, p, &va, flags TSRMLS_CC);
00949               va_end(va);
00950        }
00951        return retval;
00952 }
00953 /* }}} */
00954 
00955 /* Argument parsing API -- andrei */
00956 ZEND_API int _array_init(zval *arg, uint size ZEND_FILE_LINE_DC) /* {{{ */
00957 {
00958        ALLOC_HASHTABLE_REL(Z_ARRVAL_P(arg));
00959 
00960        _zend_hash_init(Z_ARRVAL_P(arg), size, NULL, ZVAL_PTR_DTOR, 0 ZEND_FILE_LINE_RELAY_CC);
00961        Z_TYPE_P(arg) = IS_ARRAY;
00962        return SUCCESS;
00963 }
00964 /* }}} */
00965 
00966 static int zend_merge_property(zval **value TSRMLS_DC, int num_args, va_list args, const zend_hash_key *hash_key) /* {{{ */
00967 {
00968        /* which name should a numeric property have ? */
00969        if (hash_key->nKeyLength) {
00970               zval *obj = va_arg(args, zval *);
00971               zend_object_handlers *obj_ht = va_arg(args, zend_object_handlers *);
00972               zval *member;
00973 
00974               MAKE_STD_ZVAL(member);
00975               ZVAL_STRINGL(member, hash_key->arKey, hash_key->nKeyLength-1, 1);
00976               obj_ht->write_property(obj, member, *value TSRMLS_CC);
00977               zval_ptr_dtor(&member);
00978        }
00979        return ZEND_HASH_APPLY_KEEP;
00980 }
00981 /* }}} */
00982 
00983 /* This function should be called after the constructor has been called
00984  * because it may call __set from the uninitialized object otherwise. */
00985 ZEND_API void zend_merge_properties(zval *obj, HashTable *properties, int destroy_ht TSRMLS_DC) /* {{{ */
00986 {
00987        zend_object_handlers *obj_ht = Z_OBJ_HT_P(obj);
00988        zend_class_entry *old_scope = EG(scope);
00989 
00990        EG(scope) = Z_OBJCE_P(obj);
00991        zend_hash_apply_with_arguments(properties TSRMLS_CC, (apply_func_args_t)zend_merge_property, 2, obj, obj_ht);
00992        EG(scope) = old_scope;
00993 
00994        if (destroy_ht) {
00995               zend_hash_destroy(properties);
00996               FREE_HASHTABLE(properties);
00997        }
00998 }
00999 /* }}} */
01000 
01001 ZEND_API void zend_update_class_constants(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
01002 {
01003        if (!class_type->constants_updated || !CE_STATIC_MEMBERS(class_type)) {
01004               zend_class_entry **scope = EG(in_execution)?&EG(scope):&CG(active_class_entry);
01005               zend_class_entry *old_scope = *scope;
01006 
01007               *scope = class_type;
01008               zend_hash_apply_with_argument(&class_type->constants_table, (apply_func_arg_t) zval_update_constant, (void*)1 TSRMLS_CC);
01009               zend_hash_apply_with_argument(&class_type->default_properties, (apply_func_arg_t) zval_update_constant, (void *) 1 TSRMLS_CC);
01010 
01011               if (!CE_STATIC_MEMBERS(class_type)) {
01012                      HashPosition pos;
01013                      zval **p;
01014 
01015                      if (class_type->parent) {
01016                             zend_update_class_constants(class_type->parent TSRMLS_CC);
01017                      }
01018 #if ZTS
01019                      ALLOC_HASHTABLE(CG(static_members)[(zend_intptr_t)(class_type->static_members)]);
01020 #else
01021                      ALLOC_HASHTABLE(class_type->static_members);
01022 #endif
01023                      zend_hash_init(CE_STATIC_MEMBERS(class_type), zend_hash_num_elements(&class_type->default_static_members), NULL, ZVAL_PTR_DTOR, 0);
01024 
01025                      zend_hash_internal_pointer_reset_ex(&class_type->default_static_members, &pos);
01026                      while (zend_hash_get_current_data_ex(&class_type->default_static_members, (void**)&p, &pos) == SUCCESS) {
01027                             char *str_index;
01028                             uint str_length;
01029                             ulong num_index;
01030                             zval **q;
01031 
01032                             zend_hash_get_current_key_ex(&class_type->default_static_members, &str_index, &str_length, &num_index, 0, &pos);
01033                             if (Z_ISREF_PP(p) &&
01034                                    class_type->parent &&
01035                                    zend_hash_find(&class_type->parent->default_static_members, str_index, str_length, (void**)&q) == SUCCESS &&
01036                                    *p == *q &&
01037                                    zend_hash_find(CE_STATIC_MEMBERS(class_type->parent), str_index, str_length, (void**)&q) == SUCCESS
01038                             ) {
01039                                    Z_ADDREF_PP(q);
01040                                    Z_SET_ISREF_PP(q);
01041                                    zend_hash_add(CE_STATIC_MEMBERS(class_type), str_index, str_length, (void**)q, sizeof(zval*), NULL);
01042                             } else {
01043                                    zval *r;
01044 
01045                                    ALLOC_ZVAL(r);
01046                                    *r = **p;
01047                                    INIT_PZVAL(r);
01048                                    zval_copy_ctor(r);
01049                                    zend_hash_add(CE_STATIC_MEMBERS(class_type), str_index, str_length, (void**)&r, sizeof(zval*), NULL);
01050                             }
01051                             zend_hash_move_forward_ex(&class_type->default_static_members, &pos);
01052                      }
01053               }
01054               zend_hash_apply_with_argument(CE_STATIC_MEMBERS(class_type), (apply_func_arg_t) zval_update_constant, (void *) 1 TSRMLS_CC);
01055 
01056               *scope = old_scope;
01057               class_type->constants_updated = 1;
01058        }
01059 }
01060 /* }}} */
01061 
01062 /* This function requires 'properties' to contain all props declared in the
01063  * class and all props being public. If only a subset is given or the class
01064  * has protected members then you need to merge the properties seperately by
01065  * calling zend_merge_properties(). */
01066 ZEND_API int _object_and_properties_init(zval *arg, zend_class_entry *class_type, HashTable *properties ZEND_FILE_LINE_DC TSRMLS_DC) /* {{{ */
01067 {
01068        zval *tmp;
01069        zend_object *object;
01070 
01071        if (class_type->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) {
01072               char *what = class_type->ce_flags & ZEND_ACC_INTERFACE ? "interface" : "abstract class";
01073               zend_error(E_ERROR, "Cannot instantiate %s %s", what, class_type->name);
01074        }
01075 
01076        zend_update_class_constants(class_type TSRMLS_CC);
01077 
01078        Z_TYPE_P(arg) = IS_OBJECT;
01079        if (class_type->create_object == NULL) {
01080               Z_OBJVAL_P(arg) = zend_objects_new(&object, class_type TSRMLS_CC);
01081               if (properties) {
01082                      object->properties = properties;
01083               } else {
01084                      ALLOC_HASHTABLE_REL(object->properties);
01085                      zend_hash_init(object->properties, zend_hash_num_elements(&class_type->default_properties), NULL, ZVAL_PTR_DTOR, 0);
01086                      zend_hash_copy(object->properties, &class_type->default_properties, zval_copy_property_ctor(class_type), (void *) &tmp, sizeof(zval *));
01087               }
01088        } else {
01089               Z_OBJVAL_P(arg) = class_type->create_object(class_type TSRMLS_CC);
01090        }
01091        return SUCCESS;
01092 }
01093 /* }}} */
01094 
01095 ZEND_API int _object_init_ex(zval *arg, zend_class_entry *class_type ZEND_FILE_LINE_DC TSRMLS_DC) /* {{{ */
01096 {
01097        return _object_and_properties_init(arg, class_type, 0 ZEND_FILE_LINE_RELAY_CC TSRMLS_CC);
01098 }
01099 /* }}} */
01100 
01101 ZEND_API int _object_init(zval *arg ZEND_FILE_LINE_DC TSRMLS_DC) /* {{{ */
01102 {
01103        return _object_init_ex(arg, zend_standard_class_def ZEND_FILE_LINE_RELAY_CC TSRMLS_CC);
01104 }
01105 /* }}} */
01106 
01107 ZEND_API int add_assoc_function(zval *arg, const char *key, void (*function_ptr)(INTERNAL_FUNCTION_PARAMETERS)) /* {{{ */
01108 {
01109        zend_error(E_WARNING, "add_assoc_function() is no longer supported");
01110        return FAILURE;
01111 }
01112 /* }}} */
01113 
01114 ZEND_API int add_assoc_long_ex(zval *arg, const char *key, uint key_len, long n) /* {{{ */
01115 {
01116        zval *tmp;
01117 
01118        MAKE_STD_ZVAL(tmp);
01119        ZVAL_LONG(tmp, n);
01120 
01121        return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL);
01122 }
01123 /* }}} */
01124 
01125 ZEND_API int add_assoc_null_ex(zval *arg, const char *key, uint key_len) /* {{{ */
01126 {
01127        zval *tmp;
01128 
01129        MAKE_STD_ZVAL(tmp);
01130        ZVAL_NULL(tmp);
01131 
01132        return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL);
01133 }
01134 /* }}} */
01135 
01136 ZEND_API int add_assoc_bool_ex(zval *arg, const char *key, uint key_len, int b) /* {{{ */
01137 {
01138        zval *tmp;
01139 
01140        MAKE_STD_ZVAL(tmp);
01141        ZVAL_BOOL(tmp, b);
01142 
01143        return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL);
01144 }
01145 /* }}} */
01146 
01147 ZEND_API int add_assoc_resource_ex(zval *arg, const char *key, uint key_len, int r) /* {{{ */
01148 {
01149        zval *tmp;
01150 
01151        MAKE_STD_ZVAL(tmp);
01152        ZVAL_RESOURCE(tmp, r);
01153 
01154        return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL);
01155 }
01156 /* }}} */
01157 
01158 ZEND_API int add_assoc_double_ex(zval *arg, const char *key, uint key_len, double d) /* {{{ */
01159 {
01160        zval *tmp;
01161 
01162        MAKE_STD_ZVAL(tmp);
01163        ZVAL_DOUBLE(tmp, d);
01164 
01165        return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL);
01166 }
01167 /* }}} */
01168 
01169 ZEND_API int add_assoc_string_ex(zval *arg, const char *key, uint key_len, char *str, int duplicate) /* {{{ */
01170 {
01171        zval *tmp;
01172 
01173        MAKE_STD_ZVAL(tmp);
01174        ZVAL_STRING(tmp, str, duplicate);
01175 
01176        return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL);
01177 }
01178 /* }}} */
01179 
01180 ZEND_API int add_assoc_stringl_ex(zval *arg, const char *key, uint key_len, char *str, uint length, int duplicate) /* {{{ */
01181 {
01182        zval *tmp;
01183 
01184        MAKE_STD_ZVAL(tmp);
01185        ZVAL_STRINGL(tmp, str, length, duplicate);
01186 
01187        return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL);
01188 }
01189 /* }}} */
01190 
01191 ZEND_API int add_assoc_zval_ex(zval *arg, const char *key, uint key_len, zval *value) /* {{{ */
01192 {
01193        return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &value, sizeof(zval *), NULL);
01194 }
01195 /* }}} */
01196 
01197 ZEND_API int add_index_long(zval *arg, ulong index, long n) /* {{{ */
01198 {
01199        zval *tmp;
01200 
01201        MAKE_STD_ZVAL(tmp);
01202        ZVAL_LONG(tmp, n);
01203 
01204        return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL);
01205 }
01206 /* }}} */
01207 
01208 ZEND_API int add_index_null(zval *arg, ulong index) /* {{{ */
01209 {
01210        zval *tmp;
01211 
01212        MAKE_STD_ZVAL(tmp);
01213        ZVAL_NULL(tmp);
01214 
01215        return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL);
01216 }
01217 /* }}} */
01218 
01219 ZEND_API int add_index_bool(zval *arg, ulong index, int b) /* {{{ */
01220 {
01221        zval *tmp;
01222 
01223        MAKE_STD_ZVAL(tmp);
01224        ZVAL_BOOL(tmp, b);
01225 
01226        return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL);
01227 }
01228 /* }}} */
01229 
01230 ZEND_API int add_index_resource(zval *arg, ulong index, int r) /* {{{ */
01231 {
01232        zval *tmp;
01233 
01234        MAKE_STD_ZVAL(tmp);
01235        ZVAL_RESOURCE(tmp, r);
01236 
01237        return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL);
01238 }
01239 /* }}} */
01240 
01241 ZEND_API int add_index_double(zval *arg, ulong index, double d) /* {{{ */
01242 {
01243        zval *tmp;
01244 
01245        MAKE_STD_ZVAL(tmp);
01246        ZVAL_DOUBLE(tmp, d);
01247 
01248        return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL);
01249 }
01250 /* }}} */
01251 
01252 ZEND_API int add_index_string(zval *arg, ulong index, const char *str, int duplicate) /* {{{ */
01253 {
01254        zval *tmp;
01255 
01256        MAKE_STD_ZVAL(tmp);
01257        ZVAL_STRING(tmp, str, duplicate);
01258 
01259        return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL);
01260 }
01261 /* }}} */
01262 
01263 ZEND_API int add_index_stringl(zval *arg, ulong index, const char *str, uint length, int duplicate) /* {{{ */
01264 {
01265        zval *tmp;
01266 
01267        MAKE_STD_ZVAL(tmp);
01268        ZVAL_STRINGL(tmp, str, length, duplicate);
01269 
01270        return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL);
01271 }
01272 /* }}} */
01273 
01274 ZEND_API int add_index_zval(zval *arg, ulong index, zval *value) /* {{{ */
01275 {
01276        return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &value, sizeof(zval *), NULL);
01277 }
01278 /* }}} */
01279 
01280 ZEND_API int add_next_index_long(zval *arg, long n) /* {{{ */
01281 {
01282        zval *tmp;
01283 
01284        MAKE_STD_ZVAL(tmp);
01285        ZVAL_LONG(tmp, n);
01286 
01287        return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL);
01288 }
01289 /* }}} */
01290 
01291 ZEND_API int add_next_index_null(zval *arg) /* {{{ */
01292 {
01293        zval *tmp;
01294 
01295        MAKE_STD_ZVAL(tmp);
01296        ZVAL_NULL(tmp);
01297 
01298        return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL);
01299 }
01300 /* }}} */
01301 
01302 ZEND_API int add_next_index_bool(zval *arg, int b) /* {{{ */
01303 {
01304        zval *tmp;
01305 
01306        MAKE_STD_ZVAL(tmp);
01307        ZVAL_BOOL(tmp, b);
01308 
01309        return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL);
01310 }
01311 /* }}} */
01312 
01313 ZEND_API int add_next_index_resource(zval *arg, int r) /* {{{ */
01314 {
01315        zval *tmp;
01316 
01317        MAKE_STD_ZVAL(tmp);
01318        ZVAL_RESOURCE(tmp, r);
01319 
01320        return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL);
01321 }
01322 /* }}} */
01323 
01324 ZEND_API int add_next_index_double(zval *arg, double d) /* {{{ */
01325 {
01326        zval *tmp;
01327 
01328        MAKE_STD_ZVAL(tmp);
01329        ZVAL_DOUBLE(tmp, d);
01330 
01331        return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL);
01332 }
01333 /* }}} */
01334 
01335 ZEND_API int add_next_index_string(zval *arg, const char *str, int duplicate) /* {{{ */
01336 {
01337        zval *tmp;
01338 
01339        MAKE_STD_ZVAL(tmp);
01340        ZVAL_STRING(tmp, str, duplicate);
01341 
01342        return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL);
01343 }
01344 /* }}} */
01345 
01346 ZEND_API int add_next_index_stringl(zval *arg, const char *str, uint length, int duplicate) /* {{{ */
01347 {
01348        zval *tmp;
01349 
01350        MAKE_STD_ZVAL(tmp);
01351        ZVAL_STRINGL(tmp, str, length, duplicate);
01352 
01353        return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL);
01354 }
01355 /* }}} */
01356 
01357 ZEND_API int add_next_index_zval(zval *arg, zval *value) /* {{{ */
01358 {
01359        return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &value, sizeof(zval *), NULL);
01360 }
01361 /* }}} */
01362 
01363 ZEND_API int add_get_assoc_string_ex(zval *arg, const char *key, uint key_len, const char *str, void **dest, int duplicate) /* {{{ */
01364 {
01365        zval *tmp;
01366 
01367        MAKE_STD_ZVAL(tmp);
01368        ZVAL_STRING(tmp, str, duplicate);
01369 
01370        return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), dest);
01371 }
01372 /* }}} */
01373 
01374 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) /* {{{ */
01375 {
01376        zval *tmp;
01377 
01378        MAKE_STD_ZVAL(tmp);
01379        ZVAL_STRINGL(tmp, str, length, duplicate);
01380 
01381        return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), dest);
01382 }
01383 /* }}} */
01384 
01385 ZEND_API int add_get_index_long(zval *arg, ulong index, long l, void **dest) /* {{{ */
01386 {
01387        zval *tmp;
01388 
01389        MAKE_STD_ZVAL(tmp);
01390        ZVAL_LONG(tmp, l);
01391 
01392        return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), dest);
01393 }
01394 /* }}} */
01395 
01396 ZEND_API int add_get_index_double(zval *arg, ulong index, double d, void **dest) /* {{{ */
01397 {
01398        zval *tmp;
01399 
01400        MAKE_STD_ZVAL(tmp);
01401        ZVAL_DOUBLE(tmp, d);
01402 
01403        return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), dest);
01404 }
01405 /* }}} */
01406 
01407 ZEND_API int add_get_index_string(zval *arg, ulong index, const char *str, void **dest, int duplicate) /* {{{ */
01408 {
01409        zval *tmp;
01410 
01411        MAKE_STD_ZVAL(tmp);
01412        ZVAL_STRING(tmp, str, duplicate);
01413 
01414        return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), dest);
01415 }
01416 /* }}} */
01417 
01418 ZEND_API int add_get_index_stringl(zval *arg, ulong index, const char *str, uint length, void **dest, int duplicate) /* {{{ */
01419 {
01420        zval *tmp;
01421 
01422        MAKE_STD_ZVAL(tmp);
01423        ZVAL_STRINGL(tmp, str, length, duplicate);
01424 
01425        return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), dest);
01426 }
01427 /* }}} */
01428 
01429 ZEND_API int add_property_long_ex(zval *arg, const char *key, uint key_len, long n TSRMLS_DC) /* {{{ */
01430 {
01431        zval *tmp;
01432        zval *z_key;
01433 
01434        MAKE_STD_ZVAL(tmp);
01435        ZVAL_LONG(tmp, n);
01436 
01437        MAKE_STD_ZVAL(z_key);
01438        ZVAL_STRINGL(z_key, key, key_len-1, 1);
01439 
01440        Z_OBJ_HANDLER_P(arg, write_property)(arg, z_key, tmp TSRMLS_CC);
01441        zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
01442        zval_ptr_dtor(&z_key);
01443        return SUCCESS;
01444 }
01445 /* }}} */
01446 
01447 ZEND_API int add_property_bool_ex(zval *arg, const char *key, uint key_len, int b TSRMLS_DC) /* {{{ */
01448 {
01449        zval *tmp;
01450        zval *z_key;
01451 
01452        MAKE_STD_ZVAL(tmp);
01453        ZVAL_BOOL(tmp, b);
01454 
01455        MAKE_STD_ZVAL(z_key);
01456        ZVAL_STRINGL(z_key, key, key_len-1, 1);
01457 
01458        Z_OBJ_HANDLER_P(arg, write_property)(arg, z_key, tmp TSRMLS_CC);
01459        zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
01460        zval_ptr_dtor(&z_key);
01461        return SUCCESS;
01462 }
01463 /* }}} */
01464 
01465 ZEND_API int add_property_null_ex(zval *arg, const char *key, uint key_len TSRMLS_DC) /* {{{ */
01466 {
01467        zval *tmp;
01468        zval *z_key;
01469 
01470        MAKE_STD_ZVAL(tmp);
01471        ZVAL_NULL(tmp);
01472 
01473        MAKE_STD_ZVAL(z_key);
01474        ZVAL_STRINGL(z_key, key, key_len-1, 1);
01475 
01476        Z_OBJ_HANDLER_P(arg, write_property)(arg, z_key, tmp TSRMLS_CC);
01477        zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
01478        zval_ptr_dtor(&z_key);
01479        return SUCCESS;
01480 }
01481 /* }}} */
01482 
01483 ZEND_API int add_property_resource_ex(zval *arg, const char *key, uint key_len, long n TSRMLS_DC) /* {{{ */
01484 {
01485        zval *tmp;
01486        zval *z_key;
01487 
01488        MAKE_STD_ZVAL(tmp);
01489        ZVAL_RESOURCE(tmp, n);
01490 
01491        MAKE_STD_ZVAL(z_key);
01492        ZVAL_STRINGL(z_key, key, key_len-1, 1);
01493 
01494        Z_OBJ_HANDLER_P(arg, write_property)(arg, z_key, tmp TSRMLS_CC);
01495        zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
01496        zval_ptr_dtor(&z_key);
01497        return SUCCESS;
01498 }
01499 /* }}} */
01500 
01501 ZEND_API int add_property_double_ex(zval *arg, const char *key, uint key_len, double d TSRMLS_DC) /* {{{ */
01502 {
01503        zval *tmp;
01504        zval *z_key;
01505 
01506        MAKE_STD_ZVAL(tmp);
01507        ZVAL_DOUBLE(tmp, d);
01508 
01509        MAKE_STD_ZVAL(z_key);
01510        ZVAL_STRINGL(z_key, key, key_len-1, 1);
01511 
01512        Z_OBJ_HANDLER_P(arg, write_property)(arg, z_key, tmp TSRMLS_CC);
01513        zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
01514        zval_ptr_dtor(&z_key);
01515        return SUCCESS;
01516 }
01517 /* }}} */
01518 
01519 ZEND_API int add_property_string_ex(zval *arg, const char *key, uint key_len, char *str, int duplicate TSRMLS_DC) /* {{{ */
01520 {
01521        zval *tmp;
01522        zval *z_key;
01523 
01524        MAKE_STD_ZVAL(tmp);
01525        ZVAL_STRING(tmp, str, duplicate);
01526 
01527        MAKE_STD_ZVAL(z_key);
01528        ZVAL_STRINGL(z_key, key, key_len-1, 1);
01529 
01530        Z_OBJ_HANDLER_P(arg, write_property)(arg, z_key, tmp TSRMLS_CC);
01531        zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
01532        zval_ptr_dtor(&z_key);
01533        return SUCCESS;
01534 }
01535 /* }}} */
01536 
01537 ZEND_API int add_property_stringl_ex(zval *arg, const char *key, uint key_len, char *str, uint length, int duplicate TSRMLS_DC) /* {{{ */
01538 {
01539        zval *tmp;
01540        zval *z_key;
01541 
01542        MAKE_STD_ZVAL(tmp);
01543        ZVAL_STRINGL(tmp, str, length, duplicate);
01544 
01545        MAKE_STD_ZVAL(z_key);
01546        ZVAL_STRINGL(z_key, key, key_len-1, 1);
01547 
01548        Z_OBJ_HANDLER_P(arg, write_property)(arg, z_key, tmp TSRMLS_CC);
01549        zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
01550        zval_ptr_dtor(&z_key);
01551        return SUCCESS;
01552 }
01553 /* }}} */
01554 
01555 ZEND_API int add_property_zval_ex(zval *arg, const char *key, uint key_len, zval *value TSRMLS_DC) /* {{{ */
01556 {
01557        zval *z_key;
01558 
01559        MAKE_STD_ZVAL(z_key);
01560        ZVAL_STRINGL(z_key, key, key_len-1, 1);
01561 
01562        Z_OBJ_HANDLER_P(arg, write_property)(arg, z_key, value TSRMLS_CC);
01563        zval_ptr_dtor(&z_key);
01564        return SUCCESS;
01565 }
01566 /* }}} */
01567 
01568 ZEND_API int zend_startup_module_ex(zend_module_entry *module TSRMLS_DC) /* {{{ */
01569 {
01570        int name_len;
01571        char *lcname;
01572 
01573        if (module->module_started) {
01574               return SUCCESS;
01575        }
01576        module->module_started = 1;
01577 
01578        /* Check module dependencies */
01579        if (module->deps) {
01580               const zend_module_dep *dep = module->deps;
01581 
01582               while (dep->name) {
01583                      if (dep->type == MODULE_DEP_REQUIRED) {
01584                             zend_module_entry *req_mod;
01585 
01586                             name_len = strlen(dep->name);
01587                             lcname = zend_str_tolower_dup(dep->name, name_len);
01588 
01589                             if (zend_hash_find(&module_registry, lcname, name_len+1, (void**)&req_mod) == FAILURE || !req_mod->module_started) {
01590                                    efree(lcname);
01591                                    /* TODO: Check version relationship */
01592                                    zend_error(E_CORE_WARNING, "Cannot load module '%s' because required module '%s' is not loaded", module->name, dep->name);
01593                                    module->module_started = 0;
01594                                    return FAILURE;
01595                             }
01596                             efree(lcname);
01597                      }
01598                      ++dep;
01599               }
01600        }
01601 
01602        /* Initialize module globals */
01603        if (module->globals_size) {
01604 #ifdef ZTS
01605               ts_allocate_id(module->globals_id_ptr, module->globals_size, (ts_allocate_ctor) module->globals_ctor, (ts_allocate_dtor) module->globals_dtor);
01606 #else
01607               if (module->globals_ctor) {
01608                      module->globals_ctor(module->globals_ptr TSRMLS_CC);
01609               }
01610 #endif
01611        }
01612        if (module->module_startup_func) {
01613               EG(current_module) = module;
01614               if (module->module_startup_func(module->type, module->module_number TSRMLS_CC)==FAILURE) {
01615                      zend_error(E_CORE_ERROR,"Unable to start %s module", module->name);
01616                      EG(current_module) = NULL;
01617                      return FAILURE;
01618               }
01619               EG(current_module) = NULL;
01620        }
01621        return SUCCESS;
01622 }
01623 /* }}} */
01624 
01625 static void zend_sort_modules(void *base, size_t count, size_t siz, compare_func_t compare TSRMLS_DC) /* {{{ */
01626 {
01627        Bucket **b1 = base;
01628        Bucket **b2;
01629        Bucket **end = b1 + count;
01630        Bucket *tmp;
01631        zend_module_entry *m, *r;
01632 
01633        while (b1 < end) {
01634 try_again:
01635               m = (zend_module_entry*)(*b1)->pData;
01636               if (!m->module_started && m->deps) {
01637                      const zend_module_dep *dep = m->deps;
01638                      while (dep->name) {
01639                             if (dep->type == MODULE_DEP_REQUIRED || dep->type == MODULE_DEP_OPTIONAL) {
01640                                    b2 = b1 + 1;
01641                                    while (b2 < end) {
01642                                           r = (zend_module_entry*)(*b2)->pData;
01643                                           if (strcasecmp(dep->name, r->name) == 0) {
01644                                                  tmp = *b1;
01645                                                  *b1 = *b2;
01646                                                  *b2 = tmp;
01647                                                  goto try_again;
01648                                           }
01649                                           b2++;
01650                                    }
01651                             }
01652                             dep++;
01653                      }
01654               }
01655               b1++;
01656        }
01657 }
01658 /* }}} */
01659 
01660 ZEND_API int zend_startup_modules(TSRMLS_D) /* {{{ */
01661 {
01662        zend_hash_sort(&module_registry, zend_sort_modules, NULL, 0 TSRMLS_CC);
01663        zend_hash_apply(&module_registry, (apply_func_t)zend_startup_module_ex TSRMLS_CC);
01664        return SUCCESS;
01665 }
01666 /* }}} */
01667 
01668 ZEND_API zend_module_entry* zend_register_module_ex(zend_module_entry *module TSRMLS_DC) /* {{{ */
01669 {
01670        int name_len;
01671        char *lcname;
01672        zend_module_entry *module_ptr;
01673 
01674        if (!module) {
01675               return NULL;
01676        }
01677 
01678 #if 0
01679        zend_printf("%s: Registering module %d\n", module->name, module->module_number);
01680 #endif
01681 
01682        /* Check module dependencies */
01683        if (module->deps) {
01684               const zend_module_dep *dep = module->deps;
01685 
01686               while (dep->name) {
01687                      if (dep->type == MODULE_DEP_CONFLICTS) {
01688                             name_len = strlen(dep->name);
01689                             lcname = zend_str_tolower_dup(dep->name, name_len);
01690 
01691                             if (zend_hash_exists(&module_registry, lcname, name_len+1)) {
01692                                    efree(lcname);
01693                                    /* TODO: Check version relationship */
01694                                    zend_error(E_CORE_WARNING, "Cannot load module '%s' because conflicting module '%s' is already loaded", module->name, dep->name);
01695                                    return NULL;
01696                             }
01697                             efree(lcname);
01698                      }
01699                      ++dep;
01700               }
01701        }
01702 
01703        name_len = strlen(module->name);
01704        lcname = zend_str_tolower_dup(module->name, name_len);
01705 
01706        if (zend_hash_add(&module_registry, lcname, name_len+1, (void *)module, sizeof(zend_module_entry), (void**)&module_ptr)==FAILURE) {
01707               zend_error(E_CORE_WARNING, "Module '%s' already loaded", module->name);
01708               efree(lcname);
01709               return NULL;
01710        }
01711        efree(lcname);
01712        module = module_ptr;
01713        EG(current_module) = module;
01714 
01715        if (module->functions && zend_register_functions(NULL, module->functions, NULL, module->type TSRMLS_CC)==FAILURE) {
01716               EG(current_module) = NULL;
01717               zend_error(E_CORE_WARNING,"%s: Unable to register functions, unable to load", module->name);
01718               return NULL;
01719        }
01720 
01721        EG(current_module) = NULL;
01722        return module;
01723 }
01724 /* }}} */
01725 
01726 ZEND_API zend_module_entry* zend_register_internal_module(zend_module_entry *module TSRMLS_DC) /* {{{ */
01727 {
01728        module->module_number = zend_next_free_module();
01729        module->type = MODULE_PERSISTENT;
01730        return zend_register_module_ex(module TSRMLS_CC);
01731 }
01732 /* }}} */
01733 
01734 ZEND_API void zend_check_magic_method_implementation(const zend_class_entry *ce, const zend_function *fptr, int error_type TSRMLS_DC) /* {{{ */
01735 {
01736        char lcname[16];
01737        int name_len;
01738 
01739        /* we don't care if the function name is longer, in fact lowercasing only
01740         * the beginning of the name speeds up the check process */
01741        name_len = strlen(fptr->common.function_name);
01742        zend_str_tolower_copy(lcname, fptr->common.function_name, MIN(name_len, sizeof(lcname)-1));
01743        lcname[sizeof(lcname)-1] = '\0'; /* zend_str_tolower_copy won't necessarily set the zero byte */
01744 
01745        if (name_len == sizeof(ZEND_DESTRUCTOR_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_DESTRUCTOR_FUNC_NAME, sizeof(ZEND_DESTRUCTOR_FUNC_NAME)) && fptr->common.num_args != 0) {
01746               zend_error(error_type, "Destructor %s::%s() cannot take arguments", ce->name, ZEND_DESTRUCTOR_FUNC_NAME);
01747        } else if (name_len == sizeof(ZEND_CLONE_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME)) && fptr->common.num_args != 0) {
01748               zend_error(error_type, "Method %s::%s() cannot accept any arguments", ce->name, ZEND_CLONE_FUNC_NAME);
01749        } else if (name_len == sizeof(ZEND_GET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME))) {
01750               if (fptr->common.num_args != 1) {
01751                      zend_error(error_type, "Method %s::%s() must take exactly 1 argument", ce->name, ZEND_GET_FUNC_NAME);
01752               } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr, 1)) {
01753                      zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ce->name, ZEND_GET_FUNC_NAME);
01754               }
01755        } else if (name_len == sizeof(ZEND_SET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME))) {
01756               if (fptr->common.num_args != 2) {
01757                      zend_error(error_type, "Method %s::%s() must take exactly 2 arguments", ce->name, ZEND_SET_FUNC_NAME);
01758               } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr, 1) || ARG_SHOULD_BE_SENT_BY_REF(fptr, 2)) {
01759                      zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ce->name, ZEND_SET_FUNC_NAME);
01760               }
01761        } else if (name_len == sizeof(ZEND_UNSET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_UNSET_FUNC_NAME, sizeof(ZEND_UNSET_FUNC_NAME))) {
01762               if (fptr->common.num_args != 1) {
01763                      zend_error(error_type, "Method %s::%s() must take exactly 1 argument", ce->name, ZEND_UNSET_FUNC_NAME);
01764               } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr, 1)) {
01765                      zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ce->name, ZEND_UNSET_FUNC_NAME);
01766               }
01767        } else if (name_len == sizeof(ZEND_ISSET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_ISSET_FUNC_NAME, sizeof(ZEND_ISSET_FUNC_NAME))) {
01768               if (fptr->common.num_args != 1) {
01769                      zend_error(error_type, "Method %s::%s() must take exactly 1 argument", ce->name, ZEND_ISSET_FUNC_NAME);
01770               } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr, 1)) {
01771                      zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ce->name, ZEND_ISSET_FUNC_NAME);
01772               }
01773        } else if (name_len == sizeof(ZEND_CALL_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME))) {
01774               if (fptr->common.num_args != 2) {
01775                      zend_error(error_type, "Method %s::%s() must take exactly 2 arguments", ce->name, ZEND_CALL_FUNC_NAME);
01776               } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr, 1) || ARG_SHOULD_BE_SENT_BY_REF(fptr, 2)) {
01777                      zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ce->name, ZEND_CALL_FUNC_NAME);
01778               }
01779        } else if (name_len == sizeof(ZEND_CALLSTATIC_FUNC_NAME) - 1 &&
01780               !memcmp(lcname, ZEND_CALLSTATIC_FUNC_NAME, sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1)
01781        ) {
01782               if (fptr->common.num_args != 2) {
01783                      zend_error(error_type, "Method %s::%s() must take exactly 2 arguments", ce->name, ZEND_CALLSTATIC_FUNC_NAME);
01784               } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr, 1) || ARG_SHOULD_BE_SENT_BY_REF(fptr, 2)) {
01785                      zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ce->name, ZEND_CALLSTATIC_FUNC_NAME);
01786               }
01787        } else if (name_len == sizeof(ZEND_TOSTRING_FUNC_NAME) - 1 &&
01788               !memcmp(lcname, ZEND_TOSTRING_FUNC_NAME, sizeof(ZEND_TOSTRING_FUNC_NAME)-1) && fptr->common.num_args != 0
01789        ) {
01790               zend_error(error_type, "Method %s::%s() cannot take arguments", ce->name, ZEND_TOSTRING_FUNC_NAME);
01791        }
01792 }
01793 /* }}} */
01794 
01795 /* registers all functions in *library_functions in the function hash */
01796 ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_function_entry *functions, HashTable *function_table, int type TSRMLS_DC) /* {{{ */
01797 {
01798        const zend_function_entry *ptr = functions;
01799        zend_function function, *reg_function;
01800        zend_internal_function *internal_function = (zend_internal_function *)&function;
01801        int count=0, unload=0;
01802        HashTable *target_function_table = function_table;
01803        int error_type;
01804        zend_function *ctor = NULL, *dtor = NULL, *clone = NULL, *__get = NULL, *__set = NULL, *__unset = NULL, *__isset = NULL, *__call = NULL, *__callstatic = NULL, *__tostring = NULL;
01805        char *lowercase_name;
01806        int fname_len;
01807        char *lc_class_name = NULL;
01808        int class_name_len = 0;
01809 
01810        if (type==MODULE_PERSISTENT) {
01811               error_type = E_CORE_WARNING;
01812        } else {
01813               error_type = E_WARNING;
01814        }
01815 
01816        if (!target_function_table) {
01817               target_function_table = CG(function_table);
01818        }
01819        internal_function->type = ZEND_INTERNAL_FUNCTION;
01820        internal_function->module = EG(current_module);
01821 
01822        if (scope) {
01823               class_name_len = strlen(scope->name);
01824               if ((lc_class_name = zend_memrchr(scope->name, '\\', class_name_len))) {
01825                      ++lc_class_name;
01826                      class_name_len -= (lc_class_name - scope->name);
01827                      lc_class_name = zend_str_tolower_dup(lc_class_name, class_name_len);
01828               } else {
01829                      lc_class_name = zend_str_tolower_dup(scope->name, class_name_len);
01830               }
01831        }
01832 
01833        while (ptr->fname) {
01834               internal_function->handler = ptr->handler;
01835               internal_function->function_name = (char*)ptr->fname;
01836               internal_function->scope = scope;
01837               internal_function->prototype = NULL;
01838               if (ptr->arg_info) {
01839                      internal_function->arg_info = (zend_arg_info*)ptr->arg_info+1;
01840                      internal_function->num_args = ptr->num_args;
01841                      /* Currently you cannot denote that the function can accept less arguments than num_args */
01842                      if (ptr->arg_info[0].required_num_args == -1) {
01843                             internal_function->required_num_args = ptr->num_args;
01844                      } else {
01845                             internal_function->required_num_args = ptr->arg_info[0].required_num_args;
01846                      }
01847                      internal_function->pass_rest_by_reference = ptr->arg_info[0].pass_by_reference;
01848                      internal_function->return_reference = ptr->arg_info[0].return_reference;
01849               } else {
01850                      internal_function->arg_info = NULL;
01851                      internal_function->num_args = 0;
01852                      internal_function->required_num_args = 0;
01853                      internal_function->pass_rest_by_reference = 0;
01854                      internal_function->return_reference = 0;
01855               }
01856               if (ptr->flags) {
01857                      if (!(ptr->flags & ZEND_ACC_PPP_MASK)) {
01858                             if (ptr->flags != ZEND_ACC_DEPRECATED || scope) {
01859                                    zend_error(error_type, "Invalid access level for %s%s%s() - access must be exactly one of public, protected or private", scope ? scope->name : "", scope ? "::" : "", ptr->fname);
01860                             }
01861                             internal_function->fn_flags = ZEND_ACC_PUBLIC | ptr->flags;
01862                      } else {
01863                             internal_function->fn_flags = ptr->flags;
01864                      }
01865               } else {
01866                      internal_function->fn_flags = ZEND_ACC_PUBLIC;
01867               }
01868               if (ptr->flags & ZEND_ACC_ABSTRACT) {
01869                      if (scope) {
01870                             /* This is a class that must be abstract itself. Here we set the check info. */
01871                             scope->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
01872                             if (!(scope->ce_flags & ZEND_ACC_INTERFACE)) {
01873                                    /* Since the class is not an interface it needs to be declared as a abstract class. */
01874                                    /* Since here we are handling internal functions only we can add the keyword flag. */
01875                                    /* This time we set the flag for the keyword 'abstract'. */
01876                                    scope->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;
01877                             }
01878                      }
01879                      if (ptr->flags & ZEND_ACC_STATIC && (!scope || !(scope->ce_flags & ZEND_ACC_INTERFACE))) {
01880                             zend_error(error_type, "Static function %s%s%s() cannot be abstract", scope ? scope->name : "", scope ? "::" : "", ptr->fname);
01881                      }
01882               } else {
01883                      if (scope && (scope->ce_flags & ZEND_ACC_INTERFACE)) {
01884                             efree(lc_class_name);
01885                             zend_error(error_type, "Interface %s cannot contain non abstract method %s()", scope->name, ptr->fname);
01886                             return FAILURE;
01887                      }
01888                      if (!internal_function->handler) {
01889                             if (scope) {
01890                                    efree(lc_class_name);
01891                             }
01892                             zend_error(error_type, "Method %s%s%s() cannot be a NULL function", scope ? scope->name : "", scope ? "::" : "", ptr->fname);
01893                             zend_unregister_functions(functions, count, target_function_table TSRMLS_CC);
01894                             return FAILURE;
01895                      }
01896               }
01897               fname_len = strlen(ptr->fname);
01898               lowercase_name = zend_str_tolower_dup(ptr->fname, fname_len);
01899               if (zend_hash_add(target_function_table, lowercase_name, fname_len+1, &function, sizeof(zend_function), (void**)&reg_function) == FAILURE) {
01900                      unload=1;
01901                      efree(lowercase_name);
01902                      break;
01903               }
01904               if (scope) {
01905                      /* Look for ctor, dtor, clone
01906                       * If it's an old-style constructor, store it only if we don't have
01907                       * a constructor already.
01908                       */
01909                      if ((fname_len == class_name_len) && !memcmp(lowercase_name, lc_class_name, class_name_len+1) && !ctor) {
01910                             ctor = reg_function;
01911                      } else if ((fname_len == sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME))) {
01912                             ctor = reg_function;
01913                      } else if ((fname_len == sizeof(ZEND_DESTRUCTOR_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_DESTRUCTOR_FUNC_NAME, sizeof(ZEND_DESTRUCTOR_FUNC_NAME))) {
01914                             dtor = reg_function;
01915                             if (internal_function->num_args) {
01916                                    zend_error(error_type, "Destructor %s::%s() cannot take arguments", scope->name, ptr->fname);
01917                             }
01918                      } else if ((fname_len == sizeof(ZEND_CLONE_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME))) {
01919                             clone = reg_function;
01920                      } else if ((fname_len == sizeof(ZEND_CALL_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME))) {
01921                             __call = reg_function;
01922                      } else if ((fname_len == sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_CALLSTATIC_FUNC_NAME, sizeof(ZEND_CALLSTATIC_FUNC_NAME))) {
01923                             __callstatic = reg_function;
01924                      } else if ((fname_len == sizeof(ZEND_TOSTRING_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_TOSTRING_FUNC_NAME, sizeof(ZEND_TOSTRING_FUNC_NAME))) {
01925                             __tostring = reg_function;
01926                      } else if ((fname_len == sizeof(ZEND_GET_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME))) {
01927                             __get = reg_function;
01928                      } else if ((fname_len == sizeof(ZEND_SET_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME))) {
01929                             __set = reg_function;
01930                      } else if ((fname_len == sizeof(ZEND_UNSET_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_UNSET_FUNC_NAME, sizeof(ZEND_UNSET_FUNC_NAME))) {
01931                             __unset = reg_function;
01932                      } else if ((fname_len == sizeof(ZEND_ISSET_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_ISSET_FUNC_NAME, sizeof(ZEND_ISSET_FUNC_NAME))) {
01933                             __isset = reg_function;
01934                      } else {
01935                             reg_function = NULL;
01936                      }
01937                      if (reg_function) {
01938                             zend_check_magic_method_implementation(scope, reg_function, error_type TSRMLS_CC);
01939                      }
01940               }
01941               ptr++;
01942               count++;
01943               efree(lowercase_name);
01944        }
01945        if (unload) { /* before unloading, display all remaining bad function in the module */
01946               if (scope) {
01947                      efree(lc_class_name);
01948               }
01949               while (ptr->fname) {
01950                      fname_len = strlen(ptr->fname);
01951                      lowercase_name = zend_str_tolower_dup(ptr->fname, fname_len);
01952                      if (zend_hash_exists(target_function_table, lowercase_name, fname_len+1)) {
01953                             zend_error(error_type, "Function registration failed - duplicate name - %s%s%s", scope ? scope->name : "", scope ? "::" : "", ptr->fname);
01954                      }
01955                      efree(lowercase_name);
01956                      ptr++;
01957               }
01958               zend_unregister_functions(functions, count, target_function_table TSRMLS_CC);
01959               return FAILURE;
01960        }
01961        if (scope) {
01962               scope->constructor = ctor;
01963               scope->destructor = dtor;
01964               scope->clone = clone;
01965               scope->__call = __call;
01966               scope->__callstatic = __callstatic;
01967               scope->__tostring = __tostring;
01968               scope->__get = __get;
01969               scope->__set = __set;
01970               scope->__unset = __unset;
01971               scope->__isset = __isset;
01972               if (ctor) {
01973                      ctor->common.fn_flags |= ZEND_ACC_CTOR;
01974                      if (ctor->common.fn_flags & ZEND_ACC_STATIC) {
01975                             zend_error(error_type, "Constructor %s::%s() cannot be static", scope->name, ctor->common.function_name);
01976                      }
01977                      ctor->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
01978               }
01979               if (dtor) {
01980                      dtor->common.fn_flags |= ZEND_ACC_DTOR;
01981                      if (dtor->common.fn_flags & ZEND_ACC_STATIC) {
01982                             zend_error(error_type, "Destructor %s::%s() cannot be static", scope->name, dtor->common.function_name);
01983                      }
01984                      dtor->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
01985               }
01986               if (clone) {
01987                      clone->common.fn_flags |= ZEND_ACC_CLONE;
01988                      if (clone->common.fn_flags & ZEND_ACC_STATIC) {
01989                             zend_error(error_type, "Constructor %s::%s() cannot be static", scope->name, clone->common.function_name);
01990                      }
01991                      clone->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
01992               }
01993               if (__call) {
01994                      if (__call->common.fn_flags & ZEND_ACC_STATIC) {
01995                             zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __call->common.function_name);
01996                      }
01997                      __call->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
01998               }
01999               if (__callstatic) {
02000                      if (!(__callstatic->common.fn_flags & ZEND_ACC_STATIC)) {
02001                             zend_error(error_type, "Method %s::%s() must be static", scope->name, __callstatic->common.function_name);
02002                      }
02003                      __callstatic->common.fn_flags |= ZEND_ACC_STATIC;
02004               }
02005               if (__tostring) {
02006                      if (__tostring->common.fn_flags & ZEND_ACC_STATIC) {
02007                             zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __tostring->common.function_name);
02008                      }
02009                      __tostring->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
02010               }
02011               if (__get) {
02012                      if (__get->common.fn_flags & ZEND_ACC_STATIC) {
02013                             zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __get->common.function_name);
02014                      }
02015                      __get->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
02016               }
02017               if (__set) {
02018                      if (__set->common.fn_flags & ZEND_ACC_STATIC) {
02019                             zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __set->common.function_name);
02020                      }
02021                      __set->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
02022               }
02023               if (__unset) {
02024                      if (__unset->common.fn_flags & ZEND_ACC_STATIC) {
02025                             zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __unset->common.function_name);
02026                      }
02027                      __unset->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
02028               }
02029               if (__isset) {
02030                      if (__isset->common.fn_flags & ZEND_ACC_STATIC) {
02031                             zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __isset->common.function_name);
02032                      }
02033                      __isset->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
02034               }
02035               efree(lc_class_name);
02036        }
02037        return SUCCESS;
02038 }
02039 /* }}} */
02040 
02041 /* count=-1 means erase all functions, otherwise,
02042  * erase the first count functions
02043  */
02044 ZEND_API void zend_unregister_functions(const zend_function_entry *functions, int count, HashTable *function_table TSRMLS_DC) /* {{{ */
02045 {
02046        const zend_function_entry *ptr = functions;
02047        int i=0;
02048        HashTable *target_function_table = function_table;
02049 
02050        if (!target_function_table) {
02051               target_function_table = CG(function_table);
02052        }
02053        while (ptr->fname) {
02054               if (count!=-1 && i>=count) {
02055                      break;
02056               }
02057 #if 0
02058               zend_printf("Unregistering %s()\n", ptr->fname);
02059 #endif
02060               zend_hash_del(target_function_table, ptr->fname, strlen(ptr->fname)+1);
02061               ptr++;
02062               i++;
02063        }
02064 }
02065 /* }}} */
02066 
02067 ZEND_API int zend_startup_module(zend_module_entry *module) /* {{{ */
02068 {
02069        TSRMLS_FETCH();
02070 
02071        if ((module = zend_register_internal_module(module TSRMLS_CC)) != NULL && zend_startup_module_ex(module TSRMLS_CC) == SUCCESS) {
02072               return SUCCESS;
02073        }
02074        return FAILURE;
02075 }
02076 /* }}} */
02077 
02078 ZEND_API int zend_get_module_started(const char *module_name) /* {{{ */
02079 {
02080        zend_module_entry *module;
02081 
02082        return (zend_hash_find(&module_registry, module_name, strlen(module_name)+1, (void**)&module) == SUCCESS && module->module_started) ? SUCCESS : FAILURE;
02083 }
02084 /* }}} */
02085 
02086 static int clean_module_class(const zend_class_entry **ce, int *module_number TSRMLS_DC) /* {{{ */
02087 {
02088        if ((*ce)->type == ZEND_INTERNAL_CLASS && (*ce)->module->module_number == *module_number) {
02089               return ZEND_HASH_APPLY_REMOVE;
02090        } else {
02091               return ZEND_HASH_APPLY_KEEP;
02092        }
02093 }
02094 /* }}} */
02095 
02096 static void clean_module_classes(int module_number TSRMLS_DC) /* {{{ */
02097 {
02098        zend_hash_apply_with_argument(EG(class_table), (apply_func_arg_t) clean_module_class, (void *) &module_number TSRMLS_CC);
02099 }
02100 /* }}} */
02101 
02102 void module_destructor(zend_module_entry *module) /* {{{ */
02103 {
02104        TSRMLS_FETCH();
02105 
02106        if (module->type == MODULE_TEMPORARY) {
02107               zend_clean_module_rsrc_dtors(module->module_number TSRMLS_CC);
02108               clean_module_constants(module->module_number TSRMLS_CC);
02109               clean_module_classes(module->module_number TSRMLS_CC);
02110        }
02111 
02112        if (module->module_started && module->module_shutdown_func) {
02113 #if 0
02114               zend_printf("%s: Module shutdown\n", module->name);
02115 #endif
02116               module->module_shutdown_func(module->type, module->module_number TSRMLS_CC);
02117        }
02118 
02119        /* Deinitilaise module globals */
02120        if (module->globals_size) {
02121 #ifdef ZTS
02122               ts_free_id(*module->globals_id_ptr);
02123 #else
02124               if (module->globals_dtor) {
02125                      module->globals_dtor(module->globals_ptr TSRMLS_CC);
02126               }
02127 #endif
02128        }
02129 
02130        module->module_started=0;
02131        if (module->functions) {
02132               zend_unregister_functions(module->functions, -1, NULL TSRMLS_CC);
02133        }
02134 
02135 #if HAVE_LIBDL
02136 #if !(defined(NETWARE) && defined(APACHE_1_BUILD))
02137        if (module->handle) {
02138               DL_UNLOAD(module->handle);
02139        }
02140 #endif
02141 #endif
02142 }
02143 /* }}} */
02144 
02145 /* call request startup for all modules */
02146 int module_registry_request_startup(zend_module_entry *module TSRMLS_DC) /* {{{ */
02147 {
02148        if (module->request_startup_func) {
02149 #if 0
02150               zend_printf("%s: Request startup\n", module->name);
02151 #endif
02152               if (module->request_startup_func(module->type, module->module_number TSRMLS_CC)==FAILURE) {
02153                      zend_error(E_WARNING, "request_startup() for %s module failed", module->name);
02154                      exit(1);
02155               }
02156        }
02157        return 0;
02158 }
02159 /* }}} */
02160 
02161 /* call request shutdown for all modules */
02162 int module_registry_cleanup(zend_module_entry *module TSRMLS_DC) /* {{{ */
02163 {
02164        if (module->request_shutdown_func) {
02165 #if 0
02166               zend_printf("%s: Request shutdown\n", module->name);
02167 #endif
02168               module->request_shutdown_func(module->type, module->module_number TSRMLS_CC);
02169        }
02170        return 0;
02171 }
02172 /* }}} */
02173 
02174 int module_registry_unload_temp(const zend_module_entry *module TSRMLS_DC) /* {{{ */
02175 {
02176        return (module->type == MODULE_TEMPORARY) ? ZEND_HASH_APPLY_REMOVE : ZEND_HASH_APPLY_STOP;
02177 }
02178 /* }}} */
02179 
02180 /* return the next free module number */
02181 int zend_next_free_module(void) /* {{{ */
02182 {
02183        return ++module_count;
02184 }
02185 /* }}} */
02186 
02187 static zend_class_entry *do_register_internal_class(zend_class_entry *orig_class_entry, zend_uint ce_flags TSRMLS_DC) /* {{{ */
02188 {
02189        zend_class_entry *class_entry = malloc(sizeof(zend_class_entry));
02190        char *lowercase_name = malloc(orig_class_entry->name_length + 1);
02191        *class_entry = *orig_class_entry;
02192 
02193        class_entry->type = ZEND_INTERNAL_CLASS;
02194        zend_initialize_class_data(class_entry, 0 TSRMLS_CC);
02195        class_entry->ce_flags = ce_flags;
02196        class_entry->module = EG(current_module);
02197 
02198        if (class_entry->builtin_functions) {
02199               zend_register_functions(class_entry, class_entry->builtin_functions, &class_entry->function_table, MODULE_PERSISTENT TSRMLS_CC);
02200        }
02201 
02202        zend_str_tolower_copy(lowercase_name, orig_class_entry->name, class_entry->name_length);
02203        zend_hash_update(CG(class_table), lowercase_name, class_entry->name_length+1, &class_entry, sizeof(zend_class_entry *), NULL);
02204        free(lowercase_name);
02205        return class_entry;
02206 }
02207 /* }}} */
02208 
02209 /* If parent_ce is not NULL then it inherits from parent_ce
02210  * If parent_ce is NULL and parent_name isn't then it looks for the parent and inherits from it
02211  * If both parent_ce and parent_name are NULL it does a regular class registration
02212  * If parent_name is specified but not found NULL is returned
02213  */
02214 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) /* {{{ */
02215 {
02216        zend_class_entry *register_class;
02217 
02218        if (!parent_ce && parent_name) {
02219               zend_class_entry **pce;
02220               if (zend_hash_find(CG(class_table), parent_name, strlen(parent_name)+1, (void **) &pce)==FAILURE) {
02221                      return NULL;
02222               } else {
02223                      parent_ce = *pce;
02224               }
02225        }
02226 
02227        register_class = zend_register_internal_class(class_entry TSRMLS_CC);
02228 
02229        if (parent_ce) {
02230               zend_do_inheritance(register_class, parent_ce TSRMLS_CC);
02231        }
02232        return register_class;
02233 }
02234 /* }}} */
02235 
02236 ZEND_API void zend_class_implements(zend_class_entry *class_entry TSRMLS_DC, int num_interfaces, ...) /* {{{ */
02237 {
02238        zend_class_entry *interface_entry;
02239        va_list interface_list;
02240        va_start(interface_list, num_interfaces);
02241 
02242        while (num_interfaces--) {
02243               interface_entry = va_arg(interface_list, zend_class_entry *);
02244               zend_do_implement_interface(class_entry, interface_entry TSRMLS_CC);
02245        }
02246 
02247        va_end(interface_list);
02248 }
02249 /* }}} */
02250 
02251 /* A class that contains at least one abstract method automatically becomes an abstract class.
02252  */
02253 ZEND_API zend_class_entry *zend_register_internal_class(zend_class_entry *orig_class_entry TSRMLS_DC) /* {{{ */
02254 {
02255        return do_register_internal_class(orig_class_entry, 0 TSRMLS_CC);
02256 }
02257 /* }}} */
02258 
02259 ZEND_API zend_class_entry *zend_register_internal_interface(zend_class_entry *orig_class_entry TSRMLS_DC) /* {{{ */
02260 {
02261        return do_register_internal_class(orig_class_entry, ZEND_ACC_INTERFACE TSRMLS_CC);
02262 }
02263 /* }}} */
02264 
02265 ZEND_API int zend_register_class_alias_ex(const char *name, int name_len, zend_class_entry *ce TSRMLS_DC) /* {{{ */
02266 {
02267        char *lcname = zend_str_tolower_dup(name, name_len);
02268        int ret;
02269 
02270        ret = zend_hash_add(CG(class_table), lcname, name_len+1, &ce, sizeof(zend_class_entry *), NULL);
02271        efree(lcname);
02272        if (ret == SUCCESS) {
02273               ce->refcount++;
02274        }
02275        return ret;
02276 }
02277 /* }}} */
02278 
02279 ZEND_API int zend_set_hash_symbol(zval *symbol, const char *name, int name_length, zend_bool is_ref, int num_symbol_tables, ...) /* {{{ */
02280 {
02281        HashTable *symbol_table;
02282        va_list symbol_table_list;
02283 
02284        if (num_symbol_tables <= 0) return FAILURE;
02285 
02286        Z_SET_ISREF_TO_P(symbol, is_ref);
02287 
02288        va_start(symbol_table_list, num_symbol_tables);
02289        while (num_symbol_tables-- > 0) {
02290               symbol_table = va_arg(symbol_table_list, HashTable *);
02291               zend_hash_update(symbol_table, name, name_length + 1, &symbol, sizeof(zval *), NULL);
02292               zval_add_ref(&symbol);
02293        }
02294        va_end(symbol_table_list);
02295        return SUCCESS;
02296 }
02297 /* }}} */
02298 
02299 /* Disabled functions support */
02300 
02301 /* {{{ proto void display_disabled_function(void)
02302 Dummy function which displays an error when a disabled function is called. */
02303 ZEND_API ZEND_FUNCTION(display_disabled_function)
02304 {
02305        zend_error(E_WARNING, "%s() has been disabled for security reasons", get_active_function_name(TSRMLS_C));
02306 }
02307 /* }}} */
02308 
02309 static zend_function_entry disabled_function[] = {
02310        ZEND_FE(display_disabled_function,               NULL)
02311        ZEND_FE_END
02312 };
02313 
02314 ZEND_API int zend_disable_function(char *function_name, uint function_name_length TSRMLS_DC) /* {{{ */
02315 {
02316        if (zend_hash_del(CG(function_table), function_name, function_name_length+1)==FAILURE) {
02317               return FAILURE;
02318        }
02319        disabled_function[0].fname = function_name;
02320        return zend_register_functions(NULL, disabled_function, CG(function_table), MODULE_PERSISTENT TSRMLS_CC);
02321 }
02322 /* }}} */
02323 
02324 static zend_object_value display_disabled_class(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
02325 {
02326        zend_object_value retval;
02327        zend_object *intern;
02328        retval = zend_objects_new(&intern, class_type TSRMLS_CC);
02329        ALLOC_HASHTABLE(intern->properties);
02330        zend_hash_init(intern->properties, 0, NULL, ZVAL_PTR_DTOR, 0);
02331        zend_error(E_WARNING, "%s() has been disabled for security reasons", class_type->name);
02332        return retval;
02333 }
02334 /* }}} */
02335 
02336 static const zend_function_entry disabled_class_new[] = {
02337        ZEND_FE_END
02338 };
02339 
02340 ZEND_API int zend_disable_class(char *class_name, uint class_name_length TSRMLS_DC) /* {{{ */
02341 {
02342        zend_class_entry disabled_class;
02343 
02344        zend_str_tolower(class_name, class_name_length);
02345        if (zend_hash_del(CG(class_table), class_name, class_name_length+1)==FAILURE) {
02346               return FAILURE;
02347        }
02348        INIT_OVERLOADED_CLASS_ENTRY_EX(disabled_class, class_name, class_name_length, disabled_class_new, NULL, NULL, NULL, NULL, NULL);
02349        disabled_class.create_object = display_disabled_class;
02350        disabled_class.name_length = class_name_length;
02351        zend_register_internal_class(&disabled_class TSRMLS_CC);
02352        return SUCCESS;
02353 }
02354 /* }}} */
02355 
02356 static int zend_is_callable_check_class(const char *name, int name_len, zend_fcall_info_cache *fcc, int *strict_class, char **error TSRMLS_DC) /* {{{ */
02357 {
02358        int ret = 0;
02359        zend_class_entry **pce;
02360        char *lcname = zend_str_tolower_dup(name, name_len);
02361 
02362        *strict_class = 0;
02363        if (name_len == sizeof("self") - 1 &&
02364            !memcmp(lcname, "self", sizeof("self") - 1)) {
02365               if (!EG(scope)) {
02366                      if (error) *error = estrdup("cannot access self:: when no class scope is active");
02367               } else {
02368                      fcc->called_scope = EG(called_scope);
02369                      fcc->calling_scope = EG(scope);
02370                      if (!fcc->object_ptr) {
02371                             fcc->object_ptr = EG(This);
02372                      }
02373                      ret = 1;
02374               }
02375        } else if (name_len == sizeof("parent") - 1 && 
02376                      !memcmp(lcname, "parent", sizeof("parent") - 1)) {
02377               if (!EG(scope)) {
02378                      if (error) *error = estrdup("cannot access parent:: when no class scope is active");
02379               } else if (!EG(scope)->parent) {
02380                      if (error) *error = estrdup("cannot access parent:: when current class scope has no parent");
02381               } else {
02382                      fcc->called_scope = EG(called_scope);
02383                      fcc->calling_scope = EG(scope)->parent;
02384                      if (!fcc->object_ptr) {
02385                             fcc->object_ptr = EG(This);
02386                      }
02387                      *strict_class = 1;
02388                      ret = 1;
02389               }
02390        } else if (name_len == sizeof("static") - 1 &&
02391                   !memcmp(lcname, "static", sizeof("static") - 1)) {
02392               if (!EG(called_scope)) {
02393                      if (error) *error = estrdup("cannot access static:: when no class scope is active");
02394               } else {
02395                      fcc->called_scope = EG(called_scope);
02396                      fcc->calling_scope = EG(called_scope);
02397                      if (!fcc->object_ptr) {
02398                             fcc->object_ptr = EG(This);
02399                      }
02400                      *strict_class = 1;
02401                      ret = 1;
02402               }
02403        } else if (zend_lookup_class_ex(name, name_len, 1, &pce TSRMLS_CC) == SUCCESS) {
02404               zend_class_entry *scope = EG(active_op_array) ? EG(active_op_array)->scope : NULL;
02405 
02406               fcc->calling_scope = *pce;
02407               if (scope && !fcc->object_ptr && EG(This) &&
02408                   instanceof_function(Z_OBJCE_P(EG(This)), scope TSRMLS_CC) &&
02409                   instanceof_function(scope, fcc->calling_scope TSRMLS_CC)) {
02410                      fcc->object_ptr = EG(This);
02411                      fcc->called_scope = Z_OBJCE_P(fcc->object_ptr);
02412               } else {
02413                      fcc->called_scope = fcc->object_ptr ? Z_OBJCE_P(fcc->object_ptr) : fcc->calling_scope;
02414               }
02415               *strict_class = 1;
02416               ret = 1;
02417        } else {
02418               if (error) zend_spprintf(error, 0, "class '%.*s' not found", name_len, name);
02419        }
02420        efree(lcname);
02421        return ret;
02422 }
02423 /* }}} */
02424 
02425 
02426 static int zend_is_callable_check_func(int check_flags, zval *callable, zend_fcall_info_cache *fcc, int strict_class, char **error TSRMLS_DC) /* {{{ */
02427 {
02428        zend_class_entry *ce_org = fcc->calling_scope;
02429        int retval = 0;
02430        char *mname, *lmname, *colon;
02431        int clen, mlen;
02432        zend_class_entry *last_scope;
02433        HashTable *ftable;
02434        int call_via_handler = 0;
02435 
02436        if (error) {
02437               *error = NULL;
02438        }
02439 
02440        fcc->calling_scope = NULL;
02441        fcc->function_handler = NULL;
02442 
02443        if (!ce_org) {
02444               /* Skip leading \ */
02445               if (Z_STRVAL_P(callable)[0] == '\\') {
02446                      mlen = Z_STRLEN_P(callable) - 1;
02447                      mname = Z_STRVAL_P(callable) + 1;
02448                      lmname = zend_str_tolower_dup(Z_STRVAL_P(callable) + 1, mlen);
02449               } else {
02450                      mlen = Z_STRLEN_P(callable);
02451                      mname = Z_STRVAL_P(callable);
02452                      lmname = zend_str_tolower_dup(Z_STRVAL_P(callable), mlen);
02453               }
02454               /* Check if function with given name exists.
02455                * This may be a compound name that includes namespace name */
02456               if (zend_hash_find(EG(function_table), lmname, mlen+1, (void**)&fcc->function_handler) == SUCCESS) {
02457                      efree(lmname);
02458                      return 1;
02459               }
02460               efree(lmname);
02461        }
02462 
02463        /* Split name into class/namespace and method/function names */
02464        if ((colon = zend_memrchr(Z_STRVAL_P(callable), ':', Z_STRLEN_P(callable))) != NULL &&
02465               colon > Z_STRVAL_P(callable) &&
02466               *(colon-1) == ':'
02467        ) {
02468               colon--;
02469               clen = colon - Z_STRVAL_P(callable);
02470               mlen = Z_STRLEN_P(callable) - clen - 2;
02471 
02472               if (colon == Z_STRVAL_P(callable)) {
02473                      if (error) zend_spprintf(error, 0, "invalid function name");
02474                      return 0;
02475               }
02476 
02477               /* This is a compound name.
02478                * Try to fetch class and then find static method. */
02479               last_scope = EG(scope);
02480               if (ce_org) {
02481                      EG(scope) = ce_org;
02482               }
02483 
02484               if (!zend_is_callable_check_class(Z_STRVAL_P(callable), clen, fcc, &strict_class, error TSRMLS_CC)) {
02485                      EG(scope) = last_scope;
02486                      return 0;
02487               }
02488               EG(scope) = last_scope;
02489 
02490               ftable = &fcc->calling_scope->function_table;
02491               if (ce_org && !instanceof_function(ce_org, fcc->calling_scope TSRMLS_CC)) {
02492                      if (error) zend_spprintf(error, 0, "class '%s' is not a subclass of '%s'", ce_org->name, fcc->calling_scope->name);
02493                      return 0;
02494               }
02495               mname = Z_STRVAL_P(callable) + clen + 2;
02496        } else if (ce_org) {
02497               /* Try to fetch find static method of given class. */
02498               mlen = Z_STRLEN_P(callable);
02499               mname = Z_STRVAL_P(callable);
02500               ftable = &ce_org->function_table;
02501               fcc->calling_scope = ce_org;
02502        } else {
02503               /* We already checked for plain function before. */
02504               if (error && !(check_flags & IS_CALLABLE_CHECK_SILENT)) {
02505                      zend_spprintf(error, 0, "function '%s' not found or invalid function name", Z_STRVAL_P(callable));
02506               }
02507               return 0;
02508        }
02509 
02510        lmname = zend_str_tolower_dup(mname, mlen);
02511        if (strict_class &&
02512            fcc->calling_scope &&
02513            mlen == sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1 &&
02514            !memcmp(lmname, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME))) {
02515               fcc->function_handler = fcc->calling_scope->constructor;
02516               if (fcc->function_handler) {
02517                      retval = 1;
02518               }
02519        } else if (zend_hash_find(ftable, lmname, mlen+1, (void**)&fcc->function_handler) == SUCCESS) {
02520               retval = 1;
02521               if ((fcc->function_handler->op_array.fn_flags & ZEND_ACC_CHANGED) &&
02522                   EG(scope) &&
02523                   instanceof_function(fcc->function_handler->common.scope, EG(scope) TSRMLS_CC)) {
02524                      zend_function *priv_fbc;
02525 
02526                      if (zend_hash_find(&EG(scope)->function_table, lmname, mlen+1, (void **) &priv_fbc)==SUCCESS
02527                             && priv_fbc->common.fn_flags & ZEND_ACC_PRIVATE
02528                             && priv_fbc->common.scope == EG(scope)) {
02529                             fcc->function_handler = priv_fbc;
02530                      }
02531               }
02532               if ((check_flags & IS_CALLABLE_CHECK_NO_ACCESS) == 0 &&
02533                   (fcc->calling_scope &&
02534                    (fcc->calling_scope->__call ||
02535                     fcc->calling_scope->__callstatic))) {
02536                      if (fcc->function_handler->op_array.fn_flags & ZEND_ACC_PRIVATE) {
02537                             if (!zend_check_private(fcc->function_handler, fcc->object_ptr ? Z_OBJCE_P(fcc->object_ptr) : EG(scope), lmname, mlen TSRMLS_CC)) {
02538                                    retval = 0;
02539                                    fcc->function_handler = NULL;
02540                                    goto get_function_via_handler;
02541                             }
02542                      } else if (fcc->function_handler->common.fn_flags & ZEND_ACC_PROTECTED) {
02543                             if (!zend_check_protected(fcc->function_handler->common.scope, EG(scope))) {
02544                                    retval = 0;
02545                                    fcc->function_handler = NULL;
02546                                    goto get_function_via_handler;
02547                             }
02548                      }
02549               }
02550        } else {
02551 get_function_via_handler:
02552               if (fcc->object_ptr && fcc->calling_scope == ce_org) {
02553                      if (strict_class && ce_org->__call) {
02554                             fcc->function_handler = emalloc(sizeof(zend_internal_function));
02555                             fcc->function_handler->internal_function.type = ZEND_INTERNAL_FUNCTION;
02556                             fcc->function_handler->internal_function.module = ce_org->module;
02557                             fcc->function_handler->internal_function.handler = zend_std_call_user_call;
02558                             fcc->function_handler->internal_function.arg_info = NULL;
02559                             fcc->function_handler->internal_function.num_args = 0;
02560                             fcc->function_handler->internal_function.scope = ce_org;
02561                             fcc->function_handler->internal_function.fn_flags = ZEND_ACC_CALL_VIA_HANDLER;
02562                             fcc->function_handler->internal_function.function_name = estrndup(mname, mlen);
02563                             fcc->function_handler->internal_function.pass_rest_by_reference = 0;
02564                             fcc->function_handler->internal_function.return_reference = ZEND_RETURN_VALUE;
02565                             call_via_handler = 1;
02566                             retval = 1;
02567                      } else if (Z_OBJ_HT_P(fcc->object_ptr)->get_method) {
02568                             fcc->function_handler = Z_OBJ_HT_P(fcc->object_ptr)->get_method(&fcc->object_ptr, mname, mlen TSRMLS_CC);
02569                             if (fcc->function_handler) {
02570                                    if (strict_class &&
02571                                        (!fcc->function_handler->common.scope ||
02572                                         !instanceof_function(ce_org, fcc->function_handler->common.scope TSRMLS_CC))) {
02573                                           if ((fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0) {
02574                                                  if (fcc->function_handler->type != ZEND_OVERLOADED_FUNCTION) {
02575                                                         efree(fcc->function_handler->common.function_name);
02576                                                  }
02577                                                  efree(fcc->function_handler);
02578                                           }
02579                                    } else {
02580                                           retval = 1;
02581                                           call_via_handler = (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0;
02582                                    }
02583                             }
02584                      }
02585               } else if (fcc->calling_scope) {
02586                      if (fcc->calling_scope->get_static_method) {
02587                             fcc->function_handler = fcc->calling_scope->get_static_method(fcc->calling_scope, mname, mlen TSRMLS_CC);
02588                      } else {
02589                             fcc->function_handler = zend_std_get_static_method(fcc->calling_scope, mname, mlen TSRMLS_CC);
02590                      }
02591                      if (fcc->function_handler) {
02592                             retval = 1;
02593                             call_via_handler = (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0;
02594                             if (call_via_handler && !fcc->object_ptr && EG(This) &&
02595                                 Z_OBJ_HT_P(EG(This))->get_class_entry &&
02596                                 instanceof_function(Z_OBJCE_P(EG(This)), fcc->calling_scope TSRMLS_CC)) {
02597                                    fcc->object_ptr = EG(This);
02598                             }
02599                      }
02600               }
02601        }
02602 
02603        if (retval) {
02604               if (fcc->calling_scope && !call_via_handler) {
02605                      if (!fcc->object_ptr && !(fcc->function_handler->common.fn_flags & ZEND_ACC_STATIC)) {
02606                             int severity;
02607                             char *verb;
02608                             if (fcc->function_handler->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
02609                                    severity = E_STRICT;
02610                                    verb = "should not";
02611                             } else {
02612                                    /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
02613                                    severity = E_ERROR;
02614                                    verb = "cannot";
02615                             }
02616                             if ((check_flags & IS_CALLABLE_CHECK_IS_STATIC) != 0) {
02617                                    retval = 0;
02618                             }
02619                             if (EG(This) && instanceof_function(Z_OBJCE_P(EG(This)), fcc->calling_scope TSRMLS_CC)) {
02620                                    fcc->object_ptr = EG(This);
02621                                    if (error) {
02622                                           zend_spprintf(error, 0, "non-static method %s::%s() %s be called statically, assuming $this from compatible context %s", fcc->calling_scope->name, fcc->function_handler->common.function_name, verb, Z_OBJCE_P(EG(This))->name);
02623                                           if (severity == E_ERROR) {
02624                                                  retval = 0;
02625                                           }
02626                                    } else if (retval) {
02627                                           zend_error(severity, "Non-static method %s::%s() %s be called statically, assuming $this from compatible context %s", fcc->calling_scope->name, fcc->function_handler->common.function_name, verb, Z_OBJCE_P(EG(This))->name);
02628                                    }
02629                             } else {
02630                                    if (error) {
02631                                           zend_spprintf(error, 0, "non-static method %s::%s() %s be called statically", fcc->calling_scope->name, fcc->function_handler->common.function_name, verb);
02632                                           if (severity == E_ERROR) {
02633                                                  retval = 0;
02634                                           }
02635                                    } else if (retval) {
02636                                           zend_error(severity, "Non-static method %s::%s() %s be called statically", fcc->calling_scope->name, fcc->function_handler->common.function_name, verb);
02637                                    }
02638                             }
02639                      }
02640                      if (retval && (check_flags & IS_CALLABLE_CHECK_NO_ACCESS) == 0) {
02641                             if (fcc->function_handler->op_array.fn_flags & ZEND_ACC_PRIVATE) {
02642                                    if (!zend_check_private(fcc->function_handler, fcc->object_ptr ? Z_OBJCE_P(fcc->object_ptr) : EG(scope), lmname, mlen TSRMLS_CC)) {
02643                                           if (error) {
02644                                                  if (*error) {
02645                                                         efree(*error);
02646                                                  }
02647                                                  zend_spprintf(error, 0, "cannot access private method %s::%s()", fcc->calling_scope->name, fcc->function_handler->common.function_name);
02648                                           }
02649                                           retval = 0;
02650                                    }
02651                             } else if ((fcc->function_handler->common.fn_flags & ZEND_ACC_PROTECTED)) {
02652                                    if (!zend_check_protected(fcc->function_handler->common.scope, EG(scope))) {
02653                                           if (error) {
02654                                                  if (*error) {
02655                                                         efree(*error);
02656                                                  }
02657                                                  zend_spprintf(error, 0, "cannot access protected method %s::%s()", fcc->calling_scope->name, fcc->function_handler->common.function_name);
02658                                           }
02659                                           retval = 0;
02660                                    }
02661                             }
02662                      }
02663               }
02664        } else if (error && !(check_flags & IS_CALLABLE_CHECK_SILENT)) {
02665               if (fcc->calling_scope) {
02666                      if (error) zend_spprintf(error, 0, "class '%s' does not have a method '%s'", fcc->calling_scope->name, mname);
02667               } else {
02668                      if (error) zend_spprintf(error, 0, "function '%s' does not exist", mname);
02669               }
02670        }
02671        efree(lmname);
02672 
02673        if (fcc->object_ptr) {
02674               fcc->called_scope = Z_OBJCE_P(fcc->object_ptr);
02675        }
02676        if (retval) {
02677               fcc->initialized = 1;
02678        }
02679        return retval;
02680 }
02681 /* }}} */
02682 
02683 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) /* {{{ */
02684 {
02685        zend_bool ret;
02686        int callable_name_len_local;
02687        zend_fcall_info_cache fcc_local;
02688 
02689        if (callable_name) {
02690               *callable_name = NULL;
02691        }
02692        if (callable_name_len == NULL) {
02693               callable_name_len = &callable_name_len_local;
02694        }
02695        if (fcc == NULL) {
02696               fcc = &fcc_local;
02697        }
02698        if (error) {
02699               *error = NULL;
02700        }
02701        
02702        fcc->initialized = 0;
02703        fcc->calling_scope = NULL;
02704        fcc->called_scope = NULL;
02705        fcc->function_handler = NULL;
02706        fcc->calling_scope = NULL;
02707        fcc->object_ptr = NULL;
02708 
02709        if (object_ptr && Z_TYPE_P(object_ptr) != IS_OBJECT) {
02710               object_ptr = NULL;
02711        }
02712        if (object_ptr &&
02713            (!EG(objects_store).object_buckets || 
02714             !EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(object_ptr)].valid)) {
02715               return 0;
02716        }
02717 
02718        switch (Z_TYPE_P(callable)) {
02719               case IS_STRING:
02720                      if (object_ptr) {
02721                             fcc->object_ptr = object_ptr;
02722                             fcc->calling_scope = Z_OBJCE_P(object_ptr);
02723                             if (callable_name) {
02724                                    char *ptr;
02725 
02726                                    *callable_name_len = fcc->calling_scope->name_length + Z_STRLEN_P(callable) + sizeof("::") - 1;
02727                                    ptr = *callable_name = emalloc(*callable_name_len + 1);
02728                                    memcpy(ptr, fcc->calling_scope->name, fcc->calling_scope->name_length);
02729                                    ptr += fcc->calling_scope->name_length;
02730                                    memcpy(ptr, "::", sizeof("::") - 1);
02731                                    ptr += sizeof("::") - 1;
02732                                    memcpy(ptr, Z_STRVAL_P(callable), Z_STRLEN_P(callable) + 1);
02733                             }
02734                      } else if (callable_name) {
02735                             *callable_name = estrndup(Z_STRVAL_P(callable), Z_STRLEN_P(callable));
02736                             *callable_name_len = Z_STRLEN_P(callable);
02737                      }
02738                      if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) {
02739                             fcc->called_scope = fcc->calling_scope;
02740                             return 1;
02741                      }
02742 
02743                      ret = zend_is_callable_check_func(check_flags, callable, fcc, 0, error TSRMLS_CC);
02744                      if (fcc == &fcc_local &&
02745                          fcc->function_handler &&
02746                             ((fcc->function_handler->type == ZEND_INTERNAL_FUNCTION &&
02747                            (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER)) ||
02748                           fcc->function_handler->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY ||
02749                           fcc->function_handler->type == ZEND_OVERLOADED_FUNCTION)) {
02750                             if (fcc->function_handler->type != ZEND_OVERLOADED_FUNCTION) {
02751                                    efree(fcc->function_handler->common.function_name);
02752                             }
02753                             efree(fcc->function_handler);
02754                      }
02755                      return ret;
02756 
02757               case IS_ARRAY:
02758                      {
02759                             zval **method = NULL;
02760                             zval **obj = NULL;
02761                             int strict_class = 0;
02762 
02763                             if (zend_hash_num_elements(Z_ARRVAL_P(callable)) == 2) {
02764                                    zend_hash_index_find(Z_ARRVAL_P(callable), 0, (void **) &obj);
02765                                    zend_hash_index_find(Z_ARRVAL_P(callable), 1, (void **) &method);
02766                             }
02767                             if (obj && method &&
02768                                    (Z_TYPE_PP(obj) == IS_OBJECT ||
02769                                    Z_TYPE_PP(obj) == IS_STRING) &&
02770                                    Z_TYPE_PP(method) == IS_STRING) {
02771 
02772                                    if (Z_TYPE_PP(obj) == IS_STRING) {
02773                                           if (callable_name) {
02774                                                  char *ptr;
02775 
02776                                                  *callable_name_len = Z_STRLEN_PP(obj) + Z_STRLEN_PP(method) + sizeof("::") - 1;
02777                                                  ptr = *callable_name = emalloc(*callable_name_len + 1);
02778                                                  memcpy(ptr, Z_STRVAL_PP(obj), Z_STRLEN_PP(obj));
02779                                                  ptr += Z_STRLEN_PP(obj);
02780                                                  memcpy(ptr, "::", sizeof("::") - 1);
02781                                                  ptr += sizeof("::") - 1;
02782                                                  memcpy(ptr, Z_STRVAL_PP(method), Z_STRLEN_PP(method) + 1);
02783                                           }
02784 
02785                                           if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) {
02786                                                  return 1;
02787                                           }
02788 
02789                                           if (!zend_is_callable_check_class(Z_STRVAL_PP(obj), Z_STRLEN_PP(obj), fcc, &strict_class, error TSRMLS_CC)) {
02790                                                  return 0;
02791                                           }
02792 
02793                                    } else {
02794                                           if (!EG(objects_store).object_buckets || 
02795                                               !EG(objects_store).object_buckets[Z_OBJ_HANDLE_PP(obj)].valid) {
02796                                                  return 0;
02797                                           }
02798 
02799                                           fcc->calling_scope = Z_OBJCE_PP(obj); /* TBFixed: what if it's overloaded? */
02800 
02801                                           fcc->object_ptr = *obj;
02802 
02803                                           if (callable_name) {
02804                                                  char *ptr;
02805 
02806                                                  *callable_name_len = fcc->calling_scope->name_length + Z_STRLEN_PP(method) + sizeof("::") - 1;
02807                                                  ptr = *callable_name = emalloc(*callable_name_len + 1);
02808                                                  memcpy(ptr, fcc->calling_scope->name, fcc->calling_scope->name_length);
02809                                                  ptr += fcc->calling_scope->name_length;
02810                                                  memcpy(ptr, "::", sizeof("::") - 1);
02811                                                  ptr += sizeof("::") - 1;
02812                                                  memcpy(ptr, Z_STRVAL_PP(method), Z_STRLEN_PP(method) + 1);
02813                                           }
02814 
02815                                           if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) {
02816                                                  fcc->called_scope = fcc->calling_scope;
02817                                                  return 1;
02818                                           }
02819                                    }
02820 
02821                                    ret = zend_is_callable_check_func(check_flags, *method, fcc, strict_class, error TSRMLS_CC);
02822                                    if (fcc == &fcc_local &&
02823                                        fcc->function_handler &&
02824                                           ((fcc->function_handler->type == ZEND_INTERNAL_FUNCTION &&
02825                                          (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER)) ||
02826                                         fcc->function_handler->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY ||
02827                                         fcc->function_handler->type == ZEND_OVERLOADED_FUNCTION)) {
02828                                           if (fcc->function_handler->type != ZEND_OVERLOADED_FUNCTION) {
02829                                                  efree(fcc->function_handler->common.function_name);
02830                                           }
02831                                           efree(fcc->function_handler);
02832                                    }
02833                                    return ret;
02834 
02835                             } else {
02836                                    if (zend_hash_num_elements(Z_ARRVAL_P(callable)) == 2) {
02837                                           if (!obj || (Z_TYPE_PP(obj) != IS_STRING && Z_TYPE_PP(obj) != IS_OBJECT)) {
02838                                                  if (error) zend_spprintf(error, 0, "first array member is not a valid class name or object");
02839                                           } else {
02840                                                  if (error) zend_spprintf(error, 0, "second array member is not a valid method");
02841                                           }
02842                                    } else {
02843                                           if (error) zend_spprintf(error, 0, "array must have exactly two members");
02844                                    }
02845                                    if (callable_name) {
02846                                           *callable_name = estrndup("Array", sizeof("Array")-1);
02847                                           *callable_name_len = sizeof("Array") - 1;
02848                                    }
02849                             }
02850                      }
02851                      return 0;
02852 
02853               case IS_OBJECT:
02854                      if (Z_OBJ_HANDLER_P(callable, get_closure) && Z_OBJ_HANDLER_P(callable, get_closure)(callable, &fcc->calling_scope, &fcc->function_handler, &fcc->object_ptr TSRMLS_CC) == SUCCESS) {
02855                             fcc->called_scope = fcc->calling_scope;
02856                             if (callable_name) {
02857                                    zend_class_entry *ce = Z_OBJCE_P(callable); /* TBFixed: what if it's overloaded? */
02858 
02859                                    *callable_name_len = ce->name_length + sizeof("::__invoke") - 1;
02860                                    *callable_name = emalloc(*callable_name_len + 1);
02861                                    memcpy(*callable_name, ce->name, ce->name_length);
02862                                    memcpy((*callable_name) + ce->name_length, "::__invoke", sizeof("::__invoke"));
02863                             }                                                              
02864                             return 1;
02865                      }
02866                      /* break missing intentionally */
02867 
02868               default:
02869                      if (callable_name) {
02870                             zval expr_copy;
02871                             int use_copy;
02872 
02873                             zend_make_printable_zval(callable, &expr_copy, &use_copy);
02874                             *callable_name = estrndup(Z_STRVAL(expr_copy), Z_STRLEN(expr_copy));
02875                             *callable_name_len = Z_STRLEN(expr_copy);
02876                             zval_dtor(&expr_copy);
02877                      }
02878                      if (error) zend_spprintf(error, 0, "no array or string given");
02879                      return 0;
02880        }
02881 }
02882 /* }}} */
02883 
02884 ZEND_API zend_bool zend_is_callable(zval *callable, uint check_flags, char **callable_name TSRMLS_DC) /* {{{ */
02885 {
02886        return zend_is_callable_ex(callable, NULL, check_flags, callable_name, NULL, NULL, NULL TSRMLS_CC);
02887 }
02888 /* }}} */
02889 
02890 ZEND_API zend_bool zend_make_callable(zval *callable, char **callable_name TSRMLS_DC) /* {{{ */
02891 {
02892        zend_fcall_info_cache fcc;
02893 
02894        if (zend_is_callable_ex(callable, NULL, IS_CALLABLE_STRICT, callable_name, NULL, &fcc, NULL TSRMLS_CC)) {
02895               if (Z_TYPE_P(callable) == IS_STRING && fcc.calling_scope) {
02896                      zval_dtor(callable);
02897                      array_init(callable);
02898                      add_next_index_string(callable, fcc.calling_scope->name, 1);
02899                      add_next_index_string(callable, fcc.function_handler->common.function_name, 1);
02900               }
02901               if (fcc.function_handler &&
02902                      ((fcc.function_handler->type == ZEND_INTERNAL_FUNCTION &&
02903                     (fcc.function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER)) ||
02904                    fcc.function_handler->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY ||
02905                    fcc.function_handler->type == ZEND_OVERLOADED_FUNCTION)) {
02906                      if (fcc.function_handler->type != ZEND_OVERLOADED_FUNCTION) {
02907                             efree(fcc.function_handler->common.function_name);
02908                      }
02909                      efree(fcc.function_handler);
02910               }
02911               return 1;
02912        }
02913        return 0;
02914 }
02915 /* }}} */
02916 
02917 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) /* {{{ */
02918 {
02919        if (!zend_is_callable_ex(callable, NULL, check_flags, callable_name, NULL, fcc, error TSRMLS_CC)) {
02920               return FAILURE;
02921        }
02922 
02923        fci->size = sizeof(*fci);
02924        fci->function_table = fcc->calling_scope ? &fcc->calling_scope->function_table : EG(function_table);
02925        fci->object_ptr = fcc->object_ptr;
02926        fci->function_name = callable;
02927        fci->retval_ptr_ptr = NULL;
02928        fci->param_count = 0;
02929        fci->params = NULL;
02930        fci->no_separation = 1;
02931        fci->symbol_table = NULL;
02932 
02933        return SUCCESS;
02934 }
02935 /* }}} */
02936 
02937 ZEND_API void zend_fcall_info_args_clear(zend_fcall_info *fci, int free_mem) /* {{{ */
02938 {
02939        if (fci->params) {
02940               if (free_mem) {
02941                      efree(fci->params);
02942                      fci->params = NULL;
02943               }
02944        }
02945        fci->param_count = 0;
02946 }
02947 /* }}} */
02948 
02949 ZEND_API void zend_fcall_info_args_save(zend_fcall_info *fci, int *param_count, zval ****params) /* {{{ */
02950 {
02951        *param_count = fci->param_count;
02952        *params = fci->params;
02953        fci->param_count = 0;
02954        fci->params = NULL;
02955 }
02956 /* }}} */
02957 
02958 ZEND_API void zend_fcall_info_args_restore(zend_fcall_info *fci, int param_count, zval ***params) /* {{{ */
02959 {
02960        zend_fcall_info_args_clear(fci, 1);
02961        fci->param_count = param_count;
02962        fci->params = params;
02963 }
02964 /* }}} */
02965 
02966 ZEND_API int zend_fcall_info_args(zend_fcall_info *fci, zval *args TSRMLS_DC) /* {{{ */
02967 {
02968        HashPosition pos;
02969        zval **arg, ***params;
02970 
02971        zend_fcall_info_args_clear(fci, !args);
02972 
02973        if (!args) {
02974               return SUCCESS;
02975        }
02976 
02977        if (Z_TYPE_P(args) != IS_ARRAY) {
02978               return FAILURE;
02979        }
02980 
02981        fci->param_count = zend_hash_num_elements(Z_ARRVAL_P(args));
02982        fci->params = params = (zval ***) erealloc(fci->params, fci->param_count * sizeof(zval **));
02983 
02984        zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(args), &pos);
02985        while (zend_hash_get_current_data_ex(Z_ARRVAL_P(args), (void *) &arg, &pos) == SUCCESS) {
02986               *params++ = arg;
02987               zend_hash_move_forward_ex(Z_ARRVAL_P(args), &pos);
02988        }
02989 
02990        return SUCCESS;
02991 }
02992 /* }}} */
02993 
02994 ZEND_API int zend_fcall_info_argp(zend_fcall_info *fci TSRMLS_DC, int argc, zval ***argv) /* {{{ */
02995 {
02996        int i;
02997 
02998        if (argc < 0) {
02999               return FAILURE;
03000        }
03001 
03002        zend_fcall_info_args_clear(fci, !argc);
03003 
03004        if (argc) {
03005               fci->param_count = argc;
03006               fci->params = (zval ***) erealloc(fci->params, fci->param_count * sizeof(zval **));
03007 
03008               for (i = 0; i < argc; ++i) {
03009                      fci->params[i] = argv[i];
03010               }
03011        }
03012 
03013        return SUCCESS;
03014 }
03015 /* }}} */
03016 
03017 ZEND_API int zend_fcall_info_argv(zend_fcall_info *fci TSRMLS_DC, int argc, va_list *argv) /* {{{ */
03018 {
03019        int i;
03020        zval **arg;
03021 
03022        if (argc < 0) {
03023               return FAILURE;
03024        }
03025 
03026        zend_fcall_info_args_clear(fci, !argc);
03027 
03028        if (argc) {
03029               fci->param_count = argc;
03030               fci->params = (zval ***) erealloc(fci->params, fci->param_count * sizeof(zval **));
03031 
03032               for (i = 0; i < argc; ++i) {
03033                      arg = va_arg(*argv, zval **);
03034                      fci->params[i] = arg;
03035               }
03036        }
03037 
03038        return SUCCESS;
03039 }
03040 /* }}} */
03041 
03042 ZEND_API int zend_fcall_info_argn(zend_fcall_info *fci TSRMLS_DC, int argc, ...) /* {{{ */
03043 {
03044        int ret;
03045        va_list argv;
03046 
03047        va_start(argv, argc);
03048        ret = zend_fcall_info_argv(fci TSRMLS_CC, argc, &argv);
03049        va_end(argv);
03050 
03051        return ret;
03052 }
03053 /* }}} */
03054 
03055 ZEND_API int zend_fcall_info_call(zend_fcall_info *fci, zend_fcall_info_cache *fcc, zval **retval_ptr_ptr, zval *args TSRMLS_DC) /* {{{ */
03056 {
03057        zval *retval, ***org_params = NULL;
03058        int result, org_count = 0;
03059 
03060        fci->retval_ptr_ptr = retval_ptr_ptr ? retval_ptr_ptr : &retval;
03061        if (args) {
03062               zend_fcall_info_args_save(fci, &org_count, &org_params);
03063               zend_fcall_info_args(fci, args TSRMLS_CC);
03064        }
03065        result = zend_call_function(fci, fcc TSRMLS_CC);
03066 
03067        if (!retval_ptr_ptr && retval) {
03068               zval_ptr_dtor(&retval);
03069        }
03070        if (args) {
03071               zend_fcall_info_args_restore(fci, org_count, org_params);
03072        }
03073        return result;
03074 }
03075 /* }}} */
03076 
03077 ZEND_API const char *zend_get_module_version(const char *module_name) /* {{{ */
03078 {
03079        char *lname;
03080        int name_len = strlen(module_name);
03081        zend_module_entry *module;
03082 
03083        lname = zend_str_tolower_dup(module_name, name_len);
03084        if (zend_hash_find(&module_registry, lname, name_len + 1, (void**)&module) == FAILURE) {
03085               efree(lname);
03086               return NULL;
03087        }
03088        efree(lname);
03089        return module->version;
03090 }
03091 /* }}} */
03092 
03093 ZEND_API int zend_declare_property_ex(zend_class_entry *ce, const char *name, int name_length, zval *property, int access_type, char *doc_comment, int doc_comment_len TSRMLS_DC) /* {{{ */
03094 {
03095        zend_property_info property_info;
03096        HashTable *target_symbol_table;
03097 
03098        if (!(access_type & ZEND_ACC_PPP_MASK)) {
03099               access_type |= ZEND_ACC_PUBLIC;
03100        }
03101        if (access_type & ZEND_ACC_STATIC) {
03102               target_symbol_table = &ce->default_static_members;
03103        } else {
03104               target_symbol_table = &ce->default_properties;
03105        }
03106        if (ce->type & ZEND_INTERNAL_CLASS) {
03107               switch(Z_TYPE_P(property)) {
03108                      case IS_ARRAY:
03109                      case IS_CONSTANT_ARRAY:
03110                      case IS_OBJECT:
03111                      case IS_RESOURCE:
03112                             zend_error(E_CORE_ERROR, "Internal zval's can't be arrays, objects or resources");
03113                             break;
03114                      default:
03115                             break;
03116               }
03117        }
03118        switch (access_type & ZEND_ACC_PPP_MASK) {
03119               case ZEND_ACC_PRIVATE: {
03120                             char *priv_name;
03121                             int priv_name_length;
03122 
03123                             zend_mangle_property_name(&priv_name, &priv_name_length, ce->name, ce->name_length, name, name_length, ce->type & ZEND_INTERNAL_CLASS);
03124                             zend_hash_update(target_symbol_table, priv_name, priv_name_length+1, &property, sizeof(zval *), NULL);
03125                             property_info.name = priv_name;
03126                             property_info.name_length = priv_name_length;
03127                      }
03128                      break;
03129               case ZEND_ACC_PROTECTED: {
03130                             char *prot_name;
03131                             int prot_name_length;
03132 
03133                             zend_mangle_property_name(&prot_name, &prot_name_length, "*", 1, name, name_length, ce->type & ZEND_INTERNAL_CLASS);
03134                             zend_hash_update(target_symbol_table, prot_name, prot_name_length+1, &property, sizeof(zval *), NULL);
03135                             property_info.name = prot_name;
03136                             property_info.name_length = prot_name_length;
03137                      }
03138                      break;
03139               case ZEND_ACC_PUBLIC:
03140                      if (ce->parent) {
03141                             char *prot_name;
03142                             int prot_name_length;
03143 
03144                             zend_mangle_property_name(&prot_name, &prot_name_length, "*", 1, name, name_length, ce->type & ZEND_INTERNAL_CLASS);
03145                             zend_hash_del(target_symbol_table, prot_name, prot_name_length+1);
03146                             pefree(prot_name, ce->type & ZEND_INTERNAL_CLASS);
03147                      }
03148                      zend_hash_update(target_symbol_table, name, name_length+1, &property, sizeof(zval *), NULL);
03149                      property_info.name = ce->type & ZEND_INTERNAL_CLASS ? zend_strndup(name, name_length) : estrndup(name, name_length);
03150                      property_info.name_length = name_length;
03151                      break;
03152        }
03153        property_info.flags = access_type;
03154        property_info.h = zend_get_hash_value(property_info.name, property_info.name_length+1);
03155 
03156        property_info.doc_comment = doc_comment;
03157        property_info.doc_comment_len = doc_comment_len;
03158 
03159        property_info.ce = ce;
03160 
03161        zend_hash_update(&ce->properties_info, name, name_length + 1, &property_info, sizeof(zend_property_info), NULL);
03162 
03163        return SUCCESS;
03164 }
03165 /* }}} */
03166 
03167 ZEND_API int zend_declare_property(zend_class_entry *ce, char *name, int name_length, zval *property, int access_type TSRMLS_DC) /* {{{ */
03168 {
03169        return zend_declare_property_ex(ce, name, name_length, property, access_type, NULL, 0 TSRMLS_CC);
03170 }
03171 /* }}} */
03172 
03173 ZEND_API int zend_declare_property_null(zend_class_entry *ce, char *name, int name_length, int access_type TSRMLS_DC) /* {{{ */
03174 {
03175        zval *property;
03176 
03177        if (ce->type & ZEND_INTERNAL_CLASS) {
03178               ALLOC_PERMANENT_ZVAL(property);
03179        } else {
03180               ALLOC_ZVAL(property);
03181        }
03182        INIT_ZVAL(*property);
03183        return zend_declare_property(ce, name, name_length, property, access_type TSRMLS_CC);
03184 }
03185 /* }}} */
03186 
03187 ZEND_API int zend_declare_property_bool(zend_class_entry *ce, char *name, int name_length, long value, int access_type TSRMLS_DC) /* {{{ */
03188 {
03189        zval *property;
03190 
03191        if (ce->type & ZEND_INTERNAL_CLASS) {
03192               ALLOC_PERMANENT_ZVAL(property);
03193        } else {
03194               ALLOC_ZVAL(property);
03195        }
03196        INIT_PZVAL(property);
03197        ZVAL_BOOL(property, value);
03198        return zend_declare_property(ce, name, name_length, property, access_type TSRMLS_CC);
03199 }
03200 /* }}} */
03201 
03202 ZEND_API int zend_declare_property_long(zend_class_entry *ce, char *name, int name_length, long value, int access_type TSRMLS_DC) /* {{{ */
03203 {
03204        zval *property;
03205 
03206        if (ce->type & ZEND_INTERNAL_CLASS) {
03207               ALLOC_PERMANENT_ZVAL(property);
03208        } else {
03209               ALLOC_ZVAL(property);
03210        }
03211        INIT_PZVAL(property);
03212        ZVAL_LONG(property, value);
03213        return zend_declare_property(ce, name, name_length, property, access_type TSRMLS_CC);
03214 }
03215 /* }}} */
03216 
03217 ZEND_API int zend_declare_property_double(zend_class_entry *ce, char *name, int name_length, double value, int access_type TSRMLS_DC) /* {{{ */
03218 {
03219        zval *property;
03220 
03221        if (ce->type & ZEND_INTERNAL_CLASS) {
03222               ALLOC_PERMANENT_ZVAL(property);
03223        } else {
03224               ALLOC_ZVAL(property);
03225        }
03226        INIT_PZVAL(property);
03227        ZVAL_DOUBLE(property, value);
03228        return zend_declare_property(ce, name, name_length, property, access_type TSRMLS_CC);
03229 }
03230 /* }}} */
03231 
03232 ZEND_API int zend_declare_property_string(zend_class_entry *ce, char *name, int name_length, char *value, int access_type TSRMLS_DC) /* {{{ */
03233 {
03234        zval *property;
03235        int len = strlen(value);
03236 
03237        if (ce->type & ZEND_INTERNAL_CLASS) {
03238               ALLOC_PERMANENT_ZVAL(property);
03239               ZVAL_STRINGL(property, zend_strndup(value, len), len, 0);
03240        } else {
03241               ALLOC_ZVAL(property);
03242               ZVAL_STRINGL(property, value, len, 1);
03243        }
03244        INIT_PZVAL(property);
03245        return zend_declare_property(ce, name, name_length, property, access_type TSRMLS_CC);
03246 }
03247 /* }}} */
03248 
03249 ZEND_API int zend_declare_property_stringl(zend_class_entry *ce, char *name, int name_length, char *value, int value_len, int access_type TSRMLS_DC) /* {{{ */
03250 {
03251        zval *property;
03252 
03253        if (ce->type & ZEND_INTERNAL_CLASS) {
03254               ALLOC_PERMANENT_ZVAL(property);
03255               ZVAL_STRINGL(property, zend_strndup(value, value_len), value_len, 0);
03256        } else {
03257               ALLOC_ZVAL(property);
03258               ZVAL_STRINGL(property, value, value_len, 1);
03259        }
03260        INIT_PZVAL(property);
03261        return zend_declare_property(ce, name, name_length, property, access_type TSRMLS_CC);
03262 }
03263 /* }}} */
03264 
03265 ZEND_API int zend_declare_class_constant(zend_class_entry *ce, const char *name, size_t name_length, zval *value TSRMLS_DC) /* {{{ */
03266 {
03267        return zend_hash_update(&ce->constants_table, name, name_length+1, &value, sizeof(zval *), NULL);
03268 }
03269 /* }}} */
03270 
03271 ZEND_API int zend_declare_class_constant_null(zend_class_entry *ce, const char *name, size_t name_length TSRMLS_DC) /* {{{ */
03272 {
03273        zval *constant;
03274 
03275        if (ce->type & ZEND_INTERNAL_CLASS) {
03276               ALLOC_PERMANENT_ZVAL(constant);
03277        } else {
03278               ALLOC_ZVAL(constant);
03279        }
03280        ZVAL_NULL(constant);
03281        INIT_PZVAL(constant);
03282        return zend_declare_class_constant(ce, name, name_length, constant TSRMLS_CC);
03283 }
03284 /* }}} */
03285 
03286 ZEND_API int zend_declare_class_constant_long(zend_class_entry *ce, const char *name, size_t name_length, long value TSRMLS_DC) /* {{{ */
03287 {
03288        zval *constant;
03289 
03290        if (ce->type & ZEND_INTERNAL_CLASS) {
03291               ALLOC_PERMANENT_ZVAL(constant);
03292        } else {
03293               ALLOC_ZVAL(constant);
03294        }
03295        ZVAL_LONG(constant, value);
03296        INIT_PZVAL(constant);
03297        return zend_declare_class_constant(ce, name, name_length, constant TSRMLS_CC);
03298 }
03299 /* }}} */
03300 
03301 ZEND_API int zend_declare_class_constant_bool(zend_class_entry *ce, const char *name, size_t name_length, zend_bool value TSRMLS_DC) /* {{{ */
03302 {
03303        zval *constant;
03304 
03305        if (ce->type & ZEND_INTERNAL_CLASS) {
03306               ALLOC_PERMANENT_ZVAL(constant);
03307        } else {
03308               ALLOC_ZVAL(constant);
03309        }
03310        ZVAL_BOOL(constant, value);
03311        INIT_PZVAL(constant);
03312        return zend_declare_class_constant(ce, name, name_length, constant TSRMLS_CC);
03313 }
03314 /* }}} */
03315 
03316 ZEND_API int zend_declare_class_constant_double(zend_class_entry *ce, const char *name, size_t name_length, double value TSRMLS_DC) /* {{{ */
03317 {
03318        zval *constant;
03319 
03320        if (ce->type & ZEND_INTERNAL_CLASS) {
03321               ALLOC_PERMANENT_ZVAL(constant);
03322        } else {
03323               ALLOC_ZVAL(constant);
03324        }
03325        ZVAL_DOUBLE(constant, value);
03326        INIT_PZVAL(constant);
03327        return zend_declare_class_constant(ce, name, name_length, constant TSRMLS_CC);
03328 }
03329 /* }}} */
03330 
03331 ZEND_API int zend_declare_class_constant_stringl(zend_class_entry *ce, const char *name, size_t name_length, const char *value, size_t value_length TSRMLS_DC) /* {{{ */
03332 {
03333        zval *constant;
03334 
03335        if (ce->type & ZEND_INTERNAL_CLASS) {
03336               ALLOC_PERMANENT_ZVAL(constant);
03337               ZVAL_STRINGL(constant, zend_strndup(value, value_length), value_length, 0);
03338        } else {
03339               ALLOC_ZVAL(constant);
03340               ZVAL_STRINGL(constant, value, value_length, 1);
03341        }
03342        INIT_PZVAL(constant);
03343        return zend_declare_class_constant(ce, name, name_length, constant TSRMLS_CC);
03344 }
03345 /* }}} */
03346 
03347 ZEND_API int zend_declare_class_constant_string(zend_class_entry *ce, const char *name, size_t name_length, const char *value TSRMLS_DC) /* {{{ */
03348 {
03349        return zend_declare_class_constant_stringl(ce, name, name_length, value, strlen(value) TSRMLS_CC);
03350 }
03351 /* }}} */
03352 
03353 ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, char *name, int name_length, zval *value TSRMLS_DC) /* {{{ */
03354 {
03355        zval *property;
03356        zend_class_entry *old_scope = EG(scope);
03357 
03358        EG(scope) = scope;
03359 
03360        if (!Z_OBJ_HT_P(object)->write_property) {
03361               char *class_name;
03362               zend_uint class_name_len;
03363 
03364               zend_get_object_classname(object, &class_name, &class_name_len TSRMLS_CC);
03365 
03366               zend_error(E_CORE_ERROR, "Property %s of class %s cannot be updated", name, class_name);
03367        }
03368        MAKE_STD_ZVAL(property);
03369        ZVAL_STRINGL(property, name, name_length, 1);
03370        Z_OBJ_HT_P(object)->write_property(object, property, value TSRMLS_CC);
03371        zval_ptr_dtor(&property);
03372 
03373        EG(scope) = old_scope;
03374 }
03375 /* }}} */
03376 
03377 ZEND_API void zend_update_property_null(zend_class_entry *scope, zval *object, char *name, int name_length TSRMLS_DC) /* {{{ */
03378 {
03379        zval *tmp;
03380 
03381        ALLOC_ZVAL(tmp);
03382        Z_UNSET_ISREF_P(tmp);
03383        Z_SET_REFCOUNT_P(tmp, 0);
03384        ZVAL_NULL(tmp);
03385        zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC);
03386 }
03387 /* }}} */
03388 
03389 ZEND_API void zend_update_property_bool(zend_class_entry *scope, zval *object, char *name, int name_length, long value TSRMLS_DC) /* {{{ */
03390 {
03391        zval *tmp;
03392 
03393        ALLOC_ZVAL(tmp);
03394        Z_UNSET_ISREF_P(tmp);
03395        Z_SET_REFCOUNT_P(tmp, 0);
03396        ZVAL_BOOL(tmp, value);
03397        zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC);
03398 }
03399 /* }}} */
03400 
03401 ZEND_API void zend_update_property_long(zend_class_entry *scope, zval *object, char *name, int name_length, long value TSRMLS_DC) /* {{{ */
03402 {
03403        zval *tmp;
03404 
03405        ALLOC_ZVAL(tmp);
03406        Z_UNSET_ISREF_P(tmp);
03407        Z_SET_REFCOUNT_P(tmp, 0);
03408        ZVAL_LONG(tmp, value);
03409        zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC);
03410 }
03411 /* }}} */
03412 
03413 ZEND_API void zend_update_property_double(zend_class_entry *scope, zval *object, char *name, int name_length, double value TSRMLS_DC) /* {{{ */
03414 {
03415        zval *tmp;
03416 
03417        ALLOC_ZVAL(tmp);
03418        Z_UNSET_ISREF_P(tmp);
03419        Z_SET_REFCOUNT_P(tmp, 0);
03420        ZVAL_DOUBLE(tmp, value);
03421        zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC);
03422 }
03423 /* }}} */
03424 
03425 ZEND_API void zend_update_property_string(zend_class_entry *scope, zval *object, char *name, int name_length, const char *value TSRMLS_DC) /* {{{ */
03426 {
03427        zval *tmp;
03428 
03429        ALLOC_ZVAL(tmp);
03430        Z_UNSET_ISREF_P(tmp);
03431        Z_SET_REFCOUNT_P(tmp, 0);
03432        ZVAL_STRING(tmp, value, 1);
03433        zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC);
03434 }
03435 /* }}} */
03436 
03437 ZEND_API void zend_update_property_stringl(zend_class_entry *scope, zval *object, char *name, int name_length, const char *value, int value_len TSRMLS_DC) /* {{{ */
03438 {
03439        zval *tmp;
03440 
03441        ALLOC_ZVAL(tmp);
03442        Z_UNSET_ISREF_P(tmp);
03443        Z_SET_REFCOUNT_P(tmp, 0);
03444        ZVAL_STRINGL(tmp, value, value_len, 1);
03445        zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC);
03446 }
03447 /* }}} */
03448 
03449 ZEND_API int zend_update_static_property(zend_class_entry *scope, char *name, int name_length, zval *value TSRMLS_DC) /* {{{ */
03450 {
03451        zval **property;
03452        zend_class_entry *old_scope = EG(scope);
03453 
03454        EG(scope) = scope;
03455        property = zend_std_get_static_property(scope, name, name_length, 0 TSRMLS_CC);
03456        EG(scope) = old_scope;
03457        if (!property) {
03458               return FAILURE;
03459        } else {
03460               if (*property != value) {
03461                      if (PZVAL_IS_REF(*property)) {
03462                             zval_dtor(*property);
03463                             Z_TYPE_PP(property) = Z_TYPE_P(value);
03464                             (*property)->value = value->value;
03465                             if (Z_REFCOUNT_P(value) > 0) {
03466                                    zval_copy_ctor(*property);
03467                             }
03468                      } else {
03469                             zval *garbage = *property;
03470 
03471                             Z_ADDREF_P(value);
03472                             if (PZVAL_IS_REF(value)) {
03473                                    SEPARATE_ZVAL(&value);
03474                             }
03475                             *property = value;
03476                             zval_ptr_dtor(&garbage);
03477                      }
03478               }
03479               return SUCCESS;
03480        }
03481 }
03482 /* }}} */
03483 
03484 ZEND_API int zend_update_static_property_null(zend_class_entry *scope, char *name, int name_length TSRMLS_DC) /* {{{ */
03485 {
03486        zval *tmp;
03487 
03488        ALLOC_ZVAL(tmp);
03489        Z_UNSET_ISREF_P(tmp);
03490        Z_SET_REFCOUNT_P(tmp, 0);
03491        ZVAL_NULL(tmp);
03492        return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC);
03493 }
03494 /* }}} */
03495 
03496 ZEND_API int zend_update_static_property_bool(zend_class_entry *scope, char *name, int name_length, long value TSRMLS_DC) /* {{{ */
03497 {
03498        zval *tmp;
03499 
03500        ALLOC_ZVAL(tmp);
03501        Z_UNSET_ISREF_P(tmp);
03502        Z_SET_REFCOUNT_P(tmp, 0);
03503        ZVAL_BOOL(tmp, value);
03504        return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC);
03505 }
03506 /* }}} */
03507 
03508 ZEND_API int zend_update_static_property_long(zend_class_entry *scope, char *name, int name_length, long value TSRMLS_DC) /* {{{ */
03509 {
03510        zval *tmp;
03511 
03512        ALLOC_ZVAL(tmp);
03513        Z_UNSET_ISREF_P(tmp);
03514        Z_SET_REFCOUNT_P(tmp, 0);
03515        ZVAL_LONG(tmp, value);
03516        return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC);
03517 }
03518 /* }}} */
03519 
03520 ZEND_API int zend_update_static_property_double(zend_class_entry *scope, char *name, int name_length, double value TSRMLS_DC) /* {{{ */
03521 {
03522        zval *tmp;
03523 
03524        ALLOC_ZVAL(tmp);
03525        Z_UNSET_ISREF_P(tmp);
03526        Z_SET_REFCOUNT_P(tmp, 0);
03527        ZVAL_DOUBLE(tmp, value);
03528        return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC);
03529 }
03530 /* }}} */
03531 
03532 ZEND_API int zend_update_static_property_string(zend_class_entry *scope, char *name, int name_length, const char *value TSRMLS_DC) /* {{{ */
03533 {
03534        zval *tmp;
03535 
03536        ALLOC_ZVAL(tmp);
03537        Z_UNSET_ISREF_P(tmp);
03538        Z_SET_REFCOUNT_P(tmp, 0);
03539        ZVAL_STRING(tmp, value, 1);
03540        return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC);
03541 }
03542 /* }}} */
03543 
03544 ZEND_API int zend_update_static_property_stringl(zend_class_entry *scope, char *name, int name_length, const char *value, int value_len TSRMLS_DC) /* {{{ */
03545 {
03546        zval *tmp;
03547 
03548        ALLOC_ZVAL(tmp);
03549        Z_UNSET_ISREF_P(tmp);
03550        Z_SET_REFCOUNT_P(tmp, 0);
03551        ZVAL_STRINGL(tmp, value, value_len, 1);
03552        return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC);
03553 }
03554 /* }}} */
03555 
03556 ZEND_API zval *zend_read_property(zend_class_entry *scope, zval *object, char *name, int name_length, zend_bool silent TSRMLS_DC) /* {{{ */
03557 {
03558        zval *property, *value;
03559        zend_class_entry *old_scope = EG(scope);
03560 
03561        EG(scope) = scope;
03562 
03563        if (!Z_OBJ_HT_P(object)->read_property) {
03564               char *class_name;
03565               zend_uint class_name_len;
03566 
03567               zend_get_object_classname(object, &class_name, &class_name_len TSRMLS_CC);
03568               zend_error(E_CORE_ERROR, "Property %s of class %s cannot be read", name, class_name);
03569        }
03570 
03571        MAKE_STD_ZVAL(property);
03572        ZVAL_STRINGL(property, name, name_length, 1);
03573        value = Z_OBJ_HT_P(object)->read_property(object, property, silent?BP_VAR_IS:BP_VAR_R TSRMLS_CC);
03574        zval_ptr_dtor(&property);
03575 
03576        EG(scope) = old_scope;
03577        return value;
03578 }
03579 /* }}} */
03580 
03581 ZEND_API zval *zend_read_static_property(zend_class_entry *scope, char *name, int name_length, zend_bool silent TSRMLS_DC) /* {{{ */
03582 {
03583        zval **property;
03584        zend_class_entry *old_scope = EG(scope);
03585 
03586        EG(scope) = scope;
03587        property = zend_std_get_static_property(scope, name, name_length, silent TSRMLS_CC);
03588        EG(scope) = old_scope;
03589 
03590        return property?*property:NULL;
03591 }
03592 /* }}} */
03593 
03594 ZEND_API void zend_save_error_handling(zend_error_handling *current TSRMLS_DC) /* {{{ */
03595 {
03596        current->handling = EG(error_handling);
03597        current->exception = EG(exception_class);
03598        current->user_handler = EG(user_error_handler);
03599        if (current->user_handler) {
03600               Z_ADDREF_P(current->user_handler);
03601        }
03602 }
03603 /* }}} */
03604 
03605 ZEND_API void zend_replace_error_handling(zend_error_handling_t error_handling, zend_class_entry *exception_class, zend_error_handling *current TSRMLS_DC) /* {{{ */
03606 {
03607        if (current) {
03608               zend_save_error_handling(current TSRMLS_CC);
03609               if (error_handling != EH_NORMAL && EG(user_error_handler)) {
03610                      zval_ptr_dtor(&EG(user_error_handler));
03611                      EG(user_error_handler) = NULL;
03612               }
03613        }
03614        EG(error_handling) = error_handling;
03615        EG(exception_class) = error_handling == EH_THROW ? exception_class : NULL;
03616 }
03617 /* }}} */
03618 
03619 ZEND_API void zend_restore_error_handling(zend_error_handling *saved TSRMLS_DC) /* {{{ */
03620 {
03621        EG(error_handling) = saved->handling;
03622        EG(exception_class) = saved->handling == EH_THROW ? saved->exception : NULL;
03623        if (saved->user_handler     && saved->user_handler != EG(user_error_handler)) {
03624               if (EG(user_error_handler)) {
03625                      zval_ptr_dtor(&EG(user_error_handler));
03626               }
03627               EG(user_error_handler) = saved->user_handler;
03628        } else if (saved->user_handler) {
03629               zval_ptr_dtor(&saved->user_handler);
03630        }
03631        saved->user_handler = NULL;
03632 }
03633 /* }}} */
03634 
03635 /*
03636  * Local variables:
03637  * tab-width: 4
03638  * c-basic-offset: 4
03639  * indent-tabs-mode: t
03640  * End:
03641  */