Unicode support

This commit is contained in:
Andrei Zmievski 2005-08-11 23:35:03 +00:00
parent 39072c42c4
commit b80cb7bd2f
51 changed files with 8302 additions and 2403 deletions

View File

@ -17,7 +17,7 @@ libZend_la_SOURCES=\
zend_objects_API.c zend_ts_hash.c zend_stream.c zend_mm.c \
zend_default_classes.c zend_reflection_api.c \
zend_iterators.c zend_interfaces.c zend_exceptions.c \
zend_strtod.c zend_multibyte.c
zend_strtod.c zend_multibyte.c zend_strtod.c zend_strtol.c
libZend_la_LDFLAGS =
libZend_la_LIBADD = @ZEND_EXTRA_LIBS@

View File

@ -160,12 +160,15 @@ AC_ARG_ENABLE(memory-limit,
ZEND_MEMORY_LIMIT=no
])
AC_ARG_ENABLE(zend-multibyte,
[ --enable-zend-multibyte Compile with zend multibyte support], [
ZEND_MULTIBYTE=$enableval
],[
ZEND_MULTIBYTE=no
])
dnl AC_ARG_ENABLE(zend-multibyte,
dnl [ --enable-zend-multibyte Compile with zend multibyte support], [
dnl ZEND_MULTIBYTE=$enableval
dnl ],[
dnl ZEND_MULTIBYTE=no
dnl ])
dnl Unicode PHP doesn't need ZEND_MULTIBYTE
ZEND_MULTIBYTE=no
AC_MSG_CHECKING([virtual machine dispatch method])
AC_MSG_RESULT($PHP_ZEND_VM)

View File

@ -440,18 +440,6 @@ YY_MALLOC_DECL
#define ECHO /* There is no output */
#endif
#ifdef ZEND_MULTIBYTE
# define YY_INPUT(buf, result, max_size) \
if ( ((result = zend_multibyte_yyinput(yyin, buf, max_size TSRMLS_CC)) == 0) \
&& zend_stream_ferror( yyin TSRMLS_CC) ) \
YY_FATAL_ERROR( "input in flex scanner failed" );
#else
# define YY_INPUT(buf, result, max_size) \
if ( ((result = zend_stream_read(yyin, buf, max_size TSRMLS_CC)) == 0) \
&& zend_stream_ferror( yyin TSRMLS_CC) ) \
YY_FATAL_ERROR( "input in flex scanner failed" );
#endif
#ifndef ECHO
%- Standard (non-C++) definition
/* This used to be an fputs(), but since the string might contain NUL's,

File diff suppressed because it is too large Load Diff

View File

@ -35,6 +35,7 @@
#endif
#include <stdio.h>
#include <assert.h>
/*
* general definitions
@ -225,6 +226,8 @@ char *alloca ();
#include "zend_types.h"
#include <unicode/utypes.h>
#ifdef HAVE_LIMITS_H
# include <limits.h>
#endif
@ -237,6 +240,8 @@ char *alloca ();
#define LONG_MIN (- LONG_MAX - 1)
#endif
#define EMPTY_STR "\0\0"
#undef SUCCESS
#undef FAILURE
#define SUCCESS 0
@ -258,6 +263,13 @@ void zend_error_noreturn(int type, const char *format, ...) __attribute__ ((nore
# define zend_error_noreturn zend_error
#endif
#if defined(__GNUC__) && !defined(__INTEL_COMPILER) && !defined(DARWIN)
# define ZEND_VM_ALWAYS_INLINE __attribute__ ((always_inline))
void zend_error_noreturn(int type, const char *format, ...) __attribute__ ((noreturn));
#else
# define ZEND_VM_ALWAYS_INLINE
# define zend_error_noreturn zend_error
#endif
/*
* zval
@ -287,10 +299,14 @@ struct _zend_object_value {
typedef union _zvalue_value {
long lval; /* long value */
double dval; /* double value */
struct {
struct { /* 8-bit legacy string type */
char *val;
int len;
} str;
struct { /* Unicode string type */
UChar *val;
int32_t len;
} ustr;
HashTable *ht; /* hash table value */
zend_object_value obj;
} zvalue_value;
@ -371,8 +387,8 @@ struct _zend_class_entry {
#include "zend_stream.h"
typedef struct _zend_utility_functions {
void (*error_function)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args) ZEND_ATTRIBUTE_PTR_FORMAT(printf, 4, 0);
int (*printf_function)(const char *format, ...) ZEND_ATTRIBUTE_PTR_FORMAT(printf, 1, 2);
void (*error_function)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args);
int (*printf_function)(const char *format, ...);
int (*write_function)(const char *str, uint str_length);
FILE *(*fopen_function)(const char *filename, char **opened_path);
void (*message_handler)(long message, void *data);
@ -407,6 +423,8 @@ typedef int (*zend_write_func_t)(const char *str, uint str_length);
((n) ? (((n)>0) ? 1 : -1) : 0)
#define ZEND_TRUTH(x) ((x) ? 1 : 0)
#define ZEND_LOG_XOR(a, b) (ZEND_TRUTH(a) ^ ZEND_TRUTH(b))
#define ZEND_COLL_RESULT(n) \
((n) == UCOL_EQUAL ? 0 : ((n) == UCOL_GREATER ? 1 : -1))
@ -422,6 +440,8 @@ typedef int (*zend_write_func_t)(const char *str, uint str_length);
#define IS_RESOURCE 7
#define IS_CONSTANT 8
#define IS_CONSTANT_ARRAY 9
#define IS_UNICODE 10
#define IS_BINARY 11
/* Ugly hack to support constants as static array indices */
#define IS_CONSTANT_INDEX 0x80
@ -432,14 +452,13 @@ typedef int (*zend_write_func_t)(const char *str, uint str_length);
#define OE_IS_OBJECT (1<<1)
#define OE_IS_METHOD (1<<2)
int zend_startup(zend_utility_functions *utility_functions, char **extensions, int start_builtin_functions);
void zend_shutdown(TSRMLS_D);
void zend_register_standard_ini_entries(TSRMLS_D);
#ifdef ZTS
//#ifdef ZTS
void zend_post_startup(TSRMLS_D);
#endif
//#endif
void zend_set_utility_values(zend_utility_values *utility_values);
@ -468,12 +487,14 @@ END_EXTERN_C()
BEGIN_EXTERN_C()
ZEND_API char *get_zend_version(void);
ZEND_API void zend_make_printable_zval(zval *expr, zval *expr_copy, int *use_copy);
ZEND_API void zend_make_string_zval(zval *expr, zval *expr_copy, int *use_copy);
ZEND_API void zend_make_unicode_zval(zval *expr, zval *expr_copy, int *use_copy);
ZEND_API int zend_print_zval(zval *expr, int indent);
ZEND_API int zend_print_zval_ex(zend_write_func_t write_func, zval *expr, int indent);
ZEND_API void zend_print_zval_r(zval *expr, int indent TSRMLS_DC);
ZEND_API void zend_print_flat_zval_r(zval *expr TSRMLS_DC);
ZEND_API void zend_print_zval_r_ex(zend_write_func_t write_func, zval *expr, int indent TSRMLS_DC);
ZEND_API void zend_output_debug_string(zend_bool trigger_break, char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3);
ZEND_API void zend_output_debug_string(zend_bool trigger_break, char *format, ...);
END_EXTERN_C()
void zend_activate(TSRMLS_D);
@ -510,20 +531,20 @@ END_EXTERN_C()
BEGIN_EXTERN_C()
extern ZEND_API int (*zend_printf)(const char *format, ...) ZEND_ATTRIBUTE_PTR_FORMAT(printf, 1, 2);
extern ZEND_API int (*zend_printf)(const char *format, ...);
extern ZEND_API zend_write_func_t zend_write;
extern ZEND_API FILE *(*zend_fopen)(const char *filename, char **opened_path);
extern ZEND_API void (*zend_block_interruptions)(void);
extern ZEND_API void (*zend_unblock_interruptions)(void);
extern ZEND_API void (*zend_ticks_function)(int ticks);
extern ZEND_API void (*zend_error_cb)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args) ZEND_ATTRIBUTE_PTR_FORMAT(printf, 4, 0);
extern ZEND_API void (*zend_error_cb)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args);
extern void (*zend_on_timeout)(int seconds TSRMLS_DC);
extern ZEND_API int (*zend_stream_open_function)(const char *filename, zend_file_handle *handle TSRMLS_DC);
extern int (*zend_vspprintf)(char **pbuf, size_t max_len, const char *format, va_list ap);
extern ZEND_API char *(*zend_getenv)(char *name, size_t name_len TSRMLS_DC);
ZEND_API void zend_error(int type, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3);
ZEND_API void zend_error(int type, const char *format, ...);
void zenderror(char *error);
@ -545,6 +566,7 @@ BEGIN_EXTERN_C()
ZEND_API void zend_message_dispatcher(long message, void *data);
ZEND_API int zend_get_configuration_directive(char *name, uint name_length, zval *contents);
ZEND_API void zend_reset_locale_deps(TSRMLS_D);
END_EXTERN_C()
@ -644,8 +666,15 @@ END_EXTERN_C()
#define ZEND_MAX_RESERVED_RESOURCES 4
#define ZEND_INTERNAL_ENCODING "UTF-16"
#include "zend_variables.h"
#define ZEND_U_EQUAL(type, ustr, ulen, str, slen) \
((type == IS_STRING)? \
(!memcmp((ustr),(str),(slen))): \
(!zend_cmp_unicode_and_literal(((UChar*)(ustr)), ulen, str, slen)))
#endif /* ZEND_H */
/*

File diff suppressed because it is too large Load Diff

View File

@ -126,6 +126,8 @@ typedef struct _zend_function_entry {
class_container.constructor = NULL; \
class_container.destructor = NULL; \
class_container.clone = NULL; \
class_container.serialize = NULL; \
class_container.unserialize = NULL; \
class_container.create_object = NULL; \
class_container.interface_gets_implemented = NULL; \
class_container.__call = handle_fcall; \
@ -212,6 +214,8 @@ ZEND_API int zend_declare_property_double(zend_class_entry *ce, char *name, int
ZEND_API int zend_declare_property_string(zend_class_entry *ce, char *name, int name_length, char *value, int access_type TSRMLS_DC);
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);
ZEND_API int zend_u_declare_property(zend_class_entry *ce, zend_uchar type, void *name, int name_length, zval *property, int access_type TSRMLS_DC);
ZEND_API void zend_update_class_constants(zend_class_entry *class_type TSRMLS_DC);
ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, char *name, int name_length, zval *value TSRMLS_DC);
ZEND_API void zend_update_property_null(zend_class_entry *scope, zval *object, char *name, int name_length TSRMLS_DC);
@ -225,6 +229,7 @@ ZEND_API zval *zend_read_property(zend_class_entry *scope, zval *object, char *n
ZEND_API zend_class_entry *zend_get_class_entry(zval *zobject TSRMLS_DC);
ZEND_API int zend_get_object_classname(zval *object, char **class_name, zend_uint *class_name_len TSRMLS_DC);
ZEND_API zend_uchar zend_get_best_string_type(int num_args, ...);
#define getThis() (this_ptr)
@ -260,6 +265,8 @@ ZEND_API int add_assoc_resource_ex(zval *arg, char *key, uint key_len, int r);
ZEND_API int add_assoc_double_ex(zval *arg, char *key, uint key_len, double d);
ZEND_API int add_assoc_string_ex(zval *arg, char *key, uint key_len, char *str, int duplicate);
ZEND_API int add_assoc_stringl_ex(zval *arg, char *key, uint key_len, char *str, uint length, int duplicate);
ZEND_API int add_assoc_unicode_ex(zval *arg, char *key, uint key_len, void *str, int duplicate);
ZEND_API int add_assoc_unicodel_ex(zval *arg, char *key, uint key_len, void *str, uint length, int duplicate);
ZEND_API int add_assoc_zval_ex(zval *arg, char *key, uint key_len, zval *value);
#define add_assoc_long(__arg, __key, __n) add_assoc_long_ex(__arg, __key, strlen(__key)+1, __n)
@ -269,8 +276,14 @@ ZEND_API int add_assoc_zval_ex(zval *arg, char *key, uint key_len, zval *value);
#define add_assoc_double(__arg, __key, __d) add_assoc_double_ex(__arg, __key, strlen(__key)+1, __d)
#define add_assoc_string(__arg, __key, __str, __duplicate) add_assoc_string_ex(__arg, __key, strlen(__key)+1, __str, __duplicate)
#define add_assoc_stringl(__arg, __key, __str, __length, __duplicate) add_assoc_stringl_ex(__arg, __key, strlen(__key)+1, __str, __length, __duplicate)
#define add_assoc_unicode(__arg, __key, __str, __duplicate) add_assoc_unicode_ex(__arg, __key, strlen(__key)+1, __str, __duplicate)
#define add_assoc_unicodel(__arg, __key, __str, __length, __duplicate) add_assoc_unicodel_ex(__arg, __key, strlen(__key)+1, __str, __length, __duplicate)
#define add_assoc_zval(__arg, __key, __value) add_assoc_zval_ex(__arg, __key, strlen(__key)+1, __value)
ZEND_API int add_u_assoc_zval_ex(zval *arg, zend_uchar type, void *key, uint key_len, zval *value);
#define add_u_assoc_zval(__arg, __type, __key, __value) add_u_assoc_zval_ex(__arg, __type, __key, (((__type)==IS_UNICODE)?u_strlen((UChar*)__key):strlen(__key))+1, __value)
/* unset() functions are only suported for legacy modules and null() functions should be used */
#define add_assoc_unset(__arg, __key) add_assoc_null_ex(__arg, __key, strlen(__key) + 1)
#define add_index_unset(__arg, __key) add_index_null(__arg, __key)
@ -284,6 +297,10 @@ ZEND_API int add_index_resource(zval *arg, uint idx, int r);
ZEND_API int add_index_double(zval *arg, uint idx, double d);
ZEND_API int add_index_string(zval *arg, uint idx, char *str, int duplicate);
ZEND_API int add_index_stringl(zval *arg, uint idx, char *str, uint length, int duplicate);
ZEND_API int add_index_binary(zval *arg, uint idx, char *str, int duplicate);
ZEND_API int add_index_binaryl(zval *arg, uint idx, char *str, uint length, int duplicate);
ZEND_API int add_index_unicode(zval *arg, uint idx, UChar *str, int duplicate);
ZEND_API int add_index_unicodel(zval *arg, uint idx, UChar *str, uint length, int duplicate);
ZEND_API int add_index_zval(zval *arg, uint index, zval *value);
ZEND_API int add_next_index_long(zval *arg, long n);
@ -293,6 +310,10 @@ ZEND_API int add_next_index_resource(zval *arg, int r);
ZEND_API int add_next_index_double(zval *arg, double d);
ZEND_API int add_next_index_string(zval *arg, char *str, int duplicate);
ZEND_API int add_next_index_stringl(zval *arg, char *str, uint length, int duplicate);
ZEND_API int add_next_index_binary(zval *arg, char *str, int duplicate);
ZEND_API int add_next_index_binaryl(zval *arg, char *str, uint length, int duplicate);
ZEND_API int add_next_index_unicode(zval *arg, UChar *str, int duplicate);
ZEND_API int add_next_index_unicodel(zval *arg, UChar *str, uint length, int duplicate);
ZEND_API int add_next_index_zval(zval *arg, zval *value);
ZEND_API int add_get_assoc_string_ex(zval *arg, char *key, uint key_len, char *str, void **dest, int duplicate);
@ -305,6 +326,10 @@ ZEND_API int add_get_index_long(zval *arg, uint idx, long l, void **dest);
ZEND_API int add_get_index_double(zval *arg, uint idx, double d, void **dest);
ZEND_API int add_get_index_string(zval *arg, uint idx, char *str, void **dest, int duplicate);
ZEND_API int add_get_index_stringl(zval *arg, uint idx, char *str, uint length, void **dest, int duplicate);
ZEND_API int add_get_index_binary(zval *arg, uint idx, char *str, void **dest, int duplicate);
ZEND_API int add_get_index_binaryl(zval *arg, uint idx, char *str, uint length, void **dest, int duplicate);
ZEND_API int add_get_index_unicode(zval *arg, uint idx, UChar *str, void **dest, int duplicate);
ZEND_API int add_get_index_unicodel(zval *arg, uint idx, UChar *str, uint length, void **dest, int duplicate);
ZEND_API int add_property_long_ex(zval *arg, char *key, uint key_len, long l TSRMLS_DC);
ZEND_API int add_property_null_ex(zval *arg, char *key, uint key_len TSRMLS_DC);
@ -358,6 +383,9 @@ ZEND_API int zend_set_hash_symbol(zval *symbol, char *name, int name_length,
zend_bool is_ref, int num_symbol_tables, ...);
ZEND_API int zend_delete_global_variable(char *name, int name_len TSRMLS_DC);
ZEND_API int zend_u_delete_global_variable(zend_uchar type, void *name, int name_len TSRMLS_DC);
ZEND_API zend_class_entry* zend_get_named_class_entry(char* name, int name_length TSRMLS_DC);
ZEND_API void zend_reset_all_cv(HashTable *symbol_table TSRMLS_DC);
@ -367,14 +395,24 @@ ZEND_API ZEND_FUNCTION(display_disabled_function);
ZEND_API ZEND_FUNCTION(display_disabled_class);
END_EXTERN_C()
#define BINARY_TYPE (UG(unicode) ? IS_BINARY : IS_STRING)
#if ZEND_DEBUG
#define CHECK_ZVAL_STRING(z) \
if ((z)->value.str.val[ (z)->value.str.len ] != '\0') { zend_error(E_WARNING, "String is not zero-terminated (%s)", (z)->value.str.val); }
#define CHECK_ZVAL_STRING_REL(z) \
if ((z)->value.str.val[ (z)->value.str.len ] != '\0') { zend_error(E_WARNING, "String is not zero-terminated (%s) (source: %s:%d)", (z)->value.str.val ZEND_FILE_LINE_RELAY_CC); }
#define CHECK_ZVAL_UNICODE(z) \
if ((z)->value.ustr.val[ (z)->value.ustr.len ] != 0 ) { zend_error(E_WARNING, "String is not zero-terminated"); }
#define CHECK_ZVAL_UNICODE_REL(z) \
if ((z)->value.ustr.val[ (z)->value.ustr.len ] != 0) { zend_error(E_WARNING, "String is not zero-terminated (source: %s:%d)", ZEND_FILE_LINE_RELAY_C); }
#else
#define CHECK_ZVAL_STRING(z)
#define CHECK_ZVAL_STRING_REL(z)
#define CHECK_ZVAL_UNICODE(z)
#define CHECK_ZVAL_UNICODE_REL(z)
#endif
#define ZVAL_RESOURCE(z, l) { \
@ -415,12 +453,52 @@ END_EXTERN_C()
(z)->type = IS_STRING; \
}
#define ZVAL_UNICODE(z, u, duplicate) { \
UChar *__u=(u); \
(z)->value.ustr.len = u_strlen(__u); \
(z)->value.ustr.val = (duplicate?eustrndup(__u, (z)->value.ustr.len):__u); \
(z)->type = IS_UNICODE; \
}
#define ZVAL_UNICODEL(z, u, l, duplicate) { \
UChar *__u=(u); int32_t __l=l; \
(z)->value.ustr.len = __l; \
(z)->value.ustr.val = (duplicate?eustrndup(__u, __l):__u); \
(z)->type = IS_UNICODE; \
}
#define ZVAL_BINARY(z, s, duplicate) { \
char *__s=(s); \
(z)->value.str.len = strlen(__s); \
(z)->value.str.val = (duplicate?estrndup(__s, (z)->value.str.len):__s); \
(z)->type = BINARY_TYPE; \
}
#define ZVAL_BINARYL(z, s, l, duplicate) { \
char *__s=(s); int __l=l; \
(z)->value.str.len = __l; \
(z)->value.str.val = (duplicate?estrndup(__s, __l):__s); \
(z)->type = BINARY_TYPE; \
}
#define ZVAL_EMPTY_STRING(z) { \
(z)->value.str.len = 0; \
(z)->value.str.val = STR_EMPTY_ALLOC(); \
(z)->type = IS_STRING; \
}
#define ZVAL_EMPTY_UNICODE(z) { \
(z)->value.ustr.len = 0; \
(z)->value.ustr.val = USTR_MAKE(""); \
(z)->type = IS_UNICODE; \
}
#define ZVAL_EMPTY_BINARY(z) { \
(z)->value.str.len = 0; \
(z)->value.str.val = STR_EMPTY_ALLOC(); \
(z)->type = BINARY_TYPE; \
}
#define ZVAL_ZVAL(z, zv, copy, dtor) { \
int is_ref, refcount; \
is_ref = (z)->is_ref; \
@ -450,9 +528,32 @@ END_EXTERN_C()
#define RETVAL_STRING(s, duplicate) ZVAL_STRING(return_value, s, duplicate)
#define RETVAL_STRINGL(s, l, duplicate) ZVAL_STRINGL(return_value, s, l, duplicate)
#define RETVAL_EMPTY_STRING() ZVAL_EMPTY_STRING(return_value)
#define RETVAL_UNICODE(u, duplicate) ZVAL_UNICODE(return_value, u, duplicate)
#define RETVAL_UNICODEL(u, l, duplicate) ZVAL_UNICODEL(return_value, u, l, duplicate)
#define RETVAL_EMPTY_UNICODE() ZVAL_EMPTY_UNICODE(return_value)
#define RETVAL_BINARY(s, duplicate) ZVAL_BINARY(return_value, s, duplicate)
#define RETVAL_BINARYL(s, l, duplicate) ZVAL_BINARYL(return_value, s, l, duplicate)
#define RETVAL_EMPTY_BINARY() ZVAL_EMPTY_BINARY(return_value)
#define RETVAL_ZVAL(zv, copy, dtor) ZVAL_ZVAL(return_value, zv, copy, dtor)
#define RETVAL_FALSE ZVAL_BOOL(return_value, 0)
#define RETVAL_TRUE ZVAL_BOOL(return_value, 1)
#define RETVAL_TEXT(t, duplicate) \
do { \
if (UG(unicode)) { \
RETVAL_UNICODE(t, duplicate); \
} else { \
RETVAL_STRING(t, duplicate); \
} \
} while (0);
#define RETVAL_TEXTL(t, l, duplicate) \
do { \
if (UG(unicode)) { \
RETVAL_UNICODEL(t, l, duplicate); \
} else { \
RETVAL_STRINGL(t, l, duplicate); \
} \
} while (0);
#define RETURN_RESOURCE(l) { RETVAL_RESOURCE(l); return; }
#define RETURN_BOOL(b) { RETVAL_BOOL(b); return; }
@ -462,9 +563,17 @@ END_EXTERN_C()
#define RETURN_STRING(s, duplicate) { RETVAL_STRING(s, duplicate); return; }
#define RETURN_STRINGL(s, l, duplicate) { RETVAL_STRINGL(s, l, duplicate); return; }
#define RETURN_EMPTY_STRING() { RETVAL_EMPTY_STRING(); return; }
#define RETURN_UNICODE(u, duplicate) { RETVAL_UNICODE(u, duplicate); return; }
#define RETURN_UNICODEL(u, l, duplicate) { RETVAL_UNICODEL(u, l, duplicate); return; }
#define RETURN_EMPTY_UNICODE() { RETVAL_EMPTY_UNICODE(); return; }
#define RETURN_BINARY(s, duplicate) { RETVAL_BINARY(s, duplicate); return; }
#define RETURN_BINARYL(s, l, duplicate) { RETVAL_BINARYL(s, l, duplicate); return; }
#define RETURN_EMPTY_BINARY() { RETVAL_EMPTY_BINARY(); return; }
#define RETURN_ZVAL(zv, copy, dtor) { RETVAL_ZVAL(zv, copy, dtor); return; }
#define RETURN_FALSE { RETVAL_FALSE; return; }
#define RETURN_TRUE { RETVAL_TRUE; return; }
#define RETURN_TEXT(t, duplicate) { RETVAL_TEXT(t, duplicate); return; }
#define RETURN_TEXTL(t, l, duplicate) { RETVAL_TEXTL(t, l, duplicate); return; }
#define SET_VAR_STRING(n, v) { \
{ \

View File

@ -23,6 +23,7 @@
#include "zend_alloc.h"
#include "zend_globals.h"
#include "zend_fast_cache.h"
#include "zend_unicode.h"
#ifdef HAVE_SIGNAL_H
# include <signal.h>
#endif
@ -409,6 +410,24 @@ ZEND_API char *_estrdup(const char *s ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
return p;
}
ZEND_API UChar *_eustrdup(const UChar *s ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
{
int length;
UChar *p;
length = u_strlen(s)+1;
HANDLE_BLOCK_INTERRUPTIONS();
p = (UChar *) _emalloc(sizeof(UChar) * length ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
if (!p) {
HANDLE_UNBLOCK_INTERRUPTIONS();
return (UChar *)NULL;
}
HANDLE_UNBLOCK_INTERRUPTIONS();
u_memcpy(p, s, length);
return p;
}
ZEND_API char *_estrndup(const char *s, uint length ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
{
char *p;
@ -426,6 +445,23 @@ ZEND_API char *_estrndup(const char *s, uint length ZEND_FILE_LINE_DC ZEND_FILE_
}
ZEND_API UChar *_eustrndup(const UChar *s, int32_t length ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
{
UChar *p;
HANDLE_BLOCK_INTERRUPTIONS();
p = (UChar *) _emalloc(sizeof(UChar) * (length+1) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
if (!p) {
HANDLE_UNBLOCK_INTERRUPTIONS();
return (UChar *)NULL;
}
HANDLE_UNBLOCK_INTERRUPTIONS();
memcpy(p, s, length * sizeof(UChar));
p[length] = 0;
return p;
}
ZEND_API char *zend_strndup(const char *s, uint length)
{
char *p;
@ -441,6 +477,21 @@ ZEND_API char *zend_strndup(const char *s, uint length)
return p;
}
ZEND_API UChar *zend_ustrndup(const UChar *s, uint length)
{
UChar *p;
p = (UChar *) malloc(UBYTES(length+1));
if (!p) {
return (UChar *)NULL;
}
if (length) {
memcpy(p, s, UBYTES(length));
}
p[length] = 0;
return p;
}
ZEND_API int zend_set_memory_limit(unsigned int memory_limit)
{

View File

@ -28,6 +28,7 @@
#include "zend_globals_macros.h"
#include "zend_mm.h"
#include <unicode/utypes.h>
#define MEM_BLOCK_START_MAGIC 0x7312F8DCL
#define MEM_BLOCK_END_MAGIC 0x2A8FCC84L
@ -75,6 +76,7 @@ typedef union _align_test {
BEGIN_EXTERN_C()
ZEND_API char *zend_strndup(const char *s, unsigned int length) ZEND_ATTRIBUTE_MALLOC;
ZEND_API UChar *zend_ustrndup(const UChar *s, uint length) ZEND_ATTRIBUTE_MALLOC;
ZEND_API void *_emalloc(size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC;
ZEND_API void *_safe_emalloc(size_t nmemb, size_t size, size_t offset ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC;
@ -84,6 +86,8 @@ ZEND_API void *_ecalloc(size_t nmemb, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LI
ZEND_API void *_erealloc(void *ptr, size_t size, int allow_failure ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
ZEND_API char *_estrdup(const char *s ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC;
ZEND_API char *_estrndup(const char *s, unsigned int length ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC;
ZEND_API UChar *_eustrdup(const UChar *s ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC;
ZEND_API UChar *_eustrndup(const UChar *s, int32_t length ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC;
#if USE_ZEND_ALLOC
@ -96,16 +100,23 @@ ZEND_API char *_estrndup(const char *s, unsigned int length ZEND_FILE_LINE_DC ZE
#define erealloc_recoverable(ptr, size) _erealloc((ptr), (size), 1 ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
#define estrdup(s) _estrdup((s) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
#define estrndup(s, length) _estrndup((s), (length) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
#define eumalloc(size) (UChar*)_emalloc(UBYTES(size) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
#define eurealloc(ptr, size) (UChar*)_erealloc((ptr), UBYTES(size), 0 ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
#define eustrndup(s, length) _eustrndup((s), (length) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
#define eustrdup(s) _eustrdup((s) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
/* Relay wrapper macros */
#define emalloc_rel(size) _emalloc((size) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
#define safe_emalloc_rel(nmemb, size, offset) _safe_emalloc((nmemb), (size), (offset) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
#define efree_rel(ptr) _efree((ptr) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
#define ecalloc_rel(nmemb, size) _ecalloc((nmemb), (size) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
#define erealloc_rel(ptr, size) _erealloc((ptr), (size), 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
#define erealloc_rel(ptr, size) _erealloc((ptr), (size), 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
#define erealloc_recoverable_rel(ptr, size) _erealloc((ptr), (size), 1 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
#define estrdup_rel(s) _estrdup((s) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
#define estrndup_rel(s, length) _estrndup((s), (length) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
#define eumalloc_rel(size) (UChar*)_emalloc(UBYTES(size) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
#define eurealloc_rel(ptr, size) (UChar*)_erealloc((ptr), UBYTES(size), 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
#define eustrndup_rel(s, length) _eustrndup((s), (length) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
/* Selective persistent/non persistent allocation macros */
#define pemalloc(size, persistent) ((persistent)?malloc(size):emalloc(size))
@ -115,6 +126,8 @@ ZEND_API char *_estrndup(const char *s, unsigned int length ZEND_FILE_LINE_DC ZE
#define perealloc(ptr, size, persistent) ((persistent)?realloc((ptr), (size)):erealloc((ptr), (size)))
#define perealloc_recoverable(ptr, size, persistent) ((persistent)?realloc((ptr), (size)):erealloc_recoverable((ptr), (size)))
#define pestrdup(s, persistent) ((persistent)?strdup(s):estrdup(s))
#define peumalloc(size, persistent) ((persistent)?malloc(UBYTES(size)):eumalloc(size))
#define peurealloc(ptr, size, persistent) ((persistent)?realloc((ptr),UBYTES(size)):eurealloc((ptr),size))
#define pemalloc_rel(size, persistent) ((persistent)?malloc(size):emalloc_rel(size))
#define pefree_rel(ptr, persistent) ((persistent)?free(ptr):efree_rel(ptr))

View File

@ -279,8 +279,27 @@ ZEND_NAMED_FUNCTION(zend_if_strlen)
if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &str) == FAILURE) {
ZEND_WRONG_PARAM_COUNT();
}
convert_to_string_ex(str);
RETVAL_LONG((*str)->value.str.len);
switch (Z_TYPE_PP(str)) {
case IS_UNICODE:
RETVAL_LONG(u_countChar32(Z_USTRVAL_PP(str), Z_USTRLEN_PP(str)));
break;
case IS_STRING:
case IS_BINARY:
RETVAL_LONG(Z_STRLEN_PP(str));
break;
default:
if (UG(unicode)) {
convert_to_unicode_ex(str);
RETVAL_LONG(Z_USTRLEN_PP(str));
} else {
convert_to_string_ex(str);
RETVAL_LONG(Z_STRLEN_PP(str));
}
break;
}
}
/* }}} */
@ -396,6 +415,12 @@ ZEND_FUNCTION(each)
case HASH_KEY_IS_STRING:
add_get_index_stringl(return_value, 0, string_key, string_key_len-1, (void **) &inserted_pointer, 0);
break;
case HASH_KEY_IS_BINARY:
add_get_index_binaryl(return_value, 0, string_key, string_key_len-1, (void **) &inserted_pointer, 0);
break;
case HASH_KEY_IS_UNICODE:
add_get_index_unicodel(return_value, 0, (UChar*)string_key, string_key_len-1, (void **) &inserted_pointer, 0);
break;
case HASH_KEY_IS_LONG:
add_get_index_long(return_value, 0, num_key, (void **) &inserted_pointer);
break;
@ -470,6 +495,8 @@ ZEND_FUNCTION(define)
case IS_LONG:
case IS_DOUBLE:
case IS_STRING:
case IS_BINARY:
case IS_UNICODE:
case IS_BOOL:
case IS_RESOURCE:
case IS_NULL:
@ -479,15 +506,22 @@ ZEND_FUNCTION(define)
RETURN_FALSE;
break;
}
convert_to_string_ex(var);
if (Z_TYPE_PP(var) != IS_STRING && Z_TYPE_PP(var) != IS_UNICODE) {
convert_to_string_ex(var);
}
c.value = **val;
zval_copy_ctor(&c.value);
c.flags = case_sensitive; /* non persistent */
c.name = zend_strndup((*var)->value.str.val, (*var)->value.str.len);
c.name_len = (*var)->value.str.len+1;
if (Z_TYPE_PP(var) == IS_UNICODE) {
c.name = (char*)zend_ustrndup(Z_USTRVAL_PP(var), Z_USTRLEN_PP(var));
} else {
c.name = zend_strndup(Z_STRVAL_PP(var), Z_STRLEN_PP(var));
}
c.name_len = Z_UNILEN_PP(var)+1;
c.module_number = PHP_USER_CONSTANT;
if (zend_register_constant(&c TSRMLS_CC) == SUCCESS) {
if (zend_u_register_constant(Z_TYPE_PP(var), &c TSRMLS_CC) == SUCCESS) {
RETURN_TRUE;
} else {
RETURN_FALSE;
@ -507,8 +541,8 @@ ZEND_FUNCTION(defined)
ZEND_WRONG_PARAM_COUNT();
}
convert_to_string_ex(var);
if (zend_get_constant((*var)->value.str.val, (*var)->value.str.len, &c TSRMLS_CC)) {
convert_to_text_ex(var);
if (zend_get_constant(Z_UNIVAL_PP(var), Z_UNILEN_PP(var), &c TSRMLS_CC)) {
zval_dtor(&c);
RETURN_TRUE;
} else {
@ -523,13 +557,17 @@ ZEND_FUNCTION(defined)
ZEND_FUNCTION(get_class)
{
zval **arg;
char *name = "";
char *name = EMPTY_STR;
zend_uint name_len = 0;
int dup;
if (!ZEND_NUM_ARGS()) {
if (EG(scope)) {
RETURN_STRINGL(EG(scope)->name, EG(scope)->name_length, 1);
if (UG(unicode)) {
RETURN_UNICODEL((UChar*)EG(scope)->name, EG(scope)->name_length, 1);
} else {
RETURN_STRINGL(EG(scope)->name, EG(scope)->name_length, 1);
}
} else {
zend_error(E_ERROR, "get_class() called without object from outside a class");
}
@ -543,7 +581,11 @@ ZEND_FUNCTION(get_class)
dup = zend_get_object_classname(*arg, &name, &name_len TSRMLS_CC);
RETURN_STRINGL(name, name_len, dup);
if (UG(unicode)) {
RETURN_UNICODEL((UChar*)name, name_len, 0);
} else {
RETURN_STRINGL(name, name_len, 0);
}
}
/* }}} */
@ -560,7 +602,11 @@ ZEND_FUNCTION(get_parent_class)
if (!ZEND_NUM_ARGS()) {
ce = EG(scope);
if (ce && ce->parent) {
RETURN_STRINGL(ce->parent->name, ce->parent->name_length, 1);
if (UG(unicode)) {
RETURN_UNICODEL((UChar*)ce->parent->name, ce->parent->name_length, 1);
} else {
RETURN_STRINGL(ce->parent->name, ce->parent->name_length, 1);
}
} else {
RETURN_FALSE;
}
@ -572,20 +618,28 @@ ZEND_FUNCTION(get_parent_class)
if (Z_TYPE_PP(arg) == IS_OBJECT) {
if (Z_OBJ_HT_PP(arg)->get_class_name
&& Z_OBJ_HT_PP(arg)->get_class_name(*arg, &name, &name_length, 1 TSRMLS_CC) == SUCCESS) {
RETURN_STRINGL(name, name_length, 0);
if (UG(unicode)) {
RETURN_UNICODEL((UChar*)name, name_length, 0);
} else{
RETURN_STRINGL(name, name_length, 0);
}
} else {
ce = zend_get_class_entry(*arg TSRMLS_CC);
}
} else if (Z_TYPE_PP(arg) == IS_STRING) {
} else if (Z_TYPE_PP(arg) == IS_STRING || Z_TYPE_PP(arg) == IS_UNICODE) {
zend_class_entry **pce;
if (zend_lookup_class(Z_STRVAL_PP(arg), Z_STRLEN_PP(arg), &pce TSRMLS_CC) == SUCCESS) {
if (zend_u_lookup_class(Z_TYPE_PP(arg), Z_UNIVAL_PP(arg), Z_UNILEN_PP(arg), &pce TSRMLS_CC) == SUCCESS) {
ce = *pce;
}
}
if (ce && ce->parent) {
RETURN_STRINGL(ce->parent->name, ce->parent->name_length, 1);
if (UG(unicode)) {
RETURN_UNICODEL((UChar*)ce->parent->name, ce->parent->name_length, 1);
} else {
RETURN_STRINGL(ce->parent->name, ce->parent->name_length, 1);
}
} else {
RETURN_FALSE;
}
@ -606,7 +660,7 @@ static void is_a_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool only_subclass)
if (only_subclass && Z_TYPE_PP(obj) == IS_STRING) {
zend_class_entry **the_ce;
if (zend_lookup_class(Z_STRVAL_PP(obj), Z_STRLEN_PP(obj), &the_ce TSRMLS_CC) == FAILURE) {
if (zend_u_lookup_class(Z_TYPE_PP(obj), Z_UNIVAL_PP(obj), Z_UNILEN_PP(obj), &the_ce TSRMLS_CC) == FAILURE) {
zend_error(E_WARNING, "Unknown class passed as parameter");
RETURN_FALSE;
}
@ -624,7 +678,7 @@ static void is_a_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool only_subclass)
convert_to_string_ex(class_name);
if (zend_lookup_class(Z_STRVAL_PP(class_name), Z_STRLEN_PP(class_name), &ce TSRMLS_CC) == FAILURE) {
if (zend_u_lookup_class(Z_TYPE_PP(class_name), Z_UNIVAL_PP(class_name), Z_UNILEN_PP(class_name), &ce TSRMLS_CC) == FAILURE) {
retval = 0;
} else {
if (only_subclass) {
@ -686,8 +740,9 @@ static void add_class_vars(zend_class_entry *ce, HashTable *properties, zval *re
uint key_len;
ulong num_index;
zval *prop_copy;
zend_uchar key_type;
zend_hash_get_current_key_ex(properties, &key, &key_len, &num_index, 0, &pos);
key_type = zend_hash_get_current_key_ex(properties, &key, &key_len, &num_index, 0, &pos);
zend_hash_move_forward_ex(properties, &pos);
zend_unmangle_property_name(key, &class_name, &prop_name);
if (class_name) {
@ -712,7 +767,7 @@ static void add_class_vars(zend_class_entry *ce, HashTable *properties, zval *re
zval_update_constant(&prop_copy, 0 TSRMLS_CC);
}
add_assoc_zval(return_value, prop_name, prop_copy);
add_u_assoc_zval(return_value, key_type==HASH_KEY_IS_UNICODE?IS_UNICODE:IS_STRING, prop_name, prop_copy);
}
}
}
@ -725,13 +780,14 @@ ZEND_FUNCTION(get_class_vars)
{
char *class_name;
int class_name_len;
zend_uchar type;
zend_class_entry **pce;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &class_name, &class_name_len) == FAILURE) {
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "t", &class_name, &class_name_len, &type) == FAILURE) {
return;
}
if (zend_lookup_class(class_name, class_name_len, &pce TSRMLS_CC) == FAILURE) {
if (zend_u_lookup_class(type, class_name, class_name_len, &pce TSRMLS_CC) == FAILURE) {
RETURN_FALSE;
} else {
array_init(return_value);
@ -774,17 +830,19 @@ ZEND_FUNCTION(get_object_vars)
zend_hash_internal_pointer_reset_ex(properties, &pos);
while (zend_hash_get_current_data_ex(properties, (void **) &value, &pos) == SUCCESS) {
if (zend_hash_get_current_key_ex(properties, &key, &key_len, &num_index, 0, &pos) == HASH_KEY_IS_STRING) {
if (key[0]) {
if (zend_hash_get_current_key_ex(properties, &key, &key_len, &num_index, 0, &pos) == (UG(unicode)?HASH_KEY_IS_UNICODE:HASH_KEY_IS_STRING)) {
zend_u_unmangle_property_name(UG(unicode)?IS_UNICODE:IS_STRING, key, &class_name, &prop_name);
if (class_name == NULL) {
/* Not separating references */
(*value)->refcount++;
add_assoc_zval_ex(return_value, key, key_len, *value);
add_u_assoc_zval_ex(return_value, UG(unicode)?IS_UNICODE:IS_STRING, key, key_len, *value);
} else if (instanceof) {
zend_unmangle_property_name(key, &class_name, &prop_name);
if (!memcmp(class_name, "*", 2) || (Z_OBJCE_P(EG(This)) == Z_OBJCE_PP(obj) && !strcmp(Z_OBJCE_P(EG(This))->name, class_name))) {
if (class_name[0] == '*' ||
(Z_OBJCE_P(EG(This)) == Z_OBJCE_PP(obj) &&
UG(unicode)?!u_strcmp((UChar*)Z_OBJCE_P(EG(This))->name, (UChar*)class_name):!strcmp(Z_OBJCE_P(EG(This))->name, class_name))) {
/* Not separating references */
(*value)->refcount++;
add_assoc_zval_ex(return_value, prop_name, strlen(prop_name)+1, *value);
add_u_assoc_zval(return_value, UG(unicode)?IS_UNICODE:IS_STRING, prop_name, *value);
}
}
}
@ -814,8 +872,8 @@ ZEND_FUNCTION(get_class_methods)
RETURN_FALSE;
}
ce = Z_OBJCE_PP(class);
} else if (Z_TYPE_PP(class) == IS_STRING) {
if (zend_lookup_class(Z_STRVAL_PP(class), Z_STRLEN_PP(class), &pce TSRMLS_CC) == SUCCESS) {
} else if (Z_TYPE_PP(class) == IS_STRING || Z_TYPE_PP(class) == IS_UNICODE) {
if (zend_u_lookup_class(Z_TYPE_PP(class), Z_UNIVAL_PP(class), Z_UNILEN_PP(class), &pce TSRMLS_CC) == SUCCESS) {
ce = *pce;
}
}
@ -835,7 +893,11 @@ ZEND_FUNCTION(get_class_methods)
|| ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) &&
EG(scope) == mptr->common.scope)))) {
MAKE_STD_ZVAL(method_name);
ZVAL_STRING(method_name, mptr->common.function_name, 1);
if (UG(unicode)) {
ZVAL_UNICODE(method_name, (UChar*)mptr->common.function_name, 1);
} else {
ZVAL_STRING(method_name, mptr->common.function_name, 1);
}
zend_hash_next_index_insert(return_value->value.ht, &method_name, sizeof(zval *), NULL);
}
zend_hash_move_forward_ex(&ce->function_table, &pos);
@ -849,6 +911,7 @@ ZEND_FUNCTION(get_class_methods)
ZEND_FUNCTION(method_exists)
{
zval **klass, **method_name;
unsigned int lcname_len;
char *lcname;
zend_class_entry * ce, **pce;
@ -867,8 +930,8 @@ ZEND_FUNCTION(method_exists)
}
convert_to_string_ex(method_name);
lcname = zend_str_tolower_dup(Z_STRVAL_PP(method_name), Z_STRLEN_PP(method_name));
if (zend_hash_exists(&ce->function_table, lcname, Z_STRLEN_PP(method_name)+1)) {
lcname = zend_u_str_case_fold(Z_TYPE_PP(method_name), Z_UNIVAL_PP(method_name), Z_UNILEN_PP(method_name), 1, &lcname_len);
if (zend_u_hash_exists(&ce->function_table, Z_TYPE_PP(method_name), lcname, lcname_len+1)) {
efree(lcname);
RETURN_TRUE;
} else {
@ -962,26 +1025,26 @@ ZEND_FUNCTION(property_exists)
Checks if the class exists */
ZEND_FUNCTION(class_exists)
{
char *class_name, *lc_name;
unsigned int lc_name_len;
void *class_name, *lc_name;
zend_class_entry **ce;
int class_name_len;
zend_bool autoload = 1;
zend_uchar type;
int found;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &class_name, &class_name_len, &autoload) == FAILURE) {
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "t|b", &class_name, &class_name_len, &type, &autoload) == FAILURE) {
return;
}
if (!autoload) {
lc_name = do_alloca(class_name_len + 1);
zend_str_tolower_copy(lc_name, class_name, class_name_len);
found = zend_hash_find(EG(class_table), lc_name, class_name_len+1, (void **) &ce);
free_alloca(lc_name);
lc_name = zend_u_str_case_fold(type, class_name, class_name_len, 1, &lc_name_len);
found = zend_u_hash_find(EG(class_table), type, lc_name, lc_name_len+1, (void **) &ce);
efree(lc_name);
RETURN_BOOL(found == SUCCESS && !((*ce)->ce_flags & ZEND_ACC_INTERFACE));
}
if (zend_lookup_class(class_name, class_name_len, &ce TSRMLS_CC) == SUCCESS) {
if (zend_u_lookup_class(type, class_name, class_name_len, &ce TSRMLS_CC) == SUCCESS) {
RETURN_BOOL(((*ce)->ce_flags & ZEND_ACC_INTERFACE) == 0);
} else {
RETURN_FALSE;
@ -993,26 +1056,26 @@ ZEND_FUNCTION(class_exists)
Checks if the class exists */
ZEND_FUNCTION(interface_exists)
{
char *iface_name, *lc_name;
unsigned int lc_name_len;
void *iface_name, *lc_name;
zend_class_entry **ce;
int iface_name_len;
zend_uchar type;
zend_bool autoload = 1;
int found;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &iface_name, &iface_name_len, &autoload) == FAILURE) {
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "t|b", &iface_name, &iface_name_len, &type, &autoload) == FAILURE) {
return;
}
if (!autoload) {
lc_name = do_alloca(iface_name_len + 1);
zend_str_tolower_copy(lc_name, iface_name, iface_name_len);
found = zend_hash_find(EG(class_table), lc_name, iface_name_len+1, (void **) &ce);
free_alloca(lc_name);
lc_name = zend_u_str_case_fold(type, iface_name, iface_name_len, 1, &lc_name_len);
found = zend_u_hash_find(EG(class_table), type, lc_name, lc_name_len+1, (void **) &ce);
efree(lc_name);
RETURN_BOOL(found == SUCCESS && (*ce)->ce_flags & ZEND_ACC_INTERFACE);
}
if (zend_lookup_class(iface_name, iface_name_len, &ce TSRMLS_CC) == SUCCESS) {
if (zend_u_lookup_class(type, iface_name, iface_name_len, &ce TSRMLS_CC) == SUCCESS) {
RETURN_BOOL(((*ce)->ce_flags & ZEND_ACC_INTERFACE) > 0);
} else {
RETURN_FALSE;
@ -1027,6 +1090,7 @@ ZEND_FUNCTION(function_exists)
{
zval **function_name;
zend_function *func;
unsigned int lcname_len;
char *lcname;
zend_bool retval;
@ -1034,9 +1098,9 @@ ZEND_FUNCTION(function_exists)
ZEND_WRONG_PARAM_COUNT();
}
convert_to_string_ex(function_name);
lcname = zend_str_tolower_dup((*function_name)->value.str.val, (*function_name)->value.str.len);
lcname = zend_u_str_case_fold(Z_TYPE_PP(function_name), Z_UNIVAL_PP(function_name), Z_UNILEN_PP(function_name), 1, &lcname_len);
retval = (zend_hash_find(EG(function_table), lcname, (*function_name)->value.str.len+1, (void **)&func) == SUCCESS);
retval = (zend_u_hash_find(EG(function_table), Z_TYPE_PP(function_name), lcname, lcname_len+1, (void **)&func) == SUCCESS);
efree(lcname);
@ -1283,10 +1347,17 @@ static int copy_class_or_interface_name(zend_class_entry **pce, int num_args, va
zend_uint comply = va_arg(args, zend_uint);
zend_uint comply_mask = (comply)? mask:0;
zend_class_entry *ce = *pce;
TSRMLS_FETCH();
if ((hash_key->nKeyLength==0 || hash_key->arKey[0]!=0)
if ((hash_key->nKeyLength==0 ||
(hash_key->type == IS_UNICODE && hash_key->u.unicode[0] != 0) ||
(hash_key->type == IS_STRING && hash_key->u.string[0] != 0))
&& (comply_mask == (ce->ce_flags & mask))) {
add_next_index_stringl(array, ce->name, ce->name_length, 1);
if (UG(unicode)) {
add_next_index_unicodel(array, (UChar*)ce->name, ce->name_length, 1);
} else {
add_next_index_stringl(array, ce->name, ce->name_length, 1);
}
}
return ZEND_HASH_APPLY_KEEP;
}
@ -1330,14 +1401,29 @@ static int copy_function_name(zend_function *func, int num_args, va_list args, z
zval *internal_ar = va_arg(args, zval *),
*user_ar = va_arg(args, zval *);
if (hash_key->nKeyLength == 0 || hash_key->arKey[0] == 0) {
if (hash_key->nKeyLength == 0 ||
hash_key->type == IS_BINARY ||
(hash_key->type == IS_UNICODE && hash_key->u.unicode[0] == 0) ||
(hash_key->type == IS_STRING && hash_key->u.unicode[0] == 0)) {
return 0;
}
if (func->type == ZEND_INTERNAL_FUNCTION) {
add_next_index_stringl(internal_ar, hash_key->arKey, hash_key->nKeyLength-1, 1);
if (hash_key->type == IS_STRING) {
add_next_index_stringl(internal_ar, hash_key->u.string, hash_key->nKeyLength-1, 1);
} else if (hash_key->type == IS_BINARY) {
add_next_index_binaryl(internal_ar, hash_key->u.string, hash_key->nKeyLength-1, 1);
} else {
add_next_index_unicodel(internal_ar, hash_key->u.unicode, hash_key->nKeyLength-1, 1);
}
} else if (func->type == ZEND_USER_FUNCTION) {
add_next_index_stringl(user_ar, hash_key->arKey, hash_key->nKeyLength-1, 1);
if (hash_key->type == IS_STRING) {
add_next_index_stringl(user_ar, hash_key->u.string, hash_key->nKeyLength-1, 1);
} else if (hash_key->type == IS_BINARY) {
add_next_index_binaryl(user_ar, hash_key->u.string, hash_key->nKeyLength-1, 1);
} else {
add_next_index_unicodel(user_ar, hash_key->u.unicode, hash_key->nKeyLength-1, 1);
}
}
return 0;
@ -1431,7 +1517,7 @@ ZEND_FUNCTION(create_function)
RETURN_FALSE;
}
new_function = *func;
function_add_ref(&new_function);
function_add_ref(&new_function TSRMLS_CC);
function_name = (char *) emalloc(sizeof("0lambda_")+MAX_LENGTH_OF_LONG);
@ -1507,7 +1593,7 @@ static int add_constant_info(zend_constant *constant, void *arg TSRMLS_DC)
*const_val = constant->value;
zval_copy_ctor(const_val);
INIT_PZVAL(const_val);
add_assoc_zval_ex(name_array, constant->name, constant->name_len, const_val);
add_u_assoc_zval_ex(name_array, UG(unicode)?IS_UNICODE:IS_STRING, constant->name, constant->name_len, const_val);
return 0;
}
@ -1695,6 +1781,7 @@ ZEND_FUNCTION(debug_print_backtrace)
while (ptr) {
char *free_class_name = NULL;
int function_name_string = 1;
class_name = call_type = NULL;
arg_array = NULL;
@ -1721,6 +1808,7 @@ ZEND_FUNCTION(debug_print_backtrace)
function_name = ptr->function_state.function->common.function_name;
if (function_name) {
function_name_string = !UG(unicode);
if (ptr->object) {
if (ptr->function_state.function->common.scope) {
class_name = ptr->function_state.function->common.scope->name;
@ -1791,10 +1879,18 @@ ZEND_FUNCTION(debug_print_backtrace)
}
zend_printf("#%-2d ", indent);
if (class_name) {
ZEND_PUTS(class_name);
if (UG(unicode)) {
zend_printf("%r(", class_name);
} else {
ZEND_PUTS(class_name);
}
ZEND_PUTS(call_type);
}
zend_printf("%s(", function_name?function_name:"main");
if (function_name_string) {
zend_printf("%s(", function_name?function_name:"main");
} else {
zend_printf("%r(", function_name);
}
if (arg_array) {
debug_print_backtrace_args(arg_array TSRMLS_CC);
zval_ptr_dtor(&arg_array);
@ -1898,22 +1994,37 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last TSRML
function_name = ptr->function_state.function->common.function_name;
if (function_name) {
add_assoc_string_ex(stack_frame, "function", sizeof("function"), function_name, 1);
if (UG(unicode)) {
add_assoc_unicode_ex(stack_frame, "function", sizeof("function"), function_name, 1);
} else {
add_assoc_string_ex(stack_frame, "function", sizeof("function"), function_name, 1);
}
if (ptr->object && Z_TYPE_P(ptr->object) == IS_OBJECT) {
if (ptr->function_state.function->common.scope) {
add_assoc_string_ex(stack_frame, "class", sizeof("class"), ptr->function_state.function->common.scope->name, 1);
if (UG(unicode)) {
add_assoc_unicode_ex(stack_frame, "class", sizeof("class"), ptr->function_state.function->common.scope->name, 1);
} else {
add_assoc_string_ex(stack_frame, "class", sizeof("class"), ptr->function_state.function->common.scope->name, 1);
}
} else {
zend_uint class_name_len;
int dup;
dup = zend_get_object_classname(ptr->object, &class_name, &class_name_len TSRMLS_CC);
add_assoc_string_ex(stack_frame, "class", sizeof("class"), class_name, dup);
if (UG(unicode)) {
add_assoc_unicode_ex(stack_frame, "class", sizeof("class"), class_name, dup);
} else {
add_assoc_string_ex(stack_frame, "class", sizeof("class"), class_name, dup);
}
}
add_assoc_string_ex(stack_frame, "type", sizeof("type"), "->", 1);
} else if (ptr->function_state.function->common.scope) {
add_assoc_string_ex(stack_frame, "class", sizeof("class"), ptr->function_state.function->common.scope->name, 1);
if (UG(unicode)) {
add_assoc_unicode_ex(stack_frame, "class", sizeof("class"), ptr->function_state.function->common.scope->name, 1);
} else {
add_assoc_string_ex(stack_frame, "class", sizeof("class"), ptr->function_state.function->common.scope->name, 1);
}
add_assoc_string_ex(stack_frame, "type", sizeof("type"), "::", 1);
}

File diff suppressed because it is too large Load Diff

View File

@ -237,7 +237,7 @@ typedef struct _zend_internal_function {
void (*handler)(INTERNAL_FUNCTION_PARAMETERS);
} zend_internal_function;
#define ZEND_FN_SCOPE_NAME(function) ((function) && (function)->common.scope ? (function)->common.scope->name : "")
#define ZEND_FN_SCOPE_NAME(function) ((function) && (function)->common.scope ? (function)->common.scope->name : EMPTY_STR)
typedef union _zend_function {
zend_uchar type; /* MUST be the first element of this struct! */
@ -329,6 +329,10 @@ ZEND_API int zend_get_scanned_file_offset(TSRMLS_D);
ZEND_API char* zend_get_compiled_variable_name(zend_op_array *op_array, zend_uint var, int* name_len);
ZEND_API int zend_prepare_scanner_converters(const char *onetime_encoding, int run_time TSRMLS_DC);
ZEND_API int32_t zend_convert_scanner_output(UChar **target, int32_t *target_len, const char *source, int32_t source_len, UErrorCode *status TSRMLS_DC);
int zend_unicode_yyinput(zend_file_handle *file_handle, char *buf, size_t len TSRMLS_DC);
#ifdef ZTS
const char *zend_get_zendtext(TSRMLS_D);
int zend_get_zendleng(TSRMLS_D);
@ -352,7 +356,7 @@ void fetch_array_dim(znode *result, znode *parent, znode *dim TSRMLS_DC);
void fetch_string_offset(znode *result, znode *parent, znode *offset TSRMLS_DC);
void zend_do_fetch_static_member(znode *result, znode *class_znode TSRMLS_DC);
void zend_do_print(znode *result, znode *arg TSRMLS_DC);
void zend_do_echo(znode *arg TSRMLS_DC);
void zend_do_echo(znode *arg, zend_bool inline_html TSRMLS_DC);
typedef int (*unary_op_type)(zval *, zval *);
ZEND_API unary_op_type get_unary_op(int opcode);
ZEND_API void *get_binary_op(int opcode);
@ -497,7 +501,9 @@ void zend_do_ticks(TSRMLS_D);
void zend_do_abstract_method(znode *function_name, znode *modifiers, znode *body TSRMLS_DC);
ZEND_API void function_add_ref(zend_function *function);
ZEND_API void function_add_ref(zend_function *function TSRMLS_DC);
void zend_do_normalization(znode *result, znode *str TSRMLS_DC);
#define INITIAL_OP_ARRAY_SIZE 64
@ -523,6 +529,10 @@ void zend_class_add_ref(zend_class_entry **ce);
ZEND_API void zend_mangle_property_name(char **dest, int *dest_length, char *src1, int src1_length, char *src2, int src2_length, int internal);
ZEND_API void zend_unmangle_property_name(char *mangled_property, char **prop_name, char **class_name);
ZEND_API void zend_u_mangle_property_name(char **dest, int *dest_length, zend_uchar type, char *src1, int src1_length, char *src2, int src2_length, int internal);
ZEND_API void zend_u_unmangle_property_name(zend_uchar type, char *mangled_property, char **prop_name, char **class_name);
#define ZEND_FUNCTION_DTOR (void (*)(void *)) zend_function_dtor
#define ZEND_CLASS_DTOR (void (*)(void *)) destroy_zend_class
@ -539,7 +549,7 @@ void zend_do_mark_last_catch(znode *first_catch, znode *last_additional_catch TS
ZEND_API zend_bool zend_is_compiling(TSRMLS_D);
ZEND_API char *zend_make_compiled_string_description(char *name TSRMLS_DC);
ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify_handlers TSRMLS_DC);
int zend_get_class_fetch_type(char *class_name, uint class_name_len);
int zend_get_class_fetch_type(zend_uchar type, char *class_name, uint class_name_len);
typedef zend_bool (*zend_auto_global_callback)(char *name, uint name_len TSRMLS_DC);
typedef struct _zend_auto_global {
@ -552,6 +562,7 @@ typedef struct _zend_auto_global {
void zend_auto_global_dtor(zend_auto_global *auto_global);
ZEND_API int zend_register_auto_global(char *name, uint name_len, zend_auto_global_callback auto_global_callback TSRMLS_DC);
ZEND_API zend_bool zend_is_auto_global(char *name, uint name_len TSRMLS_DC);
ZEND_API zend_bool zend_u_is_auto_global(zend_uchar type, void *name, uint name_len TSRMLS_DC);
ZEND_API int zend_auto_global_disable_jit(char *varname, zend_uint varname_length TSRMLS_DC);
int zendlex(znode *zendlval TSRMLS_DC);

View File

@ -83,7 +83,7 @@ int zend_startup_constants(TSRMLS_D)
{
EG(zend_constants) = (HashTable *) malloc(sizeof(HashTable));
if (zend_hash_init(EG(zend_constants), 20, NULL, ZEND_CONSTANT_DTOR, 1)==FAILURE) {
if (zend_u_hash_init(EG(zend_constants), 20, NULL, ZEND_CONSTANT_DTOR, 1, UG(unicode))==FAILURE) {
return FAILURE;
}
return SUCCESS;
@ -108,6 +108,11 @@ void zend_register_standard_constants(TSRMLS_D)
REGISTER_MAIN_LONG_CONSTANT("E_ALL", E_ALL, CONST_PERSISTENT | CONST_CS);
REGISTER_MAIN_LONG_CONSTANT("U_INVALID_STOP", ZEND_FROM_U_ERROR_STOP, CONST_PERSISTENT | CONST_CS);
REGISTER_MAIN_LONG_CONSTANT("U_INVALID_SKIP", ZEND_FROM_U_ERROR_SKIP, CONST_PERSISTENT | CONST_CS);
REGISTER_MAIN_LONG_CONSTANT("U_INVALID_SUBSTITUTE", ZEND_FROM_U_ERROR_SUBST, CONST_PERSISTENT | CONST_CS);
REGISTER_MAIN_LONG_CONSTANT("U_INVALID_ESCAPE", ZEND_FROM_U_ERROR_ESCAPE, CONST_PERSISTENT | CONST_CS);
/* true/false constants */
{
zend_constant c;
@ -215,13 +220,15 @@ ZEND_API int zend_get_constant(char *name, uint name_len, zval *result TSRMLS_DC
int retval = 1;
char *lookup_name;
char *colon;
zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING;
if ((colon = memchr(name, ':', name_len)) && colon[1] == ':') {
if ((UG(unicode) && (colon = (char*)u_memchr((UChar*)name, ':', name_len)) && ((UChar*)colon)[1] == ':') ||
(!UG(unicode) && (colon = memchr(name, ':', name_len)) && colon[1] == ':')) {
/* class constant */
zend_class_entry **ce = NULL, *scope;
int class_name_len = colon-name;
int class_name_len = UG(unicode)?((colon-name)/sizeof(UChar)):colon-name;
int const_name_len = name_len - class_name_len - 2;
char *constant_name = colon+2;
char *constant_name = colon + (UG(unicode)?UBYTES(2):2);
zval **ret_constant;
char *class_name;
@ -231,16 +238,22 @@ ZEND_API int zend_get_constant(char *name, uint name_len, zval *result TSRMLS_DC
scope = CG(active_class_entry);
}
class_name = estrndup(name, class_name_len);
if (UG(unicode)) {
class_name = (char*)eustrndup((UChar*)name, class_name_len);
} else {
class_name = estrndup(name, class_name_len);
}
if (class_name_len == sizeof("self")-1 && strcmp(class_name, "self") == 0) {
if (class_name_len == sizeof("self")-1 &&
ZEND_U_EQUAL(type, class_name, class_name_len, "self", sizeof("self")-1)) {
if (scope) {
ce = &scope;
} else {
zend_error(E_ERROR, "Cannot access self:: when no class scope is active");
retval = 0;
}
} else if (class_name_len == sizeof("parent")-1 && strcmp(class_name, "parent") == 0) {
} else if (class_name_len == sizeof("parent")-1 &&
ZEND_U_EQUAL(type, class_name, class_name_len, "parent", sizeof("parent")-1)) {
if (!scope) {
zend_error(E_ERROR, "Cannot access parent:: when no class scope is active");
} else if (!scope->parent) {
@ -249,14 +262,14 @@ ZEND_API int zend_get_constant(char *name, uint name_len, zval *result TSRMLS_DC
ce = &scope->parent;
}
} else {
if (zend_lookup_class(class_name, class_name_len, &ce TSRMLS_CC) != SUCCESS) {
if (zend_u_lookup_class(type, class_name, class_name_len, &ce TSRMLS_CC) != SUCCESS) {
retval = 0;
}
}
efree(class_name);
if (retval && ce) {
if (zend_hash_find(&((*ce)->constants_table), constant_name, const_name_len+1, (void **) &ret_constant) != SUCCESS) {
if (zend_u_hash_find(&((*ce)->constants_table), type, constant_name, const_name_len+1, (void **) &ret_constant) != SUCCESS) {
retval = 0;
}
} else {
@ -272,12 +285,13 @@ ZEND_API int zend_get_constant(char *name, uint name_len, zval *result TSRMLS_DC
return retval;
}
if (zend_hash_find(EG(zend_constants), name, name_len+1, (void **) &c) == FAILURE) {
lookup_name = estrndup(name, name_len);
zend_str_tolower(lookup_name, name_len);
if (zend_u_hash_find(EG(zend_constants), type, name, name_len+1, (void **) &c) == FAILURE) {
int lookup_name_len;
lookup_name = zend_u_str_case_fold(type, name, name_len, 1, &lookup_name_len);
if (zend_hash_find(EG(zend_constants), lookup_name, name_len+1, (void **) &c)==SUCCESS) {
if ((c->flags & CONST_CS) && memcmp(c->name, name, name_len)!=0) {
if (zend_u_hash_find(EG(zend_constants), type, lookup_name, lookup_name_len+1, (void **) &c)==SUCCESS) {
if ((c->flags & CONST_CS) && memcmp(c->name, name, UG(unicode)?UBYTES(name_len):name_len)!=0) {
retval=0;
}
} else {
@ -297,9 +311,10 @@ ZEND_API int zend_get_constant(char *name, uint name_len, zval *result TSRMLS_DC
}
ZEND_API int zend_register_constant(zend_constant *c TSRMLS_DC)
ZEND_API int zend_u_register_constant(zend_uchar type, zend_constant *c TSRMLS_DC)
{
char *lowercase_name = NULL;
int lookup_name_len;
char *lookup_name = NULL;
char *name;
int ret = SUCCESS;
@ -309,14 +324,14 @@ ZEND_API int zend_register_constant(zend_constant *c TSRMLS_DC)
if (!(c->flags & CONST_CS)) {
/* keep in mind that c->name_len already contains the '\0' */
lowercase_name = estrndup(c->name, c->name_len);
zend_str_tolower(lowercase_name, c->name_len);
name = lowercase_name;
name = lookup_name = zend_u_str_case_fold(type, c->name, c->name_len-1, 1, &lookup_name_len);
lookup_name_len++;
} else {
lookup_name_len = c->name_len;
name = c->name;
}
if (zend_hash_add(EG(zend_constants), name, c->name_len, (void *) c, sizeof(zend_constant), NULL)==FAILURE) {
if (zend_u_hash_add(EG(zend_constants), type, name, lookup_name_len, (void *) c, sizeof(zend_constant), NULL)==FAILURE) {
zend_error(E_NOTICE,"Constant %s already defined", name);
free(c->name);
if (!(c->flags & CONST_PERSISTENT)) {
@ -324,13 +339,16 @@ ZEND_API int zend_register_constant(zend_constant *c TSRMLS_DC)
}
ret = FAILURE;
}
if (lowercase_name) {
efree(lowercase_name);
if (lookup_name) {
efree(lookup_name);
}
return ret;
}
ZEND_API int zend_register_constant(zend_constant *c TSRMLS_DC)
{
return zend_u_register_constant(IS_STRING, c TSRMLS_CC);
}
/*
* Local variables:
* tab-width: 4

View File

@ -60,6 +60,7 @@ ZEND_API void zend_register_double_constant(char *name, uint name_len, double dv
ZEND_API void zend_register_string_constant(char *name, uint name_len, char *strval, int flags, int module_number TSRMLS_DC);
ZEND_API void zend_register_stringl_constant(char *name, uint name_len, char *strval, uint strlen, int flags, int module_number TSRMLS_DC);
ZEND_API int zend_register_constant(zend_constant *c TSRMLS_DC);
ZEND_API int zend_u_register_constant(zend_uchar type, zend_constant *c TSRMLS_DC);
void zend_copy_constants(HashTable *target, HashTable *sourc);
void copy_zend_constant(zend_constant *c);
END_EXTERN_C()

View File

@ -86,7 +86,7 @@ static zend_object_value zend_default_exception_new_ex(zend_class_entry *class_t
obj.value.obj.handlers = &default_exception_handlers;
ALLOC_HASHTABLE(object->properties);
zend_hash_init(object->properties, 0, NULL, ZVAL_PTR_DTOR, 0);
zend_u_hash_init(object->properties, 0, NULL, ZVAL_PTR_DTOR, 0, UG(unicode));
zend_hash_copy(object->properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
ALLOC_ZVAL(trace);
@ -474,8 +474,8 @@ ZEND_METHOD(exception, __toString)
_default_exception_get_entry(getThis(), "file", sizeof("file")-1, &file TSRMLS_CC);
_default_exception_get_entry(getThis(), "line", sizeof("line")-1, &line TSRMLS_CC);
convert_to_string(&message);
convert_to_string(&file);
convert_to_text(&message);
convert_to_text(&file);
convert_to_long(&line);
ZVAL_STRINGL(&fname, "gettraceasstring", sizeof("gettraceasstring")-1, 0);
@ -492,16 +492,16 @@ ZEND_METHOD(exception, __toString)
zend_call_function(&fci, NULL TSRMLS_CC);
if (Z_TYPE_P(trace) != IS_STRING) {
if (Z_TYPE_P(trace) != IS_STRING && Z_TYPE_P(trace) != IS_UNICODE) {
trace = NULL;
}
if (Z_STRLEN(message) > 0) {
len = zend_spprintf(&str, 0, "exception '%s' with message '%s' in %s:%ld\nStack trace:\n%s",
Z_OBJCE_P(getThis())->name, Z_STRVAL(message), Z_STRVAL(file), Z_LVAL(line),
if (Z_UNILEN(message) > 0) {
len = zend_spprintf(&str, 0, "exception '%v' with message '%R' in %s:%ld\nStack trace:\n%s",
Z_OBJCE_P(getThis())->name, Z_TYPE(message), Z_UNIVAL(message), Z_STRVAL(file), Z_LVAL(line),
(trace && Z_STRLEN_P(trace)) ? Z_STRVAL_P(trace) : "#0 {main}\n");
} else {
len = zend_spprintf(&str, 0, "exception '%s' in %s:%ld\nStack trace:\n%s",
len = zend_spprintf(&str, 0, "exception '%v' in %s:%ld\nStack trace:\n%s",
Z_OBJCE_P(getThis())->name, Z_STRVAL(file), Z_LVAL(line),
(trace && Z_STRLEN_P(trace)) ? Z_STRVAL_P(trace) : "#0 {main}\n");
}
@ -670,7 +670,7 @@ ZEND_API void zend_exception_error(zval *exception TSRMLS_DC)
zend_call_method_with_0_params(&exception, ce_exception, NULL, "__tostring", &str);
if (!EG(exception)) {
if (Z_TYPE_P(str) != IS_STRING) {
zend_error(E_WARNING, "%s::__toString() must return a string", ce_exception->name);
zend_error(E_WARNING, "%v::__toString() must return a string", ce_exception->name);
} else {
zend_update_property_string(default_exception_ce, exception, "string", sizeof("string")-1, EG(exception) ? ce_exception->name : Z_STRVAL_P(str) TSRMLS_CC);
}
@ -686,7 +686,7 @@ ZEND_API void zend_exception_error(zval *exception TSRMLS_DC)
file = NULL;
line = NULL;
}
zend_error_va(E_WARNING, file ? Z_STRVAL_P(file) : NULL, line ? Z_LVAL_P(line) : 0, "Uncaught %s in exception handling during call to %s::__tostring()", Z_OBJCE_P(EG(exception))->name, ce_exception->name);
zend_error_va(E_WARNING, file ? Z_STRVAL_P(file) : NULL, line ? Z_LVAL_P(line) : 0, "Uncaught %v in exception handling during call to %v::__tostring()", Z_OBJCE_P(EG(exception))->name, ce_exception->name);
}
str = zend_read_property(default_exception_ce, exception, "string", sizeof("string")-1, 1 TSRMLS_CC);
@ -695,7 +695,7 @@ ZEND_API void zend_exception_error(zval *exception TSRMLS_DC)
zend_error_va(E_ERROR, Z_STRVAL_P(file), Z_LVAL_P(line), "Uncaught %s\n thrown", Z_STRVAL_P(str));
} else {
zend_error(E_ERROR, "Uncaught exception '%s'", ce_exception->name);
zend_error(E_ERROR, "Uncaught exception '%v'", ce_exception->name);
}
}
@ -716,6 +716,12 @@ ZEND_API void zend_throw_exception_object(zval *exception TSRMLS_DC)
zend_throw_exception_internal(exception TSRMLS_CC);
}
void init_exceptions(TSRMLS_D)
{
default_exception_ce = zend_get_named_class_entry("Exception", sizeof("Exception")-1 TSRMLS_CC);
error_exception_ce = zend_get_named_class_entry("ErrorException", sizeof("ErrorException")-1 TSRMLS_CC);
}
/*
* Local variables:
* tab-width: 4

View File

@ -48,6 +48,8 @@ extern ZEND_API void (*zend_throw_exception_hook)(zval *ex TSRMLS_DC);
/* show an exception using zend_error(E_ERROR,...) */
ZEND_API void zend_exception_error(zval *exception TSRMLS_DC);
void init_exceptions(TSRMLS_D);
END_EXTERN_C()
#endif

View File

@ -35,6 +35,7 @@
#include "zend_ini.h"
#include "zend_exceptions.h"
#include "zend_vm.h"
#include "zend_unicode.h"
#define _CONST_CODE 0
#define _TMP_CODE 1
@ -148,12 +149,12 @@ ZEND_API zval** zend_get_compiled_variable_value(zend_execute_data *execute_data
return execute_data_ptr->CVs[var];
}
static inline void zend_get_cv_address(zend_compiled_variable *cv, zval ***ptr, temp_variable *Ts TSRMLS_DC)
static inline void zend_get_cv_address(zend_uchar utype, zend_compiled_variable *cv, zval ***ptr, temp_variable *Ts TSRMLS_DC)
{
zval *new_zval = &EG(uninitialized_zval);
zval *new_zval = &EG(uninitialized_zval);
new_zval->refcount++;
zend_hash_quick_update(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, &new_zval, sizeof(zval *), (void **)ptr);
new_zval->refcount++;
zend_u_hash_quick_update(EG(active_symbol_table), utype, cv->name, cv->name_len+1, cv->hash_value, &new_zval, sizeof(zval *), (void **)ptr);
}
static inline zval *_get_zval_ptr_tmp(znode *node, temp_variable *Ts, zend_free_op *should_free TSRMLS_DC)
@ -163,35 +164,53 @@ static inline zval *_get_zval_ptr_tmp(znode *node, temp_variable *Ts, zend_free_
static inline zval *_get_zval_ptr_var(znode *node, temp_variable *Ts, zend_free_op *should_free TSRMLS_DC)
{
zval *ptr = T(node->u.var).var.ptr;
if (ptr) {
PZVAL_UNLOCK(ptr, should_free);
return ptr;
if (T(node->u.var).var.ptr) {
PZVAL_UNLOCK(T(node->u.var).var.ptr, should_free);
return T(node->u.var).var.ptr;
} else {
temp_variable *T = &T(node->u.var);
zval *str = T->str_offset.str;
zval *ptr;
/* string offset */
ALLOC_ZVAL(ptr);
T->str_offset.ptr = ptr;
should_free->var = ptr;
if (T->str_offset.str->type != IS_STRING
|| ((int)T->str_offset.offset<0)
|| (T->str_offset.str->value.str.len <= T->str_offset.offset)) {
zend_error(E_NOTICE, "Uninitialized string offset: %d", T->str_offset.offset);
ptr->value.str.val = STR_EMPTY_ALLOC();
ptr->value.str.len = 0;
} else {
char c = str->value.str.val[T->str_offset.offset];
/* T->str_offset.str here is always IS_STRING or IS_UNICODE */
if (T->str_offset.str->type == IS_STRING || T->str_offset.str->type == IS_BINARY) {
if (((int)T->str_offset.offset<0)
|| (T->str_offset.str->value.str.len <= T->str_offset.offset)) {
zend_error(E_NOTICE, "Uninitialized string offset: %d", T->str_offset.offset);
ptr->value.str.val = STR_EMPTY_ALLOC();
ptr->value.str.len = 0;
} else {
char c = str->value.str.val[T->str_offset.offset];
ptr->value.str.val = estrndup(&c, 1);
ptr->value.str.len = 1;
ptr->value.str.val = estrndup(&c, 1);
ptr->value.str.len = 1;
}
ptr->type = T->str_offset.str->type;
} else {
if (((int)T->str_offset.offset<0)
|| (Z_USTRCPLEN_P(T->str_offset.str) <= T->str_offset.offset)) {
zend_error(E_NOTICE, "Uninitialized string offset: %d", T->str_offset.offset);
ptr->value.ustr.val = USTR_MAKE("");
ptr->value.ustr.len = 0;
} else {
UChar32 c = zend_get_codepoint_at(str->value.ustr.val, str->value.ustr.len, T->str_offset.offset);
int32_t i = 0;
ptr->value.ustr.val = eumalloc(3); /* potentially 2 code units + null */
U16_APPEND_UNSAFE(ptr->value.ustr.val, i, c);
ptr->value.ustr.val[i] = 0;
ptr->value.ustr.len = i;
}
ptr->type = IS_UNICODE;
}
PZVAL_UNLOCK_FREE(str);
ptr->refcount=1;
ptr->is_ref=1;
ptr->type = IS_STRING;
return ptr;
}
}
@ -202,20 +221,22 @@ static inline zval *_get_zval_ptr_cv(znode *node, temp_variable *Ts, int type TS
if (!*ptr) {
zend_compiled_variable *cv = &CV_DEF_OF(node->u.var);
if (zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void **)ptr)==FAILURE) {
zend_uchar utype = UG(unicode)?IS_UNICODE:IS_STRING;
if (zend_u_hash_quick_find(EG(active_symbol_table), utype, cv->name, cv->name_len+1, cv->hash_value, (void **)ptr)==FAILURE) {
switch (type) {
case BP_VAR_R:
case BP_VAR_UNSET:
zend_error(E_NOTICE, "Undefined variable: %s", cv->name);
zend_error(E_NOTICE, "Undefined variable: %v", cv->name);
/* break missing intentionally */
case BP_VAR_IS:
return &EG(uninitialized_zval);
break;
case BP_VAR_RW:
zend_error(E_NOTICE, "Undefined variable: %s", cv->name);
zend_error(E_NOTICE, "Undefined variable: %v", cv->name);
/* break missing intentionally */
case BP_VAR_W:
zend_get_cv_address(cv, ptr, Ts TSRMLS_CC);
zend_get_cv_address(utype, cv, ptr, Ts TSRMLS_CC);
break;
}
}
@ -270,20 +291,22 @@ static inline zval **_get_zval_ptr_ptr_cv(znode *node, temp_variable *Ts, int ty
if (!*ptr) {
zend_compiled_variable *cv = &CV_DEF_OF(node->u.var);
if (zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void **)ptr)==FAILURE) {
zend_uchar utype = UG(unicode)?IS_UNICODE:IS_STRING;
if (zend_u_hash_quick_find(EG(active_symbol_table), utype, cv->name, cv->name_len+1, cv->hash_value, (void **)ptr)==FAILURE) {
switch (type) {
case BP_VAR_R:
case BP_VAR_UNSET:
zend_error(E_NOTICE, "Undefined variable: %s", cv->name);
zend_error(E_NOTICE, "Undefined variable: %v", cv->name);
/* break missing intentionally */
case BP_VAR_IS:
return &EG(uninitialized_zval_ptr);
break;
case BP_VAR_RW:
zend_error(E_NOTICE, "Undefined variable: %s", cv->name);
zend_error(E_NOTICE, "Undefined variable: %v", cv->name);
/* break missing intentionally */
case BP_VAR_W:
zend_get_cv_address(cv, ptr, Ts TSRMLS_CC);
zend_get_cv_address(utype, cv, ptr, Ts TSRMLS_CC);
break;
}
}
@ -435,7 +458,8 @@ static inline void make_real_object(zval **object_ptr TSRMLS_DC)
/* this should modify object only if it's empty */
if ((*object_ptr)->type == IS_NULL
|| ((*object_ptr)->type == IS_BOOL && (*object_ptr)->value.lval==0)
|| ((*object_ptr)->type == IS_STRING && (*object_ptr)->value.str.len == 0)) {
|| (((*object_ptr)->type == IS_STRING && (*object_ptr)->type == IS_BINARY) && (*object_ptr)->value.str.len == 0)
|| ((*object_ptr)->type == IS_UNICODE && (*object_ptr)->value.ustr.len == 0)) {
if (!PZVAL_IS_REF(*object_ptr)) {
SEPARATE_ZVAL(object_ptr);
}
@ -459,9 +483,9 @@ static inline void zend_verify_arg_type(zend_function *zf, zend_uint arg_num, zv
if (cur_arg_info->class_name) {
if (!arg) {
if(ptr && ptr->op_array) {
zend_error_noreturn(E_ERROR, "Argument %d must be an object of class %s, called in %s on line %d and defined", arg_num, cur_arg_info->class_name, ptr->op_array->filename, ptr->opline->lineno);
zend_error_noreturn(E_ERROR, "Argument %d must be an object of class %v, called in %s on line %d and defined", arg_num, cur_arg_info->class_name, ptr->op_array->filename, ptr->opline->lineno);
} else {
zend_error_noreturn(E_ERROR, "Argument %d must be an object of class %s", arg_num, cur_arg_info->class_name);
zend_error_noreturn(E_ERROR, "Argument %d must be an object of class %v", arg_num, cur_arg_info->class_name);
}
}
switch (Z_TYPE_P(arg)) {
@ -475,7 +499,7 @@ static inline void zend_verify_arg_type(zend_function *zf, zend_uint arg_num, zv
}
break;
case IS_OBJECT: {
zend_class_entry *ce = zend_fetch_class(cur_arg_info->class_name, cur_arg_info->class_name_len, ZEND_FETCH_CLASS_AUTO TSRMLS_CC);
zend_class_entry *ce = zend_u_fetch_class(UG(unicode)?IS_UNICODE:IS_STRING, cur_arg_info->class_name, cur_arg_info->class_name_len, ZEND_FETCH_CLASS_AUTO TSRMLS_CC);
if (!instanceof_function(Z_OBJCE_P(arg), ce TSRMLS_CC)) {
char *error_msg;
@ -485,18 +509,18 @@ static inline void zend_verify_arg_type(zend_function *zf, zend_uint arg_num, zv
error_msg = "be an instance of";
}
if(ptr && ptr->op_array) {
zend_error_noreturn(E_ERROR, "Argument %d must %s %s, called in %s on line %d and defined", arg_num, error_msg, ce->name, ptr->op_array->filename, ptr->opline->lineno);
zend_error_noreturn(E_ERROR, "Argument %d must %s %v, called in %s on line %d and defined", arg_num, error_msg, ce->name, ptr->op_array->filename, ptr->opline->lineno);
} else {
zend_error_noreturn(E_ERROR, "Argument %d must %s %s", arg_num, error_msg, ce->name);
zend_error_noreturn(E_ERROR, "Argument %d must %s %v", arg_num, error_msg, ce->name);
}
}
}
break;
default:
if(ptr && ptr->op_array) {
zend_error_noreturn(E_ERROR, "Argument %d must be an object of class %s, called in %s on line %d and defined", arg_num, cur_arg_info->class_name, ptr->op_array->filename, ptr->opline->lineno);
zend_error_noreturn(E_ERROR, "Argument %d must be an object of class %v, called in %s on line %d and defined", arg_num, cur_arg_info->class_name, ptr->op_array->filename, ptr->opline->lineno);
} else {
zend_error_noreturn(E_ERROR, "Argument %d must be an object of class %s", arg_num, cur_arg_info->class_name);
zend_error_noreturn(E_ERROR, "Argument %d must be an object of class %v", arg_num, cur_arg_info->class_name);
}
break;
}
@ -569,9 +593,9 @@ static inline void zend_assign_to_object(znode *result, zval **object_ptr, znode
value->refcount = 0;
dup = zend_get_object_classname(orig_value, &class_name, &class_name_len TSRMLS_CC);
if (Z_OBJ_HANDLER_P(value, clone_obj) == NULL) {
zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", class_name);
zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %v", class_name);
}
zend_error(E_STRICT, "Implicit cloning object of class '%s' because of 'zend.ze1_compatibility_mode'", class_name);
zend_error(E_STRICT, "Implicit cloning object of class '%v' because of 'zend.ze1_compatibility_mode'", class_name);
value->value.obj = Z_OBJ_HANDLER_P(orig_value, clone_obj)(orig_value TSRMLS_CC);
if(!dup) {
efree(class_name);
@ -635,7 +659,12 @@ static inline void zend_assign_to_variable(znode *result, znode *op1, znode *op2
if (!variable_ptr_ptr) {
temp_variable *T = &T(op1->u.var);
if (T->str_offset.str->type == IS_STRING) do {
if (UG(unicode) && Z_TYPE_P(T->str_offset.str) == IS_STRING && value->type != IS_STRING) {
convert_to_unicode(T->str_offset.str);
}
if (Z_TYPE_P(T->str_offset.str) == IS_STRING ||
Z_TYPE_P(T->str_offset.str) == IS_BINARY) do {
zval tmp;
zval *final_value = value;
@ -659,9 +688,9 @@ static inline void zend_assign_to_variable(znode *result, znode *op1, znode *op2
T->str_offset.str->value.str.len = T->str_offset.offset+1;
}
if (value->type!=IS_STRING) {
if (value->type!=IS_STRING && value->type!=IS_BINARY) {
tmp = *value;
if (op2->op_type & (IS_VAR|IS_CV)) {
if (op2->op_type & (IS_VAR|IS_CV|IS_CONST)) {
zval_copy_ctor(&tmp);
}
convert_to_string(&tmp);
@ -686,6 +715,53 @@ static inline void zend_assign_to_variable(znode *result, znode *op1, znode *op2
T(result->u.var).var = &T->str_offset.str;
*/
} while (0);
else if (T->str_offset.str->type == IS_UNICODE) do {
zval tmp;
zval *final_value = value;
if (((int)T->str_offset.offset < 0)) {
zend_error(E_WARNING, "Illegal string offset: %d", T->str_offset.offset);
break;
}
if (T->str_offset.offset >= T->str_offset.str->value.ustr.len) {
zend_uint i;
if (T->str_offset.str->value.ustr.len==0) {
USTR_FREE(T->str_offset.str->value.ustr.val);
T->str_offset.str->value.ustr.val = eumalloc(T->str_offset.offset+1+1);
} else {
T->str_offset.str->value.ustr.val = eurealloc(T->str_offset.str->value.ustr.val, T->str_offset.offset+1+1);
}
for (i=T->str_offset.str->value.ustr.len; i<T->str_offset.offset; i++) {
T->str_offset.str->value.ustr.val[i] = 0x20; /* ' ' */
}
T->str_offset.str->value.ustr.val[T->str_offset.offset+1] = 0;
T->str_offset.str->value.ustr.len = T->str_offset.offset+1;
}
if (value->type!=IS_UNICODE) {
tmp = *value;
if (op2->op_type & (IS_VAR|IS_CV|IS_CONST)) {
zval_copy_ctor(&tmp);
}
convert_to_unicode(&tmp);
final_value = &tmp;
}
T->str_offset.str->value.ustr.val[T->str_offset.offset] = final_value->value.ustr.val[0];
if (op2->op_type == IS_TMP_VAR) {
if (final_value == &T(op2->u.var).tmp_var) {
/* we can safely free final_value here
* because separation is done only
* in case op2->op_type == IS_VAR */
USTR_FREE(final_value->value.ustr.val);
}
}
if (final_value == &tmp) {
zval_dtor(final_value);
}
} while (0);
/* zval_ptr_dtor(&T->str_offset.str); Nuke this line if it doesn't cause a leak */
/* T(result->u.var).var.ptr_ptr = &EG(uninitialized_zval_ptr); */
@ -727,7 +803,7 @@ static inline void zend_assign_to_variable(znode *result, znode *op1, znode *op2
dup = zend_get_object_classname(value, &class_name, &class_name_len TSRMLS_CC);
if (Z_OBJ_HANDLER_P(value, clone_obj) == NULL) {
zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", class_name);
zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %v", class_name);
} else if (PZVAL_IS_REF(variable_ptr)) {
if (variable_ptr != value) {
zend_uint refcount = variable_ptr->refcount;
@ -740,7 +816,7 @@ static inline void zend_assign_to_variable(znode *result, znode *op1, znode *op2
*variable_ptr = *value;
variable_ptr->refcount = refcount;
variable_ptr->is_ref = 1;
zend_error(E_STRICT, "Implicit cloning object of class '%s' because of 'zend.ze1_compatibility_mode'", class_name);
zend_error(E_STRICT, "Implicit cloning object of class '%v' because of 'zend.ze1_compatibility_mode'", class_name);
variable_ptr->value.obj = Z_OBJ_HANDLER_P(value, clone_obj)(value TSRMLS_CC);
if (type != IS_TMP_VAR) {
value->refcount--;
@ -759,7 +835,7 @@ static inline void zend_assign_to_variable(znode *result, znode *op1, znode *op2
}
*variable_ptr = *value;
INIT_PZVAL(variable_ptr);
zend_error(E_STRICT, "Implicit cloning object of class '%s' because of 'zend.ze1_compatibility_mode'", class_name);
zend_error(E_STRICT, "Implicit cloning object of class '%v' because of 'zend.ze1_compatibility_mode'", class_name);
variable_ptr->value.obj = Z_OBJ_HANDLER_P(value, clone_obj)(value TSRMLS_CC);
zval_ptr_dtor(&value);
}
@ -867,14 +943,14 @@ static inline void zend_receive(zval **variable_ptr_ptr, zval *value TSRMLS_DC)
dup = zend_get_object_classname(value, &class_name, &class_name_len TSRMLS_CC);
if (Z_OBJ_HANDLER_P(value, clone_obj) == NULL) {
zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", class_name);
zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %v", class_name);
} else {
variable_ptr->refcount--;
ALLOC_ZVAL(variable_ptr);
*variable_ptr_ptr = variable_ptr;
*variable_ptr = *value;
INIT_PZVAL(variable_ptr);
zend_error(E_STRICT, "Implicit cloning object of class '%s' because of 'zend.ze1_compatibility_mode'", class_name);
zend_error(E_STRICT, "Implicit cloning object of class '%v' because of 'zend.ze1_compatibility_mode'", class_name);
variable_ptr->value.obj = Z_OBJ_HANDLER_P(value, clone_obj)(value TSRMLS_CC);
}
if (!dup) {
@ -925,7 +1001,7 @@ static inline HashTable *zend_get_target_symbol_table(zend_op *opline, temp_vari
case ZEND_FETCH_STATIC:
if (!EG(active_op_array)->static_variables) {
ALLOC_HASHTABLE(EG(active_op_array)->static_variables);
zend_hash_init(EG(active_op_array)->static_variables, 2, NULL, ZVAL_PTR_DTOR, 0);
zend_u_hash_init(EG(active_op_array)->static_variables, 2, NULL, ZVAL_PTR_DTOR, 0, UG(unicode));
}
return EG(active_op_array)->static_variables;
break;
@ -939,39 +1015,61 @@ static inline zval **zend_fetch_dimension_address_inner(HashTable *ht, zval *dim
zval **retval;
char *offset_key;
int offset_key_length;
zend_uchar ztype = dim->type;
int free_offset = 0;
switch (dim->type) {
switch (ztype) {
case IS_NULL:
ztype = IS_STRING;
offset_key = "";
offset_key_length = 0;
offset_key_length = 1;
goto fetch_string_dim;
case IS_STRING:
case IS_BINARY:
case IS_UNICODE:
offset_key = dim->value.str.val;
offset_key_length = dim->value.str.len;
offset_key = Z_UNIVAL_P(dim);
offset_key_length = Z_UNILEN_P(dim)+1;
fetch_string_dim:
if (zend_symtable_find(ht, offset_key, offset_key_length+1, (void **) &retval) == FAILURE) {
if (UG(unicode) && ht == &EG(symbol_table) && ztype == IS_UNICODE) {
/* Identifier normalization */
UChar *norm;
int32_t norm_len;
if (!zend_normalize_identifier(&norm, &norm_len,
(UChar*)offset_key, offset_key_length, 0)) {
zend_error(E_WARNING, "Could not normalize identifier: %r", offset_key);
} else if ((char*)norm != offset_key) {
offset_key = (char*)norm;
offset_key_length = norm_len;
free_offset = 1;
}
}
if (zend_u_symtable_find(ht, ztype, offset_key, offset_key_length, (void **) &retval) == FAILURE) {
switch (type) {
case BP_VAR_R:
zend_error(E_NOTICE, "Undefined index: %s", offset_key);
zend_error(E_NOTICE, "Undefined index: %R", ztype, offset_key);
/* break missing intentionally */
case BP_VAR_UNSET:
case BP_VAR_IS:
retval = &EG(uninitialized_zval_ptr);
break;
case BP_VAR_RW:
zend_error(E_NOTICE,"Undefined index: %s", offset_key);
zend_error(E_NOTICE,"Undefined index: %R", ztype, offset_key);
/* break missing intentionally */
case BP_VAR_W: {
zval *new_zval = &EG(uninitialized_zval);
new_zval->refcount++;
zend_symtable_update(ht, offset_key, offset_key_length+1, &new_zval, sizeof(zval *), (void **) &retval);
zend_u_symtable_update(ht, ztype, offset_key, offset_key_length, &new_zval, sizeof(zval *), (void **) &retval);
}
break;
}
}
if (free_offset) {
efree(offset_key);
}
break;
case IS_RESOURCE:
zend_error(E_STRICT, "Resource ID#%ld used as offset, casting to integer (%ld)", dim->value.lval, dim->value.lval);
@ -1049,7 +1147,8 @@ static void zend_fetch_dimension_address(temp_variable *result, zval **container
if (container->type==IS_NULL
|| (container->type==IS_BOOL && container->value.lval==0)
|| (container->type==IS_STRING && container->value.str.len==0)) {
|| ((container->type==IS_STRING || container->type==IS_BINARY) && container->value.str.len==0)
|| (container->type==IS_UNICODE && container->value.ustr.len==0)) {
switch (type) {
case BP_VAR_RW:
case BP_VAR_W:
@ -1098,6 +1197,8 @@ static void zend_fetch_dimension_address(temp_variable *result, zval **container
}
break;
}
case IS_UNICODE:
case IS_BINARY:
case IS_STRING: {
zval tmp;
@ -1220,7 +1321,8 @@ static void zend_fetch_property_address(temp_variable *result, zval **container_
/* this should modify object only if it's empty */
if (container->type == IS_NULL
|| (container->type == IS_BOOL && container->value.lval==0)
|| (container->type == IS_STRING && container->value.str.len == 0)) {
|| ((container->type==IS_STRING || container->type==IS_BINARY) && container->value.str.len==0)
|| (container->type==IS_UNICODE && container->value.ustr.len==0)) {
switch (type) {
case BP_VAR_RW:
case BP_VAR_W:

View File

@ -65,8 +65,11 @@ static inline void safe_free_zval_ptr_rel(zval *p ZEND_FILE_LINE_DC ZEND_FILE_LI
}
}
ZEND_API int zend_lookup_class(char *name, int name_length, zend_class_entry ***ce TSRMLS_DC);
ZEND_API int zend_u_lookup_class(zend_uchar type, void *name, int name_length, zend_class_entry ***ce TSRMLS_DC);
ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name TSRMLS_DC);
ZEND_API int zend_eval_string_ex(char *str, zval *retval_ptr, char *string_name, int handle_exceptions TSRMLS_DC);
ZEND_API int zend_u_eval_string(zend_uchar type, void *str, zval *retval_ptr, char *string_name TSRMLS_DC);
ZEND_API int zend_u_eval_string_ex(zend_uchar type, void *str, zval *retval_ptr, char *string_name, int handle_exceptions TSRMLS_DC);
static inline int i_zend_is_true(zval *op)
{
@ -85,6 +88,7 @@ static inline int i_zend_is_true(zval *op)
result = (op->value.dval ? 1 : 0);
break;
case IS_STRING:
case IS_BINARY:
if (op->value.str.len == 0
|| (op->value.str.len==1 && op->value.str.val[0]=='0')) {
result = 0;
@ -92,6 +96,14 @@ static inline int i_zend_is_true(zval *op)
result = 1;
}
break;
case IS_UNICODE:
if (op->value.ustr.len == 0
|| (op->value.ustr.len==1 && op->value.ustr.val[0]=='0')) {
result = 0;
} else {
result = 1;
}
break;
case IS_ARRAY:
result = (zend_hash_num_elements(op->value.ht)?1:0);
break;
@ -155,6 +167,7 @@ ZEND_API void zend_set_timeout(long seconds);
ZEND_API void zend_unset_timeout(TSRMLS_D);
ZEND_API void zend_timeout(int dummy);
ZEND_API zend_class_entry *zend_fetch_class(char *class_name, uint class_name_len, int fetch_type TSRMLS_DC);
ZEND_API zend_class_entry *zend_u_fetch_class(zend_uchar type, void *class_name, uint class_name_len, int fetch_type TSRMLS_DC);
void zend_verify_abstract_class(zend_class_entry *ce TSRMLS_DC);
#ifdef ZEND_WIN32
@ -172,10 +185,12 @@ void zend_shutdown_timeout_thread();
/* The following tries to resolve the classname of a zval of type object.
* Since it is slow it should be only used in error messages.
*/
#define Z_OBJ_CLASS_NAME_P(zval) ((zval) && (zval)->type == IS_OBJECT && Z_OBJ_HT_P(zval)->get_class_entry != NULL && Z_OBJ_HT_P(zval)->get_class_entry(zval TSRMLS_CC) ? Z_OBJ_HT_P(zval)->get_class_entry(zval TSRMLS_CC)->name : "")
#define Z_OBJ_CLASS_NAME_P(zval) ((zval) && (zval)->type == IS_OBJECT && Z_OBJ_HT_P(zval)->get_class_entry != NULL && Z_OBJ_HT_P(zval)->get_class_entry(zval TSRMLS_CC) ? Z_OBJ_HT_P(zval)->get_class_entry(zval TSRMLS_CC)->name : EMPTY_STR)
ZEND_API zval** zend_get_compiled_variable_value(zend_execute_data *execute_data_ptr, zend_uint var);
void init_unicode_strings();
#define ZEND_USER_OPCODE_CONTINUE 0 /* execute next opcode */
#define ZEND_USER_OPCODE_RETURN 1 /* exit from executor (return from function) */
#define ZEND_USER_OPCODE_DISPATCH 2 /* call original opcode handler */

View File

@ -50,6 +50,16 @@ static DWORD timeout_thread_id;
static int timeout_thread_initialized=0;
#endif
static UChar u_main[sizeof("main")];
static UChar u_return[sizeof("return ")];
static UChar u_semicolon[sizeof(" ;")];
void init_unicode_strings() {
u_charsToUChars("main", u_main, sizeof("main"));
u_charsToUChars("return ", u_return, sizeof("return "));
u_charsToUChars(" ;", u_semicolon, sizeof(" ;"));
}
#if ZEND_DEBUG
static void (*original_sigsegv_handler)(int);
static void zend_handle_sigsegv(int dummy)
@ -143,7 +153,7 @@ void init_executor(TSRMLS_D)
zend_ptr_stack_init(&EG(argument_stack));
zend_ptr_stack_push(&EG(argument_stack), (void *) NULL);
zend_hash_init(&EG(symbol_table), 50, NULL, ZVAL_PTR_DTOR, 0);
zend_u_hash_init(&EG(symbol_table), 50, NULL, ZVAL_PTR_DTOR, 0, UG(unicode));
{
zval *globals;
@ -303,7 +313,7 @@ ZEND_API char *get_active_class_name(char **space TSRMLS_DC)
if (space) {
*space = "";
}
return "";
return EMPTY_STR;
}
switch (EG(function_state_ptr)->function->type) {
case ZEND_USER_FUNCTION:
@ -314,13 +324,13 @@ ZEND_API char *get_active_class_name(char **space TSRMLS_DC)
if (space) {
*space = ce ? "::" : "";
}
return ce ? ce->name : "";
return ce ? ce->name : EMPTY_STR;
}
default:
if (space) {
*space = "";
}
return "";
return EMPTY_STR;
}
}
@ -336,6 +346,8 @@ ZEND_API char *get_active_function_name(TSRMLS_D)
if (function_name) {
return function_name;
} else if (UG(unicode)) {
return (char*) u_main;
} else {
return "main";
}
@ -429,11 +441,11 @@ ZEND_API int zval_update_constant(zval **pp, void *arg TSRMLS_DC)
refcount = p->refcount;
is_ref = p->is_ref;
if (!zend_get_constant(p->value.str.val, p->value.str.len, &const_value TSRMLS_CC)) {
zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'",
p->value.str.val,
p->value.str.val);
p->type = IS_STRING;
if (!zend_get_constant(Z_UNIVAL_P(p), Z_UNILEN_P(p), &const_value TSRMLS_CC)) {
zend_error(E_NOTICE, "Use of undefined constant %v - assumed '%v'",
Z_UNIVAL_P(p),
Z_UNIVAL_P(p));
p->type = UG(unicode)?IS_UNICODE:IS_STRING;
if (!inline_change) {
zval_copy_ctor(p);
}
@ -464,7 +476,7 @@ ZEND_API int zval_update_constant(zval **pp, void *arg TSRMLS_DC)
continue;
}
Z_TYPE_PP(element) &= ~IS_CONSTANT_INDEX;
if (zend_hash_get_current_key_ex(p->value.ht, &str_index, &str_index_len, &num_index, 0, NULL)!=HASH_KEY_IS_STRING) {
if (zend_hash_get_current_key_ex(p->value.ht, &str_index, &str_index_len, &num_index, 0, NULL) != (UG(unicode)?HASH_KEY_IS_UNICODE:HASH_KEY_IS_STRING)) {
zend_hash_move_forward(p->value.ht);
continue;
}
@ -474,13 +486,25 @@ ZEND_API int zval_update_constant(zval **pp, void *arg TSRMLS_DC)
continue;
}
if (const_value.type == IS_STRING && const_value.value.str.len == str_index_len-1 &&
if (UG(unicode)) {
if (const_value.type == IS_UNICODE &&
const_value.value.ustr.len == str_index_len-1 &&
!u_strncmp(Z_USTRVAL(const_value), (UChar*)str_index, str_index_len)) {
/* constant value is the same as its name */
zval_dtor(&const_value);
zend_hash_move_forward(p->value.ht);
continue;
}
} else {
if (const_value.type == IS_STRING &&
const_value.value.str.len == str_index_len-1 &&
!strncmp(const_value.value.str.val, str_index, str_index_len)) {
/* constant value is the same as its name */
zval_dtor(&const_value);
zend_hash_move_forward(p->value.ht);
continue;
}
}
ALLOC_ZVAL(new_val);
*new_val = **element;
@ -498,13 +522,27 @@ ZEND_API int zval_update_constant(zval **pp, void *arg TSRMLS_DC)
long lval;
double dval;
if (is_numeric_string(const_value.value.str.val, const_value.value.str.len, &lval, &dval, 0) == IS_LONG) {
if (is_numeric_string(Z_STRVAL(const_value), Z_STRLEN(const_value), &lval, &dval, 0) == IS_LONG) {
zend_hash_update_current_key(p->value.ht, HASH_KEY_IS_LONG, NULL, 0, lval);
} else {
zend_hash_update_current_key(p->value.ht, HASH_KEY_IS_STRING, const_value.value.str.val, const_value.value.str.len+1, 0);
zend_hash_update_current_key(p->value.ht, HASH_KEY_IS_STRING, Z_STRVAL(const_value), Z_STRLEN(const_value)+1, 0);
}
break;
}
case IS_UNICODE: {
long lval;
double dval;
if (is_numeric_unicode(Z_USTRVAL(const_value), Z_USTRLEN(const_value), &lval, &dval, 0) == IS_LONG) {
zend_hash_update_current_key(p->value.ht, HASH_KEY_IS_LONG, NULL, 0, lval);
} else {
zend_hash_update_current_key(p->value.ht, HASH_KEY_IS_UNICODE, Z_USTRVAL(const_value), Z_USTRLEN(const_value)+1, 0);
}
break;
}
case IS_BINARY:
zend_hash_update_current_key(p->value.ht, HASH_KEY_IS_BINARY, Z_STRVAL(const_value), Z_STRLEN(const_value)+1, 0);
break;
case IS_BOOL:
case IS_LONG:
zend_hash_update_current_key(p->value.ht, HASH_KEY_IS_LONG, NULL, 0, const_value.value.lval);
@ -587,6 +625,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
zval *method_name;
zval *params_array;
int call_via_handler = 0;
char *old_func_name = NULL;
if (EG(exception)) {
return FAILURE; /* we would result in an instable executor otherwise */
@ -649,18 +688,23 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
calling_scope = Z_OBJCE_PP(fci->object_pp);
fci->function_table = &calling_scope->function_table;
EX(object) = *fci->object_pp;
} else if (Z_TYPE_PP(fci->object_pp) == IS_STRING) {
} else if (Z_TYPE_PP(fci->object_pp) == IS_STRING ||
Z_TYPE_PP(fci->object_pp) == IS_UNICODE) {
zend_class_entry **ce;
int found = FAILURE;
if (EG(active_op_array) && strcmp(Z_STRVAL_PP(fci->object_pp), "self") == 0) {
if (EG(active_op_array) &&
Z_UNILEN_PP(fci->object_pp) == sizeof("self")-1 &&
ZEND_U_EQUAL(Z_TYPE_PP(fci->object_pp), Z_UNIVAL_PP(fci->object_pp), Z_UNILEN_PP(fci->object_pp), "self", sizeof("self")-1)) {
if (!EG(active_op_array)->scope) {
zend_error(E_ERROR, "Cannot access self:: when no class scope is active");
}
ce = &(EG(active_op_array)->scope);
found = (*ce != NULL?SUCCESS:FAILURE);
fci->object_pp = EG(This)?&EG(This):NULL;
} else if (strcmp(Z_STRVAL_PP(fci->object_pp), "parent") == 0 && EG(active_op_array)) {
} else if (EG(active_op_array) &&
Z_UNILEN_PP(fci->object_pp) == sizeof("parent")-1 &&
ZEND_U_EQUAL(Z_TYPE_PP(fci->object_pp), Z_UNIVAL_PP(fci->object_pp), Z_UNILEN_PP(fci->object_pp), "parent", sizeof("parent")-1)) {
if (!EG(active_op_array)->scope) {
zend_error(E_ERROR, "Cannot access parent:: when no class scope is active");
@ -675,9 +719,9 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
zend_class_entry *scope;
scope = EG(active_op_array) ? EG(active_op_array)->scope : NULL;
found = zend_lookup_class(Z_STRVAL_PP(fci->object_pp), Z_STRLEN_PP(fci->object_pp), &ce TSRMLS_CC);
found = zend_u_lookup_class(Z_TYPE_PP(fci->object_pp), Z_UNIVAL_PP(fci->object_pp), Z_UNILEN_PP(fci->object_pp), &ce TSRMLS_CC);
if (found == FAILURE) {
zend_error(E_ERROR, "Class '%s' not found", Z_STRVAL_PP(fci->object_pp));
zend_error(E_ERROR, "Class '%R' not found", Z_TYPE_PP(fci->object_pp), Z_UNIVAL_PP(fci->object_pp));
}
if (scope && EG(This) &&
instanceof_function(Z_OBJCE_P(EG(This)), scope TSRMLS_CC) &&
@ -702,16 +746,24 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
}
}
if (fci->function_name->type!=IS_STRING) {
if (fci->function_name->type != IS_STRING &&
fci->function_name->type != IS_UNICODE) {
return FAILURE;
}
if (UG(unicode) && fci->function_name->type == IS_STRING) {
old_func_name = Z_STRVAL_P(fci->function_name);
Z_STRVAL_P(fci->function_name) = estrndup(Z_STRVAL_P(fci->function_name), Z_STRLEN_P(fci->function_name));
convert_to_unicode(fci->function_name);
}
if (fci->object_pp) {
if (Z_OBJ_HT_PP(fci->object_pp)->get_method == NULL) {
zend_error(E_ERROR, "Object does not support method calls");
}
EX(function_state).function =
Z_OBJ_HT_PP(fci->object_pp)->get_method(fci->object_pp, Z_STRVAL_P(fci->function_name), Z_STRLEN_P(fci->function_name) TSRMLS_CC);
Z_OBJ_HT_PP(fci->object_pp)->get_method(fci->object_pp, Z_UNIVAL_P(fci->function_name), Z_UNILEN_P(fci->function_name) TSRMLS_CC);
if (EX(function_state).function && calling_scope != EX(function_state).function->common.scope) {
char *function_name_lc = zend_str_tolower_dup(Z_STRVAL_P(fci->function_name), Z_STRLEN_P(fci->function_name));
if (zend_hash_find(&calling_scope->function_table, function_name_lc, fci->function_name->value.str.len+1, (void **) &EX(function_state).function)==FAILURE) {
@ -721,18 +773,20 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
efree(function_name_lc);
}
} else if (calling_scope) {
char *function_name_lc = zend_str_tolower_dup(Z_STRVAL_P(fci->function_name), Z_STRLEN_P(fci->function_name));
unsigned int lcname_len;
char *lcname = zend_u_str_case_fold(Z_TYPE_P(fci->function_name), Z_UNIVAL_P(fci->function_name), Z_UNILEN_P(fci->function_name), 1, &lcname_len);
EX(function_state).function =
zend_std_get_static_method(calling_scope, function_name_lc, Z_STRLEN_P(fci->function_name) TSRMLS_CC);
efree(function_name_lc);
zend_std_get_static_method(calling_scope, lcname, lcname_len TSRMLS_CC);
efree(lcname);
} else {
char *function_name_lc = zend_str_tolower_dup(Z_STRVAL_P(fci->function_name), Z_STRLEN_P(fci->function_name));
unsigned int lcname_len;
char *lcname = zend_u_str_case_fold(Z_TYPE_P(fci->function_name), Z_UNIVAL_P(fci->function_name), Z_UNILEN_P(fci->function_name), 1, &lcname_len);
if (zend_hash_find(fci->function_table, function_name_lc, fci->function_name->value.str.len+1, (void **) &EX(function_state).function)==FAILURE) {
if (zend_u_hash_find(fci->function_table, Z_TYPE_P(fci->function_name), lcname, lcname_len+1, (void **) &EX(function_state).function)==FAILURE) {
EX(function_state).function = NULL;
}
efree(function_name_lc);
efree(lcname);
}
if (EX(function_state).function == NULL) {
@ -846,7 +900,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
} else {
severity = E_ERROR;
}
zend_error(severity, "Non-static method %s::%s() cannot be called statically", calling_scope->name, EX(function_state).function->common.function_name);
zend_error(severity, "Non-static method %v::%v() cannot be called statically", calling_scope->name, EX(function_state).function->common.function_name);
}
}
@ -860,7 +914,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
EG(active_symbol_table) = fci->symbol_table;
} else {
ALLOC_HASHTABLE(EG(active_symbol_table));
zend_hash_init(EG(active_symbol_table), 0, NULL, ZVAL_PTR_DTOR, 0);
zend_u_hash_init(EG(active_symbol_table), 0, NULL, ZVAL_PTR_DTOR, 0, UG(unicode));
}
original_return_value = EG(return_value_ptr_ptr);
@ -902,17 +956,23 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
if (EG(exception)) {
zend_throw_exception_internal(NULL TSRMLS_CC);
}
if (old_func_name) {
efree(Z_STRVAL_P(fci->function_name));
Z_TYPE_P(fci->function_name) = IS_STRING;
Z_STRVAL_P(fci->function_name) = old_func_name;
}
return SUCCESS;
}
ZEND_API int zend_lookup_class(char *name, int name_length, zend_class_entry ***ce TSRMLS_DC)
ZEND_API int zend_u_lookup_class(zend_uchar type, void *name, int name_length, zend_class_entry ***ce TSRMLS_DC)
{
zval **args[1];
zval autoload_function;
zval *class_name_ptr;
zval *retval_ptr;
int retval;
unsigned int lc_name_len;
char *lc_name;
zval *exception;
char dummy = 1;
@ -923,11 +983,10 @@ ZEND_API int zend_lookup_class(char *name, int name_length, zend_class_entry ***
return FAILURE;
}
lc_name = do_alloca(name_length + 1);
zend_str_tolower_copy(lc_name, name, name_length);
lc_name = zend_u_str_case_fold(type, name, name_length, 1, &lc_name_len);
if (zend_hash_find(EG(class_table), lc_name, name_length+1, (void **) ce) == SUCCESS) {
free_alloca(lc_name);
if (zend_u_hash_find(EG(class_table), type, lc_name, lc_name_len+1, (void **) ce) == SUCCESS) {
efree(lc_name);
return SUCCESS;
}
@ -935,17 +994,17 @@ ZEND_API int zend_lookup_class(char *name, int name_length, zend_class_entry ***
* (doesn't impact fuctionality of __autoload()
*/
if (zend_is_compiling(TSRMLS_C)) {
free_alloca(lc_name);
efree(lc_name);
return FAILURE;
}
if (EG(in_autoload) == NULL) {
ALLOC_HASHTABLE(EG(in_autoload));
zend_hash_init(EG(in_autoload), 0, NULL, NULL, 0);
zend_u_hash_init(EG(in_autoload), 0, NULL, NULL, 0, UG(unicode));
}
if (zend_hash_add(EG(in_autoload), lc_name, name_length+1, (void**)&dummy, sizeof(char), NULL) == FAILURE) {
free_alloca(lc_name);
if (zend_u_hash_add(EG(in_autoload), type, lc_name, lc_name_len+1, (void**)&dummy, sizeof(char), NULL) == FAILURE) {
efree(lc_name);
return FAILURE;
}
@ -953,7 +1012,11 @@ ZEND_API int zend_lookup_class(char *name, int name_length, zend_class_entry ***
ALLOC_ZVAL(class_name_ptr);
INIT_PZVAL(class_name_ptr);
ZVAL_STRINGL(class_name_ptr, name, name_length, 1);
if (type == IS_UNICODE) {
ZVAL_UNICODEL(class_name_ptr, name, name_length, 1);
} else {
ZVAL_STRINGL(class_name_ptr, name, name_length, 1);
}
args[0] = &class_name_ptr;
@ -979,17 +1042,17 @@ ZEND_API int zend_lookup_class(char *name, int name_length, zend_class_entry ***
zval_ptr_dtor(&class_name_ptr);
zend_hash_del(EG(in_autoload), lc_name, name_length+1);
zend_u_hash_del(EG(in_autoload), type, lc_name, lc_name_len+1);
if (retval == FAILURE) {
EG(exception) = exception;
free_alloca(lc_name);
efree(lc_name);
return FAILURE;
}
if (EG(exception) && exception) {
free_alloca(lc_name);
zend_error(E_ERROR, "Function %s(%s) threw an exception of type '%s'", ZEND_AUTOLOAD_FUNC_NAME, name, Z_OBJCE_P(EG(exception))->name);
efree(lc_name);
zend_error(E_ERROR, "Function %s(%R) threw an exception of type '%v'", ZEND_AUTOLOAD_FUNC_NAME, type, name, Z_OBJCE_P(EG(exception))->name);
return FAILURE;
}
if (!EG(exception)) {
@ -997,12 +1060,17 @@ ZEND_API int zend_lookup_class(char *name, int name_length, zend_class_entry ***
zval_ptr_dtor(&retval_ptr);
}
retval = zend_hash_find(EG(class_table), lc_name, name_length + 1, (void **) ce);
free_alloca(lc_name);
retval = zend_u_hash_find(EG(class_table), type, lc_name, lc_name_len + 1, (void **) ce);
efree(lc_name);
return retval;
}
ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name TSRMLS_DC)
ZEND_API int zend_lookup_class(char *name, int name_length, zend_class_entry ***ce TSRMLS_DC)
{
return zend_u_lookup_class(IS_STRING, name, name_length, ce TSRMLS_CC);
}
ZEND_API int zend_u_eval_string(zend_uchar type, void *string, zval *retval_ptr, char *string_name TSRMLS_DC)
{
zval pv;
zend_op_array *new_op_array;
@ -1011,17 +1079,34 @@ ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name TSR
zend_uchar original_handle_op_arrays;
int retval;
if (retval_ptr) {
pv.value.str.len = strlen(str)+sizeof("return ;")-1;
pv.value.str.val = emalloc(pv.value.str.len+1);
strcpy(pv.value.str.val, "return ");
strcat(pv.value.str.val, str);
strcat(pv.value.str.val, " ;");
if (type == IS_UNICODE) {
UChar *str = (UChar*)string;
if (retval_ptr) {
pv.value.ustr.len = u_strlen(str)+sizeof("return ;")-1;
pv.value.ustr.val = eumalloc(pv.value.ustr.len+1);
u_strcpy(pv.value.ustr.val, u_return);
u_strcat(pv.value.ustr.val, str);
u_strcat(pv.value.ustr.val, u_semicolon);
} else {
pv.value.ustr.len = u_strlen(str);
pv.value.ustr.val = eustrndup(str, pv.value.str.len);
}
} else {
pv.value.str.len = strlen(str);
pv.value.str.val = estrndup(str, pv.value.str.len);
char *str = (char*)string;
if (retval_ptr) {
pv.value.str.len = strlen(str)+sizeof("return ;")-1;
pv.value.str.val = emalloc(pv.value.str.len+1);
strcpy(pv.value.str.val, "return ");
strcat(pv.value.str.val, str);
strcat(pv.value.str.val, " ;");
} else {
pv.value.str.len = strlen(str);
pv.value.str.val = estrndup(str, pv.value.str.len);
}
}
pv.type = IS_STRING;
pv.type = type;
/*printf("Evaluating '%s'\n", pv.value.str.val);*/
@ -1068,8 +1153,12 @@ ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name TSR
return retval;
}
ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name TSRMLS_DC)
{
return zend_u_eval_string(IS_STRING, str, retval_ptr, string_name TSRMLS_CC);
}
ZEND_API int zend_eval_string_ex(char *str, zval *retval_ptr, char *string_name, int handle_exceptions TSRMLS_DC)
ZEND_API int zend_u_eval_string_ex(zend_uchar type, void *str, zval *retval_ptr, char *string_name, int handle_exceptions TSRMLS_DC)
{
int result;
@ -1081,6 +1170,11 @@ ZEND_API int zend_eval_string_ex(char *str, zval *retval_ptr, char *string_name,
return result;
}
ZEND_API int zend_eval_string_ex(char *str, zval *retval_ptr, char *string_name, int handle_exceptions TSRMLS_DC)
{
return zend_u_eval_string_ex(IS_STRING, str, retval_ptr, string_name, handle_exceptions TSRMLS_CC);
}
void execute_new_code(TSRMLS_D)
{
@ -1324,7 +1418,7 @@ void zend_unset_timeout(TSRMLS_D)
}
zend_class_entry *zend_fetch_class(char *class_name, uint class_name_len, int fetch_type TSRMLS_DC)
ZEND_API zend_class_entry *zend_u_fetch_class(zend_uchar type, void *class_name, uint class_name_len, int fetch_type TSRMLS_DC)
{
zend_class_entry **pce;
@ -1344,7 +1438,7 @@ check_fetch_type:
}
return EG(scope)->parent;
case ZEND_FETCH_CLASS_AUTO: {
fetch_type = zend_get_class_fetch_type(class_name, class_name_len);
fetch_type = zend_get_class_fetch_type(type, class_name, class_name_len);
if (fetch_type!=ZEND_FETCH_CLASS_DEFAULT) {
goto check_fetch_type;
}
@ -1352,24 +1446,28 @@ check_fetch_type:
break;
}
if (zend_lookup_class(class_name, class_name_len, &pce TSRMLS_CC)==FAILURE) {
if (zend_u_lookup_class(type, class_name, class_name_len, &pce TSRMLS_CC)==FAILURE) {
if (fetch_type == ZEND_FETCH_CLASS_INTERFACE) {
zend_error(E_ERROR, "Interface '%s' not found", class_name);
zend_error(E_ERROR, "Interface '%R' not found", type, class_name);
} else {
zend_error(E_ERROR, "Class '%s' not found", class_name);
zend_error(E_ERROR, "Class '%R' not found", type, class_name);
}
}
return *pce;
}
zend_class_entry *zend_fetch_class(char *class_name, uint class_name_len, int fetch_type TSRMLS_DC)
{
return zend_u_fetch_class(IS_STRING, class_name, class_name_len, fetch_type TSRMLS_CC);
}
#define MAX_ABSTRACT_INFO_CNT 3
#define MAX_ABSTRACT_INFO_FMT "%s%s%s%s"
#define MAX_ABSTRACT_INFO_FMT "%v%s%v%s"
#define DISPLAY_ABSTRACT_FN(idx) \
ai.afn[idx] ? ZEND_FN_SCOPE_NAME(ai.afn[idx]) : "", \
ai.afn[idx] ? ZEND_FN_SCOPE_NAME(ai.afn[idx]) : EMPTY_STR, \
ai.afn[idx] ? "::" : "", \
ai.afn[idx] ? ai.afn[idx]->common.function_name : "", \
ai.afn[idx] ? ai.afn[idx]->common.function_name : EMPTY_STR, \
ai.afn[idx] && ai.afn[idx+1] ? ", " : (ai.afn[idx] && ai.cnt > MAX_ABSTRACT_INFO_CNT ? ", ..." : "")
typedef struct _zend_abstract_info {
@ -1400,7 +1498,7 @@ void zend_verify_abstract_class(zend_class_entry *ce TSRMLS_DC)
zend_hash_apply_with_argument(&ce->function_table, (apply_func_arg_t) zend_verify_abstract_class_function, &ai TSRMLS_CC);
if (ai.cnt) {
zend_error(E_ERROR, "Class %s contains %d abstract method%s and must therefore be declared abstract or implement the remaining methods (" MAX_ABSTRACT_INFO_FMT MAX_ABSTRACT_INFO_FMT MAX_ABSTRACT_INFO_FMT ")",
zend_error(E_ERROR, "Class %v contains %d abstract method%s and must therefore be declared abstract or implement the remaining methods (" MAX_ABSTRACT_INFO_FMT MAX_ABSTRACT_INFO_FMT MAX_ABSTRACT_INFO_FMT ")",
ce->name, ai.cnt,
ai.cnt > 1 ? "s" : "",
DISPLAY_ABSTRACT_FN(0),
@ -1425,30 +1523,35 @@ ZEND_API void zend_reset_all_cv(HashTable *symbol_table TSRMLS_DC)
}
}
ZEND_API int zend_delete_global_variable(char *name, int name_len TSRMLS_DC)
ZEND_API int zend_u_delete_global_variable(zend_uchar type, void *name, int name_len TSRMLS_DC)
{
zend_execute_data *ex;
ulong hash_value = zend_inline_hash_func(name, name_len+1);
ulong hash_value = zend_u_inline_hash_func(type, name, name_len+1);
if (zend_hash_quick_exists(&EG(symbol_table), name, name_len+1, hash_value)) {
if (zend_u_hash_quick_exists(&EG(symbol_table), type, name, name_len+1, hash_value)) {
for (ex = EG(current_execute_data); ex; ex = ex->prev_execute_data) {
if (ex->symbol_table == &EG(symbol_table)) {
int i;
for (i = 0; i < ex->op_array->last_var; i++) {
if (ex->op_array->vars[i].hash_value == hash_value &&
ex->op_array->vars[i].name_len == name_len &&
!memcmp(ex->op_array->vars[i].name, name, name_len)) {
!memcmp(ex->op_array->vars[i].name, name, type==IS_UNICODE?UBYTES(name_len):name_len)) {
ex->CVs[i] = NULL;
break;
}
}
}
}
return zend_hash_del(&EG(symbol_table), name, name_len+1);
return zend_u_hash_del(&EG(symbol_table), type, name, name_len+1);
}
return FAILURE;
}
ZEND_API int zend_delete_global_variable(char *name, int name_len TSRMLS_DC)
{
return zend_u_delete_global_variable(IS_STRING, name, name_len TSRMLS_CC);
}
/*
* Local variables:
* tab-width: 4

View File

@ -5,7 +5,7 @@
| Copyright (c) 1998-2005 Zend Technologies Ltd. (http://www.zend.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 2.00 of the Zend license, |
| that is bundled with this package in the file LICENSE, and is |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.zend.com/license/2_00.txt. |
| If you did not receive a copy of the Zend license and are unable to |
@ -36,9 +36,8 @@
#include "zend_objects_API.h"
#include "zend_modules.h"
#ifdef ZEND_MULTIBYTE
#include "zend_multibyte.h"
#endif /* ZEND_MULTIBYTE */
#include <unicode/ucnv.h>
#include <unicode/ucol.h>
/* Define ZTS if you want a thread-safe Zend */
/*#undef ZTS*/
@ -132,17 +131,16 @@ struct _zend_compiler_globals {
char *doc_comment;
zend_uint doc_comment_len;
#ifdef ZEND_MULTIBYTE
zend_encoding **script_encoding_list;
int script_encoding_list_size;
zend_uchar literal_type;
zend_encoding *internal_encoding;
/* multibyte utility functions */
zend_encoding_detector encoding_detector;
zend_encoding_converter encoding_converter;
zend_encoding_oddlen encoding_oddlen;
#endif /* ZEND_MULTIBYTE */
#ifdef ZTS
HashTable *global_function_table;
HashTable *global_class_table;
HashTable *global_auto_globals_table;
HashTable *global_u_function_table;
HashTable *global_u_class_table;
HashTable *global_u_auto_globals_table;
#endif
};
@ -232,6 +230,11 @@ struct _zend_executor_globals {
zend_property_info std_property_info;
#ifdef ZTS
HashTable *global_constants_table;
HashTable *global_u_constants_table;
#endif
void *reserved[ZEND_MAX_RESERVED_RESOURCES];
};
@ -286,21 +289,31 @@ struct _zend_scanner_globals {
int yy_start_stack_depth;
int *yy_start_stack;
#ifdef ZEND_MULTIBYTE
/* original (unfiltered) script */
char *script_org;
int script_org_size;
UConverter *input_conv; /* converter for flex input */
UConverter *output_conv; /* converter for data from flex output */
zend_bool encoding_checked;
char* rest_str;
int rest_len;
};
/* filtered script */
char *script_filtered;
int script_filtered_size;
struct _zend_unicode_globals {
zend_bool unicode; /* indicates whether full Unicode mode is enabled */
/* input/ouput filters */
zend_encoding_filter input_filter;
zend_encoding_filter output_filter;
zend_encoding *script_encoding;
zend_encoding *internal_encoding;
#endif /* ZEND_MULTIBYTE */
UConverter *fallback_encoding_conv; /* converter for default encoding for IS_STRING type */
UConverter *runtime_encoding_conv; /* runtime encoding converter */
UConverter *output_encoding_conv; /* output layer converter */
UConverter *script_encoding_conv; /* default script encoding converter */
UConverter *http_input_encoding_conv;/* http input encoding converter */
UConverter *utf8_conv; /* all-purpose UTF-8 converter */
uint8_t from_u_error_mode;
UChar subst_char[3];
uint8_t subst_char_len;
char *default_locale;
UCollator *default_collator;
HashTable flex_compatible;
};
#endif /* ZEND_GLOBALS_H */

View File

@ -26,6 +26,7 @@ typedef struct _zend_compiler_globals zend_compiler_globals;
typedef struct _zend_executor_globals zend_executor_globals;
typedef struct _zend_alloc_globals zend_alloc_globals;
typedef struct _zend_scanner_globals zend_scanner_globals;
typedef struct _zend_unicode_globals zend_unicode_globals;
/* Compiler */
#ifdef ZTS
@ -78,6 +79,16 @@ extern ZEND_API zend_scanner_globals ini_scanner_globals;
#endif
/* Unicode */
#ifdef ZTS
# define UG(v) TSRMG(unicode_globals_id, zend_unicode_globals *, v)
extern ZEND_API ts_rsrc_id unicode_globals_id;
#else
# define UG(v) (unicode_globals.v)
extern ZEND_API zend_unicode_globals unicode_globals;
#endif
/* For limited downwards source compatibility */
#define CLS_FETCH()
#define ELS_FETCH()

File diff suppressed because it is too large Load Diff

View File

@ -28,6 +28,8 @@
#define HASH_KEY_IS_STRING 1
#define HASH_KEY_IS_LONG 2
#define HASH_KEY_NON_EXISTANT 3
#define HASH_KEY_IS_BINARY 4
#define HASH_KEY_IS_UNICODE 5
#define HASH_UPDATE (1<<0)
#define HASH_ADD (1<<1)
@ -36,6 +38,10 @@
#define HASH_DEL_KEY 0
#define HASH_DEL_INDEX 1
#define REAL_KEY_SIZE(type, nKeyLength) \
((type == IS_UNICODE)?UBYTES(nKeyLength):nKeyLength)
typedef ulong (*hash_func_t)(char *arKey, uint nKeyLength);
typedef int (*compare_func_t)(const void *, const void * TSRMLS_DC);
typedef void (*sort_func_t)(void *, size_t, register size_t, compare_func_t TSRMLS_DC);
@ -45,6 +51,14 @@ typedef void (*copy_ctor_param_func_t)(void *pElement, void *pParam);
struct _hashtable;
typedef struct _key {
zend_uchar type;
union {
char string[1]; /* Must be last element */
UChar unicode[1]; /* Must be last element */
} u;
} HashKey;
typedef struct bucket {
ulong h; /* Used for numeric indexing */
uint nKeyLength;
@ -54,7 +68,7 @@ typedef struct bucket {
struct bucket *pListLast;
struct bucket *pNext;
struct bucket *pLast;
char arKey[1]; /* Must be last element */
HashKey key; /* Must be last element */
} Bucket;
typedef struct _hashtable {
@ -68,6 +82,7 @@ typedef struct _hashtable {
Bucket **arBuckets;
dtor_func_t pDestructor;
zend_bool persistent;
zend_bool unicode;
unsigned char nApplyCount;
zend_bool bApplyProtection;
#if ZEND_DEBUG
@ -77,9 +92,13 @@ typedef struct _hashtable {
typedef struct _zend_hash_key {
char *arKey;
uint nKeyLength;
ulong h;
uint nKeyLength;
zend_uchar type;
union {
char *string;
UChar *unicode;
} u;
} zend_hash_key;
@ -91,24 +110,38 @@ BEGIN_EXTERN_C()
/* startup/shutdown */
ZEND_API int _zend_hash_init(HashTable *ht, uint nSize, hash_func_t pHashFunction, dtor_func_t pDestructor, zend_bool persistent ZEND_FILE_LINE_DC);
ZEND_API int _zend_u_hash_init(HashTable *ht, uint nSize, hash_func_t pHashFunction, dtor_func_t pDestructor, zend_bool persistent, zend_bool unicode ZEND_FILE_LINE_DC);
ZEND_API int _zend_hash_init_ex(HashTable *ht, uint nSize, hash_func_t pHashFunction, dtor_func_t pDestructor, zend_bool persistent, zend_bool bApplyProtection ZEND_FILE_LINE_DC);
ZEND_API int _zend_u_hash_init_ex(HashTable *ht, uint nSize, hash_func_t pHashFunction, dtor_func_t pDestructor, zend_bool persistent, zend_bool unicode, zend_bool bApplyProtection ZEND_FILE_LINE_DC);
ZEND_API void zend_hash_destroy(HashTable *ht);
ZEND_API void zend_hash_clean(HashTable *ht);
#define zend_hash_init(ht, nSize, pHashFunction, pDestructor, persistent) _zend_hash_init((ht), (nSize), (pHashFunction), (pDestructor), (persistent) ZEND_FILE_LINE_CC)
#define zend_u_hash_init(ht, nSize, pHashFunction, pDestructor, persistent, unicode) _zend_u_hash_init((ht), (nSize), (pHashFunction), (pDestructor), (persistent), (unicode) ZEND_FILE_LINE_CC)
#define zend_hash_init_ex(ht, nSize, pHashFunction, pDestructor, persistent, bApplyProtection) _zend_hash_init_ex((ht), (nSize), (pHashFunction), (pDestructor), (persistent), (bApplyProtection) ZEND_FILE_LINE_CC)
#define zend_u_hash_init_ex(ht, nSize, pHashFunction, pDestructor, persistent, unicode, bApplyProtection) _zend_u_hash_init_ex((ht), (nSize), (pHashFunction), (pDestructor), (persistent), (unicode), (bApplyProtection) ZEND_FILE_LINE_CC)
/* additions/updates/changes */
ZEND_API int _zend_hash_add_or_update(HashTable *ht, char *arKey, uint nKeyLength, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC);
ZEND_API int _zend_u_hash_add_or_update(HashTable *ht, zend_uchar type, void *arKey, uint nKeyLength, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC);
#define zend_hash_update(ht, arKey, nKeyLength, pData, nDataSize, pDest) \
_zend_hash_add_or_update(ht, arKey, nKeyLength, pData, nDataSize, pDest, HASH_UPDATE ZEND_FILE_LINE_CC)
#define zend_u_hash_update(ht, type, arKey, nKeyLength, pData, nDataSize, pDest) \
_zend_u_hash_add_or_update(ht, type, arKey, nKeyLength, pData, nDataSize, pDest, HASH_UPDATE ZEND_FILE_LINE_CC)
#define zend_hash_add(ht, arKey, nKeyLength, pData, nDataSize, pDest) \
_zend_hash_add_or_update(ht, arKey, nKeyLength, pData, nDataSize, pDest, HASH_ADD ZEND_FILE_LINE_CC)
#define zend_u_hash_add(ht, type, arKey, nKeyLength, pData, nDataSize, pDest) \
_zend_u_hash_add_or_update(ht, type, arKey, nKeyLength, pData, nDataSize, pDest, HASH_ADD ZEND_FILE_LINE_CC)
ZEND_API int _zend_hash_quick_add_or_update(HashTable *ht, char *arKey, uint nKeyLength, ulong h, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC);
ZEND_API int _zend_u_hash_quick_add_or_update(HashTable *ht, zend_uchar type, void *arKey, uint nKeyLength, ulong h, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC);
#define zend_hash_quick_update(ht, arKey, nKeyLength, h, pData, nDataSize, pDest) \
_zend_hash_quick_add_or_update(ht, arKey, nKeyLength, h, pData, nDataSize, pDest, HASH_UPDATE ZEND_FILE_LINE_CC)
#define zend_u_hash_quick_update(ht, type, arKey, nKeyLength, h, pData, nDataSize, pDest) \
_zend_u_hash_quick_add_or_update(ht, type, arKey, nKeyLength, h, pData, nDataSize, pDest, HASH_UPDATE ZEND_FILE_LINE_CC)
#define zend_hash_quick_add(ht, arKey, nKeyLength, h, pData, nDataSize, pDest) \
_zend_hash_quick_add_or_update(ht, arKey, nKeyLength, h, pData, nDataSize, pDest, HASH_ADD ZEND_FILE_LINE_CC)
#define zend_u_hash_quick_add(ht, type, arKey, nKeyLength, h, pData, nDataSize, pDest) \
_zend_u_hash_quick_add_or_update(ht, type, arKey, nKeyLength, h, pData, nDataSize, pDest, HASH_ADD ZEND_FILE_LINE_CC)
ZEND_API int _zend_hash_index_update_or_next_insert(HashTable *ht, ulong h, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC);
#define zend_hash_index_update(ht, h, pData, nDataSize, pDest) \
@ -117,6 +150,7 @@ ZEND_API int _zend_hash_index_update_or_next_insert(HashTable *ht, ulong h, void
_zend_hash_index_update_or_next_insert(ht, 0, pData, nDataSize, pDest, HASH_NEXT_INSERT ZEND_FILE_LINE_CC)
ZEND_API int zend_hash_add_empty_element(HashTable *ht, char *arKey, uint nKeyLength);
ZEND_API int zend_u_hash_add_empty_element(HashTable *ht, zend_uchar type, void *arKey, uint nKeyLength);
#define ZEND_HASH_APPLY_KEEP 0
@ -145,21 +179,29 @@ ZEND_API void zend_hash_reverse_apply(HashTable *ht, apply_func_t apply_func TSR
/* Deletes */
ZEND_API int zend_hash_del_key_or_index(HashTable *ht, char *arKey, uint nKeyLength, ulong h, int flag);
ZEND_API int zend_u_hash_del_key_or_index(HashTable *ht, zend_uchar type, void *arKey, uint nKeyLength, ulong h, int flag);
#define zend_hash_del(ht, arKey, nKeyLength) \
zend_hash_del_key_or_index(ht, arKey, nKeyLength, 0, HASH_DEL_KEY)
#define zend_u_hash_del(ht, type, arKey, nKeyLength) \
zend_u_hash_del_key_or_index(ht, type, arKey, nKeyLength, 0, HASH_DEL_KEY)
#define zend_hash_index_del(ht, h) \
zend_hash_del_key_or_index(ht, NULL, 0, h, HASH_DEL_INDEX)
ZEND_API ulong zend_get_hash_value(char *arKey, uint nKeyLength);
ZEND_API ulong zend_u_get_hash_value(zend_uchar type, char *arKey, uint nKeyLength);
/* Data retreival */
ZEND_API int zend_hash_find(HashTable *ht, char *arKey, uint nKeyLength, void **pData);
ZEND_API int zend_u_hash_find(HashTable *ht, zend_uchar type, void *arKey, uint nKeyLength, void **pData);
ZEND_API int zend_hash_quick_find(HashTable *ht, char *arKey, uint nKeyLength, ulong h, void **pData);
ZEND_API int zend_u_hash_quick_find(HashTable *ht, zend_uchar type, void *arKey, uint nKeyLength, ulong h, void **pData);
ZEND_API int zend_hash_index_find(HashTable *ht, ulong h, void **pData);
/* Misc */
ZEND_API int zend_hash_exists(HashTable *ht, char *arKey, uint nKeyLength);
ZEND_API int zend_u_hash_exists(HashTable *ht, zend_uchar type, void *arKey, uint nKeyLength);
ZEND_API int zend_hash_quick_exists(HashTable *ht, char *arKey, uint nKeyLength, ulong h);
ZEND_API int zend_u_hash_quick_exists(HashTable *ht, zend_uchar type, void *arKey, uint nKeyLength, ulong h);
ZEND_API int zend_hash_index_exists(HashTable *ht, ulong h);
ZEND_API ulong zend_hash_next_free_element(HashTable *ht);
@ -272,8 +314,11 @@ EMPTY_SWITCH_DEFAULT_CASE()
return hash;
}
#define zend_u_inline_hash_func(type, arKey, nKeyLength) \
zend_inline_hash_func(arKey, REAL_KEY_SIZE(type, nKeyLength))
ZEND_API ulong zend_hash_func(char *arKey, uint nKeyLength);
ZEND_API ulong zend_u_hash_func(zend_uchar type, char *arKey, uint nKeyLength);
#if ZEND_DEBUG
/* debug */
@ -290,68 +335,15 @@ END_EXTERN_C()
zend_hash_init(ht, n, NULL, ZVAL_PTR_DTOR, persistent)
#define HANDLE_NUMERIC(key, length, func) { \
register char *tmp=key; \
\
if (*tmp=='-') { \
tmp++; \
} \
if ((*tmp>='0' && *tmp<='9')) do { /* possibly a numeric index */ \
char *end=key+length-1; \
long idx; \
\
if (*tmp++=='0' && length>2) { /* don't accept numbers with leading zeros */ \
break; \
} \
while (tmp<end) { \
if (!(*tmp>='0' && *tmp<='9')) { \
break; \
} \
tmp++; \
} \
if (tmp==end && *tmp=='\0') { /* a numeric index */ \
if (*key=='-') { \
idx = strtol(key, NULL, 10); \
if (idx!=LONG_MIN) { \
return func; \
} \
} else { \
idx = strtol(key, NULL, 10); \
if (idx!=LONG_MAX) { \
return func; \
} \
} \
} \
} while (0); \
}
ZEND_API int zend_symtable_update(HashTable *ht, char *arKey, uint nKeyLength, void *pData, uint nDataSize, void **pDest);
ZEND_API int zend_symtable_del(HashTable *ht, char *arKey, uint nKeyLength);
ZEND_API int zend_symtable_find(HashTable *ht, char *arKey, uint nKeyLength, void **pData);
ZEND_API int zend_symtable_exists(HashTable *ht, char *arKey, uint nKeyLength);
static inline int zend_symtable_update(HashTable *ht, char *arKey, uint nKeyLength, void *pData, uint nDataSize, void **pDest) \
{
HANDLE_NUMERIC(arKey, nKeyLength, zend_hash_index_update(ht, idx, pData, nDataSize, pDest));
return zend_hash_update(ht, arKey, nKeyLength, pData, nDataSize, pDest);
}
static inline int zend_symtable_del(HashTable *ht, char *arKey, uint nKeyLength)
{
HANDLE_NUMERIC(arKey, nKeyLength, zend_hash_index_del(ht, idx))
return zend_hash_del(ht, arKey, nKeyLength);
}
static inline int zend_symtable_find(HashTable *ht, char *arKey, uint nKeyLength, void **pData)
{
HANDLE_NUMERIC(arKey, nKeyLength, zend_hash_index_find(ht, idx, pData));
return zend_hash_find(ht, arKey, nKeyLength, pData);
}
static inline int zend_symtable_exists(HashTable *ht, char *arKey, uint nKeyLength)
{
HANDLE_NUMERIC(arKey, nKeyLength, zend_hash_index_exists(ht, idx));
return zend_hash_exists(ht, arKey, nKeyLength);
}
ZEND_API int zend_u_symtable_update(HashTable *ht, zend_uchar type, void *arKey, uint nKeyLength, void *pData, uint nDataSize, void **pDest);
ZEND_API int zend_u_symtable_del(HashTable *ht, zend_uchar type, void *arKey, uint nKeyLength);
ZEND_API int zend_u_symtable_find(HashTable *ht, zend_uchar type, void *arKey, uint nKeyLength, void **pData);
ZEND_API int zend_u_symtable_exists(HashTable *ht, zend_uchar type, void *arKey, uint nKeyLength);
#endif /* ZEND_HASH_H */

View File

@ -25,6 +25,7 @@
#include "zend_highlight.h"
#include "zend_ptr_stack.h"
#include "zend_globals.h"
#include "zend_operators.h"
ZEND_API void zend_html_putc(char c)
{
@ -96,6 +97,7 @@ ZEND_API void zend_highlight(zend_syntax_highlighter_ini *syntax_highlighter_ini
char *next_color;
int in_string=0, post_heredoc = 0;
CG(literal_type) = IS_STRING;
zend_printf("<code>");
zend_printf("<span style=\"color: %s\">\n", last_color);
/* highlight stuff coming back from zendlex() */
@ -119,7 +121,7 @@ ZEND_API void zend_highlight(zend_syntax_highlighter_ini *syntax_highlighter_ini
case T_CONSTANT_ENCAPSED_STRING:
next_color = syntax_highlighter_ini->highlight_string;
break;
case '"':
case '"':
next_color = syntax_highlighter_ini->highlight_string;
in_string = !in_string;
break;
@ -162,7 +164,9 @@ ZEND_API void zend_highlight(zend_syntax_highlighter_ini *syntax_highlighter_ini
break;
}
if (token.type == IS_STRING) {
if (token.type == IS_STRING ||
token.type == IS_BINARY ||
token.type == IS_UNICODE) {
switch (token_type) {
case T_OPEN_TAG:
case T_OPEN_TAG_WITH_ECHO:
@ -172,11 +176,11 @@ ZEND_API void zend_highlight(zend_syntax_highlighter_ini *syntax_highlighter_ini
case T_DOC_COMMENT:
break;
default:
efree(token.value.str.val);
efree(Z_UNIVAL(token));
break;
}
} else if (token_type == T_END_HEREDOC) {
efree(token.value.str.val);
efree(Z_UNIVAL(token));
}
token.type = 0;
}
@ -195,6 +199,7 @@ ZEND_API void zend_strip(TSRMLS_D)
int token_type;
int prev_space = 0;
CG(literal_type) = IS_STRING;
token.type = 0;
while ((token_type=lex_scan(&token TSRMLS_CC))) {
switch (token_type) {
@ -218,7 +223,7 @@ ZEND_API void zend_strip(TSRMLS_D)
if (ptr[LANG_SCNG(yy_leng) - 1] == ';') {
lex_scan(&token TSRMLS_CC);
}
efree(token.value.str.val);
efree(Z_UNIVAL(token));
}
break;
@ -227,7 +232,9 @@ ZEND_API void zend_strip(TSRMLS_D)
break;
}
if (token.type == IS_STRING) {
if (token.type == IS_STRING ||
token.type == IS_BINARY ||
token.type == IS_UNICODE) {
switch (token_type) {
case T_OPEN_TAG:
case T_OPEN_TAG_WITH_ECHO:
@ -238,7 +245,7 @@ ZEND_API void zend_strip(TSRMLS_D)
break;
default:
efree(token.value.str.val);
efree(Z_UNIVAL(token));
break;
}
}

View File

@ -134,7 +134,8 @@ static int ini_key_compare(const void *a, const void *b TSRMLS_DC)
} else if (s->nKeyLength==0) { /* s is numeric, f is not */
return 1;
} else { /* both strings */
return zend_binary_strcasecmp(f->arKey, f->nKeyLength, s->arKey, s->nKeyLength);
/*FIXME: unicode hash*/
return zend_binary_strcasecmp(f->key.u.string, f->nKeyLength, s->key.u.string, s->nKeyLength);
}
}

View File

@ -48,6 +48,10 @@ ZEND_API ts_rsrc_id ini_scanner_globals_id;
ZEND_API zend_scanner_globals ini_scanner_globals;
#endif
# define YY_INPUT(buf, result, max_size) \
if ( ((result = zend_stream_read(yyin, buf, max_size TSRMLS_CC)) == 0) \
&& zend_stream_ferror( yyin TSRMLS_CC) ) \
YY_FATAL_ERROR( "input in flex scanner failed" );
static char *ini_filename;

View File

@ -74,7 +74,7 @@ ZEND_API zval* zend_call_method(zval **object_pp, zend_class_entry *obj_ce, zend
if (!fn_proxy || !*fn_proxy) {
if (zend_hash_find(function_table, function_name, function_name_len+1, (void **) &fcic.function_handler) == FAILURE) {
/* error at c-level */
zend_error(E_CORE_ERROR, "Couldn't find implementation for method %s%s%s", obj_ce ? obj_ce->name : "", obj_ce ? "::" : "", function_name);
zend_error(E_CORE_ERROR, "Couldn't find implementation for method %v%s%s", obj_ce ? obj_ce->name : EMPTY_STR, obj_ce ? "::" : "", function_name);
}
if (fn_proxy) {
*fn_proxy = fcic.function_handler;
@ -91,7 +91,7 @@ ZEND_API zval* zend_call_method(zval **object_pp, zend_class_entry *obj_ce, zend
if (!obj_ce) {
obj_ce = object_pp ? Z_OBJCE_PP(object_pp) : NULL;
}
zend_error(E_CORE_ERROR, "Couldn't execute method %s%s%s", obj_ce ? obj_ce->name : "", obj_ce ? "::" : "", function_name);
zend_error(E_CORE_ERROR, "Couldn't execute method %v%s%s", obj_ce ? obj_ce->name : EMPTY_STR, obj_ce ? "::" : "", function_name);
}
if (!retval_ptr_ptr) {
if (retval) {
@ -195,24 +195,36 @@ static int zend_user_it_get_current_key(zend_object_iterator *_iter, char **str_
*int_key = 0;
if (!EG(exception))
{
zend_error(E_WARNING, "Nothing returned from %s::key()", iter->ce->name);
zend_error(E_WARNING, "Nothing returned from %v::key()", iter->ce->name);
}
return HASH_KEY_IS_LONG;
}
switch (retval->type) {
default:
zend_error(E_WARNING, "Illegal type returned from %s::key()", iter->ce->name);
zend_error(E_WARNING, "Illegal type returned from %v::key()", iter->ce->name);
case IS_NULL:
*int_key = 0;
zval_ptr_dtor(&retval);
return HASH_KEY_IS_LONG;
case IS_STRING:
*str_key = estrndup(retval->value.str.val, retval->value.str.len);
*str_key = estrndup(Z_STRVAL_P(retval), Z_STRLEN_P(retval));
*str_key_len = retval->value.str.len+1;
zval_ptr_dtor(&retval);
return HASH_KEY_IS_STRING;
case IS_BINARY:
*str_key = estrndup(Z_STRVAL_P(retval), Z_STRLEN_P(retval));
*str_key_len = retval->value.str.len+1;
zval_ptr_dtor(&retval);
return HASH_KEY_IS_BINARY;
case IS_UNICODE:
*str_key = (char*)eustrndup(Z_USTRVAL_P(retval), Z_USTRLEN_P(retval));
*str_key_len = retval->value.str.len+1;
zval_ptr_dtor(&retval);
return HASH_KEY_IS_UNICODE;
case IS_DOUBLE:
case IS_RESOURCE:
case IS_BOOL:
@ -286,7 +298,7 @@ static zend_object_iterator *zend_user_it_get_new_iterator(zend_class_entry *ce,
if (!ce || !ce_it || !ce_it->get_iterator || (ce_it->get_iterator == zend_user_it_get_new_iterator && iterator == object)) {
if (!EG(exception))
{
zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Objects returned by %s::getIterator() must be traversable or implement interface Iterator", ce->name);
zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Objects returned by %v::getIterator() must be traversable or implement interface Iterator", ce->name);
}
if (iterator)
{
@ -314,7 +326,7 @@ static int zend_implement_traversable(zend_class_entry *interface, zend_class_en
return SUCCESS;
}
}
zend_error(E_CORE_ERROR, "Class %s must implement interface %s as part of either %s or %s",
zend_error(E_CORE_ERROR, "Class %v must implement interface %v as part of either %v or %v",
class_type->name,
zend_ce_traversable->name,
zend_ce_iterator->name,
@ -550,6 +562,14 @@ ZEND_API void zend_register_interfaces(TSRMLS_D)
}
/* }}} */
void init_interfaces(TSRMLS_D)
{
zend_ce_traversable = zend_get_named_class_entry("Traversable", sizeof("Traversable")-1 TSRMLS_CC);
zend_ce_aggregate = zend_get_named_class_entry("IteratorAggregate", sizeof("IteratorAggregate")-1 TSRMLS_CC);
zend_ce_iterator = zend_get_named_class_entry("Iterator", sizeof("Iterator")-1 TSRMLS_CC);
zend_ce_arrayaccess = zend_get_named_class_entry("ArrayAccess", sizeof("ArrayAccess")-1 TSRMLS_CC);
}
/*
* Local variables:
* tab-width: 4

View File

@ -51,6 +51,8 @@ ZEND_API zval* zend_call_method(zval **object_pp, zend_class_entry *obj_ce, zend
ZEND_API void zend_register_interfaces(TSRMLS_D);
void init_interfaces(TSRMLS_D);
END_EXTERN_C()
#endif /* ZEND_INTERFACES_H */

View File

@ -71,7 +71,7 @@
%left '*' '/' '%'
%right '!'
%nonassoc T_INSTANCEOF
%right '~' T_INC T_DEC T_INT_CAST T_DOUBLE_CAST T_STRING_CAST T_ARRAY_CAST T_OBJECT_CAST T_BOOL_CAST T_UNSET_CAST '@'
%right '~' T_INC T_DEC T_INT_CAST T_DOUBLE_CAST T_STRING_CAST T_UNICODE_CAST T_BINARY_CAST T_ARRAY_CAST T_OBJECT_CAST T_BOOL_CAST T_UNSET_CAST '@'
%right '['
%nonassoc T_NEW T_CLONE
%token T_EXIT
@ -145,6 +145,8 @@
%token T_DOLLAR_OPEN_CURLY_BRACES
%token T_CURLY_OPEN
%token T_PAAMAYIM_NEKUDOTAYIM
%token T_BINARY_DOUBLE
%token T_BINARY_HEREDOC
%% /* Rules */
@ -210,7 +212,7 @@ unticked_statement:
| T_GLOBAL global_var_list ';'
| T_STATIC static_var_list ';'
| T_ECHO echo_expr_list ';'
| T_INLINE_HTML { zend_do_echo(&$1 TSRMLS_CC); }
| T_INLINE_HTML { zend_do_echo(&$1, 1 TSRMLS_CC); }
| expr ';' { zend_do_free(&$1 TSRMLS_CC); }
| T_USE use_filename ';' { zend_error(E_COMPILE_ERROR,"use: Not yet supported. Please use include_once() or require_once()"); zval_dtor(&$2.u.constant); }
| T_UNSET '(' unset_variables ')' ';'
@ -466,8 +468,8 @@ global_var_list:
global_var:
T_VARIABLE { $$ = $1; }
| '$' r_variable { $$ = $2; }
| '$' '{' expr '}' { $$ = $3; }
| '$' r_variable { zend_do_normalization(&$$, &$2 TSRMLS_CC); }
| '$' '{' expr '}' { zend_do_normalization(&$$, &$3 TSRMLS_CC); }
;
@ -536,8 +538,8 @@ class_constant_declaration:
;
echo_expr_list:
echo_expr_list ',' expr { zend_do_echo(&$3 TSRMLS_CC); }
| expr { zend_do_echo(&$1 TSRMLS_CC); }
echo_expr_list ',' expr { zend_do_echo(&$3, 0 TSRMLS_CC); }
| expr { zend_do_echo(&$1, 0 TSRMLS_CC); }
;
@ -610,6 +612,8 @@ expr_without_variable:
| T_INT_CAST expr { zend_do_cast(&$$, &$2, IS_LONG TSRMLS_CC); }
| T_DOUBLE_CAST expr { zend_do_cast(&$$, &$2, IS_DOUBLE TSRMLS_CC); }
| T_STRING_CAST expr { zend_do_cast(&$$, &$2, IS_STRING TSRMLS_CC); }
| T_UNICODE_CAST expr { zend_do_cast(&$$, &$2, IS_UNICODE TSRMLS_CC); }
| T_BINARY_CAST expr { zend_do_cast(&$$, &$2, UG(unicode)?IS_BINARY:IS_STRING TSRMLS_CC); }
| T_ARRAY_CAST expr { zend_do_cast(&$$, &$2, IS_ARRAY TSRMLS_CC); }
| T_OBJECT_CAST expr { zend_do_cast(&$$, &$2, IS_OBJECT TSRMLS_CC); }
| T_BOOL_CAST expr { zend_do_cast(&$$, &$2, IS_BOOL TSRMLS_CC); }
@ -618,7 +622,7 @@ expr_without_variable:
| '@' { zend_do_begin_silence(&$1 TSRMLS_CC); } expr { zend_do_end_silence(&$1 TSRMLS_CC); $$ = $3; }
| scalar { $$ = $1; }
| T_ARRAY '(' array_pair_list ')' { $$ = $3; }
| '`' encaps_list '`' { zend_do_shell_exec(&$$, &$2 TSRMLS_CC); }
| '`' encaps_list '`' { zend_do_shell_exec(&$$, &$2 TSRMLS_CC); }
| T_PRINT expr { zend_do_print(&$$, &$2 TSRMLS_CC); }
;
@ -708,9 +712,10 @@ scalar:
| T_STRING_VARNAME { $$ = $1; }
| class_constant { $$ = $1; }
| common_scalar { $$ = $1; }
| '"' encaps_list '"' { $$ = $2; }
| '\'' encaps_list '\'' { $$ = $2; }
| T_START_HEREDOC encaps_list T_END_HEREDOC { $$ = $2; zend_do_end_heredoc(TSRMLS_C); }
| '"' { CG(literal_type) = UG(unicode)?IS_UNICODE:IS_STRING; } encaps_list '"' { $$ = $3; }
| T_START_HEREDOC { CG(literal_type) = UG(unicode)?IS_UNICODE:IS_STRING; } encaps_list T_END_HEREDOC { $$ = $3; zend_do_end_heredoc(TSRMLS_C); }
| T_BINARY_DOUBLE { CG(literal_type) = UG(unicode)?IS_BINARY:IS_STRING; } encaps_list '"' { $$ = $3; }
| T_BINARY_HEREDOC { CG(literal_type) = UG(unicode)?IS_BINARY:IS_STRING; } encaps_list T_END_HEREDOC { $$ = $3; zend_do_end_heredoc(TSRMLS_C); }
;
@ -808,7 +813,7 @@ reference_variable:
compound_variable:
T_VARIABLE { $$ = $1; }
| '$' '{' expr '}' { $$ = $3; }
| '$' '{' expr '}' { zend_do_normalization(&$$, &$3 TSRMLS_CC); }
;
dim_offset:
@ -830,7 +835,7 @@ object_dim_list:
variable_name:
T_STRING { $$ = $1; }
| '{' expr '}' { $$ = $2; }
| '{' expr '}' { zend_do_normalization(&$$, &$2 TSRMLS_CC); }
;
simple_indirect_reference:

View File

@ -29,21 +29,11 @@ typedef struct _zend_lex_state {
uint lineno;
char *filename;
#ifdef ZEND_MULTIBYTE
/* original (unfiltered) script */
char *script_org;
int script_org_size;
/* filtered script */
char *script_filtered;
int script_filtered_size;
/* input/ouput filters */
zend_encoding_filter input_filter;
zend_encoding_filter output_filter;
zend_encoding *script_encoding;
zend_encoding *internal_encoding;
#endif /* ZEND_MULTIBYTE */
UConverter *input_conv; /* converter for flex input */
UConverter *output_conv; /* converter for data from flex output */
zend_bool encoding_checked;
char* rest_str;
int rest_len;
} zend_lex_state;

File diff suppressed because it is too large Load Diff

View File

@ -474,7 +474,7 @@ zend_encoding *zend_encoding_table[] = {
};
#if 0
ZEND_API int zend_multibyte_set_script_encoding(char *encoding_list, int encoding_list_size TSRMLS_DC)
{
if (CG(script_encoding_list)) {
@ -491,11 +491,14 @@ ZEND_API int zend_multibyte_set_script_encoding(char *encoding_list, int encodin
return 0;
}
#endif
ZEND_API int zend_multibyte_set_internal_encoding(char *encoding_name, int encoding_name_size TSRMLS_DC)
{
CG(internal_encoding) = zend_multibyte_fetch_encoding(encoding_name);
//CG(internal_encoding) = zend_multibyte_fetch_encoding(encoding_name);
//CG(internal_encoding) = zend_multibyte_fetch_encoding(ZEND_INTERNAL_ENCODING);
/* set this to NULL so that input filtering is done only when really necessary */
CG(internal_encoding) = NULL;
return 0;
}
@ -523,17 +526,19 @@ ZEND_API int zend_multibyte_set_filter(zend_encoding *onetime_encoding TSRMLS_DC
if (!LANG_SCNG(internal_encoding) || LANG_SCNG(script_encoding) == LANG_SCNG(internal_encoding)) {
/* if encoding specfic filters exist, use them */
/*
if (LANG_SCNG(script_encoding)->input_filter && LANG_SCNG(script_encoding)->output_filter) {
LANG_SCNG(input_filter) = LANG_SCNG(script_encoding)->input_filter;
LANG_SCNG(output_filter) = LANG_SCNG(script_encoding)->output_filter;
return 0;
}
*/
if (!LANG_SCNG(script_encoding)->compatible) {
/* and if not, work around w/ script_encoding -> utf-8 -> script_encoding conversion */
LANG_SCNG(internal_encoding) = LANG_SCNG(script_encoding);
//LANG_SCNG(internal_encoding) = LANG_SCNG(script_encoding);
LANG_SCNG(input_filter) = zend_multibyte_script_encoding_filter;
LANG_SCNG(output_filter) = zend_multibyte_internal_encoding_filter;
//LANG_SCNG(output_filter) = zend_multibyte_internal_encoding_filter;
return 0;
} else {
/* nothing to do in this case */
@ -916,6 +921,7 @@ static char* zend_multibyte_assemble_encoding_list(zend_encoding **encoding_list
}
#if 0
static int zend_multibyte_parse_encoding_list(const char *encoding_list, int encoding_list_size, zend_encoding ***result, int *result_size)
{
int n, size;
@ -982,7 +988,7 @@ static int zend_multibyte_parse_encoding_list(const char *encoding_list, int enc
return 0;
}
#endif
static zend_encoding* zend_multibyte_find_script_encoding(zend_encoding *onetime_encoding TSRMLS_DC)
{

View File

@ -220,7 +220,7 @@ ZEND_API struct _zend_property_info *zend_get_property_info(zend_class_entry *ce
if (EG(scope) != ce
&& is_derived_class(ce, EG(scope))
&& EG(scope)
&& zend_hash_quick_find(&EG(scope)->properties_info, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, h, (void **) &scope_property_info)==SUCCESS
&& zend_u_hash_quick_find(&EG(scope)->properties_info, Z_TYPE_P(member), Z_UNIVAL_P(member), Z_UNILEN_P(member)+1, h, (void **) &scope_property_info)==SUCCESS
&& scope_property_info->flags & ZEND_ACC_PRIVATE) {
return scope_property_info;
} else if (property_info) {
@ -229,15 +229,15 @@ ZEND_API struct _zend_property_info *zend_get_property_info(zend_class_entry *ce
if (silent) {
return NULL;
}
zend_error(E_ERROR, "Cannot access %s property %s::$%s", zend_visibility_string(property_info->flags), ce->name, Z_STRVAL_P(member));
zend_error(E_ERROR, "Cannot access %s property %v::$%s", zend_visibility_string(property_info->flags), ce->name, Z_STRVAL_P(member));
} else {
/* fall through, return property_info... */
}
} else {
EG(std_property_info).flags = ZEND_ACC_PUBLIC;
EG(std_property_info).name = Z_STRVAL_P(member);
EG(std_property_info).name_length = Z_STRLEN_P(member);
EG(std_property_info).h = zend_get_hash_value(EG(std_property_info).name, EG(std_property_info).name_length+1);
EG(std_property_info).name = Z_UNIVAL_P(member);
EG(std_property_info).name_length = Z_UNILEN_P(member);
EG(std_property_info).h = zend_u_get_hash_value(Z_TYPE_P(member), EG(std_property_info).name, EG(std_property_info).name_length+1);
property_info = &EG(std_property_info);
}
return property_info;
@ -249,14 +249,19 @@ ZEND_API int zend_check_property_access(zend_object *zobj, char *prop_info_name
zend_property_info *property_info;
char *class_name, *prop_name;
zval member;
zend_uchar utype = UG(unicode)?IS_UNICODE:IS_STRING;
zend_unmangle_property_name(prop_info_name, &class_name, &prop_name);
ZVAL_STRING(&member, prop_name, 0);
zend_u_unmangle_property_name(utype, prop_info_name, &class_name, &prop_name);
if (utype == IS_UNICODE) {
ZVAL_UNICODE(&member, (UChar*)prop_name, 0);
} else {
ZVAL_STRING(&member, prop_name, 0);
}
property_info = zend_get_property_info(zobj->ce, &member, 1 TSRMLS_CC);
if (!property_info) {
return FAILURE;
}
if (prop_info_name[0] == '\0' && prop_info_name[1] != '*') {
if (class_name && class_name[0] != '*') {
if (!(property_info->flags & ZEND_ACC_PRIVATE)) {
/* we we're looking for a private prop but found a non private one of the same name */
return FAILURE;
@ -298,7 +303,7 @@ zval *zend_std_read_property(zval *object, zval *member, int type TSRMLS_DC)
/* make zend_get_property_info silent if we have getter - we may want to use it */
property_info = zend_get_property_info(zobj->ce, member, use_get TSRMLS_CC);
if (!property_info || zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &retval) == FAILURE) {
if (!property_info || zend_u_hash_quick_find(zobj->properties, Z_TYPE_P(member), property_info->name, property_info->name_length+1, property_info->h, (void **) &retval) == FAILURE) {
if (use_get) {
/* have getter - try with it! */
zobj->in_get = 1; /* prevent circular getting */
@ -312,7 +317,7 @@ zval *zend_std_read_property(zval *object, zval *member, int type TSRMLS_DC)
}
} else {
if (!silent) {
zend_error(E_NOTICE,"Undefined property: %s::$%s", zobj->ce->name, Z_STRVAL_P(member));
zend_error(E_NOTICE,"Undefined property: %v::$%s", zobj->ce->name, Z_STRVAL_P(member));
}
retval = &EG(uninitialized_zval_ptr);
}
@ -338,18 +343,18 @@ static void zend_std_write_property(zval *object, zval *member, zval *value TSRM
zobj = Z_OBJ_P(object);
use_set = (zobj->ce->__set && !zobj->in_set);
if (member->type != IS_STRING) {
if (member->type != IS_STRING && member->type != IS_UNICODE) {
ALLOC_ZVAL(tmp_member);
*tmp_member = *member;
INIT_PZVAL(tmp_member);
zval_copy_ctor(tmp_member);
convert_to_string(tmp_member);
convert_to_text(tmp_member);
member = tmp_member;
}
property_info = zend_get_property_info(zobj->ce, member, use_set TSRMLS_CC);
if (property_info && zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &variable_ptr) == SUCCESS) {
if (property_info && zend_u_hash_quick_find(zobj->properties, Z_TYPE_P(member), property_info->name, property_info->name_length+1, property_info->h, (void **) &variable_ptr) == SUCCESS) {
if (*variable_ptr == value) {
/* if we already have this value there, we don't actually need to do anything */
setter_done = 1;
@ -386,7 +391,7 @@ static void zend_std_write_property(zval *object, zval *member, zval *value TSRM
if (PZVAL_IS_REF(value)) {
SEPARATE_ZVAL(&value);
}
zend_hash_quick_update(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, &value, sizeof(zval *), (void **) &foo);
zend_u_hash_quick_update(zobj->properties, Z_TYPE_P(member), property_info->name, property_info->name_length+1, property_info->h, &value, sizeof(zval *), (void **) &foo);
}
if (tmp_member) {
zval_ptr_dtor(&tmp_member);
@ -411,7 +416,7 @@ zval *zend_std_read_dimension(zval *object, zval *offset, int type TSRMLS_DC)
if (!retval) {
if (!EG(exception)) {
zend_error(E_ERROR, "Undefined offset for object of type %s used as array", ce->name);
zend_error(E_ERROR, "Undefined offset for object of type %v used as array", ce->name);
}
return 0;
}
@ -421,7 +426,7 @@ zval *zend_std_read_dimension(zval *object, zval *offset, int type TSRMLS_DC)
return retval;
} else {
zend_error(E_ERROR, "Cannot use object of type %s as array", ce->name);
zend_error(E_ERROR, "Cannot use object of type %v as array", ce->name);
return 0;
}
}
@ -440,7 +445,7 @@ static void zend_std_write_dimension(zval *object, zval *offset, zval *value TSR
zend_call_method_with_2_params(&object, ce, NULL, "offsetset", NULL, offset, value);
zval_ptr_dtor(&offset);
} else {
zend_error(E_ERROR, "Cannot use object of type %s as array", ce->name);
zend_error(E_ERROR, "Cannot use object of type %v as array", ce->name);
}
}
@ -469,7 +474,7 @@ static int zend_std_has_dimension(zval *object, zval *offset, int check_empty TS
}
zval_ptr_dtor(&offset);
} else {
zend_error(E_ERROR, "Cannot use object of type %s as array", ce->name);
zend_error(E_ERROR, "Cannot use object of type %v as array", ce->name);
return 0;
}
return result;
@ -485,10 +490,10 @@ static zval **zend_std_get_property_ptr_ptr(zval *object, zval *member TSRMLS_DC
zobj = Z_OBJ_P(object);
if (member->type != IS_STRING) {
if (member->type != IS_STRING && member->type != IS_UNICODE) {
tmp_member = *member;
zval_copy_ctor(&tmp_member);
convert_to_string(&tmp_member);
convert_to_text(&tmp_member);
member = &tmp_member;
}
@ -498,7 +503,7 @@ static zval **zend_std_get_property_ptr_ptr(zval *object, zval *member TSRMLS_DC
property_info = zend_get_property_info(zobj->ce, member, 0 TSRMLS_CC);
if (zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &retval) == FAILURE) {
if (zend_u_hash_quick_find(zobj->properties, Z_TYPE_P(member), property_info->name, property_info->name_length+1, property_info->h, (void **) &retval) == FAILURE) {
zval *new_zval;
if (!zobj->ce->__get && !zobj->ce->__set) {
@ -507,7 +512,7 @@ static zval **zend_std_get_property_ptr_ptr(zval *object, zval *member TSRMLS_DC
/* zend_error(E_NOTICE, "Undefined property: %s", Z_STRVAL_P(member)); */
new_zval->refcount++;
zend_hash_quick_update(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, &new_zval, sizeof(zval *), (void **) &retval);
zend_u_hash_quick_update(zobj->properties, Z_TYPE_P(member), property_info->name, property_info->name_length+1, property_info->h, &new_zval, sizeof(zval *), (void **) &retval);
} else {
/* we do have getter - fail and let it try again with usual get/set */
retval = NULL;
@ -530,18 +535,18 @@ static void zend_std_unset_property(zval *object, zval *member TSRMLS_DC)
zobj = Z_OBJ_P(object);
use_unset = (zobj->ce->__unset && !zobj->in_unset);
if (member->type != IS_STRING) {
if (member->type != IS_STRING && member->type != IS_UNICODE) {
ALLOC_ZVAL(tmp_member);
*tmp_member = *member;
INIT_PZVAL(tmp_member);
zval_copy_ctor(tmp_member);
convert_to_string(tmp_member);
convert_to_text(tmp_member);
member = tmp_member;
}
property_info = zend_get_property_info(zobj->ce, member, 0 TSRMLS_CC);
if (!property_info || zend_hash_del(zobj->properties, property_info->name, property_info->name_length+1) == FAILURE) {
if (!property_info || zend_u_hash_del(zobj->properties, Z_TYPE_P(member), property_info->name, property_info->name_length+1)) {
if (use_unset) {
/* have unseter - try with it! */
zobj->in_unset = 1; /* prevent circular unsetting */
@ -565,7 +570,7 @@ static void zend_std_unset_dimension(zval *object, zval *offset TSRMLS_DC)
zend_call_method_with_1_params(&object, ce, NULL, "offsetunset", NULL, offset);
zval_ptr_dtor(&offset);
} else {
zend_error(E_ERROR, "Cannot use object of type %s as array", ce->name);
zend_error(E_ERROR, "Cannot use object of type %v as array", ce->name);
}
}
@ -589,7 +594,11 @@ ZEND_API void zend_std_call_user_call(INTERNAL_FUNCTION_PARAMETERS)
ALLOC_ZVAL(method_name_ptr);
INIT_PZVAL(method_name_ptr);
ZVAL_STRING(method_name_ptr, func->function_name, 0); /* no dup - it's a copy */
if (UG(unicode)) {
ZVAL_UNICODE(method_name_ptr, (UChar*)func->function_name, 0); /* no dup - it's a copy */
} else {
ZVAL_STRING(method_name_ptr, func->function_name, 0); /* no dup - it's a copy */
}
/* __call handler is called with two arguments:
method name
@ -640,7 +649,7 @@ static inline zend_function *zend_check_private_int(zend_function *fbc, zend_cla
ce = ce->parent;
while (ce) {
if (ce == EG(scope)) {
if (zend_hash_find(&ce->function_table, function_name_strval, function_name_strlen+1, (void **) &fbc)==SUCCESS
if (zend_u_hash_find(&ce->function_table, UG(unicode)?IS_UNICODE:IS_STRING, function_name_strval, function_name_strlen+1, (void **) &fbc)==SUCCESS
&& fbc->op_array.fn_flags & ZEND_ACC_PRIVATE
&& fbc->common.scope == EG(scope)) {
return fbc;
@ -692,16 +701,19 @@ static union _zend_function *zend_std_get_method(zval **object_ptr, char *method
{
zend_object *zobj;
zend_function *fbc;
unsigned int lc_method_name_len;
char *lc_method_name;
zval *object = *object_ptr;
lc_method_name = do_alloca(method_len+1);
/* FIXME: type is default */
zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING;
/* Create a zend_copy_str_tolower(dest, src, src_length); */
zend_str_tolower_copy(lc_method_name, method_name, method_len);
lc_method_name = zend_u_str_case_fold(type, method_name, method_len, 1, &lc_method_name_len);
zobj = Z_OBJ_P(object);
if (zend_hash_find(&zobj->ce->function_table, lc_method_name, method_len+1, (void **)&fbc) == FAILURE) {
free_alloca(lc_method_name);
if (zend_u_hash_find(&zobj->ce->function_table, type, lc_method_name, lc_method_name_len+1, (void **)&fbc) == FAILURE) {
efree(lc_method_name);
if (zobj->ce->__call) {
zend_internal_function *call_user_call = emalloc(sizeof(zend_internal_function));
call_user_call->type = ZEND_INTERNAL_FUNCTION;
@ -710,7 +722,11 @@ static union _zend_function *zend_std_get_method(zval **object_ptr, char *method
call_user_call->num_args = 0;
call_user_call->scope = zobj->ce;
call_user_call->fn_flags = 0;
call_user_call->function_name = estrndup(method_name, method_len);
if (UG(unicode)) {
call_user_call->function_name = (char*)eustrndup((UChar*)method_name, method_len);
} else {
call_user_call->function_name = estrndup(method_name, method_len);
}
call_user_call->pass_rest_by_reference = 0;
call_user_call->return_reference = ZEND_RETURN_VALUE;
@ -728,7 +744,7 @@ static union _zend_function *zend_std_get_method(zval **object_ptr, char *method
if (EG(scope) && fbc->op_array.fn_flags & ZEND_ACC_CHANGED) {
zend_function *priv_fbc;
if (zend_hash_find(&EG(scope)->function_table, lc_method_name, method_len+1, (void **) &priv_fbc)==SUCCESS
if (zend_u_hash_find(&EG(scope)->function_table, type, lc_method_name, lc_method_name_len+1, (void **) &priv_fbc)==SUCCESS
&& priv_fbc->common.fn_flags & ZEND_ACC_PRIVATE
&& priv_fbc->common.scope == EG(scope)) {
fbc = priv_fbc;
@ -741,18 +757,18 @@ static union _zend_function *zend_std_get_method(zval **object_ptr, char *method
*/
updated_fbc = zend_check_private_int(fbc, object->value.obj.handlers->get_class_entry(object TSRMLS_CC), lc_method_name, method_len TSRMLS_CC);
if (!updated_fbc) {
zend_error(E_ERROR, "Call to %s method %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), method_name, EG(scope) ? EG(scope)->name : "");
zend_error(E_ERROR, "Call to %s method %v::%v() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), method_name, EG(scope) ? EG(scope)->name : "");
}
fbc = updated_fbc;
} else if ((fbc->common.fn_flags & ZEND_ACC_PROTECTED)) {
/* Ensure that if we're calling a protected function, we're allowed to do so.
*/
if (!zend_check_protected(fbc->common.scope, EG(scope))) {
zend_error(E_ERROR, "Call to %s method %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), method_name, EG(scope) ? EG(scope)->name : "");
zend_error(E_ERROR, "Call to %s method %v::%v() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), method_name, EG(scope) ? EG(scope)->name : "");
}
}
free_alloca(lc_method_name);
efree(lc_method_name);
return fbc;
}
@ -761,14 +777,16 @@ static union _zend_function *zend_std_get_method(zval **object_ptr, char *method
ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, char *function_name_strval, int function_name_strlen TSRMLS_DC)
{
zend_function *fbc;
/* FIXME: type is default */
zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING;
if (zend_hash_find(&ce->function_table, function_name_strval, function_name_strlen+1, (void **) &fbc)==FAILURE) {
if (zend_u_hash_find(&ce->function_table, type, function_name_strval, function_name_strlen+1, (void **) &fbc)==FAILURE) {
char *class_name = ce->name;
if (!class_name) {
class_name = "";
class_name = EMPTY_STR;
}
zend_error(E_ERROR, "Call to undefined method %s::%s()", class_name, function_name_strval);
zend_error(E_ERROR, "Call to undefined method %R::%R()", type, class_name, type, function_name_strval);
}
if (fbc->op_array.fn_flags & ZEND_ACC_PUBLIC) {
/* No further checks necessary, most common case */
@ -779,14 +797,14 @@ ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, char *f
*/
updated_fbc = zend_check_private_int(fbc, EG(scope), function_name_strval, function_name_strlen TSRMLS_CC);
if (!updated_fbc) {
zend_error(E_ERROR, "Call to %s method %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), function_name_strval, EG(scope) ? EG(scope)->name : "");
zend_error(E_ERROR, "Call to %s method %v::%v() from context '%v'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), function_name_strval, EG(scope) ? EG(scope)->name : EMPTY_STR);
}
fbc = updated_fbc;
} else if ((fbc->common.fn_flags & ZEND_ACC_PROTECTED)) {
/* Ensure that if we're calling a protected function, we're allowed to do so.
*/
if (!zend_check_protected(EG(scope), fbc->common.scope)) {
zend_error(E_ERROR, "Call to %s method %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), function_name_strval, EG(scope) ? EG(scope)->name : "");
zend_error(E_ERROR, "Call to %s method %v::%v() from context '%v'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), function_name_strval, EG(scope) ? EG(scope)->name : EMPTY_STR);
}
}
@ -800,8 +818,9 @@ ZEND_API zval **zend_std_get_static_property(zend_class_entry *ce, char *propert
zend_class_entry *tmp_ce = ce;
zend_property_info *property_info;
zend_property_info std_property_info;
zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING;
if (zend_hash_find(&ce->properties_info, property_name, property_name_len+1, (void **) &property_info)==FAILURE || (property_info->flags & ZEND_ACC_SHADOW)) {
if (zend_u_hash_find(&ce->properties_info, type, property_name, property_name_len+1, (void **) &property_info)==FAILURE) {
std_property_info.flags = ZEND_ACC_PUBLIC;
std_property_info.name = property_name;
std_property_info.name_length = property_name_len;
@ -810,23 +829,23 @@ ZEND_API zval **zend_std_get_static_property(zend_class_entry *ce, char *propert
}
#if DEBUG_OBJECT_HANDLERS
zend_printf("Access type for %s::%s is %s\n", ce->name, property_name, zend_visibility_string(property_info->flags));
zend_printf("Access type for %v::%s is %s\n", ce->name, property_name, zend_visibility_string(property_info->flags));
#endif
if (!zend_verify_property_access(property_info, ce TSRMLS_CC)) {
if (!silent) {
zend_error(E_ERROR, "Cannot access %s property %s::$%s", zend_visibility_string(property_info->flags), ce->name, property_name);
zend_error(E_ERROR, "Cannot access %s property %v::$%s", zend_visibility_string(property_info->flags), ce->name, property_name);
}
return NULL;
}
zend_hash_quick_find(tmp_ce->static_members, property_info->name, property_info->name_length+1, property_info->h, (void **) &retval);
zend_u_hash_quick_find(tmp_ce->static_members, type, property_info->name, property_info->name_length+1, property_info->h, (void **) &retval);
if (!retval) {
if (silent) {
return NULL;
} else {
zend_error(E_ERROR, "Access to undeclared static property: %s::$%s", ce->name, property_name);
zend_error(E_ERROR, "Access to undeclared static property: %v::$%s", ce->name, property_name);
}
}
@ -837,7 +856,7 @@ ZEND_API zval **zend_std_get_static_property(zend_class_entry *ce, char *propert
ZEND_API zend_bool zend_std_unset_static_property(zend_class_entry *ce, char *property_name, int property_name_len TSRMLS_DC)
{
zend_error(E_ERROR, "Attempt to unset static property %s::$%s", ce->name, property_name);
zend_error(E_ERROR, "Attempt to unset static property %v::$%s", ce->name, property_name);
return 0;
}
@ -854,13 +873,13 @@ static union _zend_function *zend_std_get_constructor(zval *object TSRMLS_DC)
/* Ensure that if we're calling a private function, we're allowed to do so.
*/
if (object->value.obj.handlers->get_class_entry(object TSRMLS_CC) != EG(scope)) {
zend_error(E_ERROR, "Call to private %s::%s() from context '%s'", constructor->common.scope->name, constructor->common.function_name, EG(scope) ? EG(scope)->name : "");
zend_error(E_ERROR, "Call to private %v::%v() from context '%v'", constructor->common.scope->name, constructor->common.function_name, EG(scope) ? EG(scope)->name : EMPTY_STR);
}
} else if ((constructor->common.fn_flags & ZEND_ACC_PROTECTED)) {
/* Ensure that if we're calling a protected function, we're allowed to do so.
*/
if (!zend_check_protected(constructor->common.scope, EG(scope))) {
zend_error(E_ERROR, "Call to protected %s::%s() from context '%s'", constructor->common.scope->name, constructor->common.function_name, EG(scope) ? EG(scope)->name : "");
zend_error(E_ERROR, "Call to protected %v::%v() from context '%v'", constructor->common.scope->name, constructor->common.function_name, EG(scope) ? EG(scope)->name : EMPTY_STR);
}
}
}
@ -897,12 +916,12 @@ static int zend_std_has_property(zval *object, zval *member, int has_set_exists
zobj = Z_OBJ_P(object);
use_isset = (zobj->ce->__isset && !zobj->in_isset);
if (member->type != IS_STRING) {
if (member->type != IS_STRING && member->type != IS_UNICODE) {
ALLOC_ZVAL(tmp_member);
*tmp_member = *member;
INIT_PZVAL(tmp_member);
zval_copy_ctor(tmp_member);
convert_to_string(tmp_member);
convert_to_text(tmp_member);
member = tmp_member;
}
@ -912,7 +931,7 @@ static int zend_std_has_property(zval *object, zval *member, int has_set_exists
property_info = zend_get_property_info(zobj->ce, member, 1 TSRMLS_CC);
if (!property_info || zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &value) == FAILURE) {
if (!property_info || zend_u_hash_quick_find(zobj->properties, Z_TYPE_P(member), property_info->name, property_info->name_length+1, property_info->h, (void **) &value) == FAILURE) {
result = 0;
if (use_isset && (has_set_exists != 2)) {
zval *rv;
@ -979,7 +998,11 @@ int zend_std_object_get_class_name(zval *object, char **class_name, zend_uint *c
}
*class_name_len = ce->name_length;
*class_name = estrndup(ce->name, ce->name_length);
if (UG(unicode)) {
*class_name = (char*)eustrndup((UChar*)ce->name, ce->name_length);
} else {
*class_name = estrndup(ce->name, ce->name_length);
}
return SUCCESS;
}
@ -989,14 +1012,22 @@ ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int ty
switch (type) {
case IS_STRING:
case IS_UNICODE:
if (!zend_hash_exists(&Z_OBJCE_P(readobj)->function_table, "__tostring", sizeof("__tostring"))) {
return FAILURE;
}
ZVAL_STRING(&fname, "__tostring", 0);
if (UG(unicode)) {
ZVAL_UNICODE(&fname, USTR_MAKE("__tostring"), 0);
} else {
ZVAL_STRING(&fname, "__tostring", 0);
}
if (call_user_function_ex(NULL, &readobj, &fname, &retval, 0, NULL, 0, NULL TSRMLS_CC) == SUCCESS) {
if (UG(unicode)) {
zval_dtor(&fname);
}
if (retval) {
if (Z_TYPE_P(retval) != IS_STRING) {
zend_error(E_ERROR, "Method %s::__toString() must return a string value", Z_OBJCE_P(readobj)->name);
if (Z_TYPE_P(retval) != IS_STRING && Z_TYPE_P(retval) != IS_UNICODE) {
zend_error(E_ERROR, "Method %v::__toString() must return a string value", Z_OBJCE_P(readobj)->name);
}
} else {
MAKE_STD_ZVAL(retval);
@ -1008,6 +1039,9 @@ ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int ty
zval_ptr_dtor(&retval);
return SUCCESS;
}
if (UG(unicode)) {
zval_dtor(&fname);
}
break;
default:
break;

View File

@ -42,9 +42,9 @@ ZEND_API void zend_objects_destroy_object(zend_object *object, zend_object_handl
zend_class_entry *ce = object->ce;
zend_error(EG(in_execution) ? E_ERROR : E_WARNING,
"Call to private %s::__destruct() from context '%s'%s",
"Call to private %v::__destruct() from context '%v'%s",
ce->name,
EG(scope) ? EG(scope)->name : "",
EG(scope) ? EG(scope)->name : EMPTY_STR,
EG(in_execution) ? "" : " during shutdown ignored");
return;
}
@ -55,9 +55,9 @@ ZEND_API void zend_objects_destroy_object(zend_object *object, zend_object_handl
zend_class_entry *ce = object->ce;
zend_error(EG(in_execution) ? E_ERROR : E_WARNING,
"Call to protected %s::__destruct() from context '%s'%s",
"Call to protected %v::__destruct() from context '%v'%s",
ce->name,
EG(scope) ? EG(scope)->name : "",
EG(scope) ? EG(scope)->name : EMPTY_STR,
EG(in_execution) ? "" : " during shutdown ignored");
return;
}
@ -78,7 +78,7 @@ ZEND_API void zend_objects_destroy_object(zend_object *object, zend_object_handl
zend_call_method_with_0_params(&obj, object->ce, &object->ce->destructor, ZEND_DESTRUCTOR_FUNC_NAME, NULL);
if (old_exception) {
if (EG(exception)) {
zend_error(E_ERROR, "Ignoring exception from %s::__destruct() while an exception is already active", object->ce->name);
zend_error(E_ERROR, "Ignoring exception from %v::__destruct() while an exception is already active", object->ce->name);
zval_ptr_dtor(&EG(exception));
}
EG(exception) = old_exception;
@ -167,7 +167,7 @@ ZEND_API zend_object_value zend_objects_clone_obj(zval *zobject TSRMLS_DC)
new_obj_val = zend_objects_new(&new_object, old_object->ce TSRMLS_CC);
ALLOC_HASHTABLE(new_object->properties);
zend_hash_init(new_object->properties, 0, NULL, ZVAL_PTR_DTOR, 0);
zend_u_hash_init(new_object->properties, 0, NULL, ZVAL_PTR_DTOR, 0, UG(unicode));
zend_objects_clone_members(new_object, new_obj_val, old_object, handle TSRMLS_CC);

View File

@ -186,7 +186,7 @@ ZEND_API zend_object_value zend_objects_store_clone_obj(zval *zobject TSRMLS_DC)
obj = &EG(objects_store).object_buckets[handle].bucket.obj;
if (obj->clone == NULL) {
zend_error(E_CORE_ERROR, "Trying to clone uncloneable object of class %s", Z_OBJCE_P(zobject)->name);
zend_error(E_CORE_ERROR, "Trying to clone uncloneable object of class %v", Z_OBJCE_P(zobject)->name);
}
obj->clone(obj->object, &new_object TSRMLS_CC);

View File

@ -386,9 +386,10 @@ int pass_two(zend_op_array *op_array TSRMLS_DC)
int print_class(zend_class_entry *class_entry TSRMLS_DC)
{
printf("Class %s:\n", class_entry->name);
/* UTODO: fix these to use spprintf() */
printf("Class %v:\n", class_entry->name);
zend_hash_apply(&class_entry->function_table, (apply_func_t) pass_two TSRMLS_CC);
printf("End of class %s.\n\n", class_entry->name);
printf("End of class %v.\n\n", class_entry->name);
return 0;
}

View File

@ -31,6 +31,8 @@
#include "zend_multiply.h"
#include "zend_strtod.h"
#include "unicode/uchar.h"
#define LONG_SIGN_MASK (1L << (8*sizeof(long)-1))
ZEND_API int zend_atoi(const char *str, int str_len)
@ -111,6 +113,7 @@ ZEND_API void convert_scalar_to_number(zval *op TSRMLS_DC)
{
switch (op->type) {
case IS_STRING:
case IS_BINARY:
{
char *strval;
@ -127,6 +130,24 @@ ZEND_API void convert_scalar_to_number(zval *op TSRMLS_DC)
STR_FREE(strval);
break;
}
case IS_UNICODE:
{
UChar *strval;
strval = op->value.ustr.val;
switch ((op->type=is_numeric_unicode(strval, op->value.ustr.len, &op->value.lval, &op->value.dval, 1))) {
case IS_DOUBLE:
case IS_LONG:
break;
default:
op->value.lval = zend_u_strtol(op->value.ustr.val, NULL, 10);
op->type = IS_LONG;
break;
}
USTR_FREE(strval);
break;
}
break;
case IS_BOOL:
op->type = IS_LONG;
break;
@ -152,6 +173,7 @@ ZEND_API void convert_scalar_to_number(zval *op TSRMLS_DC)
} else { \
switch ((op)->type) { \
case IS_STRING: \
case IS_BINARY: \
{ \
switch (((holder).type=is_numeric_string((op)->value.str.val, (op)->value.str.len, &(holder).value.lval, &(holder).value.dval, 1))) { \
case IS_DOUBLE: \
@ -165,6 +187,20 @@ ZEND_API void convert_scalar_to_number(zval *op TSRMLS_DC)
(op) = &(holder); \
break; \
} \
case IS_UNICODE: \
{ \
switch (((holder).type=is_numeric_unicode((op)->value.ustr.val, (op)->value.ustr.len, &(holder).value.lval, &(holder).value.dval, 1))) { \
case IS_DOUBLE: \
case IS_LONG: \
break; \
default: \
(holder).value.lval = zend_u_strtol((op)->value.ustr.val, NULL, 10); \
(holder).type = IS_LONG; \
break; \
} \
(op) = &(holder); \
break; \
} \
case IS_BOOL: \
case IS_RESOURCE: \
(holder).value.lval = (op)->value.lval; \
@ -202,8 +238,12 @@ ZEND_API void convert_scalar_to_number(zval *op TSRMLS_DC)
DVAL_TO_LVAL((op)->value.dval, (holder).value.lval); \
break; \
case IS_STRING: \
case IS_BINARY: \
(holder).value.lval = strtol((op)->value.str.val, NULL, 10); \
break; \
case IS_UNICODE: \
(holder).value.lval = zend_u_strtol((op)->value.ustr.val, NULL, 10); \
break; \
case IS_ARRAY: \
(holder).value.lval = (zend_hash_num_elements((op)->value.ht)?1:0); \
break; \
@ -242,6 +282,7 @@ ZEND_API void convert_scalar_to_number(zval *op TSRMLS_DC)
(holder).value.lval = ((op)->value.dval ? 1 : 0); \
break; \
case IS_STRING: \
case IS_BINARY: \
if ((op)->value.str.len == 0 \
|| ((op)->value.str.len==1 && (op)->value.str.val[0]=='0')) { \
(holder).value.lval = 0; \
@ -249,6 +290,15 @@ ZEND_API void convert_scalar_to_number(zval *op TSRMLS_DC)
(holder).value.lval = 1; \
} \
break; \
case IS_UNICODE: \
if ((op)->value.ustr.len == 0 \
|| ((op)->value.ustr.len==1 && \
((op)->value.ustr.val[0]=='0'))) { \
(holder).value.lval = 0; \
} else { \
(holder).value.lval = 1; \
} \
break; \
case IS_ARRAY: \
(holder).value.lval = (zend_hash_num_elements((op)->value.ht)?1:0); \
break; \
@ -293,7 +343,6 @@ ZEND_API void convert_to_long(zval *op)
ZEND_API void convert_to_long_base(zval *op, int base)
{
char *strval;
long tmp;
switch (op->type) {
@ -313,9 +362,19 @@ ZEND_API void convert_to_long_base(zval *op, int base)
DVAL_TO_LVAL(op->value.dval, op->value.lval);
break;
case IS_STRING:
strval = op->value.str.val;
op->value.lval = strtol(strval, NULL, base);
STR_FREE(strval);
case IS_BINARY:
{
char *strval = op->value.str.val;
op->value.lval = strtol(strval, NULL, base);
STR_FREE(strval);
}
break;
case IS_UNICODE:
{
UChar *strval = op->value.ustr.val;
op->value.lval = zend_u_strtol(strval, NULL, base);
USTR_FREE(strval);
}
break;
case IS_ARRAY:
tmp = (zend_hash_num_elements(op->value.ht)?1:0);
@ -358,7 +417,6 @@ ZEND_API void convert_to_long_base(zval *op, int base)
ZEND_API void convert_to_double(zval *op)
{
char *strval;
double tmp;
switch (op->type) {
@ -378,10 +436,21 @@ ZEND_API void convert_to_double(zval *op)
case IS_DOUBLE:
break;
case IS_STRING:
strval = op->value.str.val;
case IS_BINARY:
{
char *strval = op->value.str.val;
op->value.dval = zend_strtod(strval, NULL);
STR_FREE(strval);
op->value.dval = zend_strtod(strval, NULL);
STR_FREE(strval);
}
break;
case IS_UNICODE:
{
UChar *strval = op->value.ustr.val;
op->value.dval = zend_u_strtod(strval, NULL);
USTR_FREE(strval);
}
break;
case IS_ARRAY:
tmp = (zend_hash_num_elements(op->value.ht)?1:0);
@ -405,7 +474,7 @@ ZEND_API void convert_to_double(zval *op)
retval = (zend_hash_num_elements(ht)?1.0:0.0);
}
} else {
zend_error(E_NOTICE, "Object of class %s could not be converted to double", Z_OBJCE_P(op)->name);
zend_error(E_NOTICE, "Object of class %v could not be converted to double", Z_OBJCE_P(op)->name);
}
zval_dtor(op);
@ -440,7 +509,6 @@ ZEND_API void convert_to_null(zval *op)
ZEND_API void convert_to_boolean(zval *op)
{
char *strval;
int tmp;
switch (op->type) {
@ -462,15 +530,32 @@ ZEND_API void convert_to_boolean(zval *op)
op->value.lval = (op->value.dval ? 1 : 0);
break;
case IS_STRING:
strval = op->value.str.val;
case IS_BINARY:
{
char *strval = op->value.str.val;
if (op->value.str.len == 0
|| (op->value.str.len==1 && op->value.str.val[0]=='0')) {
op->value.lval = 0;
} else {
op->value.lval = 1;
if (op->value.str.len == 0
|| (op->value.str.len==1 && op->value.str.val[0]=='0')) {
op->value.lval = 0;
} else {
op->value.lval = 1;
}
STR_FREE(strval);
}
break;
case IS_UNICODE:
{
UChar *strval = op->value.ustr.val;
if (op->value.ustr.len == 0
|| (op->value.ustr.len==1 &&
(op->value.ustr.val[0]=='0'))) {
op->value.lval = 0;
} else {
op->value.lval = 1;
}
USTR_FREE(strval);
}
STR_FREE(strval);
break;
case IS_ARRAY:
tmp = (zend_hash_num_elements(op->value.ht)?1:0);
@ -507,7 +592,94 @@ ZEND_API void convert_to_boolean(zval *op)
op->type = IS_BOOL;
}
ZEND_API void _convert_to_unicode(zval *op TSRMLS_DC ZEND_FILE_LINE_DC)
{
switch (op->type) {
case IS_NULL:
op->value.ustr.val = USTR_MAKE_REL("");
op->value.ustr.len = 0;
break;
case IS_UNICODE:
break;
case IS_STRING:
zval_string_to_unicode(op TSRMLS_CC);
break;
case IS_BINARY:
zend_error(E_ERROR, "Cannot convert binary type to Unicode type");
return;
case IS_BOOL:
if (op->value.lval) {
op->value.ustr.val = USTR_MAKE_REL("1");
op->value.ustr.len = 1;
} else {
op->value.ustr.val = USTR_MAKE_REL("");
op->value.ustr.len = 0;
}
break;
case IS_RESOURCE: {
long tmp = op->value.lval;
TSRMLS_FETCH();
zend_list_delete(op->value.lval);
op->value.ustr.val = eumalloc_rel(sizeof("Resource id #")-1 + MAX_LENGTH_OF_LONG + 1);
op->value.ustr.len = u_sprintf(op->value.ustr.val, "Resource id #%ld", tmp);
break;
}
case IS_LONG: {
int32_t capacity = MAX_LENGTH_OF_LONG + 1;
long lval = op->value.lval;
op->value.ustr.val = eumalloc_rel(capacity);
op->value.ustr.len = u_sprintf(op->value.ustr.val, "%ld", lval);
break;
}
case IS_DOUBLE: {
int32_t capacity;
double dval = op->value.dval;
TSRMLS_FETCH();
capacity = MAX_LENGTH_OF_DOUBLE + EG(precision) + 1;
op->value.ustr.val = eumalloc_rel(capacity);
op->value.ustr.len = u_sprintf(op->value.ustr.val, "%.*G", (int) EG(precision), dval);
break;
}
case IS_ARRAY:
zend_error(E_NOTICE, "Array to string conversion");
zval_dtor(op);
op->value.ustr.val = USTR_MAKE_REL("Array");
op->value.ustr.len = sizeof("Array")-1;
break;
case IS_OBJECT: {
TSRMLS_FETCH();
convert_object_to_type(op, IS_UNICODE, convert_to_unicode);
if (op->type == IS_UNICODE) {
return;
}
zend_error(E_NOTICE, "Object of class %v to string conversion", Z_OBJCE_P(op)->name);
zval_dtor(op);
op->value.ustr.val = USTR_MAKE_REL("Object");
op->value.ustr.len = sizeof("Object")-1;
break;
}
default:
zval_dtor(op);
ZVAL_BOOL(op, 0);
break;
}
op->type = IS_UNICODE;
}
ZEND_API void _convert_to_string(zval *op ZEND_FILE_LINE_DC)
{
TSRMLS_FETCH();
_convert_to_string_with_converter(op, ZEND_U_CONVERTER(UG(runtime_encoding_conv)) TSRMLS_CC ZEND_FILE_LINE_CC);
}
ZEND_API void _convert_to_string_with_converter(zval *op, UConverter *conv TSRMLS_DC ZEND_FILE_LINE_DC)
{
long lval;
double dval;
@ -518,6 +690,26 @@ ZEND_API void _convert_to_string(zval *op ZEND_FILE_LINE_DC)
op->value.str.len = 0;
break;
case IS_STRING:
if (conv == ZEND_U_CONVERTER(UG(runtime_encoding_conv))) {
break;
} else {
char *s;
int32_t s_len;
UErrorCode status = U_ZERO_ERROR;
s = op->value.str.val;
s_len = op->value.str.len;
zend_convert_encodings(conv, ZEND_U_CONVERTER(UG(runtime_encoding_conv)), &op->value.str.val, &op->value.str.len, s, s_len, &status);
efree(s);
if (U_FAILURE(status)) {
zend_error(E_WARNING, "Error converting string for printing");
}
}
break;
case IS_BINARY:
zend_error(E_ERROR, "Cannot convert binary type to string type");
return;
case IS_UNICODE:
zval_unicode_to_string(op, conv TSRMLS_CC);
break;
case IS_BOOL:
if (op->value.lval) {
@ -566,7 +758,7 @@ ZEND_API void _convert_to_string(zval *op ZEND_FILE_LINE_DC)
return;
}
zend_error(E_NOTICE, "Object of class %s to string conversion", Z_OBJCE_P(op)->name);
zend_error(E_NOTICE, "Object of class %v to string conversion", Z_OBJCE_P(op)->name);
zval_dtor(op);
op->value.str.val = estrndup_rel("Object", sizeof("Object")-1);
op->value.str.len = sizeof("Object")-1;
@ -580,8 +772,35 @@ ZEND_API void _convert_to_string(zval *op ZEND_FILE_LINE_DC)
op->type = IS_STRING;
}
ZEND_API void convert_to_binary(zval *op)
{
switch (op->type) {
case IS_BINARY:
break;
case IS_OBJECT: {
TSRMLS_FETCH();
convert_object_to_type(op, IS_BINARY, convert_to_binary);
static void convert_scalar_to_array(zval *op, int type)
if (op->type == IS_BINARY) {
return;
}
zend_error(E_NOTICE, "Object of class %v to binary conversion", Z_OBJCE_P(op)->name);
zval_dtor(op);
op->value.str.val = estrndup("Object", sizeof("Object")-1);
op->value.str.len = sizeof("Object")-1;
break;
}
default:
convert_to_string(op);
break;
}
op->type = IS_BINARY;
}
static void convert_scalar_to_array(zval *op, int type TSRMLS_DC)
{
zval *entry;
@ -592,7 +811,7 @@ static void convert_scalar_to_array(zval *op, int type)
switch (type) {
case IS_ARRAY:
ALLOC_HASHTABLE(op->value.ht);
zend_hash_init(op->value.ht, 0, NULL, ZVAL_PTR_DTOR, 0);
zend_u_hash_init(op->value.ht, 0, NULL, ZVAL_PTR_DTOR, 0, UG(unicode));
zend_hash_index_update(op->value.ht, 0, (void *) &entry, sizeof(zval *), NULL);
op->type = IS_ARRAY;
break;
@ -624,7 +843,7 @@ ZEND_API void convert_to_array(zval *op)
HashTable *ht;
ALLOC_HASHTABLE(ht);
zend_hash_init(ht, 0, NULL, ZVAL_PTR_DTOR, 0);
zend_u_hash_init(ht, 0, NULL, ZVAL_PTR_DTOR, 0, UG(unicode));
if (Z_OBJ_HT_P(op)->get_properties) {
HashTable *obj_ht = Z_OBJ_HT_P(op)->get_properties(op TSRMLS_CC);
if(obj_ht) {
@ -644,11 +863,11 @@ ZEND_API void convert_to_array(zval *op)
return;
case IS_NULL:
ALLOC_HASHTABLE(op->value.ht);
zend_hash_init(op->value.ht, 0, NULL, ZVAL_PTR_DTOR, 0);
zend_u_hash_init(op->value.ht, 0, NULL, ZVAL_PTR_DTOR, 0, UG(unicode));
op->type = IS_ARRAY;
break;
default:
convert_scalar_to_array(op, IS_ARRAY);
convert_scalar_to_array(op, IS_ARRAY TSRMLS_CC);
break;
}
}
@ -656,12 +875,10 @@ ZEND_API void convert_to_array(zval *op)
ZEND_API void convert_to_object(zval *op)
{
TSRMLS_FETCH();
switch (op->type) {
case IS_ARRAY:
{
/* OBJECTS_OPTIMIZE */
TSRMLS_FETCH();
object_and_properties_init(op, zend_standard_class_def, op->value.ht);
return;
break;
@ -677,7 +894,7 @@ ZEND_API void convert_to_object(zval *op)
break;
}
default:
convert_scalar_to_array(op, IS_OBJECT);
convert_scalar_to_array(op, IS_OBJECT TSRMLS_CC);
break;
}
}
@ -957,10 +1174,10 @@ ZEND_API int bitwise_not_function(zval *result, zval *op1 TSRMLS_DC)
result->type = IS_LONG;
return SUCCESS;
}
if (op1->type == IS_STRING) {
if (op1->type == IS_STRING || op1->type == IS_BINARY) {
int i;
result->type = IS_STRING;
result->type = op1->type;
result->value.str.val = estrndup(op1->value.str.val, op1->value.str.len);
result->value.str.len = op1->value.str.len;
for (i = 0; i < op1->value.str.len; i++) {
@ -976,8 +1193,9 @@ ZEND_API int bitwise_not_function(zval *result, zval *op1 TSRMLS_DC)
ZEND_API int bitwise_or_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
{
zval op1_copy, op2_copy;
if (op1->type == IS_STRING && op2->type == IS_STRING) {
if ((op1->type == IS_STRING && op2->type == IS_STRING) ||
(op1->type == IS_BINARY && op2->type == IS_BINARY)) {
zval *longer, *shorter;
char *result_str;
int i, result_len;
@ -990,7 +1208,7 @@ ZEND_API int bitwise_or_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
shorter = op1;
}
result->type = IS_STRING;
result->type = op1->type;
result_len = longer->value.str.len;
result_str = estrndup(longer->value.str.val, longer->value.str.len);
for (i = 0; i < shorter->value.str.len; i++) {
@ -1003,6 +1221,10 @@ ZEND_API int bitwise_or_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
result->value.str.len = result_len;
return SUCCESS;
}
if (op1->type == IS_UNICODE || op2->type == IS_UNICODE) {
zend_error(E_ERROR, "Unsupported operand types");
return FAILURE;
}
zendi_convert_to_long(op1, op1_copy, result);
zendi_convert_to_long(op2, op2_copy, result);
@ -1016,7 +1238,8 @@ ZEND_API int bitwise_and_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
{
zval op1_copy, op2_copy;
if (op1->type == IS_STRING && op2->type == IS_STRING) {
if ((op1->type == IS_STRING && op2->type == IS_STRING) ||
(op1->type == IS_BINARY && op2->type == IS_BINARY)) {
zval *longer, *shorter;
char *result_str;
int i, result_len;
@ -1029,7 +1252,7 @@ ZEND_API int bitwise_and_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
shorter = op1;
}
result->type = IS_STRING;
result->type = op1->type;
result_len = shorter->value.str.len;
result_str = estrndup(shorter->value.str.val, shorter->value.str.len);
for (i = 0; i < shorter->value.str.len; i++) {
@ -1043,6 +1266,10 @@ ZEND_API int bitwise_and_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
return SUCCESS;
}
if (op1->type == IS_UNICODE || op2->type == IS_UNICODE) {
zend_error(E_ERROR, "Unsupported operand types");
return FAILURE;
}
zendi_convert_to_long(op1, op1_copy, result);
zendi_convert_to_long(op2, op2_copy, result);
@ -1057,7 +1284,8 @@ ZEND_API int bitwise_xor_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
{
zval op1_copy, op2_copy;
if (op1->type == IS_STRING && op2->type == IS_STRING) {
if ((op1->type == IS_STRING && op2->type == IS_STRING) ||
(op1->type == IS_BINARY && op2->type == IS_BINARY)) {
zval *longer, *shorter;
char *result_str;
int i, result_len;
@ -1070,7 +1298,7 @@ ZEND_API int bitwise_xor_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
shorter = op1;
}
result->type = IS_STRING;
result->type = op1->type;
result_len = shorter->value.str.len;
result_str = estrndup(shorter->value.str.val, shorter->value.str.len);
for (i = 0; i < shorter->value.str.len; i++) {
@ -1084,6 +1312,11 @@ ZEND_API int bitwise_xor_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
return SUCCESS;
}
if (op1->type == IS_UNICODE || op2->type == IS_UNICODE) {
zend_error(E_ERROR, "Unsupported operand types");
return FAILURE;
}
zendi_convert_to_long(op1, op1_copy, result);
zendi_convert_to_long(op2, op2_copy, result);
@ -1097,6 +1330,11 @@ ZEND_API int shift_left_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
{
zval op1_copy, op2_copy;
if (op1->type == IS_UNICODE || op2->type == IS_UNICODE) {
zend_error(E_ERROR, "Unsupported operand types");
return FAILURE;
}
zendi_convert_to_long(op1, op1_copy, result);
zendi_convert_to_long(op2, op2_copy, result);
result->value.lval = op1->value.lval << op2->value.lval;
@ -1109,6 +1347,11 @@ ZEND_API int shift_right_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
{
zval op1_copy, op2_copy;
if (op1->type == IS_UNICODE || op2->type == IS_UNICODE) {
zend_error(E_ERROR, "Unsupported operand types");
return FAILURE;
}
zendi_convert_to_long(op1, op1_copy, result);
zendi_convert_to_long(op2, op2_copy, result);
result->value.lval = op1->value.lval >> op2->value.lval;
@ -1117,15 +1360,31 @@ ZEND_API int shift_right_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
}
/* must support result==op1 */
ZEND_API int add_char_to_string(zval *result, zval *op1, zval *op2)
{
result->value.str.len = op1->value.str.len + 1;
result->value.str.val = (char *) erealloc(op1->value.str.val, result->value.str.len+1);
result->value.str.val[result->value.str.len - 1] = (char) op2->value.lval;
result->value.str.val[result->value.str.len] = 0;
result->type = IS_STRING;
if (op1->type == IS_UNICODE) {
UChar32 codepoint = (UChar32) op2->value.lval;
if (U_IS_BMP(codepoint)) {
result->value.ustr.len = op1->value.ustr.len + 1;
result->value.ustr.val = eurealloc(op1->value.ustr.val, result->value.ustr.len+1);
result->value.ustr.val[result->value.ustr.len - 1] = (UChar) op2->value.lval;
} else {
result->value.ustr.len = op1->value.ustr.len + 2;
result->value.ustr.val = eurealloc(op1->value.ustr.val, result->value.ustr.len+1);
result->value.ustr.val[result->value.ustr.len - 2] = (UChar) U16_LEAD(codepoint);
result->value.ustr.val[result->value.ustr.len - 1] = (UChar) U16_TRAIL(codepoint);
}
result->value.ustr.val[result->value.ustr.len] = 0;
result->type = IS_UNICODE;
} else {
result->value.str.len = op1->value.str.len + 1;
result->value.str.val = (char *) erealloc(op1->value.str.val, result->value.str.len+1);
result->value.str.val[result->value.str.len - 1] = (char) op2->value.lval;
result->value.str.val[result->value.str.len] = 0;
result->type = op1->type;
}
return SUCCESS;
}
@ -1133,13 +1392,25 @@ ZEND_API int add_char_to_string(zval *result, zval *op1, zval *op2)
/* must support result==op1 */
ZEND_API int add_string_to_string(zval *result, zval *op1, zval *op2)
{
int length = op1->value.str.len + op2->value.str.len;
assert(op1->type == op2->type);
result->value.str.val = (char *) erealloc(op1->value.str.val, length+1);
memcpy(result->value.str.val+op1->value.str.len, op2->value.str.val, op2->value.str.len);
result->value.str.val[length] = 0;
result->value.str.len = length;
result->type = IS_STRING;
if (op1->type == IS_UNICODE) {
int32_t length = op1->value.ustr.len + op2->value.ustr.len;
result->value.ustr.val = eurealloc(op1->value.ustr.val, length+1);
u_memcpy(result->value.ustr.val+op1->value.ustr.len, op2->value.ustr.val, op2->value.ustr.len);
result->value.ustr.val[length] = 0;
result->value.ustr.len = length;
result->type = IS_UNICODE;
} else {
int length = op1->value.str.len + op2->value.str.len;
result->value.str.val = (char *) erealloc(op1->value.str.val, length+1);
memcpy(result->value.str.val+op1->value.str.len, op2->value.str.val, op2->value.str.len);
result->value.str.val[length] = 0;
result->value.str.len = length;
result->type = op1->type;
}
return SUCCESS;
}
@ -1148,10 +1419,21 @@ ZEND_API int concat_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
{
zval op1_copy, op2_copy;
int use_copy1, use_copy2;
zend_uchar result_type;
zend_make_printable_zval(op1, &op1_copy, &use_copy1);
zend_make_printable_zval(op2, &op2_copy, &use_copy2);
if (op1->type == IS_UNICODE || op2->type == IS_UNICODE) {
zend_make_unicode_zval(op1, &op1_copy, &use_copy1);
zend_make_unicode_zval(op2, &op2_copy, &use_copy2);
result_type = IS_UNICODE;
} else if (op1->type == IS_BINARY && op2->type == IS_BINARY) {
result_type = IS_BINARY;
/* no conversion necessary */
use_copy1 = use_copy2 = 0;
} else {
result_type = IS_STRING;
zend_make_string_zval(op1, &op1_copy, &use_copy1);
zend_make_string_zval(op2, &op2_copy, &use_copy2);
}
if (use_copy1) {
/* We have created a converted copy of op1. Therefore, op1 won't become the result so
@ -1166,20 +1448,23 @@ ZEND_API int concat_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
op2 = &op2_copy;
}
if (result==op1) { /* special case, perform operations on result */
uint res_len = op1->value.str.len + op2->value.str.len;
result->value.str.val = erealloc(result->value.str.val, res_len+1);
memcpy(result->value.str.val+result->value.str.len, op2->value.str.val, op2->value.str.len);
result->value.str.val[res_len]=0;
result->value.str.len = res_len;
add_string_to_string(result, op1, op2);
} else {
result->value.str.len = op1->value.str.len + op2->value.str.len;
result->value.str.val = (char *) emalloc(result->value.str.len + 1);
memcpy(result->value.str.val, op1->value.str.val, op1->value.str.len);
memcpy(result->value.str.val+op1->value.str.len, op2->value.str.val, op2->value.str.len);
result->value.str.val[result->value.str.len] = 0;
result->type = IS_STRING;
if (result_type == IS_UNICODE) {
result->value.ustr.len = op1->value.ustr.len + op2->value.ustr.len;
result->value.ustr.val = eumalloc(result->value.ustr.len + 1);
u_memcpy(result->value.ustr.val, op1->value.ustr.val, op1->value.ustr.len);
u_memcpy(result->value.ustr.val+op1->value.ustr.len, op2->value.ustr.val, op2->value.ustr.len);
result->value.ustr.val[result->value.ustr.len] = 0;
result->type = IS_UNICODE;
} else {
result->value.str.len = op1->value.str.len + op2->value.str.len;
result->value.str.val = (char *) emalloc(result->value.str.len + 1);
memcpy(result->value.str.val, op1->value.str.val, op1->value.str.len);
memcpy(result->value.str.val+op1->value.str.len, op2->value.str.val, op2->value.str.len);
result->value.str.val[result->value.str.len] = 0;
result->type = result_type;
}
}
if (use_copy1) {
zval_dtor(op1);
@ -1314,8 +1599,18 @@ ZEND_API int compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
}
}
if (op1->type == IS_STRING && op2->type == IS_STRING) {
zendi_smart_strcmp(result, op1, op2);
if ((op1->type == IS_UNICODE || op1->type == IS_STRING || op1->type == IS_BINARY) &&
(op2->type == IS_UNICODE || op2->type == IS_STRING || op2->type == IS_BINARY)) {
if (op1->type == IS_UNICODE || op2->type == IS_UNICODE) {
zendi_u_smart_strcmp(result, op1, op2);
} else if (op1->type == IS_STRING || op2->type == IS_STRING) {
zendi_smart_strcmp(result, op1, op2);
} else {
result->value.lval = zend_binary_zval_strcmp(op1, op2);
result->value.lval = ZEND_NORMALIZE_BOOL(result->value.lval);
result->type = IS_LONG;
}
COMPARE_RETURN_AND_FREE(SUCCESS);
}
@ -1421,6 +1716,7 @@ ZEND_API int is_identical_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
result->value.lval = (op1->value.dval == op2->value.dval);
break;
case IS_STRING:
case IS_BINARY:
if ((op1->value.str.len == op2->value.str.len)
&& (!memcmp(op1->value.str.val, op2->value.str.val, op1->value.str.len))) {
result->value.lval = 1;
@ -1428,6 +1724,14 @@ ZEND_API int is_identical_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
result->value.lval = 0;
}
break;
case IS_UNICODE:
if ((op1->value.ustr.len == op2->value.ustr.len)
&& (!memcmp(op1->value.ustr.val, op2->value.ustr.val, UBYTES(op1->value.ustr.len)))) {
result->value.lval = 1;
} else {
result->value.lval = 0;
}
break;
case IS_ARRAY:
if (zend_hash_compare(op1->value.ht, op2->value.ht, (compare_func_t) hash_zval_identical_function, 1 TSRMLS_CC)==0) {
result->value.lval = 1;
@ -1682,6 +1986,7 @@ ZEND_API int increment_function(zval *op1)
op1->value.lval = 1;
op1->type = IS_LONG;
break;
case IS_BINARY:
case IS_STRING: {
long lval;
double dval;
@ -1711,6 +2016,9 @@ ZEND_API int increment_function(zval *op1)
}
}
break;
case IS_UNICODE:
zend_error(E_ERROR, "Unsupported operand type");
break;
default:
return FAILURE;
}
@ -1735,6 +2043,7 @@ ZEND_API int decrement_function(zval *op1)
case IS_DOUBLE:
op1->value.dval = op1->value.dval - 1;
break;
case IS_BINARY:
case IS_STRING: /* Like perl we only support string increment */
if (op1->value.str.len == 0) { /* consider as 0 */
STR_FREE(op1->value.str.val);
@ -1760,6 +2069,9 @@ ZEND_API int decrement_function(zval *op1)
break;
}
break;
case IS_UNICODE:
zend_error(E_ERROR, "Unsupported operand type");
break;
default:
return FAILURE;
}
@ -1788,6 +2100,38 @@ ZEND_API char *zend_str_tolower_copy(char *dest, const char *source, unsigned in
return dest;
}
ZEND_API char *zend_str_tolower_dup(const char *source, unsigned int length)
{
return zend_str_tolower_copy((char *)emalloc(length+1), source, length);
}
ZEND_API void *zend_u_str_tolower_copy(zend_uchar type, void *dest, const void *source, unsigned int length)
{
if (type == IS_UNICODE) {
register UChar *str = (UChar*)source;
register UChar *result = (UChar*)dest;
register UChar *end = str + length;
while (str < end) {
*result++ = u_tolower((int)*str++);
}
*result = *end;
return dest;
} else {
return zend_str_tolower_copy(dest, source, length);
}
}
ZEND_API void *zend_u_str_tolower_dup(zend_uchar type, const void *source, unsigned int length)
{
if (type == IS_UNICODE) {
return zend_u_str_tolower_copy(IS_UNICODE, emalloc(UBYTES(length+1)), source, length);
} else {
return zend_str_tolower_copy((char*)emalloc(length+1), (char*)source, length);
}
}
ZEND_API void zend_str_tolower(char *str, unsigned int length)
{
register unsigned char *p = (unsigned char*)str;
@ -1799,6 +2143,42 @@ ZEND_API void zend_str_tolower(char *str, unsigned int length)
}
}
ZEND_API void zend_u_str_tolower(zend_uchar type, void *str, unsigned int length) {
if (type == IS_UNICODE) {
register UChar *p = (UChar*)str;
register UChar *end = p + length;
while (p < end) {
*p = u_tolower((int)*p);
p++;
}
} else {
zend_str_tolower((char*)str, length);
}
}
ZEND_API void *zend_u_str_case_fold(zend_uchar type, const void *source, unsigned int length, zend_bool normalize, unsigned int *new_len)
{
if (type == IS_UNICODE) {
UChar *ret;
int32_t ret_len;
if (normalize) {
zend_normalize_identifier(&ret, &ret_len, (UChar*)source, length, 1);
} else {
UErrorCode status = U_ZERO_ERROR;
zend_case_fold_string(&ret, &ret_len, (UChar*)source, length, U_FOLD_CASE_DEFAULT, &status);
}
*new_len = ret_len;
return ret;
} else {
*new_len = length;
return zend_str_tolower_dup(source, length);
}
}
ZEND_API int zend_binary_strcmp(char *s1, uint len1, char *s2, uint len2)
{
int retval;
@ -1811,6 +2191,20 @@ ZEND_API int zend_binary_strcmp(char *s1, uint len1, char *s2, uint len2)
}
}
ZEND_API int zend_u_binary_strcmp(UChar *s1, int32_t len1, UChar *s2, int32_t len2)
{
int retval;
retval = u_memcmpCodePointOrder(s1, s2, MIN(len1, len2));
if (!retval) {
return (len1 - len2);
} else {
return retval;
}
}
ZEND_API int zend_binary_strncmp(char *s1, uint len1, char *s2, uint len2, uint length)
{
int retval;
@ -1867,6 +2261,13 @@ ZEND_API int zend_binary_zval_strcmp(zval *s1, zval *s2)
return zend_binary_strcmp(s1->value.str.val, s1->value.str.len, s2->value.str.val, s2->value.str.len);
}
ZEND_API int zend_u_binary_zval_strcmp(zval *s1, zval *s2)
{
return zend_u_binary_strcmp(s1->value.ustr.val, s1->value.ustr.len, s2->value.ustr.val, s2->value.ustr.len);
}
ZEND_API int zend_binary_zval_strncmp(zval *s1, zval *s2, zval *s3)
{
return zend_binary_strncmp(s1->value.str.val, s1->value.str.len, s2->value.str.val, s2->value.str.len, s3->value.lval);
@ -1891,6 +2292,11 @@ ZEND_API void zendi_smart_strcmp(zval *result, zval *s1, zval *s2)
long lval1, lval2;
double dval1, dval2;
if (s1->type == IS_BINARY || s2->type == IS_BINARY) {
zend_error(E_ERROR, "Cannot convert binary type to string type");
return;
}
if ((ret1=is_numeric_string(s1->value.str.val, s1->value.str.len, &lval1, &dval1, 0)) &&
(ret2=is_numeric_string(s2->value.str.val, s2->value.str.len, &lval2, &dval2, 0))) {
if ((ret1==IS_DOUBLE) || (ret2==IS_DOUBLE)) {
@ -1916,6 +2322,57 @@ ZEND_API void zendi_smart_strcmp(zval *result, zval *s1, zval *s2)
}
ZEND_API void zendi_u_smart_strcmp(zval *result, zval *s1, zval *s2)
{
int ret1, ret2;
long lval1, lval2;
double dval1, dval2;
zval s1_copy, s2_copy;
int use_copy1 = 0, use_copy2 = 0;
if (s1->type != IS_UNICODE || s2->type != IS_UNICODE) {
zend_make_unicode_zval(s1, &s1_copy, &use_copy1);
zend_make_unicode_zval(s2, &s2_copy, &use_copy2);
if (use_copy1) {
s1 = &s1_copy;
}
if (use_copy2) {
s2 = &s2_copy;
}
}
if ((ret1=is_numeric_unicode(s1->value.ustr.val, s1->value.ustr.len, &lval1, &dval1, 0)) &&
(ret2=is_numeric_unicode(s2->value.ustr.val, s2->value.ustr.len, &lval2, &dval2, 0))) {
if ((ret1==IS_DOUBLE) || (ret2==IS_DOUBLE)) {
if (ret1!=IS_DOUBLE) {
dval1 = zend_u_strtod(s1->value.ustr.val, NULL);
} else if (ret2!=IS_DOUBLE) {
dval2 = zend_u_strtod(s2->value.ustr.val, NULL);
}
result->value.dval = dval1 - dval2;
result->value.lval = ZEND_NORMALIZE_BOOL(result->value.dval);
result->type = IS_LONG;
} else { /* they both have to be long's */
result->value.lval = lval1 - lval2;
result->value.lval = ZEND_NORMALIZE_BOOL(result->value.lval);
result->type = IS_LONG;
}
} else {
result->value.lval = zend_u_binary_zval_strcmp(s1, s2);
result->value.lval = ZEND_NORMALIZE_BOOL(result->value.lval);
result->type = IS_LONG;
}
if (use_copy1) {
zval_dtor(s1);
}
if (use_copy2) {
zval_dtor(s2);
}
return;
}
static int hash_zval_compare_function(const zval **z1, const zval **z2 TSRMLS_DC)
{
zval result;
@ -1962,6 +2419,22 @@ ZEND_API void zend_compare_objects(zval *result, zval *o1, zval *o2 TSRMLS_DC)
}
}
ZEND_API void zend_locale_usprintf_double(zval *op ZEND_FILE_LINE_DC)
{
double dval = op->value.dval;
UFILE *strf;
int32_t capacity;
TSRMLS_FETCH();
capacity = MAX_LENGTH_OF_DOUBLE + EG(precision) + 1;
op->value.ustr.val = eumalloc_rel(capacity);
/* UTODO uses default locale for now */
strf = u_fstropen(op->value.ustr.val, capacity, NULL);
op->value.ustr.len = u_fprintf(strf, "%.*G", (int) EG(precision), dval);
u_fclose(strf);
}
ZEND_API void zend_locale_sprintf_double(zval *op ZEND_FILE_LINE_DC)
{
double dval = op->value.dval;
@ -1973,6 +2446,20 @@ ZEND_API void zend_locale_sprintf_double(zval *op ZEND_FILE_LINE_DC)
op->value.str.len = strlen(op->value.str.val);
}
ZEND_API void zend_locale_usprintf_long(zval *op ZEND_FILE_LINE_DC)
{
long lval = op->value.lval;
UFILE *strf;
int32_t capacity;
capacity = MAX_LENGTH_OF_LONG + 1;
op->value.ustr.val = eumalloc_rel(capacity);
/* UTODO uses default locale for now */
strf = u_fstropen(op->value.ustr.val, capacity, NULL);
op->value.ustr.len = u_fprintf(strf, "%ld", lval);
u_fclose(strf);
}
/*
* Local variables:
* tab-width: 4

View File

@ -30,6 +30,7 @@
#endif
#include "zend_strtod.h"
#include "zend_unicode.h"
#if 0&&HAVE_BCMATH
#include "ext/bcmath/libbcmath/src/bcmath.h"
@ -63,6 +64,8 @@ ZEND_API int is_smaller_or_equal_function(zval *result, zval *op1, zval *op2 TSR
ZEND_API zend_bool instanceof_function_ex(zend_class_entry *instance_ce, zend_class_entry *ce, zend_bool interfaces_only TSRMLS_DC);
ZEND_API zend_bool instanceof_function(zend_class_entry *instance_ce, zend_class_entry *ce TSRMLS_DC);
ZEND_API long zend_u_strtol(const UChar *nptr, UChar **endptr, int base);
ZEND_API double zend_u_strtod(const UChar *nptr, UChar **endptr);
END_EXTERN_C()
static inline zend_bool is_numeric_string(char *str, int length, long *lval, double *dval, zend_bool allow_errors)
@ -128,6 +131,77 @@ static inline zend_bool is_numeric_string(char *str, int length, long *lval, dou
return 0;
}
static inline zend_bool is_numeric_unicode(UChar *str, int32_t length, long *lval, double *dval, zend_bool allow_errors)
{
int32_t local_lval;
double local_dval;
UChar *end_ptr_long, *end_ptr_double;
int conv_base=10;
if (!length) {
return 0;
}
/* handle hex numbers */
if (length>=2 && str[0]=='0' && (str[1]=='x' || str[1]=='X')) {
conv_base=16;
}
errno=0;
local_lval = zend_u_strtol(str, &end_ptr_long, conv_base);
if (errno != ERANGE) {
if (end_ptr_long == str+length) { /* integer string */
if (lval) {
*lval = local_lval;
}
return IS_LONG;
} else if (end_ptr_long == str && *end_ptr_long != '\0' && *str != '.' && *str != '-') { /* ignore partial string matches */
return 0;
}
} else {
end_ptr_long = NULL;
}
if (conv_base == 16) { /* hex string, under UNIX strtod() messes it up */
/* UTODO: keep compatibility with is_numeric_string() here? */
return 0;
}
local_dval = zend_u_strtod(str, &end_ptr_double);
if (local_dval == 0 && end_ptr_double == str) {
end_ptr_double = NULL;
} else {
if (end_ptr_double == str+length) { /* floating point string */
if (!zend_finite(local_dval)) {
/* "inf","nan" and maybe other weird ones */
return 0;
}
if (dval) {
*dval = local_dval;
}
return IS_DOUBLE;
}
}
if (allow_errors) {
if (end_ptr_double > end_ptr_long && dval) {
*dval = local_dval;
return IS_DOUBLE;
} else if (end_ptr_long && lval) {
*lval = local_lval;
return IS_LONG;
}
}
return 0;
}
static inline UChar*
zend_u_memnstr(UChar *haystack, UChar *needle, int32_t needle_len, UChar *end)
{
return u_strFindFirst(haystack, end - haystack, needle, needle_len);
}
static inline char *
zend_memnstr(char *haystack, char *needle, int needle_len, char *end)
{
@ -160,6 +234,10 @@ ZEND_API int decrement_function(zval *op2);
ZEND_API void convert_scalar_to_number(zval *op TSRMLS_DC);
ZEND_API void _convert_to_string(zval *op ZEND_FILE_LINE_DC);
ZEND_API void _convert_to_string_with_converter(zval *op, UConverter *conv TSRMLS_DC ZEND_FILE_LINE_DC);
ZEND_API void _convert_to_unicode(zval *op TSRMLS_DC ZEND_FILE_LINE_DC);
ZEND_API void _convert_to_unicode_with_converter(zval *op, UConverter *conv TSRMLS_DC ZEND_FILE_LINE_DC);
ZEND_API void convert_to_binary(zval *op);
ZEND_API void convert_to_long(zval *op);
ZEND_API void convert_to_double(zval *op);
ZEND_API void convert_to_long_base(zval *op, int base);
@ -172,7 +250,11 @@ ZEND_API void multi_convert_to_double_ex(int argc, ...);
ZEND_API void multi_convert_to_string_ex(int argc, ...);
ZEND_API int add_char_to_string(zval *result, zval *op1, zval *op2);
ZEND_API int add_string_to_string(zval *result, zval *op1, zval *op2);
#define convert_to_string(op) _convert_to_string((op) ZEND_FILE_LINE_CC)
#define convert_to_string(op) _convert_to_string((op) ZEND_FILE_LINE_CC)
#define convert_to_string_with_converter(op, conv) _convert_to_string_with_converter((op), (conv) TSRMLS_CC ZEND_FILE_LINE_CC)
#define convert_to_unicode(op) _convert_to_unicode((op) TSRMLS_CC ZEND_FILE_LINE_CC)
#define convert_to_unicode_with_converter(op, conv) _convert_to_unicode_with_converter((op), (conv) TSRMLS_CC ZEND_FILE_LINE_CC)
#define convert_to_text(op) (UG(unicode)?convert_to_unicode(op):convert_to_string(op))
ZEND_API double zend_string_to_double(const char *number, zend_uint length);
@ -186,15 +268,14 @@ ZEND_API int string_locale_compare_function(zval *result, zval *op1, zval *op2 T
ZEND_API void zend_str_tolower(char *str, unsigned int length);
ZEND_API char *zend_str_tolower_copy(char *dest, const char *source, unsigned int length);
END_EXTERN_C()
ZEND_API char *zend_str_tolower_dup(const char *source, unsigned int length);
static inline char *
zend_str_tolower_dup(const char *source, unsigned int length)
{
return zend_str_tolower_copy((char *)emalloc(length+1), source, length);
}
ZEND_API void zend_u_str_tolower(zend_uchar type, void *str, unsigned int length);
ZEND_API void *zend_u_str_tolower_copy(zend_uchar type, void *dest, const void *source, unsigned int length);
ZEND_API void *zend_u_str_tolower_dup(zend_uchar type, const void *source, unsigned int length);
ZEND_API void *zend_u_str_case_fold(zend_uchar type, const void *source, unsigned int length, zend_bool normalize, unsigned int *new_len);
BEGIN_EXTERN_C()
ZEND_API int zend_binary_zval_strcmp(zval *s1, zval *s2);
ZEND_API int zend_binary_zval_strncmp(zval *s1, zval *s2, zval *s3);
ZEND_API int zend_binary_zval_strcasecmp(zval *s1, zval *s2);
@ -204,7 +285,11 @@ ZEND_API int zend_binary_strncmp(char *s1, uint len1, char *s2, uint len2, uint
ZEND_API int zend_binary_strcasecmp(char *s1, uint len1, char *s2, uint len2);
ZEND_API int zend_binary_strncasecmp(char *s1, uint len1, char *s2, uint len2, uint length);
ZEND_API int zend_u_binary_zval_strcmp(zval *s1, zval *s2);
ZEND_API int zend_u_binary_strcmp(UChar *s1, int32_t len1, UChar *s2, int32_t len2);
ZEND_API void zendi_smart_strcmp(zval *result, zval *s1, zval *s2);
ZEND_API void zendi_u_smart_strcmp(zval *result, zval *s1, zval *s2);
ZEND_API void zend_compare_symbol_tables(zval *result, HashTable *ht1, HashTable *ht2 TSRMLS_DC);
ZEND_API void zend_compare_arrays(zval *result, zval *a1, zval *a2 TSRMLS_DC);
ZEND_API void zend_compare_objects(zval *result, zval *o1, zval *o2 TSRMLS_DC);
@ -212,6 +297,8 @@ ZEND_API void zend_compare_objects(zval *result, zval *o1, zval *o2 TSRMLS_DC);
ZEND_API int zend_atoi(const char *str, int str_len);
ZEND_API void zend_locale_sprintf_double(zval *op ZEND_FILE_LINE_DC);
ZEND_API void zend_locale_usprintf_double(zval *op ZEND_FILE_LINE_DC);
ZEND_API void zend_locale_usprintf_long(zval *op ZEND_FILE_LINE_DC);
END_EXTERN_C()
#define convert_to_ex_master(ppzv, lower_type, upper_type) \
if ((*ppzv)->type!=IS_##upper_type) { \
@ -219,14 +306,59 @@ END_EXTERN_C()
convert_to_##lower_type(*ppzv); \
}
#define convert_to_explicit_type(pzv, type) \
do { \
switch (type) { \
case IS_NULL: \
convert_to_null(pzv); \
break; \
case IS_LONG: \
convert_to_long(pzv); \
break; \
case IS_DOUBLE: \
convert_to_double(pzv); \
break; \
case IS_BOOL: \
convert_to_bool(pzv); \
break; \
case IS_ARRAY: \
convert_to_array(pzv); \
break; \
case IS_OBJECT: \
convert_to_object(pzv); \
break; \
case IS_STRING: \
convert_to_string(pzv); \
break; \
case IS_UNICODE: \
convert_to_unicode(pzv); \
break; \
case IS_BINARY: \
convert_to_binary(pzv); \
break; \
default: \
assert(0); \
break; \
} \
} while (0); \
#define convert_to_explicit_type_ex(ppzv, type) \
if ((*ppzv)->type != type) { \
SEPARATE_ZVAL_IF_NOT_REF(ppzv); \
convert_to_explicit_type(*ppzv, type); \
} \
}
#define convert_to_boolean_ex(ppzv) convert_to_ex_master(ppzv, boolean, BOOL)
#define convert_to_long_ex(ppzv) convert_to_ex_master(ppzv, long, LONG)
#define convert_to_double_ex(ppzv) convert_to_ex_master(ppzv, double, DOUBLE)
#define convert_to_string_ex(ppzv) convert_to_ex_master(ppzv, string, STRING)
#define convert_to_unicode_ex(ppzv) convert_to_ex_master(ppzv, unicode, UNICODE)
#define convert_to_binary_ex(ppzv) convert_to_ex_master(ppzv, binary, BINARY)
#define convert_to_array_ex(ppzv) convert_to_ex_master(ppzv, array, ARRAY)
#define convert_to_object_ex(ppzv) convert_to_ex_master(ppzv, object, OBJECT)
#define convert_to_null_ex(ppzv) convert_to_ex_master(ppzv, null, NULL)
#define convert_to_text_ex(ppzv) if (UG(unicode)) {convert_to_unicode_ex(ppzv);} else {convert_to_string_ex(ppzv);}
#define convert_scalar_to_number_ex(ppzv) \
if ((*ppzv)->type!=IS_LONG && (*ppzv)->type!=IS_DOUBLE) { \
@ -242,6 +374,11 @@ END_EXTERN_C()
#define Z_DVAL(zval) (zval).value.dval
#define Z_STRVAL(zval) (zval).value.str.val
#define Z_STRLEN(zval) (zval).value.str.len
#define Z_USTRVAL(zval) (zval).value.ustr.val
#define Z_USTRLEN(zval) (zval).value.ustr.len
#define Z_USTRCPLEN(zval) (u_countChar32((zval).value.ustr.val, (zval).value.ustr.len))
#define Z_BINVAL(zval) Z_STRVAL(zval)
#define Z_BINLEN(zval) Z_STRLEN(zval)
#define Z_ARRVAL(zval) (zval).value.ht
#define Z_OBJ_HANDLE(zval) (zval).value.obj.handle
#define Z_OBJ_HT(zval) (zval).value.obj.handlers
@ -249,12 +386,19 @@ END_EXTERN_C()
#define Z_OBJPROP(zval) Z_OBJ_HT((zval))->get_properties(&(zval) TSRMLS_CC)
#define Z_OBJ_HANDLER(zval, hf) Z_OBJ_HT((zval))->hf
#define Z_RESVAL(zval) (zval).value.lval
#define Z_UNIVAL(zval) ((zval).type==IS_UNICODE?(char*)(zval).value.ustr.val:(zval).value.str.val)
#define Z_UNILEN(zval) ((zval).type==IS_UNICODE?(zval).value.ustr.len:(zval).value.str.len)
#define Z_LVAL_P(zval_p) Z_LVAL(*zval_p)
#define Z_BVAL_P(zval_p) Z_BVAL(*zval_p)
#define Z_DVAL_P(zval_p) Z_DVAL(*zval_p)
#define Z_STRVAL_P(zval_p) Z_STRVAL(*zval_p)
#define Z_STRLEN_P(zval_p) Z_STRLEN(*zval_p)
#define Z_USTRVAL_P(zval_p) Z_USTRVAL(*zval_p)
#define Z_USTRLEN_P(zval_p) Z_USTRLEN(*zval_p)
#define Z_USTRCPLEN_P(zval_p) Z_USTRCPLEN(*zval_p)
#define Z_BINVAL_P(zval) Z_STRVAL_P(zval)
#define Z_BINLEN_P(zval) Z_STRLEN_P(zval)
#define Z_ARRVAL_P(zval_p) Z_ARRVAL(*zval_p)
#define Z_OBJPROP_P(zval_p) Z_OBJPROP(*zval_p)
#define Z_OBJCE_P(zval_p) Z_OBJCE(*zval_p)
@ -262,12 +406,19 @@ END_EXTERN_C()
#define Z_OBJ_HANDLE_P(zval_p) Z_OBJ_HANDLE(*zval_p)
#define Z_OBJ_HT_P(zval_p) Z_OBJ_HT(*zval_p)
#define Z_OBJ_HANDLER_P(zval_p, h) Z_OBJ_HANDLER(*zval_p, h)
#define Z_UNIVAL_P(zval_p) Z_UNIVAL(*zval_p)
#define Z_UNILEN_P(zval_p) Z_UNILEN(*zval_p)
#define Z_LVAL_PP(zval_pp) Z_LVAL(**zval_pp)
#define Z_BVAL_PP(zval_pp) Z_BVAL(**zval_pp)
#define Z_DVAL_PP(zval_pp) Z_DVAL(**zval_pp)
#define Z_STRVAL_PP(zval_pp) Z_STRVAL(**zval_pp)
#define Z_STRLEN_PP(zval_pp) Z_STRLEN(**zval_pp)
#define Z_USTRVAL_PP(zval_pp) Z_USTRVAL(**zval_pp)
#define Z_USTRLEN_PP(zval_pp) Z_USTRLEN(**zval_pp)
#define Z_USTRCPLEN_PP(zval_pp) Z_USTRCPLEN(**zval_pp)
#define Z_BINVAL_PP(zval) Z_STRVAL_PP(zval)
#define Z_BINLEN_PP(zval) Z_STRLEN_PP(zval)
#define Z_ARRVAL_PP(zval_pp) Z_ARRVAL(**zval_pp)
#define Z_OBJPROP_PP(zval_pp) Z_OBJPROP(**zval_pp)
#define Z_OBJCE_PP(zval_pp) Z_OBJCE(**zval_pp)
@ -275,6 +426,8 @@ END_EXTERN_C()
#define Z_OBJ_HANDLE_PP(zval_p) Z_OBJ_HANDLE(**zval_p)
#define Z_OBJ_HT_PP(zval_p) Z_OBJ_HT(**zval_p)
#define Z_OBJ_HANDLER_PP(zval_p, h) Z_OBJ_HANDLER(**zval_p, h)
#define Z_UNIVAL_PP(zval_pp) Z_UNIVAL(**zval_pp)
#define Z_UNILEN_PP(zval_pp) Z_UNILEN(**zval_pp)
#define Z_TYPE(zval) (zval).type
#define Z_TYPE_P(zval_p) Z_TYPE(*zval_p)

View File

@ -43,7 +43,7 @@ zend_class_entry *reflection_extension_ptr;
/* Method macros */
#define METHOD_NOTSTATIC \
if (!this_ptr) { \
zend_error(E_ERROR, "%s() cannot be called statically", get_active_function_name(TSRMLS_C)); \
zend_error(E_ERROR, "%v() cannot be called statically", get_active_function_name(TSRMLS_C)); \
return; \
} \
@ -233,7 +233,7 @@ static zend_object_value reflection_objects_new(zend_class_entry *class_type TSR
intern->free_ptr = 0;
ALLOC_HASHTABLE(intern->zo.properties);
zend_hash_init(intern->zo.properties, 0, NULL, ZVAL_PTR_DTOR, 0);
zend_u_hash_init(intern->zo.properties, 0, NULL, ZVAL_PTR_DTOR, 0, UG(unicode));
zend_hash_copy(intern->zo.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
retval.handle = zend_objects_store_put(intern, NULL, reflection_free_objects_storage, reflection_objects_clone TSRMLS_CC);
retval.handlers = &reflection_object_handlers;
@ -297,17 +297,17 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in
}
string_printf(str, "class ");
}
string_write(str, ce->name, ce->name_length);
string_printf(str, "%v", ce->name);
if (ce->parent) {
string_printf(str, " extends %s", ce->parent->name);
string_printf(str, " extends %v", ce->parent->name);
}
if (ce->num_interfaces) {
zend_uint i;
string_printf(str, " implements %s", ce->interfaces[0]->name);
string_printf(str, " implements %v", ce->interfaces[0]->name);
for (i = 1; i < ce->num_interfaces; ++i) {
string_printf(str, ", %s", ce->interfaces[i]->name);
string_printf(str, ", %v", ce->interfaces[i]->name);
}
}
string_printf(str, " ] {\n");
@ -540,7 +540,7 @@ static void _parameter_string(string *str, zend_function *fptr, struct _zend_arg
string_printf(str, "<required> ");
}
if (arg_info->class_name) {
string_printf(str, "%s ", arg_info->class_name);
string_printf(str, "%v ", arg_info->class_name);
if (arg_info->allow_null) {
string_printf(str, "or NULL ");
}
@ -554,7 +554,7 @@ static void _parameter_string(string *str, zend_function *fptr, struct _zend_arg
string_write(str, "&", sizeof("&")-1);
}
if (arg_info->name) {
string_printf(str, "$%s", arg_info->name);
string_printf(str, "$%v", arg_info->name);
} else {
string_printf(str, "$param%d", offset);
}
@ -671,7 +671,7 @@ static void _function_string(string *str, zend_function *fptr, char* indent TSRM
if (fptr->op_array.return_reference) {
string_printf(str, "&");
}
string_printf(str, "%s ] {\n", fptr->common.function_name);
string_printf(str, "%v ] {\n", fptr->common.function_name);
/* The information where a function is declared is only available for user classes */
if (fptr->type == ZEND_USER_FUNCTION) {
string_printf(str, "%s @@ %s %d - %d\n", indent,
@ -720,8 +720,8 @@ static void _property_string(string *str, zend_property_info *prop, char *prop_n
string_printf(str, "static ");
}
zend_unmangle_property_name(prop->name, &class_name, &prop_name);
string_printf(str, "$%s", prop_name);
zend_u_unmangle_property_name(UG(unicode)?IS_UNICODE:IS_STRING, prop->name, &class_name, &prop_name);
string_printf(str, "$%v", prop_name);
}
string_printf(str, " ]\n");
@ -865,7 +865,11 @@ ZEND_API void zend_reflection_class_factory(zend_class_entry *ce, zval *object T
zval *name;
MAKE_STD_ZVAL(name);
ZVAL_STRINGL(name, ce->name, ce->name_length, 1);
if (UG(unicode)) {
ZVAL_UNICODEL(name, (UChar*)ce->name, ce->name_length, 1);
} else {
ZVAL_STRINGL(name, ce->name, ce->name_length, 1);
}
reflection_instanciate(reflection_class_ptr, object TSRMLS_CC);
intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
intern->ptr = ce;
@ -912,7 +916,11 @@ static void reflection_parameter_factory(zend_function *fptr, struct _zend_arg_i
MAKE_STD_ZVAL(name);
if (arg_info->name) {
ZVAL_STRINGL(name, arg_info->name, arg_info->name_len, 1);
if (UG(unicode)) {
ZVAL_UNICODEL(name, (UChar*)arg_info->name, arg_info->name_len, 1);
} else {
ZVAL_STRINGL(name, arg_info->name, arg_info->name_len, 1);
}
} else {
ZVAL_NULL(name);
}
@ -937,7 +945,11 @@ static void reflection_function_factory(zend_function *function, zval *object TS
zval *name;
MAKE_STD_ZVAL(name);
ZVAL_STRING(name, function->common.function_name, 1);
if (UG(unicode)) {
ZVAL_UNICODE(name, (UChar*)function->common.function_name, 1);
} else {
ZVAL_STRING(name, function->common.function_name, 1);
}
reflection_instanciate(reflection_function_ptr, object TSRMLS_CC);
intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
@ -956,9 +968,14 @@ static void reflection_method_factory(zend_class_entry *ce, zend_function *metho
zval *classname;
MAKE_STD_ZVAL(name);
ZVAL_STRING(name, method->common.function_name, 1);
MAKE_STD_ZVAL(classname);
ZVAL_STRINGL(classname, ce->name, ce->name_length, 1);
if (UG(unicode)) {
ZVAL_UNICODE(name, (UChar*)method->common.function_name, 1);
ZVAL_UNICODEL(classname, (UChar*)ce->name, ce->name_length, 1);
} else {
ZVAL_STRING(name, method->common.function_name, 1);
ZVAL_STRINGL(classname, ce->name, ce->name_length, 1);
}
reflection_instanciate(reflection_method_ptr, object TSRMLS_CC);
intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
intern->ptr = method;
@ -978,7 +995,7 @@ static void reflection_property_factory(zend_class_entry *ce, zend_property_info
property_reference *reference;
char *class_name, *prop_name;
zend_unmangle_property_name(prop->name, &class_name, &prop_name);
zend_u_unmangle_property_name(UG(unicode)?IS_UNICODE:IS_STRING, prop->name, &class_name, &prop_name);
if (!(prop->flags & ZEND_ACC_PRIVATE)) {
/* we have to seach the class hierarchy for this (implicit) public or protected property */
@ -997,10 +1014,14 @@ static void reflection_property_factory(zend_class_entry *ce, zend_property_info
}
MAKE_STD_ZVAL(name);
ZVAL_STRING(name, prop_name, 1);
MAKE_STD_ZVAL(classname);
ZVAL_STRINGL(classname, ce->name, ce->name_length, 1);
if (UG(unicode)) {
ZVAL_UNICODE(name, (UChar*)prop_name, 1);
ZVAL_UNICODEL(classname, (UChar*)ce->name, ce->name_length, 1);
} else {
ZVAL_STRING(name, prop_name, 1);
ZVAL_STRINGL(classname, ce->name, ce->name_length, 1);
}
reflection_instanciate(reflection_property_ptr, object TSRMLS_CC);
intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
@ -1144,7 +1165,7 @@ ZEND_METHOD(reflection, export)
}
if (!retval_ptr) {
zend_error(E_WARNING, "%s::__toString() did not return anything", Z_OBJCE_P(object)->name);
zend_error(E_WARNING, "%v::__toString() did not return anything", Z_OBJCE_P(object)->name);
RETURN_FALSE;
}
@ -1211,13 +1232,15 @@ ZEND_METHOD(reflection_function, __construct)
{
zval *name;
zval *object;
unsigned int lcname_len;
char *lcname;
reflection_object *intern;
zend_function *fptr;
char *name_str;
int name_len;
zend_uchar type;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name_str, &name_len) == FAILURE) {
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "t", &name_str, &name_len, &type) == FAILURE) {
return;
}
@ -1226,17 +1249,20 @@ ZEND_METHOD(reflection_function, __construct)
if (intern == NULL) {
return;
}
lcname = do_alloca(name_len + 1);
zend_str_tolower_copy(lcname, name_str, name_len);
if (zend_hash_find(EG(function_table), lcname, name_len + 1, (void **)&fptr) == FAILURE) {
free_alloca(lcname);
lcname = zend_u_str_case_fold(type, name_str, name_len, 1, &lcname_len);
if (zend_u_hash_find(EG(function_table), type, lcname, lcname_len + 1, (void **)&fptr) == FAILURE) {
efree(lcname);
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Function %s() does not exist", name_str);
"Function %R() does not exist", type, name_str);
return;
}
free_alloca(lcname);
efree(lcname);
MAKE_STD_ZVAL(name);
ZVAL_STRING(name, fptr->common.function_name, 1);
if (UG(unicode)) {
ZVAL_UNICODE(name, (UChar*)fptr->common.function_name, 1);
} else {
ZVAL_STRING(name, fptr->common.function_name, 1);
}
zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
intern->ptr = fptr;
intern->free_ptr = 0;
@ -1421,7 +1447,7 @@ ZEND_METHOD(reflection_function, invoke)
if (result == FAILURE) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Invocation of function %s() failed", fptr->common.function_name);
"Invocation of function %v() failed", fptr->common.function_name);
return;
}
@ -1485,7 +1511,7 @@ ZEND_METHOD(reflection_function, invokeArgs)
if (result == FAILURE) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Invocation of function %s() failed", fptr->common.function_name);
"Invocation of function %v() failed", fptr->common.function_name);
return;
}
@ -1598,19 +1624,20 @@ ZEND_METHOD(reflection_parameter, __construct)
/* First, find the function */
switch (Z_TYPE_P(reference)) {
case IS_UNICODE:
case IS_STRING: {
char *lcname;
unsigned int lcname_len;
char *lcname;
convert_to_string_ex(&reference);
lcname = do_alloca(Z_STRLEN_P(reference) + 1);
zend_str_tolower_copy(lcname, Z_STRVAL_P(reference), Z_STRLEN_P(reference));
if (zend_hash_find(EG(function_table), lcname, (int) Z_STRLEN_P(reference) + 1, (void**) &fptr) == FAILURE) {
free_alloca(lcname);
convert_to_text_ex(&reference);
lcname = zend_u_str_case_fold(Z_TYPE_P(reference), Z_STRVAL_P(reference), Z_STRLEN_P(reference), 1, &lcname_len);
if (zend_u_hash_find(EG(function_table), Z_TYPE_P(reference), lcname, lcname_len + 1, (void**) &fptr) == FAILURE) {
efree(lcname);
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Function %s() does not exist", Z_STRVAL_P(reference));
"Function %R() does not exist", Z_TYPE_P(reference), Z_STRVAL_P(reference));
return;
}
free_alloca(lcname);
efree(lcname);
}
break;
@ -1618,7 +1645,8 @@ ZEND_METHOD(reflection_parameter, __construct)
zval **classref;
zval **method;
zend_class_entry **pce;
char *lcname;
unsigned int lcname_len;
char *lcname;
if ((zend_hash_index_find(Z_ARRVAL_P(reference), 0, (void **) &classref) == FAILURE)
|| (zend_hash_index_find(Z_ARRVAL_P(reference), 1, (void **) &method) == FAILURE)) {
@ -1629,25 +1657,24 @@ ZEND_METHOD(reflection_parameter, __construct)
if (Z_TYPE_PP(classref) == IS_OBJECT) {
ce = Z_OBJCE_PP(classref);
} else {
convert_to_string_ex(classref);
if (zend_lookup_class(Z_STRVAL_PP(classref), Z_STRLEN_PP(classref), &pce TSRMLS_CC) == FAILURE) {
convert_to_text_ex(classref);
if (zend_u_lookup_class(Z_TYPE_PP(classref), Z_UNIVAL_PP(classref), Z_UNILEN_PP(classref), &pce TSRMLS_CC) == FAILURE) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Class %s does not exist", Z_STRVAL_PP(classref));
"Class %R does not exist", Z_TYPE_PP(classref), Z_UNIVAL_PP(classref));
return;
}
ce = *pce;
}
convert_to_string_ex(method);
lcname = do_alloca(Z_STRLEN_PP(method) + 1);
zend_str_tolower_copy(lcname, Z_STRVAL_PP(method), Z_STRLEN_PP(method));
if (zend_hash_find(&ce->function_table, lcname, (int)(Z_STRLEN_PP(method) + 1), (void **) &fptr) == FAILURE) {
free_alloca(lcname);
convert_to_text_ex(method);
lcname = zend_u_str_case_fold(Z_TYPE_PP(method), Z_UNIVAL_PP(method), Z_UNILEN_PP(method), 1, &lcname_len);
if (zend_u_hash_find(&ce->function_table, Z_TYPE_PP(method), lcname, lcname_len + 1, (void **) &fptr) == FAILURE) {
efree(lcname);
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Method %s::%s() does not exist", Z_STRVAL_PP(classref), Z_STRVAL_PP(method));
"Method %R::%R() does not exist", Z_TYPE_PP(classref), Z_UNIVAL_PP(classref), Z_TYPE_PP(method), Z_UNIVAL_PP(method));
return;
}
free_alloca(lcname);
efree(lcname);
}
break;
@ -1683,7 +1710,11 @@ ZEND_METHOD(reflection_parameter, __construct)
MAKE_STD_ZVAL(name);
if (arg_info[position].name) {
ZVAL_STRINGL(name, arg_info[position].name, arg_info[position].name_len, 1);
if (UG(unicode)) {
ZVAL_UNICODEL(name, (UChar*)arg_info[position].name, arg_info[position].name_len, 1);
} else {
ZVAL_STRINGL(name, arg_info[position].name, arg_info[position].name_len, 1);
}
} else {
ZVAL_NULL(name);
}
@ -1739,15 +1770,16 @@ ZEND_METHOD(reflection_parameter, getClass)
RETURN_NULL();
} else {
zend_class_entry **pce;
char *lcname = do_alloca(param->arg_info->class_name_len + 1);
zend_str_tolower_copy(lcname, param->arg_info->class_name, param->arg_info->class_name_len);
if (zend_hash_find(EG(class_table), lcname, param->arg_info->class_name_len + 1, (void **) &pce) == FAILURE) {
free_alloca(lcname);
unsigned int lcname_len;
char *lcname = zend_u_str_case_fold(UG(unicode)?IS_UNICODE:IS_STRING, param->arg_info->class_name, param->arg_info->class_name_len, 0, &lcname_len);
if (zend_u_hash_find(EG(class_table), UG(unicode)?IS_UNICODE:IS_STRING, lcname, lcname_len + 1, (void **) &pce) == FAILURE) {
efree(lcname);
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Class %s does not exist", param->arg_info->class_name);
"Class %v does not exist", param->arg_info->class_name);
return;
}
free_alloca(lcname);
efree(lcname);
zend_reflection_class_factory(*pce, return_value TSRMLS_CC);
}
}
@ -1884,14 +1916,16 @@ ZEND_METHOD(reflection_method, __construct)
zval *name, *classname;
zval *object;
reflection_object *intern;
unsigned int lcname_len;
char *lcname;
zend_class_entry **pce;
zend_class_entry *ce;
zend_function *mptr;
char *name_str;
int name_len;
zend_uchar type;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zs", &classname, &name_str, &name_len) == FAILURE) {
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zt", &classname, &name_str, &name_len, &type) == FAILURE) {
return;
}
@ -1904,9 +1938,10 @@ ZEND_METHOD(reflection_method, __construct)
/* Find the class entry */
switch (Z_TYPE_P(classname)) {
case IS_STRING:
if (zend_lookup_class(Z_STRVAL_P(classname), Z_STRLEN_P(classname), &pce TSRMLS_CC) == FAILURE) {
case IS_UNICODE:
if (zend_u_lookup_class(Z_TYPE_P(classname), Z_UNIVAL_P(classname), Z_UNILEN_P(classname), &pce TSRMLS_CC) == FAILURE) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Class %s does not exist", Z_STRVAL_P(classname));
"Class %v does not exist", Z_UNIVAL_P(classname));
return;
}
ce = *pce;
@ -1922,22 +1957,29 @@ ZEND_METHOD(reflection_method, __construct)
}
MAKE_STD_ZVAL(classname);
ZVAL_STRINGL(classname, ce->name, ce->name_length, 1);
if (UG(unicode)) {
ZVAL_UNICODEL(classname, (UChar*)ce->name, ce->name_length, 1);
} else {
ZVAL_STRINGL(classname, ce->name, ce->name_length, 1);
}
zend_hash_update(Z_OBJPROP_P(object), "class", sizeof("class"), (void **) &classname, sizeof(zval *), NULL);
lcname = do_alloca(name_len + 1);
zend_str_tolower_copy(lcname, name_str, name_len);
lcname = zend_u_str_case_fold(type, name_str, name_len, 1, &lcname_len);
if (zend_hash_find(&ce->function_table, lcname, name_len + 1, (void **) &mptr) == FAILURE) {
free_alloca(lcname);
if (zend_u_hash_find(&ce->function_table, type, lcname, lcname_len + 1, (void **) &mptr) == FAILURE) {
efree(lcname);
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Method %s::%s() does not exist", ce->name, name_str);
"Method %v::%R() does not exist", ce->name, type, name_str);
return;
}
free_alloca(lcname);
efree(lcname);
MAKE_STD_ZVAL(name);
ZVAL_STRING(name, mptr->common.function_name, 1);
if (UG(unicode)) {
ZVAL_UNICODE(name, (UChar*)mptr->common.function_name, 1);
} else {
ZVAL_STRING(name, mptr->common.function_name, 1);
}
zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
intern->ptr = mptr;
intern->free_ptr = 0;
@ -1989,11 +2031,11 @@ ZEND_METHOD(reflection_method, invoke)
(mptr->common.fn_flags & ZEND_ACC_ABSTRACT)) {
if (mptr->common.fn_flags & ZEND_ACC_ABSTRACT) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Trying to invoke abstract method %s::%s()",
"Trying to invoke abstract method %v::%v()",
mptr->common.scope->name, mptr->common.function_name);
} else {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Trying to invoke %s method %s::%s() from scope %s",
"Trying to invoke %s method %v::%v() from scope %v",
mptr->common.fn_flags & ZEND_ACC_PROTECTED ? "protected" : "private",
mptr->common.scope->name, mptr->common.function_name,
Z_OBJCE_P(getThis())->name);
@ -2054,7 +2096,7 @@ ZEND_METHOD(reflection_method, invoke)
if (result == FAILURE) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Invocation of method %s::%s() failed", mptr->common.scope->name, mptr->common.function_name);
"Invocation of method %v::%v() failed", mptr->common.scope->name, mptr->common.function_name);
return;
}
@ -2092,11 +2134,11 @@ ZEND_METHOD(reflection_method, invokeArgs)
(mptr->common.fn_flags & ZEND_ACC_ABSTRACT)) {
if (mptr->common.fn_flags & ZEND_ACC_ABSTRACT) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Trying to invoke abstract method %s::%s",
"Trying to invoke abstract method %v::%v",
mptr->common.scope->name, mptr->common.function_name);
} else {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Trying to invoke %s method %s::%s from scope %s",
"Trying to invoke %s method %v::%v from scope %v",
mptr->common.fn_flags & ZEND_ACC_PROTECTED ? "protected" : "private",
mptr->common.scope->name, mptr->common.function_name,
Z_OBJCE_P(getThis())->name);
@ -2123,7 +2165,7 @@ ZEND_METHOD(reflection_method, invokeArgs)
if (!object) {
efree(params);
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Trying to invoke non static method %s::%s without an object",
"Trying to invoke non static method %v::%v without an object",
mptr->common.scope->name, mptr->common.function_name);
return;
}
@ -2158,7 +2200,7 @@ ZEND_METHOD(reflection_method, invokeArgs)
if (result == FAILURE) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Invocation of method %s::%s() failed", mptr->common.scope->name, mptr->common.function_name);
"Invocation of method %v::%v() failed", mptr->common.scope->name, mptr->common.function_name);
return;
}
@ -2308,7 +2350,11 @@ static void reflection_class_object_ctor(INTERNAL_FUNCTION_PARAMETERS, int is_ob
if (Z_TYPE_P(argument) == IS_OBJECT) {
MAKE_STD_ZVAL(classname);
ZVAL_STRINGL(classname, Z_OBJCE_P(argument)->name, Z_OBJCE_P(argument)->name_length, 1);
if (UG(unicode)) {
ZVAL_UNICODEL(classname, (UChar*)Z_OBJCE_P(argument)->name, Z_OBJCE_P(argument)->name_length, 1);
} else {
ZVAL_STRINGL(classname, Z_OBJCE_P(argument)->name, Z_OBJCE_P(argument)->name_length, 1);
}
zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &classname, sizeof(zval *), NULL);
intern->ptr = Z_OBJCE_P(argument);
if (is_object) {
@ -2317,7 +2363,7 @@ static void reflection_class_object_ctor(INTERNAL_FUNCTION_PARAMETERS, int is_ob
}
} else {
convert_to_string_ex(&argument);
if (zend_lookup_class(Z_STRVAL_P(argument), Z_STRLEN_P(argument), &ce TSRMLS_CC) == FAILURE) {
if (zend_u_lookup_class(Z_TYPE_P(argument), Z_UNIVAL_P(argument), Z_UNILEN_P(argument), &ce TSRMLS_CC) == FAILURE) {
if (!EG(exception)) {
zend_throw_exception_ex(reflection_exception_ptr, -1 TSRMLS_CC, "Class %s does not exist", Z_STRVAL_P(argument));
}
@ -2325,7 +2371,11 @@ static void reflection_class_object_ctor(INTERNAL_FUNCTION_PARAMETERS, int is_ob
}
MAKE_STD_ZVAL(classname);
ZVAL_STRINGL(classname, (*ce)->name, (*ce)->name_length, 1);
if (UG(unicode)) {
ZVAL_UNICODEL(classname, (UChar*)((*ce)->name), (*ce)->name_length, 1);
} else {
ZVAL_STRINGL(classname, (*ce)->name, (*ce)->name_length, 1);
}
zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &classname, sizeof(zval *), NULL);
intern->ptr = *ce;
@ -2613,17 +2663,19 @@ ZEND_METHOD(reflection_class, hasMethod)
{
reflection_object *intern;
zend_class_entry *ce;
unsigned int lc_name_len;
char *name, *lc_name;
int name_len;
zend_uchar type;
METHOD_NOTSTATIC;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "t", &name, &name_len, &type) == FAILURE) {
return;
}
GET_REFLECTION_OBJECT_PTR(ce);
lc_name = zend_str_tolower_dup(name, name_len);
if (zend_hash_exists(&ce->function_table, lc_name, name_len + 1)) {
lc_name = zend_u_str_case_fold(type, name, name_len, 1, &lc_name_len);
if (zend_u_hash_exists(&ce->function_table, type, lc_name, lc_name_len + 1)) {
efree(lc_name);
RETURN_TRUE;
} else {
@ -2640,23 +2692,25 @@ ZEND_METHOD(reflection_class, getMethod)
reflection_object *intern;
zend_class_entry *ce;
zend_function *mptr;
unsigned int lc_name_len;
char *name, *lc_name;
int name_len;
zend_uchar type;
METHOD_NOTSTATIC;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "t", &name, &name_len, &type) == FAILURE) {
return;
}
GET_REFLECTION_OBJECT_PTR(ce);
lc_name = zend_str_tolower_dup(name, name_len);
if (zend_hash_find(&ce->function_table, lc_name, name_len + 1, (void**) &mptr) == SUCCESS) {
lc_name = zend_u_str_case_fold(type, name, name_len, 1, &lc_name_len);
if (zend_u_hash_find(&ce->function_table, type, lc_name, lc_name_len + 1, (void**) &mptr) == SUCCESS) {
reflection_method_factory(ce, mptr, return_value TSRMLS_CC);
efree(lc_name);
} else {
efree(lc_name);
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Method %s does not exist", name);
"Method %R does not exist", type, name);
return;
}
}
@ -2989,7 +3043,7 @@ ZEND_METHOD(reflection_class, newInstance)
zend_fcall_info_cache fcc;
if (!(ce->constructor->common.fn_flags & ZEND_ACC_PUBLIC)) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Access to non-public constructor of class %s", ce->name);
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Access to non-public constructor of class %v", ce->name);
return;
}
@ -3017,7 +3071,7 @@ ZEND_METHOD(reflection_class, newInstance)
if (zend_call_function(&fci, &fcc TSRMLS_CC) == FAILURE) {
efree(params);
zval_ptr_dtor(&retval_ptr);
zend_error(E_WARNING, "Invocation of %s's constructor failed", ce->name);
zend_error(E_WARNING, "Invocation of %v's constructor failed", ce->name);
RETURN_NULL();
}
if (retval_ptr) {
@ -3089,7 +3143,8 @@ ZEND_METHOD(reflection_class, isSubclassOf)
switch(class_name->type) {
case IS_STRING:
if (zend_lookup_class(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), &pce TSRMLS_CC) == FAILURE) {
case IS_UNICODE:
if (zend_u_lookup_class(Z_TYPE_P(class_name), Z_UNIVAL_P(class_name), Z_UNILEN_P(class_name), &pce TSRMLS_CC) == FAILURE) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Interface %s does not exist", Z_STRVAL_P(class_name));
return;
@ -3135,7 +3190,8 @@ ZEND_METHOD(reflection_class, implementsInterface)
switch(interface->type) {
case IS_STRING:
if (zend_lookup_class(Z_STRVAL_P(interface), Z_STRLEN_P(interface), &pce TSRMLS_CC) == FAILURE) {
case IS_UNICODE:
if (zend_u_lookup_class(Z_TYPE_P(interface), Z_UNIVAL_P(interface), Z_UNILEN_P(interface), &pce TSRMLS_CC) == FAILURE) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Interface %s does not exist", Z_STRVAL_P(interface));
return;
@ -3161,7 +3217,7 @@ ZEND_METHOD(reflection_class, implementsInterface)
if (!(interface_ce->ce_flags & ZEND_ACC_INTERFACE)) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Interface %s is a Class", interface_ce->name);
"Interface %v is a Class", interface_ce->name);
return;
}
RETURN_BOOL(instanceof_function(ce, interface_ce TSRMLS_CC));
@ -3267,7 +3323,8 @@ ZEND_METHOD(reflection_property, __construct)
/* Find the class entry */
switch (Z_TYPE_P(classname)) {
case IS_STRING:
if (zend_lookup_class(Z_STRVAL_P(classname), Z_STRLEN_P(classname), &pce TSRMLS_CC) == FAILURE) {
case IS_UNICODE:
if (zend_u_lookup_class(Z_TYPE_P(classname), Z_UNIVAL_P(classname), Z_UNILEN_P(classname), &pce TSRMLS_CC) == FAILURE) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Class %s does not exist", Z_STRVAL_P(classname));
return;
@ -3286,7 +3343,7 @@ ZEND_METHOD(reflection_property, __construct)
if (zend_hash_find(&ce->properties_info, name_str, name_len + 1, (void **) &property_info) == FAILURE || (property_info->flags & ZEND_ACC_SHADOW)) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Property %s::$%s does not exist", ce->name, name_str);
"Property %v::$%s does not exist", ce->name, name_str);
return;
}
@ -3307,12 +3364,20 @@ ZEND_METHOD(reflection_property, __construct)
}
MAKE_STD_ZVAL(classname);
ZVAL_STRINGL(classname, ce->name, ce->name_length, 1);
if (UG(unicode)) {
ZVAL_UNICODEL(classname, (UChar*)ce->name, ce->name_length, 1);
} else {
ZVAL_STRINGL(classname, ce->name, ce->name_length, 1);
}
zend_hash_update(Z_OBJPROP_P(object), "class", sizeof("class"), (void **) &classname, sizeof(zval *), NULL);
zend_unmangle_property_name(property_info->name, &class_name, &prop_name);
zend_u_unmangle_property_name(UG(unicode)?IS_UNICODE:IS_STRING, property_info->name, &class_name, &prop_name);
MAKE_STD_ZVAL(propname);
ZVAL_STRING(propname, prop_name, 1);
if (UG(unicode)) {
ZVAL_UNICODE(propname, (UChar*)prop_name, 1);
} else {
ZVAL_STRING(propname, prop_name, 1);
}
zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &propname, sizeof(zval *), NULL);
reference = (property_reference*) emalloc(sizeof(property_reference));
@ -3421,6 +3486,7 @@ ZEND_METHOD(reflection_property, getValue)
property_reference *ref;
zval *object;
zval **member= NULL;
zend_uchar utype = UG(unicode)?IS_UNICODE:IS_STRING;
METHOD_NOTSTATIC;
GET_REFLECTION_OBJECT_PTR(ref);
@ -3432,16 +3498,16 @@ ZEND_METHOD(reflection_property, getValue)
if ((ref->prop->flags & ZEND_ACC_STATIC)) {
zend_update_class_constants(intern->ce TSRMLS_CC);
if (zend_hash_quick_find(intern->ce->static_members, ref->prop->name, ref->prop->name_length + 1, ref->prop->h, (void **) &member) == FAILURE) {
zend_error(E_ERROR, "Internal error: Could not find the property %s", ref->prop->name);
if (zend_u_hash_quick_find(intern->ce->static_members, utype, ref->prop->name, ref->prop->name_length + 1, ref->prop->h, (void **) &member) == FAILURE) {
zend_error(E_ERROR, "Internal error: Could not find the property %v", ref->prop->name);
/* Bails out */
}
} else {
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &object) == FAILURE) {
return;
}
if (zend_hash_quick_find(Z_OBJPROP_P(object), ref->prop->name, ref->prop->name_length + 1, ref->prop->h, (void **) &member) == FAILURE) {
zend_error(E_ERROR, "Internal error: Could not find the property %s", ref->prop->name);
if (zend_u_hash_quick_find(Z_OBJPROP_P(object), utype, ref->prop->name, ref->prop->name_length + 1, ref->prop->h, (void **) &member) == FAILURE) {
zend_error(E_ERROR, "Internal error: Could not find the property %v", ref->prop->name);
/* Bails out */
}
}
@ -3463,6 +3529,7 @@ ZEND_METHOD(reflection_property, setValue)
int setter_done = 0;
zval *tmp;
HashTable *prop_table;
zend_uchar utype = UG(unicode)?IS_UNICODE:IS_STRING;
METHOD_NOTSTATIC;
GET_REFLECTION_OBJECT_PTR(ref);
@ -3486,8 +3553,8 @@ ZEND_METHOD(reflection_property, setValue)
prop_table = Z_OBJPROP_P(object);
}
if (zend_hash_quick_find(prop_table, ref->prop->name, ref->prop->name_length + 1, ref->prop->h, (void **) &variable_ptr) == FAILURE) {
zend_error(E_ERROR, "Internal error: Could not find the property %s", ref->prop->name);
if (zend_u_hash_quick_find(prop_table, utype, ref->prop->name, ref->prop->name_length + 1, ref->prop->h, (void **) &variable_ptr) == FAILURE) {
zend_error(E_ERROR, "Internal error: Could not find the property %v", ref->prop->name);
/* Bails out */
}
if (*variable_ptr == value) {
@ -3510,7 +3577,7 @@ ZEND_METHOD(reflection_property, setValue)
if (PZVAL_IS_REF(value)) {
SEPARATE_ZVAL(&value);
}
zend_hash_quick_update(prop_table, ref->prop->name, ref->prop->name_length+1, ref->prop->h, &value, sizeof(zval *), (void **) &foo);
zend_u_hash_quick_update(prop_table, utype, ref->prop->name, ref->prop->name_length+1, ref->prop->h, &value, sizeof(zval *), (void **) &foo);
}
}
/* }}} */
@ -3943,12 +4010,13 @@ static zend_object_handlers *zend_std_obj_handlers;
/* {{{ _reflection_write_property */
static void _reflection_write_property(zval *object, zval *member, zval *value TSRMLS_DC)
{
if (Z_TYPE_P(member) == IS_STRING
&& zend_hash_exists(&Z_OBJCE_P(object)->default_properties, Z_STRVAL_P(member), Z_STRLEN_P(member)+1)
&& (!strcmp(Z_STRVAL_P(member), "name") || !strcmp(Z_STRVAL_P(member), "class")))
if ((Z_TYPE_P(member) == IS_STRING || Z_TYPE_P(member) == IS_UNICODE)
&& zend_u_hash_exists(&Z_OBJCE_P(object)->default_properties, Z_TYPE_P(member), Z_UNIVAL_P(member), Z_UNILEN_P(member)+1)
&& (ZEND_U_EQUAL(Z_TYPE_P(member), Z_UNIVAL_P(member), Z_UNILEN_P(member), "name", sizeof("name")-1) ||
ZEND_U_EQUAL(Z_TYPE_P(member), Z_UNIVAL_P(member), Z_UNILEN_P(member), "class", sizeof("class")-1)))
{
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Cannot set read-only property %s::$%s", Z_OBJCE_P(object)->name, Z_STRVAL_P(member));
"Cannot set read-only property %v::$%R", Z_OBJCE_P(object)->name, Z_TYPE_P(member), Z_UNIVAL_P(member));
}
else
{
@ -4038,6 +4106,20 @@ ZEND_API void zend_register_reflection_api(TSRMLS_D) {
}
/* }}} */
void init_reflection_api(TSRMLS_D)
{
reflection_exception_ptr = zend_get_named_class_entry("ReflectionException", sizeof("ReflectionException")-1 TSRMLS_CC);
reflection_ptr = zend_get_named_class_entry("Reflection", sizeof("Reflection")-1 TSRMLS_CC);
reflector_ptr = zend_get_named_class_entry("Reflector", sizeof("Reflector")-1 TSRMLS_CC);
reflection_function_ptr = zend_get_named_class_entry("ReflectionFunction", sizeof("ReflectionFunction")-1 TSRMLS_CC);
reflection_parameter_ptr = zend_get_named_class_entry("ReflectionParameter", sizeof("ReflectionParameter")-1 TSRMLS_CC);
reflection_method_ptr = zend_get_named_class_entry("ReflectionMethod", sizeof("ReflectionMethod")-1 TSRMLS_CC);
reflection_class_ptr = zend_get_named_class_entry("ReflectionClass", sizeof("ReflectionClass")-1 TSRMLS_CC);
reflection_object_ptr = zend_get_named_class_entry("ReflectionObject", sizeof("ReflectionObject")-1 TSRMLS_CC);
reflection_property_ptr = zend_get_named_class_entry("ReflectionProperty", sizeof("ReflectionProperty")-1 TSRMLS_CC);
reflection_extension_ptr = zend_get_named_class_entry("ReflectionExtension", sizeof("ReflectionExtension")-1 TSRMLS_CC);
}
/*
* Local variables:
* tab-width: 4

View File

@ -26,6 +26,8 @@ BEGIN_EXTERN_C()
ZEND_API void zend_register_reflection_api(TSRMLS_D);
ZEND_API void zend_reflection_class_factory(zend_class_entry *ce, zval *object TSRMLS_DC);
void init_reflection_api(TSRMLS_D);
END_EXTERN_C()
#endif

View File

@ -90,6 +90,8 @@
*/
#include <zend_strtod.h>
#include <unicode/utypes.h>
#include <unicode/ustdio.h>
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
@ -1778,3 +1780,23 @@ zend_strtod
result = sign ? -value(rv) : value(rv);
return result;
}
/* UTODO: someone can reimplement this using the code above, if they really want to. */
ZEND_API double zend_u_strtod(const UChar *nptr, UChar **endptr)
{
double value;
int32_t num_conv = 0, num_read = 0;
num_conv = u_sscanf(nptr, "%f%n", &value, &num_read);
if (num_conv != EOF) {
if (endptr != 0) {
*endptr = (UChar *)nptr + num_read;
}
return value;
} else {
if (endptr != 0) {
*endptr = (UChar *)nptr;
}
return 0;
}
}

122
Zend/zend_strtol.c Normal file
View File

@ -0,0 +1,122 @@
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <limits.h>
#include <ctype.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <unicode/utypes.h>
#include <unicode/uchar.h>
/*
* Convert a Unicode string to a long integer.
*
* Ignores `locale' stuff.
*/
long
zend_u_strtol(nptr, endptr, base)
const UChar *nptr;
UChar **endptr;
register int base;
{
register const UChar *s = nptr;
register unsigned long acc;
register UChar c;
register unsigned long cutoff;
register int neg = 0, any, cutlim;
register int32_t val;
/*
* Skip white space and pick up leading +/- sign if any.
* If base is 0, allow 0x for hex and 0 for octal, else
* assume decimal; if base is already 16, allow 0x.
*/
do {
c = *s++;
} while (u_isspace(c));
if (c == '-') {
neg = 1;
c = *s++;
} else if (c == '+')
c = *s++;
if ((base == 0 || base == 16) &&
(c == '0')
&& (*s == 'x' || *s == 'X')) {
c = s[1];
s += 2;
base = 16;
}
if (base == 0)
base = (c == '0') ? 8 : 10;
/*
* Compute the cutoff value between legal numbers and illegal
* numbers. That is the largest legal value, divided by the
* base. An input number that is greater than this value, if
* followed by a legal input character, is too big. One that
* is equal to this value may be valid or not; the limit
* between valid and invalid numbers is then based on the last
* digit. For instance, if the range for longs is
* [-2147483648..2147483647] and the input base is 10,
* cutoff will be set to 214748364 and cutlim to either
* 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
* a value > 214748364, or equal but the next digit is > 7 (or 8),
* the number is too big, and we will return a range error.
*
* Set any if any `digits' consumed; make it negative to indicate
* overflow.
*/
cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX;
cutlim = cutoff % (unsigned long)base;
cutoff /= (unsigned long)base;
for (acc = 0, any = 0;; c = *s++) {
if ((val = u_digit(c, base)) < 0)
break;
if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
any = -1;
else {
any = 1;
acc *= base;
acc += val;
}
}
if (any < 0) {
acc = neg ? LONG_MIN : LONG_MAX;
errno = ERANGE;
} else if (neg)
acc = -acc;
if (endptr != 0)
*endptr = (UChar *)(any ? s - 1 : nptr);
return (acc);
}

597
Zend/zend_unicode.c Normal file
View File

@ -0,0 +1,597 @@
/*
+----------------------------------------------------------------------+
| Zend Engine |
+----------------------------------------------------------------------+
| Copyright (c) 1998-2004 Zend Technologies Ltd. (http://www.zend.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 2.00 of the Zend license, |
| that is bundled with this package in the file LICENSE, and is |
| available at through the world-wide-web at |
| http://www.zend.com/license/2_00.txt. |
| If you did not receive a copy of the Zend license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@zend.com so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: Andrei Zmievski <andrei@php.net> |
+----------------------------------------------------------------------+
*/
#include "zend.h"
#include "zend_globals.h"
#include "zend_operators.h"
#include "zend_API.h"
#include "zend_unicode.h"
#include <unicode/unorm.h>
#ifdef ZTS
ZEND_API ts_rsrc_id unicode_globals_id;
#else
ZEND_API zend_unicode_globals unicode_globals;
#endif
static void zend_from_unicode_substitute_cb(
const void *context,
UConverterFromUnicodeArgs *toUArgs,
const char *codeUnits,
int32_t length,
UConverterCallbackReason reason,
UErrorCode *err
)
{
if (context == NULL) {
if (reason > UCNV_IRREGULAR)
{
return;
}
*err = U_ZERO_ERROR;
//ucnv_cbFromUWriteSub(fromArgs, 0, err);
return;
} else if (*((char*)context)=='i') {
if (reason != UCNV_UNASSIGNED)
{
/* the caller must have set
* the error code accordingly
*/
return;
} else {
*err = U_ZERO_ERROR;
//ucnv_cbFromUWriteSub(fromArgs, 0, err);
return;
}
}
}
/* {{{ zend_set_converter_error_mode */
void zend_set_converter_error_mode(UConverter *conv, uint8_t error_mode)
{
UErrorCode status = U_ZERO_ERROR;
switch (error_mode) {
case ZEND_FROM_U_ERROR_STOP:
ucnv_setFromUCallBack(conv, UCNV_FROM_U_CALLBACK_STOP, NULL, NULL, NULL, &status);
break;
case ZEND_FROM_U_ERROR_SKIP:
ucnv_setFromUCallBack(conv, UCNV_FROM_U_CALLBACK_SKIP, UCNV_SKIP_STOP_ON_ILLEGAL, NULL, NULL, &status);
break;
case ZEND_FROM_U_ERROR_ESCAPE:
/* UTODO replace with custom callback for various substitution patterns */
ucnv_setFromUCallBack(conv, UCNV_FROM_U_CALLBACK_ESCAPE, UCNV_ESCAPE_UNICODE, NULL, NULL, &status);
break;
case ZEND_FROM_U_ERROR_SUBST:
ucnv_setFromUCallBack(conv, UCNV_FROM_U_CALLBACK_SUBSTITUTE, UCNV_SKIP_STOP_ON_ILLEGAL, NULL, NULL, &status);
break;
default:
assert(0);
break;
}
}
/* }}} */
/* {{{ zend_set_converter_subst_char */
void zend_set_converter_subst_char(UConverter *conv, UChar *subst_char, int8_t subst_char_len)
{
char dest[8];
int8_t dest_len = 8;
UErrorCode status = U_ZERO_ERROR;
UErrorCode temp = U_ZERO_ERROR;
const void *old_context;
UConverterFromUCallback old_cb;
if (!subst_char_len)
return;
ucnv_setFromUCallBack(conv, UCNV_FROM_U_CALLBACK_STOP, NULL, &old_cb, &old_context, &temp);
dest_len = ucnv_fromUChars(conv, dest, dest_len, subst_char, subst_char_len, &status);
ucnv_setFromUCallBack(conv, old_cb, old_context, NULL, NULL, &temp);
if (U_FAILURE(status)) {
zend_error(E_WARNING, "Could not set substitution character for the converter");
return;
}
ucnv_setSubstChars(conv, dest, dest_len, &status);
if (status == U_ILLEGAL_ARGUMENT_ERROR) {
zend_error(E_WARNING, "Substitution character byte sequence is too short or long for this converter");
return;
}
}
/* }}} */
/* {{{ zend_set_converter_encoding */
int zend_set_converter_encoding(UConverter **converter, const char *encoding)
{
UErrorCode status = U_ZERO_ERROR;
UConverter *new_converter = NULL;
if (!converter) {
return FAILURE;
}
/*
* The specified encoding might be the same as converter's existing one,
* which results in a no-op.
*/
if (*converter && encoding && encoding[0]) {
const char *current = ucnv_getName(*converter, &status);
status = U_ZERO_ERROR; /* reset error */
if (!ucnv_compareNames(current, encoding)) {
return SUCCESS;
}
}
/*
* If encoding is NULL, ucnv_open() will return a converter based on
* the default platform encoding as determined by ucnv_getDefaultName().
*/
new_converter = ucnv_open(encoding, &status);
if (U_FAILURE(status)) {
return FAILURE;
}
if (*converter) {
ucnv_close(*converter);
}
*converter = new_converter;
return SUCCESS;
}
/* }}} */
/* {{{ zend_copy_converter */
int zend_copy_converter(UConverter **target, UConverter *source)
{
UErrorCode status = U_ZERO_ERROR;
const char *encoding;
assert(source != NULL);
encoding = ucnv_getName(source, &status);
if (U_FAILURE(status)) {
return FAILURE;
}
return zend_set_converter_encoding(target, encoding);
}
/* }}} */
/* {{{ zend_convert_to_unicode */
ZEND_API void zend_convert_to_unicode(UConverter *conv, UChar **target, int32_t *target_len, const char *source, int32_t source_len, UErrorCode *status)
{
UChar *buffer = NULL;
UChar *output;
int32_t buffer_len = 0;
int32_t converted = 0;
const char *input = source;
UConverterType conv_type;
if (U_FAILURE(*status)) {
return;
}
ucnv_resetToUnicode(conv);
conv_type = ucnv_getType(conv);
switch (conv_type) {
case UCNV_SBCS:
case UCNV_LATIN_1:
case UCNV_US_ASCII:
/*
* For single-byte charsets, 1 input byte = 1 output UChar
*/
buffer_len = source_len;
break;
default:
/*
* Initial estimate: 1.25 UChar's for every 2 source bytes + 2 (past a
* certain limit (2)). The rationale behind this is that (atleast
* in the case of GB2312) it is possible that there are single byte
* characters in the input string. By using an GD2312 text as
* example it seemed that a value of 1.25 allowed for as little
* re-allocations as possible without over estimating the buffer
* too much. In case there is a lot of single-byte characters
* around a single multi-byte character this estimation is too low,
* and then the re-allocation routines in the loop below kick in.
* Here we multiply by 1.33 and add 1 so that it's even quite
* efficient for smaller input strings without causing too much
* iterations of this loop.
*/
buffer_len = (source_len > 2) ? ((source_len >> 1) + (source_len >> 3) + 2) : source_len;
break;
}
while (1) {
buffer = eurealloc(buffer, buffer_len + 1);
output = buffer + converted;
ucnv_toUnicode(conv, &output, buffer + buffer_len, &input, source + source_len, NULL, TRUE, status);
converted = (int32_t) (output - buffer);
if (*status == U_BUFFER_OVERFLOW_ERROR) {
buffer_len = (buffer_len * 1.33) + 1;
*status = U_ZERO_ERROR;
} else {
break;
}
}
/*
* We return the buffer in case of failure anyway. The caller may want to
* use partially converted string for something.
*/
buffer[converted] = 0;
*target = buffer;
*target_len = converted;
}
/* }}} */
/* {{{ zend_convert_from_unicode */
ZEND_API void zend_convert_from_unicode(UConverter *conv, char **target, int32_t *target_len, const UChar *source, int32_t source_len, UErrorCode *status)
{
char *buffer = NULL;
char *output;
int32_t buffer_len = 0;
int32_t converted = 0;
const UChar *input = source;
if (U_FAILURE(*status)) {
return;
}
ucnv_resetFromUnicode(conv);
buffer_len = ucnv_getMaxCharSize(conv) * source_len;
while (1) {
buffer = erealloc(buffer, buffer_len + 1);
output = buffer + converted;
ucnv_fromUnicode(conv, &output, buffer + buffer_len, &input, source + source_len, NULL, TRUE, status);
converted = (int32_t) (output - buffer);
if (*status == U_BUFFER_OVERFLOW_ERROR) {
buffer_len += 64;
*status = U_ZERO_ERROR;
} else {
break;
}
}
/*
* We return the buffer in case of failure anyway. The caller may want to
* use partially converted string for something.
*/
buffer[converted] = 0; /* NULL-terminate the output string */
*target = buffer;
*target_len = converted;
/* Report the conversion error */
if (U_FAILURE(*status)) {
zend_error(E_NOTICE, "Error converting from Unicode to codepage string: %s", u_errorName(*status));
}
}
/* }}} */
/* {{{ zend_convert_encodings */
ZEND_API void zend_convert_encodings(UConverter *target_conv, UConverter *source_conv,
char **target, int32_t *target_len,
const char *source, int32_t source_len, UErrorCode *status)
{
char *buffer = NULL;
char *output;
const char *input = source;
int32_t allocated = 0;
int32_t converted = 0;
int8_t null_size;
UChar pivot_buf[1024], *pivot, *pivot2;
if (U_FAILURE(*status)) {
return;
}
null_size = ucnv_getMinCharSize(target_conv);
allocated = source_len + null_size;
ucnv_resetToUnicode(source_conv);
ucnv_resetFromUnicode(target_conv);
pivot = pivot2 = pivot_buf;
while (1) {
buffer = (char *) erealloc(buffer, allocated);
output = buffer + converted;
ucnv_convertEx(target_conv, source_conv, &output, buffer + allocated - null_size,
&input, source + source_len, pivot_buf, &pivot, &pivot2, pivot_buf + 1024, FALSE, TRUE, status);
converted = (int32_t) (output - buffer);
if (*status == U_BUFFER_OVERFLOW_ERROR) {
allocated += 1024;
*status = U_ZERO_ERROR;
} else {
break;
}
}
memset(buffer + converted, 0, null_size); /* NULL-terminate the output string */
*target = buffer;
*target_len = converted;
/* Report the conversion error */
if (U_FAILURE(*status)) {
zend_error(E_NOTICE, "Error converting from codepage string to Unicode: %s", u_errorName(*status));
}
}
/* }}} */
/* {{{ zval_unicode_to_string */
ZEND_API int zval_unicode_to_string(zval *string, UConverter *conv TSRMLS_DC)
{
UErrorCode status = U_ZERO_ERROR;
int retval = TRUE;
char *s = NULL;
int s_len;
#if 0
/* UTODO Putting it here for now, until we figure out the framework */
switch (UG(from_u_error_mode)) {
case ZEND_FROM_U_ERROR_STOP:
ucnv_setFromUCallBack(UG(runtime_encoding_conv), UCNV_FROM_U_CALLBACK_STOP, NULL, NULL, NULL, &status);
break;
case ZEND_FROM_U_ERROR_SKIP:
ucnv_setFromUCallBack(UG(runtime_encoding_conv), UCNV_FROM_U_CALLBACK_SKIP, NULL, NULL, NULL, &status);
break;
case ZEND_FROM_U_ERROR_ESCAPE:
ucnv_setFromUCallBack(UG(runtime_encoding_conv), UCNV_FROM_U_CALLBACK_ESCAPE, UCNV_ESCAPE_UNICODE, NULL, NULL, &status);
break;
case ZEND_FROM_U_ERROR_SUBST:
ucnv_setFromUCallBack(UG(runtime_encoding_conv), UCNV_FROM_U_CALLBACK_SUBSTITUTE, NULL, NULL, NULL, &status);
break;
default:
assert(0);
break;
}
if (UG(subst_chars)) {
char subchar[16];
int8_t char_len = 16;
status = U_ZERO_ERROR;
ucnv_getSubstChars(UG(runtime_encoding_conv), subchar, &char_len, &status);
if (U_FAILURE(status)) {
zend_error(E_WARNING, "Could not get substitution characters");
return FAILURE;
}
status = U_ZERO_ERROR;
ucnv_setSubstChars(UG(runtime_encoding_conv), UG(subst_chars), MIN(char_len, UG(subst_chars_len)), &status);
if (U_FAILURE(status)) {
zend_error(E_WARNING, "Could not set substitution characters");
return FAILURE;
}
}
status = U_ZERO_ERROR;
#endif
UChar *u = Z_USTRVAL_P(string);
int32_t u_len = Z_USTRLEN_P(string);
Z_TYPE_P(string) = IS_STRING;
zend_convert_from_unicode(conv, &s, &s_len, u, u_len, &status);
ZVAL_STRINGL(string, s, s_len, 0);
if (U_FAILURE(status)) {
retval = FAILURE;
}
efree(u);
return retval;
}
/* }}} */
/* {{{ zval_string_to_unicode */
ZEND_API int zval_string_to_unicode(zval *string TSRMLS_DC)
{
UErrorCode status = U_ZERO_ERROR;
int retval = TRUE;
UChar *u = NULL;
int32_t u_len;
char *s = Z_STRVAL_P(string);
int s_len = Z_STRLEN_P(string);
Z_TYPE_P(string) = IS_UNICODE;
zend_convert_to_unicode(ZEND_U_CONVERTER(UG(runtime_encoding_conv)), &u, &u_len, s, s_len, &status);
ZVAL_UNICODEL(string, u, u_len, 0);
if (U_FAILURE(status)) {
retval = FALSE;
}
efree(s);
return retval;
}
/* }}} */
/* {{{ zend_cmp_unicode_and_string */
ZEND_API int zend_cmp_unicode_and_string(UChar *ustr, char* str, uint len)
{
UErrorCode status = U_ZERO_ERROR;
UChar *u = NULL;
int32_t u_len;
int retval = TRUE;
TSRMLS_FETCH();
zend_convert_to_unicode(ZEND_U_CONVERTER(UG(runtime_encoding_conv)), &u, &u_len, str, len, &status);
if (U_FAILURE(status)) {
efree(u);
return FALSE;
}
retval = u_memcmp(ustr, u, u_len);
efree(u);
return retval;
}
/* }}} */
/* {{{ zend_cmp_unicode_and_literal */
/*
* Compare a Unicode string and an ASCII literal. Because ASCII maps nicely onto Unicode
* range U+0000 .. U+007F, we can simply casst ASCII chars to Unicode values and avoid
* memory allocation.
*/
ZEND_API int zend_cmp_unicode_and_literal(UChar *ustr, int32_t ulen, char *str, int32_t slen)
{
int32_t result;
uint len = MIN(ulen, slen);
while (len--) {
result = (int32_t)(uint16_t)*ustr - (int32_t)(uint16_t)*str;
if (result != 0)
return result;
ustr++;
str++;
}
return ulen - slen;
}
/* }}} */
/* {{{ zend_is_valid_identifier */
ZEND_API int zend_is_valid_identifier(UChar *ident, int32_t ident_len)
{
UChar32 codepoint;
int32_t i;
UProperty id_prop = UCHAR_XID_START;
for (i = 0; i < ident_len; ) {
U16_NEXT(ident, i, ident_len, codepoint);
if (!u_hasBinaryProperty(codepoint, id_prop) &&
codepoint != 0x5f) { /* special case for starting '_' */
return 0;
}
id_prop = UCHAR_XID_CONTINUE;
}
return 1;
}
/* }}} */
/* {{{ zend_normalize_string */
static inline void zend_normalize_string(UChar **dest, int32_t *dest_len, UChar *src, int32_t src_len, UErrorCode *status)
{
UChar *buffer = NULL;
int32_t buffer_len;
buffer_len = src_len;
while (1) {
*status = U_ZERO_ERROR;
buffer = eurealloc(buffer, buffer_len+1);
buffer_len = unorm_normalize(src, src_len, UNORM_NFKC, 0, buffer, buffer_len, status);
if (*status != U_BUFFER_OVERFLOW_ERROR) {
break;
}
}
if (U_SUCCESS(*status)) {
buffer[buffer_len] = 0;
*dest = buffer;
*dest_len = buffer_len;
} else {
efree(buffer);
}
}
/* }}} */
/* {{{ zend_case_fold_string */
ZEND_API void zend_case_fold_string(UChar **dest, int32_t *dest_len, UChar *src, int32_t src_len, uint32_t options, UErrorCode *status)
{
UChar *buffer = NULL;
int32_t buffer_len;
buffer_len = src_len;
while (1) {
*status = U_ZERO_ERROR;
buffer = eurealloc(buffer, buffer_len+1);
buffer_len = u_strFoldCase(buffer, buffer_len, src, src_len, options, status);
if (*status != U_BUFFER_OVERFLOW_ERROR) {
break;
}
}
if (U_SUCCESS(*status)) {
buffer[buffer_len] = 0;
*dest = buffer;
*dest_len = buffer_len;
} else {
efree(buffer);
}
}
/* }}} */
/* {{{ zend_normalize_identifier */
ZEND_API int zend_normalize_identifier(UChar **dest, int32_t *dest_len, UChar *ident, int32_t ident_len, zend_bool fold_case)
{
UChar *buffer = NULL;
UChar *orig_ident = ident;
int32_t buffer_len;
UErrorCode status = U_ZERO_ERROR;
if (unorm_quickCheck(ident, ident_len, UNORM_NFKC, &status) != UNORM_YES) {
zend_normalize_string(&buffer, &buffer_len, ident, ident_len, &status);
if (U_FAILURE(status)) {
return 0;
}
ident = buffer;
ident_len = buffer_len;
}
if (fold_case) {
zend_case_fold_string(&buffer, &buffer_len, ident, ident_len, U_FOLD_CASE_DEFAULT, &status);
if (ident != orig_ident) {
efree(ident);
}
if (U_FAILURE(status)) {
return 0;
}
ident = buffer;
ident_len = buffer_len;
if (unorm_quickCheck(ident, ident_len, UNORM_NFKC, &status) != UNORM_YES) {
zend_normalize_string(&buffer, &buffer_len, ident, ident_len, &status);
if (ident != orig_ident) {
efree(ident);
}
if (U_FAILURE(status)) {
return 0;
}
ident = buffer;
ident_len = buffer_len;
}
}
*dest = ident;
*dest_len = ident_len;
return 1;
}
/* }}} */
/* vim: set fdm=marker et sts=4: */

90
Zend/zend_unicode.h Normal file
View File

@ -0,0 +1,90 @@
/*
+----------------------------------------------------------------------+
| Zend Engine |
+----------------------------------------------------------------------+
| Copyright (c) 1998-2004 Zend Technologies Ltd. (http://www.zend.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 2.00 of the Zend license, |
| that is bundled with this package in the file LICENSE, and is |
| available at through the world-wide-web at |
| http://www.zend.com/license/2_00.txt. |
| If you did not receive a copy of the Zend license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@zend.com so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: Andrei Zmievski <andrei@php.net> |
+----------------------------------------------------------------------+
*/
#ifndef ZEND_UNICODE_H
#define ZEND_UNICODE_H
#include "zend.h"
#include <unicode/utypes.h>
#include <unicode/ustring.h>
#include <unicode/ucnv.h>
#include <unicode/ustdio.h>
#include <unicode/uchar.h>
#include <unicode/uloc.h>
#include <unicode/ucol.h>
#define ZEND_FROM_U_ERROR_STOP 0
#define ZEND_FROM_U_ERROR_SKIP 1
#define ZEND_FROM_U_ERROR_SUBST 2
#define ZEND_FROM_U_ERROR_ESCAPE 3
/* internal functions */
int zend_set_converter_encoding(UConverter **converter, const char *encoding);
void zend_set_converter_subst_char(UConverter *conv, UChar *subst_char, int8_t subst_char_len);
void zend_set_converter_error_mode(UConverter *conv, uint8_t error_mode);
/* API functions */
ZEND_API void zend_convert_to_unicode(UConverter *conv, UChar **target, int32_t *target_len, const char *source, int32_t source_len, UErrorCode *status);
ZEND_API void zend_convert_from_unicode(UConverter *conv, char **target, int32_t *target_len, const UChar *source, int32_t source_len, UErrorCode *status);
ZEND_API void zend_convert_encodings(UConverter *target_conv, UConverter *source_conv, char **target, int32_t *target_len, const char *source, int32_t source_len, UErrorCode *status);
ZEND_API int zval_string_to_unicode(zval *string TSRMLS_DC);
ZEND_API int zval_unicode_to_string(zval *string, UConverter *conv TSRMLS_DC);
ZEND_API int zend_cmp_unicode_and_string(UChar *ustr, char* str, uint len);
ZEND_API int zend_cmp_unicode_and_literal(UChar *ustr, int32_t ulen, char* str, int32_t slen);
ZEND_API void zend_case_fold_string(UChar **dest, int32_t *dest_len, UChar *src, int32_t src_len, uint32_t options, UErrorCode *status);
ZEND_API int zend_is_valid_identifier(UChar *ident, int32_t ident_len);
ZEND_API int zend_normalize_identifier(UChar **dest, int32_t *dest_len, UChar *ident, int32_t ident_len, zend_bool fold_case);
/*
* Function to get a codepoint at position n. Iterates over codepoints starting from the
* beginning of the string. Does not check for n > length, this is left up to the caller.
*/
static inline UChar32 zend_get_codepoint_at(UChar *str, int32_t length, int32_t n)
{
int32_t offset = 0;
UChar32 c = 0;
U16_FWD_N(str, offset, length, n);
U16_GET(str, 0, offset, length, c);
return c;
}
#define ZEND_U_CONVERTER(c) ((c)?(c):UG(fallback_encoding_conv))
#define USTR_FREE(ustr) do { if (ustr) { efree(ustr); } } while (0);
#define UBYTES(len) ((len) * sizeof(UChar))
#define USTR_LEN(str) (UG(unicode)?u_strlen((UChar*)(str)):strlen((char*)(str)))
#define USTR_MAKE(cs) zend_ascii_to_unicode(cs, sizeof(cs) ZEND_FILE_LINE_CC)
#define USTR_MAKE_REL(cs) zend_ascii_to_unicode(cs, sizeof(cs) ZEND_FILE_LINE_RELAY_CC)
static inline UChar* zend_ascii_to_unicode(const char *cs, size_t cs_size ZEND_FILE_LINE_DC)
{
/* u_charsToUChars() takes care of the terminating NULL */
UChar *us = eumalloc_rel(cs_size);
u_charsToUChars(cs, us, cs_size);
return us;
}
#endif /* ZEND_UNICODE_H */

View File

@ -30,11 +30,21 @@
ZEND_API void _zval_dtor_func(zval *zvalue ZEND_FILE_LINE_DC)
{
switch (zvalue->type & ~IS_CONSTANT_INDEX) {
case IS_CONSTANT: {
TSRMLS_FETCH();
if (UG(unicode)) goto dtor_unicode;
}
case IS_STRING:
case IS_CONSTANT:
case IS_BINARY:
CHECK_ZVAL_STRING_REL(zvalue);
STR_FREE_REL(zvalue->value.str.val);
break;
case IS_UNICODE:
dtor_unicode:
CHECK_ZVAL_UNICODE_REL(zvalue);
STR_FREE_REL(zvalue->value.ustr.val);
break;
case IS_ARRAY:
case IS_CONSTANT_ARRAY: {
TSRMLS_FETCH();
@ -74,11 +84,21 @@ ZEND_API void _zval_dtor_func(zval *zvalue ZEND_FILE_LINE_DC)
ZEND_API void _zval_internal_dtor(zval *zvalue ZEND_FILE_LINE_DC)
{
switch (zvalue->type & ~IS_CONSTANT_INDEX) {
case IS_CONSTANT: {
TSRMLS_FETCH();
if (UG(unicode)) goto dtor_unicode;
}
case IS_STRING:
case IS_CONSTANT:
case IS_BINARY:
CHECK_ZVAL_STRING_REL(zvalue);
free(zvalue->value.str.val);
break;
case IS_UNICODE:
dtor_unicode:
CHECK_ZVAL_UNICODE_REL(zvalue);
free(zvalue->value.ustr.val);
break;
case IS_ARRAY:
case IS_CONSTANT_ARRAY:
case IS_OBJECT:
@ -114,11 +134,21 @@ ZEND_API void _zval_copy_ctor_func(zval *zvalue ZEND_FILE_LINE_DC)
case IS_LONG:
case IS_NULL:
break;
case IS_CONSTANT:
case IS_CONSTANT: {
TSRMLS_FETCH();
if (UG(unicode)) goto copy_unicode;
}
case IS_STRING:
case IS_BINARY:
CHECK_ZVAL_STRING_REL(zvalue);
zvalue->value.str.val = (char *) estrndup_rel(zvalue->value.str.val, zvalue->value.str.len);
break;
case IS_UNICODE:
copy_unicode:
CHECK_ZVAL_UNICODE_REL(zvalue);
zvalue->value.ustr.val = eustrndup_rel(zvalue->value.ustr.val, zvalue->value.ustr.len);
break;
case IS_ARRAY:
case IS_CONSTANT_ARRAY: {
zval *tmp;
@ -130,7 +160,7 @@ ZEND_API void _zval_copy_ctor_func(zval *zvalue ZEND_FILE_LINE_DC)
return; /* do nothing */
}
ALLOC_HASHTABLE_REL(tmp_ht);
zend_hash_init(tmp_ht, 0, NULL, ZVAL_PTR_DTOR, 0);
zend_u_hash_init(tmp_ht, 0, NULL, ZVAL_PTR_DTOR, 0, original_ht->unicode);
zend_hash_copy(tmp_ht, original_ht, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
zvalue->value.ht = tmp_ht;
}
@ -144,7 +174,6 @@ ZEND_API void _zval_copy_ctor_func(zval *zvalue ZEND_FILE_LINE_DC)
}
}
ZEND_API int zend_print_variable(zval *var)
{
return zend_print_zval(var, 0);

View File

@ -886,11 +886,27 @@ ZEND_VM_HANDLER(40, ZEND_ECHO, CONST|TMP|VAR|CV, ANY)
zval *z = GET_OP1_ZVAL_PTR(BP_VAR_R);
if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get_method != NULL &&
zend_std_cast_object_tostring(z, &z_copy, IS_STRING, 0 TSRMLS_CC) == SUCCESS) {
zend_std_cast_object_tostring(z, &z_copy, UG(unicode) ? IS_UNICODE : IS_STRING, 0 TSRMLS_CC) == SUCCESS) {
zend_print_variable(&z_copy);
zval_dtor(&z_copy);
} else {
zend_print_variable(z);
UErrorCode status = U_ZERO_ERROR;
/* Convert inline HTML blocks to the output encoding, but only if necessary. */
if (opline->extended_value &&
strcmp(ucnv_getName(ZEND_U_CONVERTER(UG(output_encoding_conv)), &status),
ucnv_getName(ZEND_U_CONVERTER(UG(script_encoding_conv)), &status))) {
zval z_conv;
zend_convert_encodings(ZEND_U_CONVERTER(UG(output_encoding_conv)), ZEND_U_CONVERTER(UG(script_encoding_conv)), &z_conv.value.str.val, &z_conv.value.str.len, z->value.str.val, z->value.str.len, &status);
z_conv.type = IS_BINARY;
if (U_SUCCESS(status)) {
zend_print_variable(&z_conv);
} else {
zend_error(E_WARNING, "Could not convert inline HTML for output");
}
zval_dtor(&z_conv);
} else {
zend_print_variable(z);
}
}
FREE_OP1();
@ -932,23 +948,23 @@ ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMP|VAR|CV, ANY, int type
ZEND_VM_NEXT_OPCODE();
}
*/
if (zend_hash_find(target_symbol_table, varname->value.str.val, varname->value.str.len+1, (void **) &retval) == FAILURE) {
if (zend_u_hash_find(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1, (void **) &retval) == FAILURE) {
switch (type) {
case BP_VAR_R:
case BP_VAR_UNSET:
zend_error(E_NOTICE,"Undefined variable: %s", varname->value.str.val);
zend_error(E_NOTICE,"Undefined variable: %R", Z_TYPE_P(varname), Z_UNIVAL_P(varname));
/* break missing intentionally */
case BP_VAR_IS:
retval = &EG(uninitialized_zval_ptr);
break;
case BP_VAR_RW:
zend_error(E_NOTICE,"Undefined variable: %s", varname->value.str.val);
zend_error(E_NOTICE,"Undefined variable: %R", Z_TYPE_P(varname), Z_UNIVAL_P(varname));
/* break missing intentionally */
case BP_VAR_W: {
zval *new_zval = &EG(uninitialized_zval);
new_zval->refcount++;
zend_hash_update(target_symbol_table, varname->value.str.val, varname->value.str.len+1, &new_zval, sizeof(zval *), (void **) &retval);
zend_u_hash_update(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1, &new_zval, sizeof(zval *), (void **) &retval);
}
break;
EMPTY_SWITCH_DEFAULT_CASE()
@ -956,6 +972,10 @@ ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMP|VAR|CV, ANY, int type
}
switch (opline->op2.u.EA.type) {
case ZEND_FETCH_GLOBAL:
if (OP1_TYPE != IS_TMP_VAR) {
FREE_OP1();
}
break;
case ZEND_FETCH_LOCAL:
FREE_OP1();
break;
@ -1519,11 +1539,18 @@ ZEND_VM_HANDLER(53, ZEND_INIT_STRING, ANY, ANY)
{
zval *tmp = &EX_T(EX(opline)->result.u.var).tmp_var;
tmp->value.str.val = emalloc(1);
tmp->value.str.val[0] = 0;
tmp->value.str.len = 0;
if (EX(opline)->extended_value == IS_UNICODE) {
tmp->value.ustr.val = eumalloc(1);
tmp->value.ustr.val[0] = 0;
tmp->value.ustr.len = 0;
tmp->type = IS_UNICODE;
} else {
tmp->value.str.val = emalloc(1);
tmp->value.str.val[0] = 0;
tmp->value.str.len = 0;
tmp->type = EX(opline)->extended_value;
}
tmp->refcount = 1;
tmp->type = IS_STRING;
tmp->is_ref = 0;
ZEND_VM_NEXT_OPCODE();
}
@ -1534,8 +1561,8 @@ ZEND_VM_HANDLER(54, ZEND_ADD_CHAR, TMP, CONST)
zend_free_op free_op1;
add_char_to_string(&EX_T(opline->result.u.var).tmp_var,
GET_OP1_ZVAL_PTR(BP_VAR_NA),
&opline->op2.u.constant);
GET_OP1_ZVAL_PTR(BP_VAR_NA),
&opline->op2.u.constant);
/* FREE_OP is missing intentionally here - we're always working on the same temporary variable */
ZEND_VM_NEXT_OPCODE();
}
@ -1546,8 +1573,8 @@ ZEND_VM_HANDLER(55, ZEND_ADD_STRING, TMP, CONST)
zend_free_op free_op1;
add_string_to_string(&EX_T(opline->result.u.var).tmp_var,
GET_OP1_ZVAL_PTR(BP_VAR_NA),
&opline->op2.u.constant);
GET_OP1_ZVAL_PTR(BP_VAR_NA),
&opline->op2.u.constant);
/* FREE_OP is missing intentionally here - we're always working on the same temporary variable */
ZEND_VM_NEXT_OPCODE();
}
@ -1560,13 +1587,16 @@ ZEND_VM_HANDLER(56, ZEND_ADD_VAR, TMP, TMP|VAR|CV)
zval var_copy;
int use_copy;
zend_make_printable_zval(var, &var_copy, &use_copy);
if (opline->extended_value == IS_UNICODE) {
zend_make_unicode_zval(var, &var_copy, &use_copy);
} else {
zend_make_printable_zval(var, &var_copy, &use_copy);
}
if (use_copy) {
var = &var_copy;
}
add_string_to_string( &EX_T(opline->result.u.var).tmp_var,
GET_OP1_ZVAL_PTR(BP_VAR_NA),
var);
add_string_to_string(&EX_T(opline->result.u.var).tmp_var,
GET_OP1_ZVAL_PTR(BP_VAR_NA), var);
if (use_copy) {
zval_dtor(var);
}
@ -1600,7 +1630,8 @@ ZEND_VM_HANDLER(109, ZEND_FETCH_CLASS, ANY, CONST|TMP|VAR|UNUSED|CV)
EX_T(opline->result.u.var).class_entry = Z_OBJCE_P(class_name);
break;
case IS_STRING:
EX_T(opline->result.u.var).class_entry = zend_fetch_class(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), opline->extended_value TSRMLS_CC);
case IS_UNICODE:
EX_T(opline->result.u.var).class_entry = zend_u_fetch_class(Z_TYPE_P(class_name), Z_UNIVAL_P(class_name), Z_UNILEN_P(class_name), opline->extended_value TSRMLS_CC);
break;
default:
zend_error_noreturn(E_ERROR, "Class name must be a valid object or a string");
@ -1618,17 +1649,19 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV)
char *function_name_strval;
int function_name_strlen;
zend_free_op free_op1, free_op2;
/* FIXME: type is default */
zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(calling_scope));
function_name = GET_OP2_ZVAL_PTR(BP_VAR_R);
if (Z_TYPE_P(function_name)!=IS_STRING) {
if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
zend_error_noreturn(E_ERROR, "Method name must be a string");
}
function_name_strval = function_name->value.str.val;
function_name_strlen = function_name->value.str.len;
function_name_strval = Z_UNIVAL_P(function_name);
function_name_strlen = Z_UNILEN_P(function_name);
EX(calling_scope) = EG(scope);
@ -1642,10 +1675,10 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV)
/* First, locate the function. */
EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
if (!EX(fbc)) {
zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval);
}
} else {
zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval);
}
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
@ -1685,21 +1718,20 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, ANY, CONST|TMP|VAR|UNUSED|CV)
ce = EX_T(opline->op1.u.var).class_entry;
if(OP2_TYPE != IS_UNUSED) {
char *function_name_strval;
int function_name_strlen;
unsigned int function_name_strlen;
zend_bool is_const = (OP2_TYPE == IS_CONST);
zend_free_op free_op2;
if (is_const) {
function_name_strval = opline->op2.u.constant.value.str.val;
function_name_strlen = opline->op2.u.constant.value.str.len;
function_name_strval = Z_UNIVAL(opline->op2.u.constant);
function_name_strlen = Z_UNILEN(opline->op2.u.constant);
} else {
function_name = GET_OP2_ZVAL_PTR(BP_VAR_R);
if (Z_TYPE_P(function_name) != IS_STRING) {
if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
zend_error_noreturn(E_ERROR, "Function name must be a string");
}
function_name_strval = zend_str_tolower_dup(function_name->value.str.val, function_name->value.str.len);
function_name_strlen = function_name->value.str.len;
function_name_strval = zend_u_str_case_fold(Z_TYPE_P(function_name), Z_UNIVAL_P(function_name), Z_UNILEN_P(function_name), 1, &function_name_strlen);
}
EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
@ -1733,29 +1765,28 @@ ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST|TMP|VAR|CV)
zend_op *opline = EX(opline);
zval *function_name;
zend_function *function;
char *function_name_strval, *lcname;
int function_name_strlen;
void *function_name_strval, *lcname;
unsigned int function_name_strlen, lcname_len;
zend_free_op free_op2;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(calling_scope));
if (OP2_TYPE == IS_CONST) {
function_name_strval = opline->op2.u.constant.value.str.val;
function_name_strlen = opline->op2.u.constant.value.str.len;
function_name = &opline->op2.u.constant;
} else {
function_name = GET_OP2_ZVAL_PTR(BP_VAR_R);
if (Z_TYPE_P(function_name) != IS_STRING) {
if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
zend_error_noreturn(E_ERROR, "Function name must be a string");
}
function_name_strval = function_name->value.str.val;
function_name_strlen = function_name->value.str.len;
}
function_name_strval = Z_UNIVAL_P(function_name);
function_name_strlen = Z_UNILEN_P(function_name);
lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
if (zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &function)==FAILURE) {
lcname = zend_u_str_case_fold(Z_TYPE_P(function_name), Z_STRVAL_P(function_name), function_name_strlen, 1, &lcname_len);
if (zend_u_hash_find(EG(function_table), Z_TYPE_P(function_name), lcname, lcname_len+1, (void **) &function)==FAILURE) {
efree(lcname);
zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
zend_error_noreturn(E_ERROR, "Call to undefined function %R()", Z_TYPE_P(function_name), function_name_strval);
}
efree(lcname);
@ -1782,7 +1813,8 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
zend_bool should_change_scope;
if (EX(function_state).function->common.fn_flags & ZEND_ACC_ABSTRACT) {
zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", EX(function_state).function->common.scope->name, EX(function_state).function->common.function_name);
/* FIXME: output identifiers properly */
zend_error_noreturn(E_ERROR, "Cannot call abstract method %v::%v()", EX(function_state).function->common.scope->name, EX(function_state).function->common.function_name);
ZEND_VM_NEXT_OPCODE(); /* Never reached */
}
@ -1814,7 +1846,8 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
severity = E_ERROR;
severity_word = "cannot";
}
zend_error(severity, "Non-static method %s::%s() %s be called statically", EX(function_state).function->common.scope->name, EX(function_state).function->common.function_name, severity_word);
/* FIXME: output identifiers properly */
zend_error(severity, "Non-static method %v::%v() %s be called statically", EX(function_state).function->common.scope->name, EX(function_state).function->common.function_name, severity_word);
}
}
if (EX(function_state).function->type == ZEND_INTERNAL_FUNCTION) {
@ -1862,7 +1895,7 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
EX(function_state).function_symbol_table = *(EG(symtable_cache_ptr)--);
} else {
ALLOC_HASHTABLE(EX(function_state).function_symbol_table);
zend_hash_init(EX(function_state).function_symbol_table, 0, NULL, ZVAL_PTR_DTOR, 0);
zend_u_hash_init(EX(function_state).function_symbol_table, 0, NULL, ZVAL_PTR_DTOR, 0, UG(unicode));
/*printf("Cache miss! Initialized %x\n", function_state.function_symbol_table);*/
}
calling_symbol_table = EG(active_symbol_table);
@ -1968,8 +2001,9 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, CONST, ANY)
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(calling_scope));
if (zend_hash_find(EG(function_table), fname->value.str.val, fname->value.str.len+1, (void **) &EX(function_state).function)==FAILURE) {
zend_error_noreturn(E_ERROR, "Unknown function: %s()\n", fname->value.str.val);
if (zend_u_hash_find(EG(function_table), Z_TYPE_P(fname), Z_UNIVAL_P(fname), Z_UNILEN_P(fname)+1, (void **) &EX(function_state).function)==FAILURE) {
/* FIXME: output identifiers properly */
zend_error_noreturn(E_ERROR, "Unknown function: %R()\n", Z_TYPE_P(fname), Z_UNIVAL_P(fname));
}
EX(object) = NULL;
EX(calling_scope) = EX(function_state).function->common.scope;
@ -2031,9 +2065,9 @@ ZEND_VM_C_LABEL(return_by_value):
INIT_PZVAL_COPY(ret, retval_ptr);
dup = zend_get_object_classname(retval_ptr, &class_name, &class_name_len TSRMLS_CC);
if (Z_OBJ_HT_P(retval_ptr)->clone_obj == NULL) {
zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", class_name);
zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %v", Z_OBJCE_P(retval_ptr)->name);
}
zend_error(E_STRICT, "Implicit cloning object of class '%s' because of 'zend.ze1_compatibility_mode'", class_name);
zend_error(E_STRICT, "Implicit cloning object of class '%v' because of 'zend.ze1_compatibility_mode'", Z_OBJCE_P(retval_ptr)->name);
ret->value.obj = Z_OBJ_HT_P(retval_ptr)->clone_obj(retval_ptr TSRMLS_CC);
*EG(return_value_ptr_ptr) = ret;
if (!dup) {
@ -2110,8 +2144,8 @@ ZEND_VM_HANDLER(107, ZEND_CATCH, ANY, ANY)
}
}
zend_hash_update(EG(active_symbol_table), opline->op2.u.constant.value.str.val,
opline->op2.u.constant.value.str.len+1, &EG(exception), sizeof(zval *), (void **) NULL);
zend_u_hash_update(EG(active_symbol_table), Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant),
Z_UNILEN(opline->op2.u.constant)+1, &EG(exception), sizeof(zval *), (void **) NULL);
EG(exception) = NULL;
ZEND_VM_NEXT_OPCODE();
}
@ -2243,9 +2277,9 @@ ZEND_VM_HANDLER(63, ZEND_RECV, ANY, ANY)
zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, NULL TSRMLS_CC);
if(ptr && ptr->op_array) {
zend_error(E_WARNING, "Missing argument %ld for %s%s%s(), called in %s on line %d and defined", opline->op1.u.constant.value.lval, class_name, space, get_active_function_name(TSRMLS_C), ptr->op_array->filename, ptr->opline->lineno);
zend_error(E_WARNING, "Missing argument %ld for %v%s%v(), called in %s on line %d and defined", opline->op1.u.constant.value.lval, class_name, space, get_active_function_name(TSRMLS_C), ptr->op_array->filename, ptr->opline->lineno);
} else {
zend_error(E_WARNING, "Missing argument %ld for %s%s%s()", opline->op1.u.constant.value.lval, class_name, space, get_active_function_name(TSRMLS_C));
zend_error(E_WARNING, "Missing argument %ld for %v%s%v()", opline->op1.u.constant.value.lval, class_name, space, get_active_function_name(TSRMLS_C));
}
if (opline->result.op_type == IS_VAR) {
PZVAL_UNLOCK_FREE(*EX_T(opline->result.u.var).var.ptr_ptr);
@ -2400,7 +2434,7 @@ ZEND_VM_HANDLER(68, ZEND_NEW, ANY, ANY)
} else {
class_type = "abstract class";
}
zend_error_noreturn(E_ERROR, "Cannot instantiate %s %s", class_type, EX_T(opline->op1.u.var).class_entry->name);
zend_error_noreturn(E_ERROR, "Cannot instantiate %s %v", class_type, EX_T(opline->op1.u.var).class_entry->name);
}
ALLOC_ZVAL(object_zval);
object_init_ex(object_zval, EX_T(opline->op1.u.var).class_entry);
@ -2458,7 +2492,7 @@ ZEND_VM_HANDLER(110, ZEND_CLONE, CONST|TMP|VAR|UNUSED|CV, ANY)
clone = ce ? ce->clone : NULL;
clone_call = Z_OBJ_HT_P(obj)->clone_obj;
if (!clone_call) {
zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", ce->name);
zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %v", ce->name);
EX_T(opline->result.u.var).var.ptr = EG(error_zval_ptr);
EX_T(opline->result.u.var).var.ptr->refcount++;
}
@ -2468,13 +2502,13 @@ ZEND_VM_HANDLER(110, ZEND_CLONE, CONST|TMP|VAR|UNUSED|CV, ANY)
/* Ensure that if we're calling a private function, we're allowed to do so.
*/
if (ce != EG(scope)) {
zend_error_noreturn(E_ERROR, "Call to private %s::__clone() from context '%s'", ce->name, EG(scope) ? EG(scope)->name : "");
zend_error_noreturn(E_ERROR, "Call to private %v::__clone() from context '%v'", ce->name, EG(scope) ? EG(scope)->name : EMPTY_STR);
}
} else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) {
/* Ensure that if we're calling a protected function, we're allowed to do so.
*/
if (!zend_check_protected(clone->common.scope, EG(scope))) {
zend_error_noreturn(E_ERROR, "Call to protected %s::__clone() from context '%s'", ce->name, EG(scope) ? EG(scope)->name : "");
zend_error_noreturn(E_ERROR, "Call to protected %v::__clone() from context '%v'", ce->name, EG(scope) ? EG(scope)->name : EMPTY_STR);
}
}
}
@ -2511,10 +2545,12 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, CONST|UNUSED, CONST)
}
}
*/
if (!zend_get_constant(opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len, &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) {
zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'",
opline->op2.u.constant.value.str.val,
opline->op2.u.constant.value.str.val);
if (!zend_get_constant(Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) {
zend_error(E_NOTICE, "Use of undefined constant %R - assumed '%R'",
Z_TYPE(opline->op2.u.constant),
Z_UNIVAL(opline->op2.u.constant),
Z_TYPE(opline->op2.u.constant),
Z_UNIVAL(opline->op2.u.constant));
EX_T(opline->result.u.var).tmp_var = opline->op2.u.constant;
zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
}
@ -2523,12 +2559,12 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, CONST|UNUSED, CONST)
ce = EX_T(opline->op1.u.var).class_entry;
if (zend_hash_find(&ce->constants_table, opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len+1, (void **) &value) == SUCCESS) {
if (zend_u_hash_find(&ce->constants_table, Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant)+1, (void **) &value) == SUCCESS) {
zval_update_constant(value, (void *) 1 TSRMLS_CC);
EX_T(opline->result.u.var).tmp_var = **value;
zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
} else {
zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", opline->op2.u.constant.value.str.val);
zend_error_noreturn(E_ERROR, "Undefined class constant '%R'", Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant));
}
ZEND_VM_NEXT_OPCODE();
@ -2587,7 +2623,9 @@ ZEND_VM_HANDLER(72, ZEND_ADD_ARRAY_ELEMENT, CONST|TMP|VAR|UNUSED|CV, CONST|TMP|V
zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
zend_symtable_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL);
case IS_BINARY:
case IS_UNICODE:
zend_u_symtable_update(array_ptr->value.ht, Z_TYPE_P(offset), Z_UNIVAL_P(offset), Z_UNILEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
zend_hash_update(array_ptr->value.ht, "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
@ -2643,13 +2681,27 @@ ZEND_VM_HANDLER(21, ZEND_CAST, CONST|TMP|VAR|CV, ANY)
zval var_copy;
int use_copy;
zend_make_printable_zval(result, &var_copy, &use_copy);
zend_make_string_zval(result, &var_copy, &use_copy);
if (use_copy) {
zval_dtor(result);
*result = var_copy;
}
break;
}
case IS_UNICODE: {
zval var_copy;
int use_copy;
zend_make_unicode_zval(result, &var_copy, &use_copy);
if (use_copy) {
zval_dtor(result);
*result = var_copy;
}
break;
}
case IS_BINARY:
convert_to_binary(result);
break;
case IS_ARRAY:
convert_to_array(result);
break;
@ -2672,7 +2724,14 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMP|VAR|CV, ANY)
zval tmp_inc_filename;
zend_bool failure_retval=0;
if (inc_filename->type!=IS_STRING) {
if (UG(unicode) && opline->op2.u.constant.value.lval == ZEND_EVAL) {
if (inc_filename->type != IS_UNICODE) {
tmp_inc_filename = *inc_filename;
zval_copy_ctor(&tmp_inc_filename);
convert_to_unicode(&tmp_inc_filename);
inc_filename = &tmp_inc_filename;
}
} else if (inc_filename->type!=IS_STRING) {
tmp_inc_filename = *inc_filename;
zval_copy_ctor(&tmp_inc_filename);
convert_to_string(&tmp_inc_filename);
@ -2789,10 +2848,10 @@ ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMP|VAR|CV, ANY)
varname = GET_OP1_ZVAL_PTR(BP_VAR_R);
if (varname->type != IS_STRING) {
if (varname->type != IS_STRING && varname->type != IS_UNICODE) {
tmp = *varname;
zval_copy_ctor(&tmp);
convert_to_string(&tmp);
convert_to_text(&tmp);
varname = &tmp;
}
@ -2800,17 +2859,17 @@ ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMP|VAR|CV, ANY)
zend_std_unset_static_property(EX_T(opline->op2.u.var).class_entry, Z_STRVAL_P(varname), Z_STRLEN_P(varname) TSRMLS_CC);
} else {
target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), BP_VAR_IS, varname TSRMLS_CC);
if (zend_hash_del(target_symbol_table, varname->value.str.val, varname->value.str.len+1) == SUCCESS) {
if (zend_u_hash_del(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1) == SUCCESS) {
zend_execute_data *ex = EXECUTE_DATA;
ulong hash_value = zend_inline_hash_func(varname->value.str.val, varname->value.str.len+1);
ulong hash_value = zend_u_inline_hash_func(Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1);
do {
int i;
for (i = 0; i < ex->op_array->last_var; i++) {
if (ex->op_array->vars[i].hash_value == hash_value &&
ex->op_array->vars[i].name_len == varname->value.str.len &&
!memcmp(ex->op_array->vars[i].name, varname->value.str.val, varname->value.str.len)) {
ex->op_array->vars[i].name_len == Z_UNILEN_P(varname) &&
!memcmp(ex->op_array->vars[i].name, Z_UNIVAL_P(varname), Z_TYPE_P(varname)==IS_UNICODE?UBYTES(Z_UNILEN_P(varname)):Z_UNILEN_P(varname))) {
ex->CVs[i] = NULL;
break;
}
@ -2857,10 +2916,31 @@ ZEND_VM_HANDLER(75, ZEND_UNSET_DIM, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
zend_hash_index_del(ht, index);
break;
case IS_STRING:
if (zend_symtable_del(ht, offset->value.str.val, offset->value.str.len+1) == SUCCESS &&
ht == &EG(symbol_table)) {
case IS_BINARY:
case IS_UNICODE: {
void *offset_key = Z_UNIVAL_P(offset);
int offset_len = Z_UNILEN_P(offset);
int free_offset = 0;
if (UG(unicode) && ht == &EG(symbol_table) && offset->type == IS_UNICODE) {
/* Identifier normalization */
UChar *norm;
int32_t norm_len;
if (!zend_normalize_identifier(&norm, &norm_len,
(UChar*)offset_key, offset_len, 0)) {
zend_error(E_WARNING, "Could not normalize identifier: %r", offset_key);
} else if ((char*)norm != offset_key) {
offset_key = (char*)norm;
offset_len = norm_len;
free_offset = 1;
}
}
if (zend_u_symtable_del(ht, Z_TYPE_P(offset), offset_key, offset_len+1) == SUCCESS &&
ht == &EG(symbol_table)) {
zend_execute_data *ex;
ulong hash_value = zend_inline_hash_func(offset->value.str.val, offset->value.str.len+1);
ulong hash_value = zend_u_inline_hash_func(Z_TYPE_P(offset), offset_key, offset_len+1);
for (ex = EXECUTE_DATA; ex; ex = ex->prev_execute_data) {
if (ex->symbol_table == ht) {
@ -2868,8 +2948,8 @@ ZEND_VM_HANDLER(75, ZEND_UNSET_DIM, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
for (i = 0; i < ex->op_array->last_var; i++) {
if (ex->op_array->vars[i].hash_value == hash_value &&
ex->op_array->vars[i].name_len == offset->value.str.len &&
!memcmp(ex->op_array->vars[i].name, offset->value.str.val, offset->value.str.len)) {
ex->op_array->vars[i].name_len == offset_len &&
!memcmp(ex->op_array->vars[i].name, offset_key, Z_TYPE_P(offset)==IS_UNICODE?UBYTES(offset_len):offset_len)) {
ex->CVs[i] = NULL;
break;
}
@ -2877,7 +2957,11 @@ ZEND_VM_HANDLER(75, ZEND_UNSET_DIM, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
}
}
}
if (free_offset) {
efree(offset_key);
}
break;
}
case IS_NULL:
zend_hash_del(ht, "", sizeof(""));
break;
@ -3008,7 +3092,7 @@ ZEND_VM_HANDLER(77, ZEND_FE_RESET, CONST|TMP|VAR|CV, ANY)
FREE_OP1_IF_VAR();
}
if (!EG(exception)) {
zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Object of type %s did not create an Iterator", ce->name);
zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Object of type %v did not create an Iterator", ce->name);
}
zend_throw_exception_internal(NULL TSRMLS_CC);
ZEND_VM_NEXT_OPCODE();
@ -3043,8 +3127,11 @@ ZEND_VM_HANDLER(77, ZEND_FE_RESET, CONST|TMP|VAR|CV, ANY)
char *str_key;
uint str_key_len;
ulong int_key;
if (zend_hash_get_current_key_ex(fe_ht, &str_key, &str_key_len, &int_key, 0, NULL) == HASH_KEY_IS_STRING
&& zend_check_property_access(zobj, str_key TSRMLS_CC) == SUCCESS) {
zend_uchar key_type;
key_type = zend_hash_get_current_key_ex(fe_ht, &str_key, &str_key_len, &int_key, 0, NULL);
if (key_type != HASH_KEY_NON_EXISTANT &&
zend_check_property_access(zobj, str_key TSRMLS_CC) == SUCCESS) {
break;
}
zend_hash_move_forward(fe_ht);
@ -3106,11 +3193,16 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY)
key_type = zend_hash_get_current_key_ex(fe_ht, &str_key, &str_key_len, &int_key, 0, NULL);
zend_hash_move_forward(fe_ht);
} while (key_type != HASH_KEY_IS_STRING || zend_check_property_access(zobj, str_key TSRMLS_CC) != SUCCESS);
} while (key_type == HASH_KEY_NON_EXISTANT || zend_check_property_access(zobj, str_key TSRMLS_CC) != SUCCESS);
if (use_key) {
zend_unmangle_property_name(str_key, &class_name, &prop_name);
str_key_len = strlen(prop_name);
str_key = estrndup(prop_name, str_key_len);
zend_u_unmangle_property_name(key_type == HASH_KEY_IS_UNICODE?IS_UNICODE:IS_STRING, str_key, &class_name, &prop_name);
if (key_type == HASH_KEY_IS_UNICODE) {
str_key_len = u_strlen((UChar*)prop_name);
str_key = (char*)eustrndup((UChar*)prop_name, str_key_len);
} else {
str_key_len = strlen(prop_name);
str_key = estrndup(prop_name, str_key_len);
}
str_key_len++;
}
break;
@ -3200,6 +3292,16 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY)
key->value.str.len = str_key_len-1;
key->type = IS_STRING;
break;
case HASH_KEY_IS_BINARY:
key->value.str.val = str_key;
key->value.str.len = str_key_len-1;
key->type = IS_BINARY;
break;
case HASH_KEY_IS_UNICODE:
key->value.ustr.val = (UChar*)str_key;
key->value.ustr.len = str_key_len-1;
key->type = IS_UNICODE;
break;
case HASH_KEY_IS_LONG:
key->value.lval = int_key;
key->type = IS_LONG;
@ -3221,10 +3323,10 @@ ZEND_VM_HANDLER(114, ZEND_ISSET_ISEMPTY_VAR, CONST|TMP|VAR|CV, ANY)
zend_bool isset = 1;
HashTable *target_symbol_table;
if (varname->type != IS_STRING) {
if (varname->type != IS_STRING && varname->type != IS_UNICODE) {
tmp = *varname;
zval_copy_ctor(&tmp);
convert_to_string(&tmp);
convert_to_text(&tmp);
varname = &tmp;
}
@ -3235,7 +3337,7 @@ ZEND_VM_HANDLER(114, ZEND_ISSET_ISEMPTY_VAR, CONST|TMP|VAR|CV, ANY)
}
} else {
target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), BP_VAR_IS, varname TSRMLS_CC);
if (zend_hash_find(target_symbol_table, varname->value.str.val, varname->value.str.len+1, (void **) &value) == FAILURE) {
if (zend_u_hash_find(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1, (void **) &value) == FAILURE) {
isset = 0;
}
}
@ -3301,10 +3403,34 @@ ZEND_VM_HELPER_EX(zend_isset_isempty_dim_prop_obj_handler, VAR|UNUSED|CV, CONST|
}
break;
case IS_STRING:
if (zend_symtable_find(ht, offset->value.str.val, offset->value.str.len+1, (void **) &value) == SUCCESS) {
case IS_BINARY:
case IS_UNICODE: {
char *offset_key = Z_UNIVAL_P(offset);
int offset_len = Z_UNILEN_P(offset);
int free_offset = 0;
if (UG(unicode) && ht == &EG(symbol_table) && Z_TYPE_P(offset) == IS_UNICODE) {
/* Identifier normalization */
UChar *norm;
int32_t norm_len;
if (!zend_normalize_identifier(&norm, &norm_len,
(UChar*)offset_key, offset_len, 0)) {
zend_error(E_WARNING, "Could not normalize identifier: %r", offset_key);
} else if ((char*)norm != offset_key) {
offset_key = (char*)norm;
offset_len = norm_len;
free_offset = 1;
}
}
if (zend_u_symtable_find(ht, Z_TYPE_P(offset), offset_key, offset_len+1, (void **) &value) == SUCCESS) {
isset = 1;
}
if (free_offset) {
efree(offset_key);
}
break;
}
case IS_NULL:
if (zend_hash_find(ht, "", sizeof(""), (void **) &value) == SUCCESS) {
isset = 1;
@ -3347,7 +3473,9 @@ ZEND_VM_HELPER_EX(zend_isset_isempty_dim_prop_obj_handler, VAR|UNUSED|CV, CONST|
} else {
FREE_OP2();
}
} else if ((*container)->type == IS_STRING && !prop_dim) { /* string offsets */
} else if (((*container)->type == IS_STRING ||
(*container)->type == IS_BINARY ||
(*container)->type == IS_UNICODE) && !prop_dim) { /* string offsets */
zval tmp;
if (offset->type != IS_LONG) {
@ -3359,12 +3487,17 @@ ZEND_VM_HELPER_EX(zend_isset_isempty_dim_prop_obj_handler, VAR|UNUSED|CV, CONST|
if (offset->type == IS_LONG) {
switch (opline->extended_value) {
case ZEND_ISSET:
if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container)) {
if (offset->value.lval >= 0 &&
offset->value.lval < Z_UNILEN_PP(container)) {
result = 1;
}
break;
case ZEND_ISEMPTY:
if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container) && Z_STRVAL_PP(container)[offset->value.lval] != '0') {
if (offset->value.lval >= 0 &&
offset->value.lval < Z_UNILEN_PP(container) &&
((Z_TYPE_PP(container) == IS_UNICODE)?
(Z_USTRVAL_PP(container)[offset->value.lval] != 0):
(Z_STRVAL_PP(container)[offset->value.lval] != '0'))) {
result = 1;
}
break;
@ -3432,7 +3565,7 @@ ZEND_VM_HANDLER(57, ZEND_BEGIN_SILENCE, ANY, ANY)
ZEND_VM_HANDLER(142, ZEND_RAISE_ABSTRACT_ERROR, ANY, ANY)
{
zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", EG(scope)->name, EX(op_array)->function_name);
zend_error_noreturn(E_ERROR, "Cannot call abstract method %v::%v()", EG(scope)->name, EX(op_array)->function_name);
ZEND_VM_NEXT_OPCODE(); /* Never reached */
}
@ -3558,7 +3691,7 @@ ZEND_VM_HANDLER(144, ZEND_ADD_INTERFACE, ANY, ANY)
zend_class_entry *iface = EX_T(opline->op2.u.var).class_entry;
if (!(iface->ce_flags & ZEND_ACC_INTERFACE)) {
zend_error_noreturn(E_ERROR, "%s cannot implement %s - it is not an interface", ce->name, iface->name);
zend_error_noreturn(E_ERROR, "%v cannot implement %v - it is not an interface", ce->name, iface->name);
}
ce->interfaces[opline->extended_value] = iface;
@ -3631,4 +3764,39 @@ ZEND_VM_HANDLER(150, ZEND_USER_OPCODE, ANY, ANY)
}
}
ZEND_VM_HANDLER(151, ZEND_U_NORMALIZE, CONST|TMP|VAR|CV, ANY)
{
zend_op *opline = EX(opline);
zend_free_op free_op1;
zval *string = GET_OP1_ZVAL_PTR(BP_VAR_R);
zval *result = &EX_T(opline->result.u.var).tmp_var;
*result = *string;
if (!IS_OP1_TMP_FREE()) {
zendi_zval_copy_ctor(*result);
}
if (UG(unicode)) {
zval var_copy;
int use_copy;
UChar *norm;
int32_t norm_len;
zend_make_unicode_zval(result, &var_copy, &use_copy);
if (use_copy) {
zval_dtor(result);
*result = var_copy;
}
if (!zend_normalize_identifier(&norm, &norm_len,
Z_USTRVAL_P(result), Z_USTRLEN_P(result), 0)) {
zend_error(E_WARNING, "Could not normalize identifier: %r", Z_USTRVAL_P(result));
} else if (norm != Z_USTRVAL_P(result)) {
efree(Z_USTRVAL_P(result));
ZVAL_UNICODEL(result, norm, norm_len, 0);
}
}
FREE_OP1_IF_VAR();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_EXPORT_HELPER(zend_do_fcall, zend_do_fcall_common_helper)

File diff suppressed because it is too large Load Diff

View File

@ -1058,7 +1058,7 @@ function gen_vm($def, $skel) {
fputs($f,"#define $op $code\n");
}
fclose($f);
echo "zend_vm_opcodes.h generated succesfull.\n";
echo "zend_vm_opcodes.h generated succesfully.\n";
// Generate zend_vm_execute.h
$f = fopen("zend_vm_execute.h", "w+") or die("ERROR: Cannot create zend_vm_execute.h\n");
@ -1198,7 +1198,7 @@ function gen_vm($def, $skel) {
}
fclose($f);
echo "zend_vm_execute.h generated succesfull.\n";
echo "zend_vm_execute.h generated succesfully.\n";
}
function usage() {

View File

@ -147,3 +147,4 @@
#define ZEND_ISSET_ISEMPTY_PROP_OBJ 148
#define ZEND_HANDLE_EXCEPTION 149
#define ZEND_USER_OPCODE 150
#define ZEND_U_NORMALIZE 151

View File

@ -43,7 +43,7 @@ zend_class_entry *reflection_extension_ptr;
/* Method macros */
#define METHOD_NOTSTATIC \
if (!this_ptr) { \
zend_error(E_ERROR, "%s() cannot be called statically", get_active_function_name(TSRMLS_C)); \
zend_error(E_ERROR, "%v() cannot be called statically", get_active_function_name(TSRMLS_C)); \
return; \
} \
@ -233,7 +233,7 @@ static zend_object_value reflection_objects_new(zend_class_entry *class_type TSR
intern->free_ptr = 0;
ALLOC_HASHTABLE(intern->zo.properties);
zend_hash_init(intern->zo.properties, 0, NULL, ZVAL_PTR_DTOR, 0);
zend_u_hash_init(intern->zo.properties, 0, NULL, ZVAL_PTR_DTOR, 0, UG(unicode));
zend_hash_copy(intern->zo.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
retval.handle = zend_objects_store_put(intern, NULL, reflection_free_objects_storage, reflection_objects_clone TSRMLS_CC);
retval.handlers = &reflection_object_handlers;
@ -297,17 +297,17 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in
}
string_printf(str, "class ");
}
string_write(str, ce->name, ce->name_length);
string_printf(str, "%v", ce->name);
if (ce->parent) {
string_printf(str, " extends %s", ce->parent->name);
string_printf(str, " extends %v", ce->parent->name);
}
if (ce->num_interfaces) {
zend_uint i;
string_printf(str, " implements %s", ce->interfaces[0]->name);
string_printf(str, " implements %v", ce->interfaces[0]->name);
for (i = 1; i < ce->num_interfaces; ++i) {
string_printf(str, ", %s", ce->interfaces[i]->name);
string_printf(str, ", %v", ce->interfaces[i]->name);
}
}
string_printf(str, " ] {\n");
@ -540,7 +540,7 @@ static void _parameter_string(string *str, zend_function *fptr, struct _zend_arg
string_printf(str, "<required> ");
}
if (arg_info->class_name) {
string_printf(str, "%s ", arg_info->class_name);
string_printf(str, "%v ", arg_info->class_name);
if (arg_info->allow_null) {
string_printf(str, "or NULL ");
}
@ -554,7 +554,7 @@ static void _parameter_string(string *str, zend_function *fptr, struct _zend_arg
string_write(str, "&", sizeof("&")-1);
}
if (arg_info->name) {
string_printf(str, "$%s", arg_info->name);
string_printf(str, "$%v", arg_info->name);
} else {
string_printf(str, "$param%d", offset);
}
@ -671,7 +671,7 @@ static void _function_string(string *str, zend_function *fptr, char* indent TSRM
if (fptr->op_array.return_reference) {
string_printf(str, "&");
}
string_printf(str, "%s ] {\n", fptr->common.function_name);
string_printf(str, "%v ] {\n", fptr->common.function_name);
/* The information where a function is declared is only available for user classes */
if (fptr->type == ZEND_USER_FUNCTION) {
string_printf(str, "%s @@ %s %d - %d\n", indent,
@ -720,8 +720,8 @@ static void _property_string(string *str, zend_property_info *prop, char *prop_n
string_printf(str, "static ");
}
zend_unmangle_property_name(prop->name, &class_name, &prop_name);
string_printf(str, "$%s", prop_name);
zend_u_unmangle_property_name(UG(unicode)?IS_UNICODE:IS_STRING, prop->name, &class_name, &prop_name);
string_printf(str, "$%v", prop_name);
}
string_printf(str, " ]\n");
@ -865,7 +865,11 @@ ZEND_API void zend_reflection_class_factory(zend_class_entry *ce, zval *object T
zval *name;
MAKE_STD_ZVAL(name);
ZVAL_STRINGL(name, ce->name, ce->name_length, 1);
if (UG(unicode)) {
ZVAL_UNICODEL(name, (UChar*)ce->name, ce->name_length, 1);
} else {
ZVAL_STRINGL(name, ce->name, ce->name_length, 1);
}
reflection_instanciate(reflection_class_ptr, object TSRMLS_CC);
intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
intern->ptr = ce;
@ -912,7 +916,11 @@ static void reflection_parameter_factory(zend_function *fptr, struct _zend_arg_i
MAKE_STD_ZVAL(name);
if (arg_info->name) {
ZVAL_STRINGL(name, arg_info->name, arg_info->name_len, 1);
if (UG(unicode)) {
ZVAL_UNICODEL(name, (UChar*)arg_info->name, arg_info->name_len, 1);
} else {
ZVAL_STRINGL(name, arg_info->name, arg_info->name_len, 1);
}
} else {
ZVAL_NULL(name);
}
@ -937,7 +945,11 @@ static void reflection_function_factory(zend_function *function, zval *object TS
zval *name;
MAKE_STD_ZVAL(name);
ZVAL_STRING(name, function->common.function_name, 1);
if (UG(unicode)) {
ZVAL_UNICODE(name, (UChar*)function->common.function_name, 1);
} else {
ZVAL_STRING(name, function->common.function_name, 1);
}
reflection_instanciate(reflection_function_ptr, object TSRMLS_CC);
intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
@ -956,9 +968,14 @@ static void reflection_method_factory(zend_class_entry *ce, zend_function *metho
zval *classname;
MAKE_STD_ZVAL(name);
ZVAL_STRING(name, method->common.function_name, 1);
MAKE_STD_ZVAL(classname);
ZVAL_STRINGL(classname, ce->name, ce->name_length, 1);
if (UG(unicode)) {
ZVAL_UNICODE(name, (UChar*)method->common.function_name, 1);
ZVAL_UNICODEL(classname, (UChar*)ce->name, ce->name_length, 1);
} else {
ZVAL_STRING(name, method->common.function_name, 1);
ZVAL_STRINGL(classname, ce->name, ce->name_length, 1);
}
reflection_instanciate(reflection_method_ptr, object TSRMLS_CC);
intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
intern->ptr = method;
@ -978,7 +995,7 @@ static void reflection_property_factory(zend_class_entry *ce, zend_property_info
property_reference *reference;
char *class_name, *prop_name;
zend_unmangle_property_name(prop->name, &class_name, &prop_name);
zend_u_unmangle_property_name(UG(unicode)?IS_UNICODE:IS_STRING, prop->name, &class_name, &prop_name);
if (!(prop->flags & ZEND_ACC_PRIVATE)) {
/* we have to seach the class hierarchy for this (implicit) public or protected property */
@ -997,10 +1014,14 @@ static void reflection_property_factory(zend_class_entry *ce, zend_property_info
}
MAKE_STD_ZVAL(name);
ZVAL_STRING(name, prop_name, 1);
MAKE_STD_ZVAL(classname);
ZVAL_STRINGL(classname, ce->name, ce->name_length, 1);
if (UG(unicode)) {
ZVAL_UNICODE(name, (UChar*)prop_name, 1);
ZVAL_UNICODEL(classname, (UChar*)ce->name, ce->name_length, 1);
} else {
ZVAL_STRING(name, prop_name, 1);
ZVAL_STRINGL(classname, ce->name, ce->name_length, 1);
}
reflection_instanciate(reflection_property_ptr, object TSRMLS_CC);
intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
@ -1144,7 +1165,7 @@ ZEND_METHOD(reflection, export)
}
if (!retval_ptr) {
zend_error(E_WARNING, "%s::__toString() did not return anything", Z_OBJCE_P(object)->name);
zend_error(E_WARNING, "%v::__toString() did not return anything", Z_OBJCE_P(object)->name);
RETURN_FALSE;
}
@ -1211,13 +1232,15 @@ ZEND_METHOD(reflection_function, __construct)
{
zval *name;
zval *object;
unsigned int lcname_len;
char *lcname;
reflection_object *intern;
zend_function *fptr;
char *name_str;
int name_len;
zend_uchar type;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name_str, &name_len) == FAILURE) {
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "t", &name_str, &name_len, &type) == FAILURE) {
return;
}
@ -1226,17 +1249,20 @@ ZEND_METHOD(reflection_function, __construct)
if (intern == NULL) {
return;
}
lcname = do_alloca(name_len + 1);
zend_str_tolower_copy(lcname, name_str, name_len);
if (zend_hash_find(EG(function_table), lcname, name_len + 1, (void **)&fptr) == FAILURE) {
free_alloca(lcname);
lcname = zend_u_str_case_fold(type, name_str, name_len, 1, &lcname_len);
if (zend_u_hash_find(EG(function_table), type, lcname, lcname_len + 1, (void **)&fptr) == FAILURE) {
efree(lcname);
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Function %s() does not exist", name_str);
"Function %R() does not exist", type, name_str);
return;
}
free_alloca(lcname);
efree(lcname);
MAKE_STD_ZVAL(name);
ZVAL_STRING(name, fptr->common.function_name, 1);
if (UG(unicode)) {
ZVAL_UNICODE(name, (UChar*)fptr->common.function_name, 1);
} else {
ZVAL_STRING(name, fptr->common.function_name, 1);
}
zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
intern->ptr = fptr;
intern->free_ptr = 0;
@ -1421,7 +1447,7 @@ ZEND_METHOD(reflection_function, invoke)
if (result == FAILURE) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Invocation of function %s() failed", fptr->common.function_name);
"Invocation of function %v() failed", fptr->common.function_name);
return;
}
@ -1485,7 +1511,7 @@ ZEND_METHOD(reflection_function, invokeArgs)
if (result == FAILURE) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Invocation of function %s() failed", fptr->common.function_name);
"Invocation of function %v() failed", fptr->common.function_name);
return;
}
@ -1598,19 +1624,20 @@ ZEND_METHOD(reflection_parameter, __construct)
/* First, find the function */
switch (Z_TYPE_P(reference)) {
case IS_UNICODE:
case IS_STRING: {
char *lcname;
unsigned int lcname_len;
char *lcname;
convert_to_string_ex(&reference);
lcname = do_alloca(Z_STRLEN_P(reference) + 1);
zend_str_tolower_copy(lcname, Z_STRVAL_P(reference), Z_STRLEN_P(reference));
if (zend_hash_find(EG(function_table), lcname, (int) Z_STRLEN_P(reference) + 1, (void**) &fptr) == FAILURE) {
free_alloca(lcname);
convert_to_text_ex(&reference);
lcname = zend_u_str_case_fold(Z_TYPE_P(reference), Z_STRVAL_P(reference), Z_STRLEN_P(reference), 1, &lcname_len);
if (zend_u_hash_find(EG(function_table), Z_TYPE_P(reference), lcname, lcname_len + 1, (void**) &fptr) == FAILURE) {
efree(lcname);
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Function %s() does not exist", Z_STRVAL_P(reference));
"Function %R() does not exist", Z_TYPE_P(reference), Z_STRVAL_P(reference));
return;
}
free_alloca(lcname);
efree(lcname);
}
break;
@ -1618,7 +1645,8 @@ ZEND_METHOD(reflection_parameter, __construct)
zval **classref;
zval **method;
zend_class_entry **pce;
char *lcname;
unsigned int lcname_len;
char *lcname;
if ((zend_hash_index_find(Z_ARRVAL_P(reference), 0, (void **) &classref) == FAILURE)
|| (zend_hash_index_find(Z_ARRVAL_P(reference), 1, (void **) &method) == FAILURE)) {
@ -1629,25 +1657,24 @@ ZEND_METHOD(reflection_parameter, __construct)
if (Z_TYPE_PP(classref) == IS_OBJECT) {
ce = Z_OBJCE_PP(classref);
} else {
convert_to_string_ex(classref);
if (zend_lookup_class(Z_STRVAL_PP(classref), Z_STRLEN_PP(classref), &pce TSRMLS_CC) == FAILURE) {
convert_to_text_ex(classref);
if (zend_u_lookup_class(Z_TYPE_PP(classref), Z_UNIVAL_PP(classref), Z_UNILEN_PP(classref), &pce TSRMLS_CC) == FAILURE) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Class %s does not exist", Z_STRVAL_PP(classref));
"Class %R does not exist", Z_TYPE_PP(classref), Z_UNIVAL_PP(classref));
return;
}
ce = *pce;
}
convert_to_string_ex(method);
lcname = do_alloca(Z_STRLEN_PP(method) + 1);
zend_str_tolower_copy(lcname, Z_STRVAL_PP(method), Z_STRLEN_PP(method));
if (zend_hash_find(&ce->function_table, lcname, (int)(Z_STRLEN_PP(method) + 1), (void **) &fptr) == FAILURE) {
free_alloca(lcname);
convert_to_text_ex(method);
lcname = zend_u_str_case_fold(Z_TYPE_PP(method), Z_UNIVAL_PP(method), Z_UNILEN_PP(method), 1, &lcname_len);
if (zend_u_hash_find(&ce->function_table, Z_TYPE_PP(method), lcname, lcname_len + 1, (void **) &fptr) == FAILURE) {
efree(lcname);
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Method %s::%s() does not exist", Z_STRVAL_PP(classref), Z_STRVAL_PP(method));
"Method %R::%R() does not exist", Z_TYPE_PP(classref), Z_UNIVAL_PP(classref), Z_TYPE_PP(method), Z_UNIVAL_PP(method));
return;
}
free_alloca(lcname);
efree(lcname);
}
break;
@ -1683,7 +1710,11 @@ ZEND_METHOD(reflection_parameter, __construct)
MAKE_STD_ZVAL(name);
if (arg_info[position].name) {
ZVAL_STRINGL(name, arg_info[position].name, arg_info[position].name_len, 1);
if (UG(unicode)) {
ZVAL_UNICODEL(name, (UChar*)arg_info[position].name, arg_info[position].name_len, 1);
} else {
ZVAL_STRINGL(name, arg_info[position].name, arg_info[position].name_len, 1);
}
} else {
ZVAL_NULL(name);
}
@ -1739,15 +1770,16 @@ ZEND_METHOD(reflection_parameter, getClass)
RETURN_NULL();
} else {
zend_class_entry **pce;
char *lcname = do_alloca(param->arg_info->class_name_len + 1);
zend_str_tolower_copy(lcname, param->arg_info->class_name, param->arg_info->class_name_len);
if (zend_hash_find(EG(class_table), lcname, param->arg_info->class_name_len + 1, (void **) &pce) == FAILURE) {
free_alloca(lcname);
unsigned int lcname_len;
char *lcname = zend_u_str_case_fold(UG(unicode)?IS_UNICODE:IS_STRING, param->arg_info->class_name, param->arg_info->class_name_len, 0, &lcname_len);
if (zend_u_hash_find(EG(class_table), UG(unicode)?IS_UNICODE:IS_STRING, lcname, lcname_len + 1, (void **) &pce) == FAILURE) {
efree(lcname);
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Class %s does not exist", param->arg_info->class_name);
"Class %v does not exist", param->arg_info->class_name);
return;
}
free_alloca(lcname);
efree(lcname);
zend_reflection_class_factory(*pce, return_value TSRMLS_CC);
}
}
@ -1884,14 +1916,16 @@ ZEND_METHOD(reflection_method, __construct)
zval *name, *classname;
zval *object;
reflection_object *intern;
unsigned int lcname_len;
char *lcname;
zend_class_entry **pce;
zend_class_entry *ce;
zend_function *mptr;
char *name_str;
int name_len;
zend_uchar type;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zs", &classname, &name_str, &name_len) == FAILURE) {
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zt", &classname, &name_str, &name_len, &type) == FAILURE) {
return;
}
@ -1904,9 +1938,10 @@ ZEND_METHOD(reflection_method, __construct)
/* Find the class entry */
switch (Z_TYPE_P(classname)) {
case IS_STRING:
if (zend_lookup_class(Z_STRVAL_P(classname), Z_STRLEN_P(classname), &pce TSRMLS_CC) == FAILURE) {
case IS_UNICODE:
if (zend_u_lookup_class(Z_TYPE_P(classname), Z_UNIVAL_P(classname), Z_UNILEN_P(classname), &pce TSRMLS_CC) == FAILURE) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Class %s does not exist", Z_STRVAL_P(classname));
"Class %v does not exist", Z_UNIVAL_P(classname));
return;
}
ce = *pce;
@ -1922,22 +1957,29 @@ ZEND_METHOD(reflection_method, __construct)
}
MAKE_STD_ZVAL(classname);
ZVAL_STRINGL(classname, ce->name, ce->name_length, 1);
if (UG(unicode)) {
ZVAL_UNICODEL(classname, (UChar*)ce->name, ce->name_length, 1);
} else {
ZVAL_STRINGL(classname, ce->name, ce->name_length, 1);
}
zend_hash_update(Z_OBJPROP_P(object), "class", sizeof("class"), (void **) &classname, sizeof(zval *), NULL);
lcname = do_alloca(name_len + 1);
zend_str_tolower_copy(lcname, name_str, name_len);
lcname = zend_u_str_case_fold(type, name_str, name_len, 1, &lcname_len);
if (zend_hash_find(&ce->function_table, lcname, name_len + 1, (void **) &mptr) == FAILURE) {
free_alloca(lcname);
if (zend_u_hash_find(&ce->function_table, type, lcname, lcname_len + 1, (void **) &mptr) == FAILURE) {
efree(lcname);
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Method %s::%s() does not exist", ce->name, name_str);
"Method %v::%R() does not exist", ce->name, type, name_str);
return;
}
free_alloca(lcname);
efree(lcname);
MAKE_STD_ZVAL(name);
ZVAL_STRING(name, mptr->common.function_name, 1);
if (UG(unicode)) {
ZVAL_UNICODE(name, (UChar*)mptr->common.function_name, 1);
} else {
ZVAL_STRING(name, mptr->common.function_name, 1);
}
zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
intern->ptr = mptr;
intern->free_ptr = 0;
@ -1989,11 +2031,11 @@ ZEND_METHOD(reflection_method, invoke)
(mptr->common.fn_flags & ZEND_ACC_ABSTRACT)) {
if (mptr->common.fn_flags & ZEND_ACC_ABSTRACT) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Trying to invoke abstract method %s::%s()",
"Trying to invoke abstract method %v::%v()",
mptr->common.scope->name, mptr->common.function_name);
} else {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Trying to invoke %s method %s::%s() from scope %s",
"Trying to invoke %s method %v::%v() from scope %v",
mptr->common.fn_flags & ZEND_ACC_PROTECTED ? "protected" : "private",
mptr->common.scope->name, mptr->common.function_name,
Z_OBJCE_P(getThis())->name);
@ -2054,7 +2096,7 @@ ZEND_METHOD(reflection_method, invoke)
if (result == FAILURE) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Invocation of method %s::%s() failed", mptr->common.scope->name, mptr->common.function_name);
"Invocation of method %v::%v() failed", mptr->common.scope->name, mptr->common.function_name);
return;
}
@ -2092,11 +2134,11 @@ ZEND_METHOD(reflection_method, invokeArgs)
(mptr->common.fn_flags & ZEND_ACC_ABSTRACT)) {
if (mptr->common.fn_flags & ZEND_ACC_ABSTRACT) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Trying to invoke abstract method %s::%s",
"Trying to invoke abstract method %v::%v",
mptr->common.scope->name, mptr->common.function_name);
} else {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Trying to invoke %s method %s::%s from scope %s",
"Trying to invoke %s method %v::%v from scope %v",
mptr->common.fn_flags & ZEND_ACC_PROTECTED ? "protected" : "private",
mptr->common.scope->name, mptr->common.function_name,
Z_OBJCE_P(getThis())->name);
@ -2123,7 +2165,7 @@ ZEND_METHOD(reflection_method, invokeArgs)
if (!object) {
efree(params);
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Trying to invoke non static method %s::%s without an object",
"Trying to invoke non static method %v::%v without an object",
mptr->common.scope->name, mptr->common.function_name);
return;
}
@ -2158,7 +2200,7 @@ ZEND_METHOD(reflection_method, invokeArgs)
if (result == FAILURE) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Invocation of method %s::%s() failed", mptr->common.scope->name, mptr->common.function_name);
"Invocation of method %v::%v() failed", mptr->common.scope->name, mptr->common.function_name);
return;
}
@ -2308,7 +2350,11 @@ static void reflection_class_object_ctor(INTERNAL_FUNCTION_PARAMETERS, int is_ob
if (Z_TYPE_P(argument) == IS_OBJECT) {
MAKE_STD_ZVAL(classname);
ZVAL_STRINGL(classname, Z_OBJCE_P(argument)->name, Z_OBJCE_P(argument)->name_length, 1);
if (UG(unicode)) {
ZVAL_UNICODEL(classname, (UChar*)Z_OBJCE_P(argument)->name, Z_OBJCE_P(argument)->name_length, 1);
} else {
ZVAL_STRINGL(classname, Z_OBJCE_P(argument)->name, Z_OBJCE_P(argument)->name_length, 1);
}
zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &classname, sizeof(zval *), NULL);
intern->ptr = Z_OBJCE_P(argument);
if (is_object) {
@ -2317,7 +2363,7 @@ static void reflection_class_object_ctor(INTERNAL_FUNCTION_PARAMETERS, int is_ob
}
} else {
convert_to_string_ex(&argument);
if (zend_lookup_class(Z_STRVAL_P(argument), Z_STRLEN_P(argument), &ce TSRMLS_CC) == FAILURE) {
if (zend_u_lookup_class(Z_TYPE_P(argument), Z_UNIVAL_P(argument), Z_UNILEN_P(argument), &ce TSRMLS_CC) == FAILURE) {
if (!EG(exception)) {
zend_throw_exception_ex(reflection_exception_ptr, -1 TSRMLS_CC, "Class %s does not exist", Z_STRVAL_P(argument));
}
@ -2325,7 +2371,11 @@ static void reflection_class_object_ctor(INTERNAL_FUNCTION_PARAMETERS, int is_ob
}
MAKE_STD_ZVAL(classname);
ZVAL_STRINGL(classname, (*ce)->name, (*ce)->name_length, 1);
if (UG(unicode)) {
ZVAL_UNICODEL(classname, (UChar*)((*ce)->name), (*ce)->name_length, 1);
} else {
ZVAL_STRINGL(classname, (*ce)->name, (*ce)->name_length, 1);
}
zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &classname, sizeof(zval *), NULL);
intern->ptr = *ce;
@ -2613,17 +2663,19 @@ ZEND_METHOD(reflection_class, hasMethod)
{
reflection_object *intern;
zend_class_entry *ce;
unsigned int lc_name_len;
char *name, *lc_name;
int name_len;
zend_uchar type;
METHOD_NOTSTATIC;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "t", &name, &name_len, &type) == FAILURE) {
return;
}
GET_REFLECTION_OBJECT_PTR(ce);
lc_name = zend_str_tolower_dup(name, name_len);
if (zend_hash_exists(&ce->function_table, lc_name, name_len + 1)) {
lc_name = zend_u_str_case_fold(type, name, name_len, 1, &lc_name_len);
if (zend_u_hash_exists(&ce->function_table, type, lc_name, lc_name_len + 1)) {
efree(lc_name);
RETURN_TRUE;
} else {
@ -2640,23 +2692,25 @@ ZEND_METHOD(reflection_class, getMethod)
reflection_object *intern;
zend_class_entry *ce;
zend_function *mptr;
unsigned int lc_name_len;
char *name, *lc_name;
int name_len;
zend_uchar type;
METHOD_NOTSTATIC;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "t", &name, &name_len, &type) == FAILURE) {
return;
}
GET_REFLECTION_OBJECT_PTR(ce);
lc_name = zend_str_tolower_dup(name, name_len);
if (zend_hash_find(&ce->function_table, lc_name, name_len + 1, (void**) &mptr) == SUCCESS) {
lc_name = zend_u_str_case_fold(type, name, name_len, 1, &lc_name_len);
if (zend_u_hash_find(&ce->function_table, type, lc_name, lc_name_len + 1, (void**) &mptr) == SUCCESS) {
reflection_method_factory(ce, mptr, return_value TSRMLS_CC);
efree(lc_name);
} else {
efree(lc_name);
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Method %s does not exist", name);
"Method %R does not exist", type, name);
return;
}
}
@ -2989,7 +3043,7 @@ ZEND_METHOD(reflection_class, newInstance)
zend_fcall_info_cache fcc;
if (!(ce->constructor->common.fn_flags & ZEND_ACC_PUBLIC)) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Access to non-public constructor of class %s", ce->name);
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Access to non-public constructor of class %v", ce->name);
return;
}
@ -3017,7 +3071,7 @@ ZEND_METHOD(reflection_class, newInstance)
if (zend_call_function(&fci, &fcc TSRMLS_CC) == FAILURE) {
efree(params);
zval_ptr_dtor(&retval_ptr);
zend_error(E_WARNING, "Invocation of %s's constructor failed", ce->name);
zend_error(E_WARNING, "Invocation of %v's constructor failed", ce->name);
RETURN_NULL();
}
if (retval_ptr) {
@ -3089,7 +3143,8 @@ ZEND_METHOD(reflection_class, isSubclassOf)
switch(class_name->type) {
case IS_STRING:
if (zend_lookup_class(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), &pce TSRMLS_CC) == FAILURE) {
case IS_UNICODE:
if (zend_u_lookup_class(Z_TYPE_P(class_name), Z_UNIVAL_P(class_name), Z_UNILEN_P(class_name), &pce TSRMLS_CC) == FAILURE) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Interface %s does not exist", Z_STRVAL_P(class_name));
return;
@ -3135,7 +3190,8 @@ ZEND_METHOD(reflection_class, implementsInterface)
switch(interface->type) {
case IS_STRING:
if (zend_lookup_class(Z_STRVAL_P(interface), Z_STRLEN_P(interface), &pce TSRMLS_CC) == FAILURE) {
case IS_UNICODE:
if (zend_u_lookup_class(Z_TYPE_P(interface), Z_UNIVAL_P(interface), Z_UNILEN_P(interface), &pce TSRMLS_CC) == FAILURE) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Interface %s does not exist", Z_STRVAL_P(interface));
return;
@ -3161,7 +3217,7 @@ ZEND_METHOD(reflection_class, implementsInterface)
if (!(interface_ce->ce_flags & ZEND_ACC_INTERFACE)) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Interface %s is a Class", interface_ce->name);
"Interface %v is a Class", interface_ce->name);
return;
}
RETURN_BOOL(instanceof_function(ce, interface_ce TSRMLS_CC));
@ -3267,7 +3323,8 @@ ZEND_METHOD(reflection_property, __construct)
/* Find the class entry */
switch (Z_TYPE_P(classname)) {
case IS_STRING:
if (zend_lookup_class(Z_STRVAL_P(classname), Z_STRLEN_P(classname), &pce TSRMLS_CC) == FAILURE) {
case IS_UNICODE:
if (zend_u_lookup_class(Z_TYPE_P(classname), Z_UNIVAL_P(classname), Z_UNILEN_P(classname), &pce TSRMLS_CC) == FAILURE) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Class %s does not exist", Z_STRVAL_P(classname));
return;
@ -3286,7 +3343,7 @@ ZEND_METHOD(reflection_property, __construct)
if (zend_hash_find(&ce->properties_info, name_str, name_len + 1, (void **) &property_info) == FAILURE || (property_info->flags & ZEND_ACC_SHADOW)) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Property %s::$%s does not exist", ce->name, name_str);
"Property %v::$%s does not exist", ce->name, name_str);
return;
}
@ -3307,12 +3364,20 @@ ZEND_METHOD(reflection_property, __construct)
}
MAKE_STD_ZVAL(classname);
ZVAL_STRINGL(classname, ce->name, ce->name_length, 1);
if (UG(unicode)) {
ZVAL_UNICODEL(classname, (UChar*)ce->name, ce->name_length, 1);
} else {
ZVAL_STRINGL(classname, ce->name, ce->name_length, 1);
}
zend_hash_update(Z_OBJPROP_P(object), "class", sizeof("class"), (void **) &classname, sizeof(zval *), NULL);
zend_unmangle_property_name(property_info->name, &class_name, &prop_name);
zend_u_unmangle_property_name(UG(unicode)?IS_UNICODE:IS_STRING, property_info->name, &class_name, &prop_name);
MAKE_STD_ZVAL(propname);
ZVAL_STRING(propname, prop_name, 1);
if (UG(unicode)) {
ZVAL_UNICODE(propname, (UChar*)prop_name, 1);
} else {
ZVAL_STRING(propname, prop_name, 1);
}
zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &propname, sizeof(zval *), NULL);
reference = (property_reference*) emalloc(sizeof(property_reference));
@ -3421,6 +3486,7 @@ ZEND_METHOD(reflection_property, getValue)
property_reference *ref;
zval *object;
zval **member= NULL;
zend_uchar utype = UG(unicode)?IS_UNICODE:IS_STRING;
METHOD_NOTSTATIC;
GET_REFLECTION_OBJECT_PTR(ref);
@ -3432,16 +3498,16 @@ ZEND_METHOD(reflection_property, getValue)
if ((ref->prop->flags & ZEND_ACC_STATIC)) {
zend_update_class_constants(intern->ce TSRMLS_CC);
if (zend_hash_quick_find(intern->ce->static_members, ref->prop->name, ref->prop->name_length + 1, ref->prop->h, (void **) &member) == FAILURE) {
zend_error(E_ERROR, "Internal error: Could not find the property %s", ref->prop->name);
if (zend_u_hash_quick_find(intern->ce->static_members, utype, ref->prop->name, ref->prop->name_length + 1, ref->prop->h, (void **) &member) == FAILURE) {
zend_error(E_ERROR, "Internal error: Could not find the property %v", ref->prop->name);
/* Bails out */
}
} else {
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &object) == FAILURE) {
return;
}
if (zend_hash_quick_find(Z_OBJPROP_P(object), ref->prop->name, ref->prop->name_length + 1, ref->prop->h, (void **) &member) == FAILURE) {
zend_error(E_ERROR, "Internal error: Could not find the property %s", ref->prop->name);
if (zend_u_hash_quick_find(Z_OBJPROP_P(object), utype, ref->prop->name, ref->prop->name_length + 1, ref->prop->h, (void **) &member) == FAILURE) {
zend_error(E_ERROR, "Internal error: Could not find the property %v", ref->prop->name);
/* Bails out */
}
}
@ -3463,6 +3529,7 @@ ZEND_METHOD(reflection_property, setValue)
int setter_done = 0;
zval *tmp;
HashTable *prop_table;
zend_uchar utype = UG(unicode)?IS_UNICODE:IS_STRING;
METHOD_NOTSTATIC;
GET_REFLECTION_OBJECT_PTR(ref);
@ -3486,8 +3553,8 @@ ZEND_METHOD(reflection_property, setValue)
prop_table = Z_OBJPROP_P(object);
}
if (zend_hash_quick_find(prop_table, ref->prop->name, ref->prop->name_length + 1, ref->prop->h, (void **) &variable_ptr) == FAILURE) {
zend_error(E_ERROR, "Internal error: Could not find the property %s", ref->prop->name);
if (zend_u_hash_quick_find(prop_table, utype, ref->prop->name, ref->prop->name_length + 1, ref->prop->h, (void **) &variable_ptr) == FAILURE) {
zend_error(E_ERROR, "Internal error: Could not find the property %v", ref->prop->name);
/* Bails out */
}
if (*variable_ptr == value) {
@ -3510,7 +3577,7 @@ ZEND_METHOD(reflection_property, setValue)
if (PZVAL_IS_REF(value)) {
SEPARATE_ZVAL(&value);
}
zend_hash_quick_update(prop_table, ref->prop->name, ref->prop->name_length+1, ref->prop->h, &value, sizeof(zval *), (void **) &foo);
zend_u_hash_quick_update(prop_table, utype, ref->prop->name, ref->prop->name_length+1, ref->prop->h, &value, sizeof(zval *), (void **) &foo);
}
}
/* }}} */
@ -3943,12 +4010,13 @@ static zend_object_handlers *zend_std_obj_handlers;
/* {{{ _reflection_write_property */
static void _reflection_write_property(zval *object, zval *member, zval *value TSRMLS_DC)
{
if (Z_TYPE_P(member) == IS_STRING
&& zend_hash_exists(&Z_OBJCE_P(object)->default_properties, Z_STRVAL_P(member), Z_STRLEN_P(member)+1)
&& (!strcmp(Z_STRVAL_P(member), "name") || !strcmp(Z_STRVAL_P(member), "class")))
if ((Z_TYPE_P(member) == IS_STRING || Z_TYPE_P(member) == IS_UNICODE)
&& zend_u_hash_exists(&Z_OBJCE_P(object)->default_properties, Z_TYPE_P(member), Z_UNIVAL_P(member), Z_UNILEN_P(member)+1)
&& (ZEND_U_EQUAL(Z_TYPE_P(member), Z_UNIVAL_P(member), Z_UNILEN_P(member), "name", sizeof("name")-1) ||
ZEND_U_EQUAL(Z_TYPE_P(member), Z_UNIVAL_P(member), Z_UNILEN_P(member), "class", sizeof("class")-1)))
{
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Cannot set read-only property %s::$%s", Z_OBJCE_P(object)->name, Z_STRVAL_P(member));
"Cannot set read-only property %v::$%R", Z_OBJCE_P(object)->name, Z_TYPE_P(member), Z_UNIVAL_P(member));
}
else
{
@ -4038,6 +4106,20 @@ ZEND_API void zend_register_reflection_api(TSRMLS_D) {
}
/* }}} */
void init_reflection_api(TSRMLS_D)
{
reflection_exception_ptr = zend_get_named_class_entry("ReflectionException", sizeof("ReflectionException")-1 TSRMLS_CC);
reflection_ptr = zend_get_named_class_entry("Reflection", sizeof("Reflection")-1 TSRMLS_CC);
reflector_ptr = zend_get_named_class_entry("Reflector", sizeof("Reflector")-1 TSRMLS_CC);
reflection_function_ptr = zend_get_named_class_entry("ReflectionFunction", sizeof("ReflectionFunction")-1 TSRMLS_CC);
reflection_parameter_ptr = zend_get_named_class_entry("ReflectionParameter", sizeof("ReflectionParameter")-1 TSRMLS_CC);
reflection_method_ptr = zend_get_named_class_entry("ReflectionMethod", sizeof("ReflectionMethod")-1 TSRMLS_CC);
reflection_class_ptr = zend_get_named_class_entry("ReflectionClass", sizeof("ReflectionClass")-1 TSRMLS_CC);
reflection_object_ptr = zend_get_named_class_entry("ReflectionObject", sizeof("ReflectionObject")-1 TSRMLS_CC);
reflection_property_ptr = zend_get_named_class_entry("ReflectionProperty", sizeof("ReflectionProperty")-1 TSRMLS_CC);
reflection_extension_ptr = zend_get_named_class_entry("ReflectionExtension", sizeof("ReflectionExtension")-1 TSRMLS_CC);
}
/*
* Local variables:
* tab-width: 4

View File

@ -26,6 +26,8 @@ BEGIN_EXTERN_C()
ZEND_API void zend_register_reflection_api(TSRMLS_D);
ZEND_API void zend_reflection_class_factory(zend_class_entry *ce, zval *object TSRMLS_DC);
void init_reflection_api(TSRMLS_D);
END_EXTERN_C()
#endif