From 40f3524247f36e6f485f3f1247a222cedab5cbdf Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Sun, 14 Jan 2001 16:36:30 +0000 Subject: [PATCH] Added localeconv() function. Operates similarly to localeconv() defined in locale.h. Should work well under non-ZTS as well as ZTS. --- configure.in | 1 + ext/standard/basic_functions.c | 7 ++ ext/standard/php_string.h | 1 + ext/standard/string.c | 150 +++++++++++++++++++++++++++++++++ main/config.w32.h | 2 + 5 files changed, 161 insertions(+) diff --git a/configure.in b/configure.in index f16671bc16..e60a53143c 100644 --- a/configure.in +++ b/configure.in @@ -379,6 +379,7 @@ rand_r \ regcomp \ setitimer \ setlocale \ +localeconv \ setsockopt \ setvbuf \ shutdown \ diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index 7221f83dc9..4c71abf18e 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -182,6 +182,7 @@ function_entry basic_functions[] = { PHP_FE(explode, NULL) PHP_FE(implode, NULL) PHP_FE(setlocale, NULL) + PHP_FE(localeconv, NULL) PHP_FE(soundex, NULL) PHP_FE(levenshtein, NULL) PHP_FE(chr, NULL) @@ -713,6 +714,9 @@ PHP_MINIT_FUNCTION(basic) PHP_MINIT(pack)(INIT_FUNC_ARGS_PASSTHRU); PHP_MINIT(browscap)(INIT_FUNC_ARGS_PASSTHRU); PHP_MINIT(lcg)(INIT_FUNC_ARGS_PASSTHRU); +#ifdef ZTS + PHP_MINIT(localeconv)(INIT_FUNC_ARGS_PASSTHRU); +#endif #if HAVE_CRYPT PHP_MINIT(crypt)(INIT_FUNC_ARGS_PASSTHRU); @@ -769,6 +773,9 @@ PHP_MSHUTDOWN_FUNCTION(basic) PHP_MSHUTDOWN(url_scanner_ex)(SHUTDOWN_FUNC_ARGS_PASSTHRU); #endif PHP_MSHUTDOWN(file)(SHUTDOWN_FUNC_ARGS_PASSTHRU); +#ifdef ZTS + PHP_MSHUTDOWN(localeconv)(SHUTDOWN_FUNC_ARGS_PASSTHRU); +#endif return SUCCESS; } diff --git a/ext/standard/php_string.h b/ext/standard/php_string.h index d4d89c8778..807ea2c5d6 100644 --- a/ext/standard/php_string.h +++ b/ext/standard/php_string.h @@ -65,6 +65,7 @@ PHP_FUNCTION(chr); PHP_FUNCTION(ord); PHP_FUNCTION(nl2br); PHP_FUNCTION(setlocale); +PHP_FUNCTION(localeconv); PHP_FUNCTION(stristr); PHP_FUNCTION(chunk_split); PHP_FUNCTION(parse_str); diff --git a/ext/standard/string.c b/ext/standard/string.c index c354e4482c..98e0c3a73b 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -36,6 +36,9 @@ #include "php_globals.h" #include "basic_functions.h" #include "php_smart_str.h" +#ifdef ZTS +#include "TSRM.h" +#endif #define STR_PAD_LEFT 0 #define STR_PAD_RIGHT 1 @@ -53,6 +56,17 @@ void register_string_constants(INIT_FUNC_ARGS) REGISTER_LONG_CONSTANT("PATHINFO_BASENAME", PHP_PATHINFO_BASENAME, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("PATHINFO_EXTENSION", PHP_PATHINFO_EXTENSION, CONST_CS | CONST_PERSISTENT); +#ifdef HAVE_LOCALECONV + /* If last members of struct lconv equal CHAR_MAX, no grouping is done */ + +/* This is bad, but since we are going to be hardcoding in the POSIX stuff anyway... */ +# ifndef HAVE_LIMITS_H +# define CHAR_MAX 127 +# endif + + REGISTER_LONG_CONSTANT("CHAR_MAX", CHAR_MAX, CONST_CS | CONST_PERSISTENT); +#endif + #ifdef HAVE_LOCALE_H REGISTER_LONG_CONSTANT("LC_CTYPE", LC_CTYPE, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("LC_NUMERIC", LC_NUMERIC, CONST_CS | CONST_PERSISTENT); @@ -72,6 +86,11 @@ int php_tag_find(char *tag, int len, char *set); /* this is read-only, so it's ok */ static char hexconvtab[] = "0123456789abcdef"; +/* localeconv mutex */ +#ifdef ZTS +static MUTEX_T locale_mutex = NULL; +#endif + static char *php_bin2hex(const unsigned char *old, const size_t oldlen, size_t *newlen) { unsigned char *result = NULL; @@ -92,6 +111,47 @@ static char *php_bin2hex(const unsigned char *old, const size_t oldlen, size_t * return result; } +#ifdef HAVE_LOCALECONV +/* glibc's localeconv is not reentrant, so lets make it so ... sorta */ +struct lconv *localeconv_r(struct lconv *out) +{ + struct lconv *res; + +# ifdef ZTS + tsrm_mutex_lock( locale_mutex ); +# endif + + /* localeconv doesn't return an error condition */ + res = localeconv(); + + *out = *res; + +# ifdef ZTS + tsrm_mutex_unlock( locale_mutex ); +# endif + + return out; +} + +# ifdef ZTS +PHP_MINIT_FUNCTION(localeconv) +{ + locale_mutex = tsrm_mutex_alloc(); + + return SUCCESS; +} + +PHP_MSHUTDOWN_FUNCTION(localeconv) +{ + tsrm_mutex_free( locale_mutex ); + + locale_mutex = NULL; + + return SUCCESS; +} +# endif +#endif + /* {{{ proto string bin2hex(string data) Converts the binary representation of data to hex */ PHP_FUNCTION(bin2hex) @@ -2805,6 +2865,96 @@ PHP_FUNCTION(strnatcmp) } /* }}} */ +/* {{{ proto array localeconv( void ) + Returns all the information stored in the lconv struct defined + in locale.h based on the currently selected locale */ +PHP_FUNCTION(localeconv) +{ + zval *grouping, *mon_grouping; + int len, i; + + MAKE_STD_ZVAL(grouping); + MAKE_STD_ZVAL(mon_grouping); + + /* We don't need no stinkin' parameters... */ + if (ZEND_NUM_ARGS() > 0) { + WRONG_PARAM_COUNT; + } + + if (array_init(return_value) == FAILURE) { + RETURN_FALSE; + } + + if (array_init(grouping) == FAILURE || array_init(mon_grouping) == FAILURE) { + RETURN_FALSE; + } + +#ifdef HAVE_LOCALECONV + { + struct lconv currlocdata; + + localeconv_r( &currlocdata ); + + /* Grab the grouping data out of the array */ + len = strlen(currlocdata.grouping); + + for (i=0;ivalue.ht, "grouping", 9, &grouping, sizeof(zval *), NULL); + zend_hash_update(return_value->value.ht, "mon_grouping", 13, &mon_grouping, sizeof(zval *), NULL); +} + /* {{{ proto int strnatcasecmp(string s1, string s2) Returns the result of case-insensitive string comparison using 'natural' algorithm */ diff --git a/main/config.w32.h b/main/config.w32.h index 8bac9868c8..4e042ee680 100644 --- a/main/config.w32.h +++ b/main/config.w32.h @@ -226,6 +226,8 @@ /* Define if you have the setlocale function. */ #define HAVE_SETLOCALE 1 +#define HAVE_LOCALECONV 1 + #define HAVE_LOCALE_H 1 /* Define if you have the setvbuf function. */ -- 2.40.0