From: Bruno Haible Date: Sat, 4 Oct 2008 14:54:19 +0000 (+0000) Subject: Use the range flag to allow some specific plural form translations. X-Git-Tag: v0.18~300 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e45a90c63083f89ebc8ecdd979ed462fa8fa1ca0;p=thirdparty%2Fgettext.git Use the range flag to allow some specific plural form translations. --- diff --git a/gettext-tools/src/ChangeLog b/gettext-tools/src/ChangeLog index a1171cb9b..e1cfad645 100644 --- a/gettext-tools/src/ChangeLog +++ b/gettext-tools/src/ChangeLog @@ -1,3 +1,21 @@ +2008-10-04 Bruno Haible + + * plural-distrib.h (struct plural_distribution): New field 'histogram'. + * format.h (check_msgid_msgstr_format_i, check_msgid_msgstr_format): + Add range argument. + * format.c (check_msgid_msgstr_format_i): Add range argument. Set + strict_checking to false if, due to the range, the plural forms applies + to only one value of n. + (check_msgid_msgstr_format): Add range argument. + * msgl-check.c (plural_expression_histogram): New function. + (check_plural_eval, check_plural): Update. + (check_pair): Pass the range to check_msgid_msgstr_format. + (check_message_list): Update. + * msgmerge.c (message_merge): Pass the range to + check_msgid_msgstr_format_i. + Reported by Anatoly Techtonik + via . + 2008-10-04 Bruno Haible * message.h (struct argument_range): New type. diff --git a/gettext-tools/src/format.c b/gettext-tools/src/format.c index cd56afee5..592a398dd 100644 --- a/gettext-tools/src/format.c +++ b/gettext-tools/src/format.c @@ -64,6 +64,7 @@ int check_msgid_msgstr_format_i (const char *msgid, const char *msgid_plural, const char *msgstr, size_t msgstr_len, size_t i, + struct argument_range range, const struct plural_distribution *distribution, formatstring_error_logger_t error_logger) { @@ -112,19 +113,24 @@ check_msgid_msgstr_format_i (const char *msgid, const char *msgid_plural, /* Use strict checking (require same number of format directives on both sides) if the message has no plurals, or if msgid_plural exists but on the msgstr[] side - there is only msgstr[0], or if plural_distribution[j] + there is only msgstr[0], or if distribution->often[j] indicates that the variant applies to infinitely many - values of N. + values of N and the N range is not restricted in a way + that the variant applies to only one N. Use relaxed checking when there are at least two - msgstr[] forms and the plural_distribution array does - not give more precise information. */ + msgstr[] forms and the distribution does not give more + precise information. */ bool strict_checking = (msgid_plural == NULL || !has_plural_translations || (distribution != NULL && distribution->often != NULL && j < distribution->often_length - && distribution->often[j])); + && distribution->often[j] + && !(has_range_p (range) + && distribution->histogram (distribution, + range.min, range.max, j) + <= 1))); if (parser->check (msgid_descr, msgstr_descr, strict_checking, @@ -159,6 +165,7 @@ int check_msgid_msgstr_format (const char *msgid, const char *msgid_plural, const char *msgstr, size_t msgstr_len, const enum is_format is_format[NFORMATS], + struct argument_range range, const struct plural_distribution *distribution, formatstring_error_logger_t error_logger) { @@ -175,6 +182,7 @@ check_msgid_msgstr_format (const char *msgid, const char *msgid_plural, if (possible_format_p (is_format[i])) seen_errors += check_msgid_msgstr_format_i (msgid, msgid_plural, msgstr, msgstr_len, i, + range, distribution, error_logger); diff --git a/gettext-tools/src/format.h b/gettext-tools/src/format.h index 38bbadcfe..8de202ae0 100644 --- a/gettext-tools/src/format.h +++ b/gettext-tools/src/format.h @@ -146,6 +146,7 @@ extern int check_msgid_msgstr_format_i (const char *msgid, const char *msgid_plural, const char *msgstr, size_t msgstr_len, size_t i, + struct argument_range range, const struct plural_distribution *distribution, formatstring_error_logger_t error_logger); @@ -156,6 +157,7 @@ extern int check_msgid_msgstr_format (const char *msgid, const char *msgid_plural, const char *msgstr, size_t msgstr_len, const enum is_format is_format[NFORMATS], + struct argument_range range, const struct plural_distribution *distribution, formatstring_error_logger_t error_logger); diff --git a/gettext-tools/src/msgl-check.c b/gettext-tools/src/msgl-check.c index 00c93c0f0..74737cf76 100644 --- a/gettext-tools/src/msgl-check.c +++ b/gettext-tools/src/msgl-check.c @@ -47,6 +47,46 @@ #define SIZEOF(a) (sizeof(a) / sizeof(a[0])) +/* Evaluates the plural formula for min <= n <= max + and returns the estimated number of times the value j was assumed. */ +static unsigned int +plural_expression_histogram (const struct plural_distribution *self, + int min, int max, unsigned long j) +{ + if (min < 0) + min = 0; + /* Limit the number of evaluations. Nothing interesting happens beyond + 1000. */ + if (max - min > 1000) + max = min + 1000; + if (min <= max) + { + const struct expression *expr = self->expr; + unsigned long n; + unsigned int count; + + /* Protect against arithmetic exceptions. */ + install_sigfpe_handler (); + + count = 0; + for (n = min; n <= max; n++) + { + unsigned long val = plural_eval (expr, n); + + if (val == j) + count++; + } + + /* End of protection against arithmetic exceptions. */ + uninstall_sigfpe_handler (); + + return count; + } + else + return 0; +} + + /* Check the values returned by plural_eval. Signals the errors through po_xerror. Return the number of errors that were seen. @@ -125,6 +165,7 @@ check_plural_eval (const struct expression *plural_expr, distribution->expr = plural_expr; distribution->often = array; distribution->often_length = (array != NULL ? nplurals_value : 0); + distribution->histogram = plural_expression_histogram; return 0; } @@ -260,6 +301,7 @@ check_plural (message_list_ty *mlp, struct plural_distribution *distributionp) distribution.expr = NULL; distribution.often = NULL; distribution.often_length = 0; + distribution.histogram = NULL; for (j = 0; j < mlp->nitems; j++) { message_ty *mp = mlp->item[j]; @@ -475,6 +517,7 @@ check_plural (message_list_ty *mlp, struct plural_distribution *distributionp) distribution.often = array; } distribution.often_length = 2; + distribution.histogram = plural_expression_histogram; } /* distribution is not needed if we report errors. @@ -645,7 +688,7 @@ plural handling is a GNU gettext extension")); curr_msgid_pos = *msgid_pos; seen_errors += check_msgid_msgstr_format (msgid, msgid_plural, msgstr, msgstr_len, - is_format, distribution, + is_format, mp->range, distribution, formatstring_error_logger); } @@ -832,6 +875,7 @@ check_message_list (message_list_ty *mlp, distribution.expr = NULL; distribution.often = NULL; distribution.often_length = 0; + distribution.histogram = NULL; if (check_header) seen_errors += check_plural (mlp, &distribution); diff --git a/gettext-tools/src/msgmerge.c b/gettext-tools/src/msgmerge.c index 4ab4c5e0b..352c59409 100644 --- a/gettext-tools/src/msgmerge.c +++ b/gettext-tools/src/msgmerge.c @@ -1271,7 +1271,7 @@ message_merge (message_ty *def, message_ty *ref, bool force_fuzzy, && possible_format_p (ref->is_format[i]) && !possible_format_p (def->is_format[i]) && check_msgid_msgstr_format_i (ref->msgid, ref->msgid_plural, - msgstr, msgstr_len, i, + msgstr, msgstr_len, i, ref->range, distribution, silent_error_logger) > 0) result->is_fuzzy = true; diff --git a/gettext-tools/src/plural-distrib.h b/gettext-tools/src/plural-distrib.h index f25f91891..decde3c2c 100644 --- a/gettext-tools/src/plural-distrib.h +++ b/gettext-tools/src/plural-distrib.h @@ -41,6 +41,11 @@ struct plural_distribution /* The length of the OFTEN array. */ unsigned long often_length; + + /* A function which evaluates the plural formula for min <= n <= max + and returns the estimated number of times the value j was assumed. */ + unsigned int (*histogram) (const struct plural_distribution *self, + int min, int max, unsigned long j); };