@ -55,9 +55,6 @@ struct _pcre_cache_entry {
uint32_t compile_options ;
uint32_t compile_options ;
uint32_t extra_compile_options ;
uint32_t extra_compile_options ;
uint32_t refcount ;
uint32_t refcount ;
# if HAVE_SETLOCALE
const uint8_t * tables ;
# endif
} ;
} ;
enum {
enum {
@ -100,6 +97,16 @@ static MUTEX_T pcre_mt = NULL;
# define php_pcre_mutex_unlock()
# define php_pcre_mutex_unlock()
# endif
# endif
# if HAVE_SETLOCALE
ZEND_TLS HashTable char_tables ;
static void php_pcre_free_char_table ( zval * data )
{ /*{{{*/
void * ptr = Z_PTR_P ( data ) ;
pefree ( ptr , 1 ) ;
} /*}}}*/
# endif
static void pcre_handle_exec_error ( int pcre_code ) /* { { { */
static void pcre_handle_exec_error ( int pcre_code ) /* { { { */
{
{
int preg_code = 0 ;
int preg_code = 0 ;
@ -141,9 +148,6 @@ static void php_free_pcre_cache(zval *data) /* {{{ */
pcre_cache_entry * pce = ( pcre_cache_entry * ) Z_PTR_P ( data ) ;
pcre_cache_entry * pce = ( pcre_cache_entry * ) Z_PTR_P ( data ) ;
if ( ! pce ) return ;
if ( ! pce ) return ;
pcre2_code_free ( pce - > re ) ;
pcre2_code_free ( pce - > re ) ;
# if HAVE_SETLOCALE
if ( ( void * ) pce - > tables ) pefree ( ( void * ) pce - > tables , 1 ) ;
# endif
pefree ( pce , 1 ) ;
pefree ( pce , 1 ) ;
}
}
/* }}} */
/* }}} */
@ -262,6 +266,9 @@ static PHP_GINIT_FUNCTION(pcre) /* {{{ */
# endif
# endif
php_pcre_init_pcre2 ( 1 ) ;
php_pcre_init_pcre2 ( 1 ) ;
# if HAVE_SETLOCALE
zend_hash_init ( & char_tables , 1 , NULL , php_pcre_free_char_table , 1 ) ;
# endif
}
}
/* }}} */
/* }}} */
@ -270,6 +277,9 @@ static PHP_GSHUTDOWN_FUNCTION(pcre) /* {{{ */
zend_hash_destroy ( & pcre_globals - > pcre_cache ) ;
zend_hash_destroy ( & pcre_globals - > pcre_cache ) ;
php_pcre_shutdown_pcre2 ( ) ;
php_pcre_shutdown_pcre2 ( ) ;
# if HAVE_SETLOCALE
zend_hash_destroy ( & char_tables ) ;
# endif
php_pcre_mutex_free ( ) ;
php_pcre_mutex_free ( ) ;
}
}
@ -535,6 +545,7 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(zend_string *regex)
size_t pattern_len ;
size_t pattern_len ;
uint32_t poptions = 0 ;
uint32_t poptions = 0 ;
const uint8_t * tables = NULL ;
const uint8_t * tables = NULL ;
uint8_t save_tables = 0 ;
zval * zv ;
zval * zv ;
pcre_cache_entry new_entry ;
pcre_cache_entry new_entry ;
int rc ;
int rc ;
@ -705,13 +716,11 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(zend_string *regex)
# if HAVE_SETLOCALE
# if HAVE_SETLOCALE
if ( key ! = regex ) {
if ( key ! = regex ) {
/* XXX a better solution here were to create a copy of cctx
and to cache it along with the generated tables . Once same locale
is encountered , the cached cctx and tables would be fetched .
Currently the tables are generated every time a locale based
pattern is used , and the tables are overwritten in the global
cctx . */
tables = pcre2_maketables ( gctx ) ;
tables = ( uint8_t * ) zend_hash_find_ptr ( & char_tables , BG ( locale_string ) ) ;
if ( ! tables ) {
save_tables = 1 ;
tables = pcre2_maketables ( gctx ) ;
}
pcre2_set_character_tables ( cctx , tables ) ;
pcre2_set_character_tables ( cctx , tables ) ;
}
}
# endif
# endif
@ -739,7 +748,7 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(zend_string *regex)
php_error_docref ( NULL , E_WARNING , " Compilation failed: %s at offset %zu " , error , erroffset ) ;
php_error_docref ( NULL , E_WARNING , " Compilation failed: %s at offset %zu " , error , erroffset ) ;
pcre_handle_exec_error ( PCRE2_ERROR_INTERNAL ) ;
pcre_handle_exec_error ( PCRE2_ERROR_INTERNAL ) ;
efree ( pattern ) ;
efree ( pattern ) ;
if ( tables ) {
if ( save_ tables) {
pefree ( ( void * ) tables , 1 ) ;
pefree ( ( void * ) tables , 1 ) ;
}
}
return NULL ;
return NULL ;
@ -779,7 +788,9 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(zend_string *regex)
new_entry . compile_options = coptions ;
new_entry . compile_options = coptions ;
new_entry . extra_compile_options = extra_coptions ;
new_entry . extra_compile_options = extra_coptions ;
# if HAVE_SETLOCALE
# if HAVE_SETLOCALE
new_entry . tables = tables ;
if ( save_tables ) {
zend_hash_add_ptr ( & char_tables , BG ( locale_string ) , ( void * ) tables ) ;
}
# endif
# endif
new_entry . refcount = 0 ;
new_entry . refcount = 0 ;