diff options
| author | Sean Bright <elixer@php.net> | 2001-01-14 16:36:30 +0000 | 
|---|---|---|
| committer | Sean Bright <elixer@php.net> | 2001-01-14 16:36:30 +0000 | 
| commit | 40f3524247f36e6f485f3f1247a222cedab5cbdf (patch) | |
| tree | e09bc8dd354a46a1435cb5effe697b98c843f971 | |
| parent | 5311bfa5c5f0d72be0c8b7ead00e30138f560863 (diff) | |
| download | php-git-40f3524247f36e6f485f3f1247a222cedab5cbdf.tar.gz | |
Added localeconv() function.  Operates similarly to localeconv() defined in
locale.h.  Should work well under non-ZTS as well as ZTS.
| -rw-r--r-- | configure.in | 1 | ||||
| -rw-r--r-- | ext/standard/basic_functions.c | 7 | ||||
| -rw-r--r-- | ext/standard/php_string.h | 1 | ||||
| -rw-r--r-- | ext/standard/string.c | 150 | ||||
| -rw-r--r-- | main/config.w32.h | 2 | 
5 files changed, 161 insertions, 0 deletions
| 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;i<len;i++) { +			add_index_long(grouping, i, currlocdata.grouping[i]); +		} + +		/* Grab the monetary grouping data out of the array */ +		len = strlen(currlocdata.mon_grouping); + +		for (i=0;i<len;i++) { +			add_index_long(mon_grouping, i, currlocdata.mon_grouping[i]); +		} + +		add_assoc_string(return_value, "decimal_point",     currlocdata.decimal_point,     1); +		add_assoc_string(return_value, "thousands_sep",     currlocdata.thousands_sep,     1); +		add_assoc_string(return_value, "int_curr_symbol",   currlocdata.int_curr_symbol,   1); +		add_assoc_string(return_value, "currency_symbol",   currlocdata.currency_symbol,   1); +		add_assoc_string(return_value, "mon_decimal_point", currlocdata.mon_decimal_point, 1); +		add_assoc_string(return_value, "mon_thousands_sep", currlocdata.mon_thousands_sep, 1); +		add_assoc_string(return_value, "positive_sign",     currlocdata.positive_sign,     1); +		add_assoc_string(return_value, "negative_sign",     currlocdata.negative_sign,     1); +		add_assoc_long(  return_value, "int_frac_digits",   currlocdata.int_frac_digits     ); +		add_assoc_long(  return_value, "frac_digits",       currlocdata.frac_digits         ); +		add_assoc_long(  return_value, "p_cs_precedes",     currlocdata.p_cs_precedes       ); +		add_assoc_long(  return_value, "p_sep_by_space",    currlocdata.p_sep_by_space      ); +		add_assoc_long(  return_value, "n_cs_precedes",     currlocdata.n_cs_precedes       ); +		add_assoc_long(  return_value, "n_sep_by_space",    currlocdata.n_sep_by_space      ); +		add_assoc_long(  return_value, "p_sign_posn",       currlocdata.p_sign_posn         ); +		add_assoc_long(  return_value, "n_sign_posn",       currlocdata.n_sign_posn         ); +	} +#else +	/* Ok, it doesn't look like we have locale info floating around, so I guess it +	   wouldn't hurt to just go ahead and return the POSIX locale information?  */ + +	add_index_long(grouping, 0, -1); +	add_index_long(mon_grouping, 0, -1); + +	add_assoc_string(return_value, "decimal_point",     "\x2E", 1); +	add_assoc_string(return_value, "thousands_sep",     "",     1); +	add_assoc_string(return_value, "int_curr_symbol",   "",     1); +	add_assoc_string(return_value, "currency_symbol",   "",     1); +	add_assoc_string(return_value, "mon_decimal_point", "\x2E", 1); +	add_assoc_string(return_value, "mon_thousands_sep", "",     1); +	add_assoc_string(return_value, "positive_sign",     "",     1); +	add_assoc_string(return_value, "negative_sign",     "",     1); +	add_assoc_long(  return_value, "int_frac_digits",   CHAR_MAX ); +	add_assoc_long(  return_value, "frac_digits",       CHAR_MAX ); +	add_assoc_long(  return_value, "p_cs_precedes",     CHAR_MAX ); +	add_assoc_long(  return_value, "p_sep_by_space",    CHAR_MAX ); +	add_assoc_long(  return_value, "n_cs_precedes",     CHAR_MAX ); +	add_assoc_long(  return_value, "n_sep_by_space",    CHAR_MAX ); +	add_assoc_long(  return_value, "p_sign_posn",       CHAR_MAX ); +	add_assoc_long(  return_value, "n_sign_posn",       CHAR_MAX ); +#endif + +	zend_hash_update(return_value->value.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.  */ | 
