From: Bruno Haible Date: Sun, 29 Sep 2019 18:52:48 +0000 (+0200) Subject: xgettext: Signal a warning when the same msgid is used with and without plural. X-Git-Tag: v0.21~157 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b0d8038c1fc6cd0f549136674966388d2f562c36;p=thirdparty%2Fgettext.git xgettext: Signal a warning when the same msgid is used with and without plural. * gettext-tools/src/xg-message.h (remember_a_message): Add pluralp argument. * gettext-tools/src/xg-message.c (remember_a_message): Likewise. Signal a warning when the same msgid is used with and without plural. * gettext-tools/src/xg-arglist-parser.c (arglist_parser_done): Update remember_a_message invocation. * gettext-tools/src/xgettext.c (xgettext_its_extract_callback): Update remember_a_message invocations. * gettext-tools/src/x-awk.c (extract_parenthesized): Likewise. * gettext-tools/src/x-c.c (extract_parenthesized): Likewise. * gettext-tools/src/x-csharp.c (extract_parenthesized): Likewise. * gettext-tools/src/x-desktop.c (extract_desktop_handle_pair): Likewise. * gettext-tools/src/x-elisp.c (read_object): Likewise. * gettext-tools/src/x-java.c (extract_parenthesized): Likewise. * gettext-tools/src/x-javascript.c (extract_balanced): Likewise. * gettext-tools/src/x-librep.c (read_object): Likewise. * gettext-tools/src/x-lisp.c (read_object): Likewise. * gettext-tools/src/x-lua.c (extract_balanced): Likewise. * gettext-tools/src/x-perl.c (extract_variable, interpolate_keywords, extract_balanced): Likewise. * gettext-tools/src/x-php.c (extract_balanced): Likewise. * gettext-tools/src/x-python.c (extract_balanced): Likewise. * gettext-tools/src/x-rst.c (extract_rst, extract_rsj): Likewise. * gettext-tools/src/x-scheme.c (read_object): Likewise. * gettext-tools/src/x-sh.c (read_word, read_command): Likewise. * gettext-tools/src/x-tcl.c (read_command): Likewise. * gettext-tools/src/x-vala.c (extract_balanced): Likewise. * gettext-tools/src/x-smalltalk.c (phase3_pushback, phase3_pushback_length): New variables. (phase3_get): Renamed from x_smalltalk_lex. Handle pushback. (phase3_unget): New function. (extract_smalltalk): Update remember_a_message invocations through a lookahead of one token. * gettext-tools/src/x-ycp.c (phase8_pushback, phase8_pushback_length): New variables. (phase8_get): Handle pushback. (phase8_unget): New function. (extract_parenthesized): Update remember_a_message invocations through a lookahead of one token. * gettext-tools/tests/xgettext-15: New file. * gettext-tools/tests/Makefile.am (TESTS): Add it. --- diff --git a/gettext-tools/src/x-awk.c b/gettext-tools/src/x-awk.c index da74c0042..af066ff15 100644 --- a/gettext-tools/src/x-awk.c +++ b/gettext-tools/src/x-awk.c @@ -1,5 +1,5 @@ /* xgettext awk backend. - Copyright (C) 2002-2003, 2005-2009, 2018 Free Software Foundation, Inc. + Copyright (C) 2002-2003, 2005-2009, 2018-2019 Free Software Foundation, Inc. This file was written by Bruno Haible , 2002. @@ -789,8 +789,9 @@ extract_parenthesized (message_list_ty *mlp, pos.line_number = token.line_number; if (extract_all) - remember_a_message (mlp, NULL, token.string, false, inner_context, - &pos, NULL, savable_comment, false); + remember_a_message (mlp, NULL, token.string, false, false, + inner_context, &pos, + NULL, savable_comment, false); else { mixed_string_ty *ms = @@ -814,8 +815,9 @@ extract_parenthesized (message_list_ty *mlp, pos.file_name = logical_file_name; pos.line_number = token.line_number; - remember_a_message (mlp, NULL, token.string, false, inner_context, - &pos, NULL, savable_comment, false); + remember_a_message (mlp, NULL, token.string, false, false, + inner_context, &pos, + NULL, savable_comment, false); } next_is_argument = false; next_context_iter = null_context_list_iterator; diff --git a/gettext-tools/src/x-c.c b/gettext-tools/src/x-c.c index a81b85101..de99a707c 100644 --- a/gettext-tools/src/x-c.c +++ b/gettext-tools/src/x-c.c @@ -1,5 +1,5 @@ /* xgettext C/C++/ObjectiveC backend. - Copyright (C) 1995-1998, 2000-2009, 2012-2015, 2018 Free Software Foundation, Inc. + Copyright (C) 1995-1998, 2000-2009, 2012-2015, 2018-2019 Free Software Foundation, Inc. This file was written by Peter Miller @@ -2297,8 +2297,9 @@ extract_parenthesized (message_list_ty *mlp, { char *string = mixed_string_contents (token.mixed_string); mixed_string_free (token.mixed_string); - remember_a_message (mlp, NULL, string, true, inner_context, - &token.pos, NULL, token.comment, false); + remember_a_message (mlp, NULL, string, true, false, + inner_context, &token.pos, + NULL, token.comment, false); } else arglist_parser_remember (argparser, arg, token.mixed_string, diff --git a/gettext-tools/src/x-csharp.c b/gettext-tools/src/x-csharp.c index 4e3c5904b..71678b3ef 100644 --- a/gettext-tools/src/x-csharp.c +++ b/gettext-tools/src/x-csharp.c @@ -2009,8 +2009,9 @@ extract_parenthesized (message_list_ty *mlp, token_type_ty terminator, { char *string = mixed_string_contents (token.mixed_string); mixed_string_free (token.mixed_string); - remember_a_message (mlp, NULL, string, true, inner_context, - &pos, NULL, token.comment, true); + remember_a_message (mlp, NULL, string, true, false, + inner_context, &pos, + NULL, token.comment, true); } else arglist_parser_remember (argparser, arg, token.mixed_string, diff --git a/gettext-tools/src/x-desktop.c b/gettext-tools/src/x-desktop.c index 93e206ee9..6efcaa62d 100644 --- a/gettext-tools/src/x-desktop.c +++ b/gettext-tools/src/x-desktop.c @@ -128,7 +128,7 @@ extract_desktop_handle_pair (struct desktop_reader_ty *reader, remember_a_message (extract_reader->mlp, NULL, desktop_unescape_string (value, is_list), false, - null_context, key_pos, + false, null_context, key_pos, NULL, savable_comment, false); } savable_comment_reset (); diff --git a/gettext-tools/src/x-elisp.c b/gettext-tools/src/x-elisp.c index 90a45c455..c85739fe3 100644 --- a/gettext-tools/src/x-elisp.c +++ b/gettext-tools/src/x-elisp.c @@ -904,8 +904,8 @@ read_object (struct object *op, bool first_in_list, bool new_backquote_flag, pos.file_name = logical_file_name; pos.line_number = op->line_number_at_start; remember_a_message (mlp, NULL, string_of_object (op), false, - null_context, &pos, NULL, savable_comment, - false); + false, null_context, &pos, + NULL, savable_comment, false); } last_non_comment_line = line_number; return; diff --git a/gettext-tools/src/x-java.c b/gettext-tools/src/x-java.c index 8c0ee331f..64a7f2b64 100644 --- a/gettext-tools/src/x-java.c +++ b/gettext-tools/src/x-java.c @@ -1647,8 +1647,9 @@ extract_parenthesized (message_list_ty *mlp, token_type_ty terminator, { char *string = mixed_string_contents (token.mixed_string); mixed_string_free (token.mixed_string); - remember_a_message (mlp, NULL, string, true, inner_context, - &pos, NULL, token.comment, true); + remember_a_message (mlp, NULL, string, true, false, + inner_context, &pos, + NULL, token.comment, true); } else arglist_parser_remember (argparser, arg, token.mixed_string, diff --git a/gettext-tools/src/x-javascript.c b/gettext-tools/src/x-javascript.c index 514fd3063..4823b295c 100644 --- a/gettext-tools/src/x-javascript.c +++ b/gettext-tools/src/x-javascript.c @@ -1661,8 +1661,9 @@ extract_balanced (message_list_ty *mlp, { char *string = mixed_string_contents (token.mixed_string); mixed_string_free (token.mixed_string); - remember_a_message (mlp, NULL, string, true, inner_context, - &pos, NULL, token.comment, true); + remember_a_message (mlp, NULL, string, true, false, + inner_context, &pos, + NULL, token.comment, true); } else arglist_parser_remember (argparser, arg, token.mixed_string, diff --git a/gettext-tools/src/x-librep.c b/gettext-tools/src/x-librep.c index b516b84c7..d1ad681fc 100644 --- a/gettext-tools/src/x-librep.c +++ b/gettext-tools/src/x-librep.c @@ -840,8 +840,8 @@ read_object (struct object *op, flag_context_ty outer_context) pos.file_name = logical_file_name; pos.line_number = op->line_number_at_start; remember_a_message (mlp, NULL, string_of_object (op), false, - null_context, &pos, NULL, savable_comment, - false); + false, null_context, &pos, + NULL, savable_comment, false); } last_non_comment_line = line_number; return; diff --git a/gettext-tools/src/x-lisp.c b/gettext-tools/src/x-lisp.c index 6dab49049..a436f444c 100644 --- a/gettext-tools/src/x-lisp.c +++ b/gettext-tools/src/x-lisp.c @@ -1200,7 +1200,7 @@ read_object (struct object *op, flag_context_ty outer_context) pos.file_name = logical_file_name; pos.line_number = op->line_number_at_start; remember_a_message (mlp, NULL, string_of_object (op), false, - null_context, &pos, + false, null_context, &pos, NULL, savable_comment, false); } last_non_comment_line = line_number; diff --git a/gettext-tools/src/x-lua.c b/gettext-tools/src/x-lua.c index 5aed25745..25970fea9 100644 --- a/gettext-tools/src/x-lua.c +++ b/gettext-tools/src/x-lua.c @@ -1151,8 +1151,9 @@ extract_balanced (message_list_ty *mlp, token_type_ty delim, pos.line_number = token.line_number; if (extract_all) - remember_a_message (mlp, NULL, token.string, false, inner_context, - &pos, NULL, token.comment, false); + remember_a_message (mlp, NULL, token.string, false, false, + inner_context, &pos, + NULL, token.comment, false); else { mixed_string_ty *ms = diff --git a/gettext-tools/src/x-perl.c b/gettext-tools/src/x-perl.c index 1517cb117..e16f9b608 100644 --- a/gettext-tools/src/x-perl.c +++ b/gettext-tools/src/x-perl.c @@ -1590,8 +1590,8 @@ extract_variable (message_list_ty *mlp, token_ty *tp, int first) pos.file_name = logical_file_name; remember_a_message (mlp, NULL, xstrdup (t1->string), - true, context, &pos, NULL, - savable_comment, true); + true, false, context, &pos, + NULL, savable_comment, true); free_token (t2); free_token (t1); } @@ -2018,8 +2018,8 @@ interpolate_keywords (message_list_ty *mlp, const char *string, int lineno) buffer[bufpos] = '\0'; token.string = xstrdup (buffer); extract_quotelike_pass3 (&token, EXIT_FAILURE); - remember_a_message (mlp, NULL, token.string, true, context, &pos, - NULL, savable_comment, true); + remember_a_message (mlp, NULL, token.string, true, false, context, + &pos, NULL, savable_comment, true); /* FALLTHROUGH */ default: context = null_context; @@ -3304,8 +3304,8 @@ extract_balanced (message_list_ty *mlp, pos.file_name = logical_file_name; pos.line_number = tp->line_number; - remember_a_message (mlp, NULL, string, true, inner_context, &pos, - NULL, tp->comment, true); + remember_a_message (mlp, NULL, string, true, false, inner_context, + &pos, NULL, tp->comment, true); } else if (!skip_until_comma) { diff --git a/gettext-tools/src/x-php.c b/gettext-tools/src/x-php.c index de9b89f54..cccb9dc2d 100644 --- a/gettext-tools/src/x-php.c +++ b/gettext-tools/src/x-php.c @@ -1,5 +1,5 @@ /* xgettext PHP backend. - Copyright (C) 2001-2003, 2005-2010, 2014, 2018 Free Software Foundation, Inc. + Copyright (C) 2001-2003, 2005-2010, 2014, 2018-2019 Free Software Foundation, Inc. This file was written by Bruno Haible , 2002. @@ -1532,8 +1532,9 @@ extract_balanced (message_list_ty *mlp, pos.line_number = token.line_number; if (extract_all) - remember_a_message (mlp, NULL, token.string, false, inner_context, - &pos, NULL, token.comment, false); + remember_a_message (mlp, NULL, token.string, false, false, + inner_context, &pos, + NULL, token.comment, false); else { mixed_string_ty *ms = diff --git a/gettext-tools/src/x-python.c b/gettext-tools/src/x-python.c index 94e9930d6..a27669eec 100644 --- a/gettext-tools/src/x-python.c +++ b/gettext-tools/src/x-python.c @@ -1648,8 +1648,9 @@ extract_balanced (message_list_ty *mlp, { char *string = mixed_string_contents (token.mixed_string); mixed_string_free (token.mixed_string); - remember_a_message (mlp, NULL, string, true, inner_context, - &pos, NULL, token.comment, true); + remember_a_message (mlp, NULL, string, true, false, + inner_context, &pos, + NULL, token.comment, true); } else arglist_parser_remember (argparser, arg, token.mixed_string, diff --git a/gettext-tools/src/x-rst.c b/gettext-tools/src/x-rst.c index d9705e11b..cde1ee6c0 100644 --- a/gettext-tools/src/x-rst.c +++ b/gettext-tools/src/x-rst.c @@ -1,5 +1,5 @@ /* xgettext RST/RSJ backend. - Copyright (C) 2001-2003, 2005-2009, 2018 Free Software Foundation, Inc. + Copyright (C) 2001-2003, 2005-2009, 2018-2019 Free Software Foundation, Inc. This file was written by Bruno Haible , 2001. @@ -228,8 +228,8 @@ extract_rst (FILE *f, pos.file_name = location; pos.line_number = (size_t)(-1); - remember_a_message (mlp, NULL, msgid, false, null_context, &pos, NULL, - NULL, false); + remember_a_message (mlp, NULL, msgid, false, false, null_context, &pos, + NULL, NULL, false); /* Here c is the last read character: EOF or '\n'. */ if (c == EOF) @@ -635,8 +635,9 @@ extract_rsj (FILE *f, pos.file_name = location; pos.line_number = (size_t)(-1); - remember_a_message (mlp, NULL, msgid, true, null_context, - &pos, NULL, NULL, false); + remember_a_message (mlp, NULL, msgid, true, false, + null_context, &pos, + NULL, NULL, false); /* Parse a comma. */ c = phase2_getc (); diff --git a/gettext-tools/src/x-scheme.c b/gettext-tools/src/x-scheme.c index 075f46795..6f627b75e 100644 --- a/gettext-tools/src/x-scheme.c +++ b/gettext-tools/src/x-scheme.c @@ -1332,8 +1332,8 @@ read_object (struct object *op, flag_context_ty outer_context) pos.file_name = logical_file_name; pos.line_number = op->line_number_at_start; remember_a_message (mlp, NULL, string_of_object (op), false, - null_context, &pos, NULL, savable_comment, - false); + false, null_context, &pos, + NULL, savable_comment, false); } last_non_comment_line = line_number; return; diff --git a/gettext-tools/src/x-sh.c b/gettext-tools/src/x-sh.c index 2d863aae5..ce8a864d4 100644 --- a/gettext-tools/src/x-sh.c +++ b/gettext-tools/src/x-sh.c @@ -1133,8 +1133,8 @@ read_word (struct word *wp, int looking_for, flag_context_ty context) string.chars[string.charcount++] = (unsigned char) c; } remember_a_message (mlp, NULL, string_of_token (&string), - false, context, &pos, NULL, - savable_comment, false); + false, false, context, &pos, + NULL, savable_comment, false); free_token (&string); error_with_progname = false; @@ -1302,8 +1302,8 @@ read_command (int looking_for, flag_context_ty outer_context) pos.file_name = logical_file_name; pos.line_number = inner.line_number_at_start; remember_a_message (mlp, NULL, string_of_word (&inner), false, - inner_context, &pos, NULL, savable_comment, - false); + false, inner_context, &pos, + NULL, savable_comment, false); } } diff --git a/gettext-tools/src/x-smalltalk.c b/gettext-tools/src/x-smalltalk.c index 73c2b038d..1a2b60998 100644 --- a/gettext-tools/src/x-smalltalk.c +++ b/gettext-tools/src/x-smalltalk.c @@ -1,5 +1,5 @@ /* xgettext Smalltalk backend. - Copyright (C) 2002-2003, 2005-2009, 2011, 2018 Free Software Foundation, Inc. + Copyright (C) 2002-2003, 2005-2009, 2011, 2018-2019 Free Software Foundation, Inc. This file was written by Bruno Haible , 2002. @@ -446,9 +446,18 @@ phase2_unget (token_ty *tp) /* 3. Combine "# string_literal" and "# symbol" to a single token. */ +static token_ty phase3_pushback[1]; +static int phase3_pushback_length; + static void -x_smalltalk_lex (token_ty *tp) +phase3_get (token_ty *tp) { + if (phase3_pushback_length) + { + *tp = phase3_pushback[--phase3_pushback_length]; + return; + } + phase2_get (tp); if (tp->type == token_type_uniq) { @@ -466,6 +475,18 @@ x_smalltalk_lex (token_ty *tp) } } +/* Supports only one pushback token. */ +static void +phase3_unget (token_ty *tp) +{ + if (tp->type != token_type_eof) + { + if (phase3_pushback_length == SIZEOF (phase3_pushback)) + abort (); + phase3_pushback[phase3_pushback_length++] = *tp; + } +} + /* ========================= Extracting strings. ========================== */ @@ -516,7 +537,7 @@ extract_smalltalk (FILE *f, { token_ty token; - x_smalltalk_lex (&token); + phase3_get (&token); switch (token.type) { @@ -535,7 +556,7 @@ extract_smalltalk (FILE *f, lex_pos_ty pos; pos.file_name = logical_file_name; pos.line_number = token.line_number; - remember_a_message (mlp, NULL, token.string, false, + remember_a_message (mlp, NULL, token.string, false, false, null_context, &pos, NULL, savable_comment, false); state = 0; @@ -544,11 +565,22 @@ extract_smalltalk (FILE *f, if (state == 3) { lex_pos_ty pos; + token_ty token2; + pos.file_name = logical_file_name; pos.line_number = token.line_number; - plural_mp = remember_a_message (mlp, NULL, token.string, false, - null_context, &pos, - NULL, savable_comment, false); + + phase3_get (&token2); + + plural_mp = + remember_a_message (mlp, NULL, token.string, false, + token2.type == token_type_symbol + && strcmp (token.string, "plural:") == 0, + null_context, &pos, + NULL, savable_comment, false); + + phase3_unget (&token2); + state = 4; break; } diff --git a/gettext-tools/src/x-tcl.c b/gettext-tools/src/x-tcl.c index 0c814cd04..1be2bcbfa 100644 --- a/gettext-tools/src/x-tcl.c +++ b/gettext-tools/src/x-tcl.c @@ -889,7 +889,7 @@ read_command (int looking_for, flag_context_ty outer_context) pos.file_name = logical_file_name; pos.line_number = inner.line_number_at_start; remember_a_message (mlp, NULL, string_of_word (&inner), false, - inner_context, &pos, + false, inner_context, &pos, NULL, savable_comment, false); } } diff --git a/gettext-tools/src/x-vala.c b/gettext-tools/src/x-vala.c index 7bf0979a7..49e822d7a 100644 --- a/gettext-tools/src/x-vala.c +++ b/gettext-tools/src/x-vala.c @@ -1324,8 +1324,9 @@ extract_balanced (message_list_ty *mlp, token_type_ty delim, { char *string = mixed_string_contents (token.mixed_string); mixed_string_free (token.mixed_string); - remember_a_message (mlp, NULL, string, true, inner_context, - &pos, NULL, token.comment, false); + remember_a_message (mlp, NULL, string, true, false, + inner_context, &pos, + NULL, token.comment, false); } else { diff --git a/gettext-tools/src/x-ycp.c b/gettext-tools/src/x-ycp.c index e27ba12d0..51c4cb3b3 100644 --- a/gettext-tools/src/x-ycp.c +++ b/gettext-tools/src/x-ycp.c @@ -1,5 +1,5 @@ /* xgettext YCP backend. - Copyright (C) 2001-2003, 2005-2009, 2011, 2018 Free Software Foundation, Inc. + Copyright (C) 2001-2003, 2005-2009, 2011, 2018-2019 Free Software Foundation, Inc. This file was written by Bruno Haible , 2001. @@ -581,9 +581,17 @@ phase5_unget (token_ty *tp) /* Concatenate adjacent string literals to form single string literals. (See libycp/src/parser.yy, rule 'string' vs. terminal 'STRING'.) */ +static token_ty phase8_pushback[1]; +static int phase8_pushback_length; + static void phase8_get (token_ty *tp) { + if (phase8_pushback_length) + { + *tp = phase8_pushback[--phase8_pushback_length]; + return; + } phase5_get (tp); if (tp->type != token_type_string_literal) return; @@ -605,6 +613,18 @@ phase8_get (token_ty *tp) } } +/* Supports only one pushback token. */ +static void +phase8_unget (token_ty *tp) +{ + if (tp->type != token_type_eof) + { + if (phase8_pushback_length == SIZEOF (phase8_pushback)) + abort (); + phase8_pushback[phase8_pushback_length++] = *tp; + } +} + /* ========================= Extracting strings. ========================== */ @@ -680,9 +700,24 @@ extract_parenthesized (message_list_ty *mlp, if (plural_state == 0) { /* Seen an msgid. */ - plural_mp = remember_a_message (mlp, NULL, token.string, - false, inner_context, &pos, - NULL, token.comment, false); + token_ty token2; + + if (in_i18n) + phase8_get (&token2); + else + phase5_get (&token2); + + plural_mp = + remember_a_message (mlp, NULL, token.string, false, + token2.type == token_type_comma, + inner_context, &pos, + NULL, token.comment, false); + + if (in_i18n) + phase8_unget (&token2); + else + phase5_unget (&token2); + plural_state = 1; state = 2; } diff --git a/gettext-tools/src/xg-arglist-parser.c b/gettext-tools/src/xg-arglist-parser.c index a99dc5fc5..d9795eb2d 100644 --- a/gettext-tools/src/xg-arglist-parser.c +++ b/gettext-tools/src/xg-arglist-parser.c @@ -1,6 +1,6 @@ /* Resolving ambiguity of argument lists: Progressive parsing of an argument list, keeping track of all possibilities. - Copyright (C) 2001-2018 Free Software Foundation, Inc. + Copyright (C) 2001-2019 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -503,6 +503,7 @@ arglist_parser_done (struct arglist_parser *ap, int argnum) } mp = remember_a_message (ap->mlp, best_msgctxt, best_msgid, true, + best_msgid_plural != NULL, msgid_context, &best_cp->msgid_pos, NULL, best_cp->msgid_comment, diff --git a/gettext-tools/src/xg-message.c b/gettext-tools/src/xg-message.c index b1938407c..5b9d3577f 100644 --- a/gettext-tools/src/xg-message.c +++ b/gettext-tools/src/xg-message.c @@ -1,5 +1,5 @@ /* Extracting a message. Accumulating the message list. - Copyright (C) 2001-2018 Free Software Foundation, Inc. + Copyright (C) 2001-2019 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -136,7 +136,8 @@ and a mapping instead of a tuple for the arguments.\n"), message_ty * remember_a_message (message_list_ty *mlp, char *msgctxt, char *msgid, - bool is_utf8, flag_context_ty context, lex_pos_ty *pos, + bool is_utf8, bool pluralp, flag_context_ty context, + lex_pos_ty *pos, const char *extracted_comment, refcounted_string_list_ty *comment, bool comment_is_utf8) { @@ -202,6 +203,43 @@ meta information, not the empty string.\n"))); mp = message_list_search (mlp, msgctxt, msgid); if (mp != NULL) { + if (pluralp != (mp->msgid_plural != NULL)) + { + lex_pos_ty pos1; + lex_pos_ty pos2; + char buffer1[21]; + char buffer2[21]; + + if (pluralp) + { + pos1 = mp->pos; + pos2 = *pos; + } + else + { + pos1 = *pos; + pos2 = mp->pos; + } + + if (pos1.line_number == (size_t)(-1)) + buffer1[0] = '\0'; + else + sprintf (buffer1, ":%ld", (long) pos1.line_number); + if (pos2.line_number == (size_t)(-1)) + buffer2[0] = '\0'; + else + sprintf (buffer2, ":%ld", (long) pos2.line_number); + multiline_warning (xstrdup (_("warning: ")), + xasprintf ("%s\n%s\n%s\n%s\n", + xasprintf (_("msgid '%s' is used without plural and with plural."), + msgid), + xasprintf (_("%s%s: Here is the occurrence without plural."), + pos1.file_name, buffer1), + xasprintf (_("%s%s: Here is the occurrence with plural."), + pos2.file_name, buffer2), + xstrdup (_("Workaround: If the msgid is a sentence, change the wording of the sentence; otherwise, use contexts for disambiguation.")))); + } + if (msgctxt != NULL) free (msgctxt); free (msgid); diff --git a/gettext-tools/src/xg-message.h b/gettext-tools/src/xg-message.h index 83ba4a6a4..8def094e7 100644 --- a/gettext-tools/src/xg-message.h +++ b/gettext-tools/src/xg-message.h @@ -1,5 +1,5 @@ /* Extracting a message. Accumulating the message list. - Copyright (C) 2001-2018 Free Software Foundation, Inc. + Copyright (C) 2001-2019 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -37,6 +37,8 @@ extern "C" { MSGID must be a malloc()ed string; its ownership is passed to the callee. IS_UTF8 must be true if MSGCTXT and MSGID have already been converted to UTF-8. + PLURALP must be true if and only if a call to remember_a_message_plural will + follow. POS->file_name must be allocated with indefinite extent. EXTRACTED_COMMENT is a comment that needs to be copied into the POT file, or NULL. @@ -49,6 +51,7 @@ extern message_ty *remember_a_message (message_list_ty *mlp, char *msgctxt, char *msgid, bool is_utf8, + bool pluralp, flag_context_ty context, lex_pos_ty *pos, const char *extracted_comment, diff --git a/gettext-tools/src/xgettext.c b/gettext-tools/src/xgettext.c index 96dff8dac..e2e4525de 100644 --- a/gettext-tools/src/xgettext.c +++ b/gettext-tools/src/xgettext.c @@ -1804,7 +1804,7 @@ xgettext_its_extract_callback (message_list_ty *mlp, message = remember_a_message (mlp, msgctxt == NULL ? NULL : xstrdup (msgctxt), xstrdup (msgid), - false, + false, false, null_context, pos, extracted_comment, NULL, false); diff --git a/gettext-tools/tests/Makefile.am b/gettext-tools/tests/Makefile.am index 53d6af754..b2bd779e4 100644 --- a/gettext-tools/tests/Makefile.am +++ b/gettext-tools/tests/Makefile.am @@ -77,7 +77,7 @@ TESTS = gettext-1 gettext-2 \ recode-sr-latin-1 recode-sr-latin-2 \ xgettext-2 xgettext-3 xgettext-4 xgettext-5 xgettext-6 \ xgettext-7 xgettext-8 xgettext-9 xgettext-10 xgettext-11 xgettext-12 \ - xgettext-13 xgettext-14 \ + xgettext-13 xgettext-14 xgettext-15 \ xgettext-appdata-1 \ xgettext-awk-1 xgettext-awk-2 \ xgettext-c-2 xgettext-c-3 xgettext-c-4 xgettext-c-5 xgettext-c-6 \ diff --git a/gettext-tools/tests/xgettext-15 b/gettext-tools/tests/xgettext-15 new file mode 100755 index 000000000..355d91b3d --- /dev/null +++ b/gettext-tools/tests/xgettext-15 @@ -0,0 +1,55 @@ +#!/bin/sh +. "${srcdir=.}/init.sh"; path_prepend_ . ../src + +# Test for a warning when the same msgid is used with and without msgid_plural. +# +# +# + +# Case when the message with plural appears first. + +cat <<\EOF > xg-test15-1.py +ngettext("Language", "Languages", n) +_("Language") +EOF + +: ${XGETTEXT=xgettext} +LANGUAGE= LC_ALL=C ${XGETTEXT} --omit-header --add-comments -d xg-test15-1.tmp xg-test15-1.py 2>xg-test15-1.err || Exit 1 +LC_ALL=C tr -d '\r' < xg-test15-1.tmp.po > xg-test15-1.po || Exit 1 + +grep "is used without plural and with plural" xg-test15-1.err || Exit 1 + +cat <<\EOF > xg-test15-1.ok +#: xg-test15-1.py:1 xg-test15-1.py:2 +msgid "Language" +msgid_plural "Languages" +msgstr[0] "" +msgstr[1] "" +EOF + +: ${DIFF=diff} +${DIFF} xg-test15-1.ok xg-test15-1.po || Exit 1 + +# Case when the message without plural appears first. + +cat <<\EOF > xg-test15-2.py +_("Language") +ngettext("Language", "Languages", n) +EOF + +: ${XGETTEXT=xgettext} +LANGUAGE= LC_ALL=C ${XGETTEXT} --omit-header --add-comments -d xg-test15-2.tmp xg-test15-2.py 2>xg-test15-2.err || Exit 1 +LC_ALL=C tr -d '\r' < xg-test15-2.tmp.po > xg-test15-2.po || Exit 1 + +grep "is used without plural and with plural" xg-test15-2.err || Exit 1 + +cat <<\EOF > xg-test15-2.ok +#: xg-test15-2.py:1 xg-test15-2.py:2 +msgid "Language" +msgid_plural "Languages" +msgstr[0] "" +msgstr[1] "" +EOF + +: ${DIFF=diff} +${DIFF} xg-test15-2.ok xg-test15-2.po || Exit 1