ext/gettext: update arguments handling.

using zend_string whenever relevant too.

Close GH-13582.
This commit is contained in:
David Carlier 2024-03-03 11:53:49 +00:00
parent 782af7a963
commit 5823a96f1e
No known key found for this signature in database
GPG key ID: CEF290BB40D2086B
4 changed files with 99 additions and 68 deletions

View file

@ -81,18 +81,20 @@ PHP_MINFO_FUNCTION(php_gettext)
/* {{{ Set the textdomain to "domain". Returns the current domain */
PHP_FUNCTION(textdomain)
{
char *domain_name = NULL, *retval;
char *domain_name = NULL, *retval = NULL;
zend_string *domain = NULL;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "S!", &domain) == FAILURE) {
RETURN_THROWS();
}
ZEND_PARSE_PARAMETERS_START(0, 1)
Z_PARAM_OPTIONAL
Z_PARAM_STR_OR_NULL(domain)
ZEND_PARSE_PARAMETERS_END();
if (domain != NULL) {
PHP_GETTEXT_DOMAIN_LENGTH_CHECK(1, ZSTR_LEN(domain))
}
if (domain != NULL && !zend_string_equals_literal(domain, "0")) {
if (zend_string_equals_literal(domain, "0")) {
zend_argument_value_error(1, "cannot be zero");
RETURN_THROWS();
}
domain_name = ZSTR_VAL(domain);
}
@ -105,7 +107,7 @@ PHP_FUNCTION(textdomain)
/* {{{ Return the translation of msgid for the current domain, or msgid unaltered if a translation does not exist */
PHP_FUNCTION(gettext)
{
char *msgstr;
char *msgstr = NULL;
zend_string *msgid;
ZEND_PARSE_PARAMETERS_START(1, 1)
@ -126,12 +128,13 @@ PHP_FUNCTION(gettext)
/* {{{ Return the translation of msgid for domain_name, or msgid unaltered if a translation does not exist */
PHP_FUNCTION(dgettext)
{
char *msgstr;
char *msgstr = NULL;
zend_string *domain, *msgid;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS", &domain, &msgid) == FAILURE) {
RETURN_THROWS();
}
ZEND_PARSE_PARAMETERS_START(2, 2)
Z_PARAM_STR(domain)
Z_PARAM_STR(msgid)
ZEND_PARSE_PARAMETERS_END();
PHP_GETTEXT_DOMAIN_LENGTH_CHECK(1, ZSTR_LEN(domain))
PHP_GETTEXT_LENGTH_CHECK(2, ZSTR_LEN(msgid))
@ -149,13 +152,15 @@ PHP_FUNCTION(dgettext)
/* {{{ Return the translation of msgid for domain_name and category, or msgid unaltered if a translation does not exist */
PHP_FUNCTION(dcgettext)
{
char *msgstr;
char *msgstr = NULL;
zend_string *domain, *msgid;
zend_long category;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "SSl", &domain, &msgid, &category) == FAILURE) {
RETURN_THROWS();
}
ZEND_PARSE_PARAMETERS_START(3, 3)
Z_PARAM_STR(domain)
Z_PARAM_STR(msgid)
Z_PARAM_LONG(category)
ZEND_PARSE_PARAMETERS_END();
PHP_GETTEXT_DOMAIN_LENGTH_CHECK(1, ZSTR_LEN(domain))
PHP_GETTEXT_LENGTH_CHECK(2, ZSTR_LEN(msgid))
@ -174,19 +179,24 @@ PHP_FUNCTION(dcgettext)
/* {{{ Bind to the text domain domain_name, looking for translations in dir. Returns the current domain */
PHP_FUNCTION(bindtextdomain)
{
char *domain;
size_t domain_len;
zend_string *dir = NULL;
zend_string *domain, *dir = NULL;
char *retval, dir_name[MAXPATHLEN];
if (zend_parse_parameters(ZEND_NUM_ARGS(), "sS!", &domain, &domain_len, &dir) == FAILURE) {
ZEND_PARSE_PARAMETERS_START(1, 2)
Z_PARAM_STR(domain)
Z_PARAM_OPTIONAL
Z_PARAM_STR_OR_NULL(dir)
ZEND_PARSE_PARAMETERS_END();
PHP_GETTEXT_DOMAIN_LENGTH_CHECK(1, ZSTR_LEN(domain))
if (!ZSTR_LEN(domain)) {
zend_argument_value_error(1, "cannot be empty");
RETURN_THROWS();
}
PHP_GETTEXT_DOMAIN_LENGTH_CHECK(1, domain_len)
if (dir == NULL) {
RETURN_STRING(bindtextdomain(domain, NULL));
RETURN_STRING(bindtextdomain(ZSTR_VAL(domain), NULL));
}
if (ZSTR_LEN(dir) != 0 && !zend_string_equals_literal(dir, "0")) {
@ -197,7 +207,7 @@ PHP_FUNCTION(bindtextdomain)
RETURN_FALSE;
}
retval = bindtextdomain(domain, dir_name);
retval = bindtextdomain(ZSTR_VAL(domain), dir_name);
RETURN_STRING(retval);
}
@ -207,18 +217,20 @@ PHP_FUNCTION(bindtextdomain)
/* {{{ Plural version of gettext() */
PHP_FUNCTION(ngettext)
{
char *msgid1, *msgid2, *msgstr;
size_t msgid1_len, msgid2_len;
char *msgstr = NULL;
zend_string *msgid1, *msgid2;
zend_long count;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "ssl", &msgid1, &msgid1_len, &msgid2, &msgid2_len, &count) == FAILURE) {
RETURN_THROWS();
}
ZEND_PARSE_PARAMETERS_START(3, 3)
Z_PARAM_STR(msgid1)
Z_PARAM_STR(msgid2)
Z_PARAM_LONG(count)
ZEND_PARSE_PARAMETERS_END();
PHP_GETTEXT_LENGTH_CHECK(1, msgid1_len)
PHP_GETTEXT_LENGTH_CHECK(2, msgid2_len)
PHP_GETTEXT_LENGTH_CHECK(1, ZSTR_LEN(msgid1))
PHP_GETTEXT_LENGTH_CHECK(2, ZSTR_LEN(msgid2))
msgstr = ngettext(msgid1, msgid2, count);
msgstr = ngettext(ZSTR_VAL(msgid1), ZSTR_VAL(msgid2), count);
ZEND_ASSERT(msgstr);
RETURN_STRING(msgstr);
@ -230,20 +242,22 @@ PHP_FUNCTION(ngettext)
/* {{{ Plural version of dgettext() */
PHP_FUNCTION(dngettext)
{
char *domain, *msgid1, *msgid2, *msgstr = NULL;
size_t domain_len, msgid1_len, msgid2_len;
char *msgstr = NULL;
zend_string *domain, *msgid1, *msgid2;
zend_long count;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "sssl", &domain, &domain_len,
&msgid1, &msgid1_len, &msgid2, &msgid2_len, &count) == FAILURE) {
RETURN_THROWS();
}
ZEND_PARSE_PARAMETERS_START(4, 4)
Z_PARAM_STR(domain)
Z_PARAM_STR(msgid1)
Z_PARAM_STR(msgid2)
Z_PARAM_LONG(count)
ZEND_PARSE_PARAMETERS_END();
PHP_GETTEXT_DOMAIN_LENGTH_CHECK(1, domain_len)
PHP_GETTEXT_LENGTH_CHECK(2, msgid1_len)
PHP_GETTEXT_LENGTH_CHECK(3, msgid2_len)
PHP_GETTEXT_DOMAIN_LENGTH_CHECK(1, ZSTR_LEN(domain))
PHP_GETTEXT_LENGTH_CHECK(2, ZSTR_LEN(msgid1))
PHP_GETTEXT_LENGTH_CHECK(3, ZSTR_LEN(msgid2))
msgstr = dngettext(domain, msgid1, msgid2, count);
msgstr = dngettext(ZSTR_VAL(domain), ZSTR_VAL(msgid1), ZSTR_VAL(msgid2), count);
ZEND_ASSERT(msgstr);
RETURN_STRING(msgstr);
@ -255,23 +269,26 @@ PHP_FUNCTION(dngettext)
/* {{{ Plural version of dcgettext() */
PHP_FUNCTION(dcngettext)
{
char *domain, *msgid1, *msgid2, *msgstr = NULL;
size_t domain_len, msgid1_len, msgid2_len;
char *msgstr = NULL;
zend_string *domain, *msgid1, *msgid2;
zend_long count, category;
RETVAL_FALSE;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "sssll", &domain, &domain_len,
&msgid1, &msgid1_len, &msgid2, &msgid2_len, &count, &category) == FAILURE) {
RETURN_THROWS();
}
ZEND_PARSE_PARAMETERS_START(5, 5)
Z_PARAM_STR(domain)
Z_PARAM_STR(msgid1)
Z_PARAM_STR(msgid2)
Z_PARAM_LONG(count)
Z_PARAM_LONG(category)
ZEND_PARSE_PARAMETERS_END();
PHP_GETTEXT_DOMAIN_LENGTH_CHECK(1, domain_len)
PHP_GETTEXT_LENGTH_CHECK(2, msgid1_len)
PHP_GETTEXT_LENGTH_CHECK(3, msgid2_len)
PHP_GETTEXT_DOMAIN_LENGTH_CHECK(1, ZSTR_LEN(domain))
PHP_GETTEXT_LENGTH_CHECK(2, ZSTR_LEN(msgid1))
PHP_GETTEXT_LENGTH_CHECK(3, ZSTR_LEN(msgid2))
PHP_DCGETTEXT_CATEGORY_CHECK(5, category)
msgstr = dcngettext(domain, msgid1, msgid2, count, category);
msgstr = dcngettext(ZSTR_VAL(domain), ZSTR_VAL(msgid1), ZSTR_VAL(msgid2), count, category);
ZEND_ASSERT(msgstr);
RETURN_STRING(msgstr);
@ -284,16 +301,23 @@ PHP_FUNCTION(dcngettext)
/* {{{ Specify the character encoding in which the messages from the DOMAIN message catalog will be returned. */
PHP_FUNCTION(bind_textdomain_codeset)
{
char *domain, *codeset = NULL, *retval = NULL;
size_t domain_len, codeset_len;
char *retval = NULL;
zend_string *domain, *codeset = NULL;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss!", &domain, &domain_len, &codeset, &codeset_len) == FAILURE) {
ZEND_PARSE_PARAMETERS_START(1, 2)
Z_PARAM_STR(domain)
Z_PARAM_OPTIONAL
Z_PARAM_STR_OR_NULL(codeset)
ZEND_PARSE_PARAMETERS_END();
PHP_GETTEXT_DOMAIN_LENGTH_CHECK(1, ZSTR_LEN(domain))
if (!ZSTR_LEN(domain)) {
zend_argument_value_error(1, "cannot be empty");
RETURN_THROWS();
}
PHP_GETTEXT_DOMAIN_LENGTH_CHECK(1, domain_len)
retval = bind_textdomain_codeset(domain, codeset);
retval = bind_textdomain_codeset(ZSTR_VAL(domain), codeset ? ZSTR_VAL(codeset) : NULL);
if (!retval) {
RETURN_FALSE;

View file

@ -3,7 +3,7 @@
/** @generate-class-entries */
/** @refcount 1 */
function textdomain(?string $domain): string {}
function textdomain(?string $domain = null): string {}
/** @refcount 1 */
function gettext(string $message): string {}
@ -18,7 +18,7 @@ function dgettext(string $domain, string $message): string {}
function dcgettext(string $domain, string $message, int $category): string {}
/** @refcount 1 */
function bindtextdomain(string $domain, ?string $directory): string|false {}
function bindtextdomain(string $domain, ?string $directory = null): string|false {}
#ifdef HAVE_NGETTEXT
/** @refcount 1 */
@ -37,5 +37,5 @@ function dcngettext(string $domain, string $singular, string $plural, int $count
#ifdef HAVE_BIND_TEXTDOMAIN_CODESET
/** @refcount 1 */
function bind_textdomain_codeset(string $domain, ?string $codeset): string|false {}
function bind_textdomain_codeset(string $domain, ?string $codeset = null): string|false {}
#endif

View file

@ -1,8 +1,8 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: 864b3389d4f99b0d7302ae399544e6fb9fb80b7e */
* Stub hash: c675dc9492943bbac106c5906b75c31436964423 */
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_textdomain, 0, 1, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, domain, IS_STRING, 1)
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_textdomain, 0, 0, IS_STRING, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, domain, IS_STRING, 1, "null")
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_gettext, 0, 1, IS_STRING, 0)
@ -22,9 +22,9 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_dcgettext, 0, 3, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, category, IS_LONG, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_bindtextdomain, 0, 2, MAY_BE_STRING|MAY_BE_FALSE)
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_bindtextdomain, 0, 1, MAY_BE_STRING|MAY_BE_FALSE)
ZEND_ARG_TYPE_INFO(0, domain, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, directory, IS_STRING, 1)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, directory, IS_STRING, 1, "null")
ZEND_END_ARG_INFO()
#if defined(HAVE_NGETTEXT)
@ -55,9 +55,9 @@ ZEND_END_ARG_INFO()
#endif
#if defined(HAVE_BIND_TEXTDOMAIN_CODESET)
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_bind_textdomain_codeset, 0, 2, MAY_BE_STRING|MAY_BE_FALSE)
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_bind_textdomain_codeset, 0, 1, MAY_BE_STRING|MAY_BE_FALSE)
ZEND_ARG_TYPE_INFO(0, domain, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, codeset, IS_STRING, 1)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, codeset, IS_STRING, 1, "null")
ZEND_END_ARG_INFO()
#endif

View file

@ -19,6 +19,12 @@ echo textdomain('test'), "\n";
echo textdomain(null), "\n";
echo textdomain('foo'), "\n";
try {
textdomain('0');
} catch (\ValueError $e) {
echo $e->getMessage() . PHP_EOL;
}
try {
textdomain('');
} catch (\ValueError $e) {
@ -29,6 +35,7 @@ try {
test
test
foo
textdomain(): Argument #1 ($domain) cannot be zero
textdomain(): Argument #1 ($domain) cannot be empty
--CREDITS--
Christian Weiske, cweiske@php.net