From 3f5a362d35f04be9978a939edcb68092429c55c8 Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Sun, 13 Oct 2024 20:18:15 +0200 Subject: [PATCH] xgettext: Desktop: Correct the line numbers in the output and in error messages. * gettext-tools/src/read-desktop.c (struct token_ty): Add a 'lineno' field. (desktop_lex): Correct the line numbers in error messages. For a token of type token_type_pair, store the line number. (desktop_parse): Pass the line number from the token to desktop_reader_handle_pair. * gettext-tools/tests/xgettext-desktop-1: Update expected output. * gettext-tools/tests/xgettext-desktop-2: Likewise. * NEWS: Mention the change. --- NEWS | 1 + gettext-tools/src/read-desktop.c | 34 ++++++++++++++++++++------ gettext-tools/tests/xgettext-desktop-1 | 6 ++--- gettext-tools/tests/xgettext-desktop-2 | 4 +-- 4 files changed, 32 insertions(+), 13 deletions(-) diff --git a/NEWS b/NEWS index 2689fce00..98fc2b023 100644 --- a/NEWS +++ b/NEWS @@ -59,6 +59,7 @@ Version 0.23 - October 2024 o Heredoc and Nowdoc strings are now scanned correctly. o The format string directives %E, %F, %g, %G, %h, %H are now regarded as valid. + - Desktop: xgettext now produces POT files with correct line numbers. * Runtime behaviour: - In the C.UTF-8 locale, like in the C locale, the *gettext() functions diff --git a/gettext-tools/src/read-desktop.c b/gettext-tools/src/read-desktop.c index cd3554217..8bfa01aed 100644 --- a/gettext-tools/src/read-desktop.c +++ b/gettext-tools/src/read-desktop.c @@ -195,6 +195,7 @@ struct token_ty char *string; const char *value; const char *locale; + size_t lineno; }; /* Free the memory pointed to by a 'struct token_ty'. */ @@ -231,6 +232,7 @@ desktop_lex (token_ty *tp) case '[': { bool non_blank = false; + size_t non_blank_lineno = 0; for (;;) { @@ -240,7 +242,7 @@ desktop_lex (token_ty *tp) if (c == '\n') { po_xerror (PO_SEVERITY_WARNING, NULL, - real_file_name, pos.line_number, 0, false, + real_file_name, pos.line_number - 1, 0, false, _("unterminated group name")); break; } @@ -257,11 +259,14 @@ desktop_lex (token_ty *tp) if (c == EOF) break; if (!c_isspace (c)) - non_blank = true; + { + non_blank = true; + non_blank_lineno = pos.line_number; + } } if (non_blank) po_xerror (PO_SEVERITY_WARNING, NULL, - real_file_name, pos.line_number, 0, false, + real_file_name, non_blank_lineno, 0, false, _("invalid non-blank character")); APPEND (0); tp->type = token_type_group; @@ -348,6 +353,7 @@ desktop_lex (token_ty *tp) APPEND (0); /* Skip any space before '='. */ + size_t before_equals_lineno = pos.line_number; for (;;) { c = phase2_getc (); @@ -368,7 +374,7 @@ desktop_lex (token_ty *tp) if (c != '=') { po_xerror (PO_SEVERITY_WARNING, NULL, - real_file_name, pos.line_number, 0, false, + real_file_name, before_equals_lineno, 0, false, xasprintf (_("missing '=' after \"%s\""), sb_xcontents_c (&buffer))); sb_free (&buffer); @@ -399,6 +405,7 @@ desktop_lex (token_ty *tp) break; } + size_t before_value_lineno = pos.line_number; value_start = string_desc_length (sb_contents (&buffer)); for (;;) { @@ -415,11 +422,13 @@ desktop_lex (token_ty *tp) live. */ tp->locale = found_locale ? &buffer_contents[locale_start] : NULL; tp->value = &buffer_contents[value_start]; + tp->lineno = before_value_lineno; return; } default: { bool non_blank = false; + size_t non_blank_lineno = 0; for (;;) { @@ -427,7 +436,10 @@ desktop_lex (token_ty *tp) break; if (!c_isspace (c)) - non_blank = true; + { + non_blank = true; + non_blank_lineno = pos.line_number; + } else APPEND (c); @@ -436,7 +448,7 @@ desktop_lex (token_ty *tp) if (non_blank) { po_xerror (PO_SEVERITY_WARNING, NULL, - real_file_name, pos.line_number, 0, false, + real_file_name, non_blank_lineno, 0, false, _("invalid non-blank line")); sb_free (&buffer); tp->type = token_type_other; @@ -476,8 +488,14 @@ desktop_parse (desktop_reader_ty *reader, FILE *file, desktop_reader_handle_comment (reader, token.string); break; case token_type_pair: - desktop_reader_handle_pair (reader, &pos, - token.string, token.locale, token.value); + { + lex_pos_ty token_pos; + token_pos.file_name = pos.file_name; + token_pos.line_number = token.lineno; + + desktop_reader_handle_pair (reader, &token_pos, + token.string, token.locale, token.value); + } break; case token_type_blank: desktop_reader_handle_blank (reader, token.string); diff --git a/gettext-tools/tests/xgettext-desktop-1 b/gettext-tools/tests/xgettext-desktop-1 index be859b4fe..3801bc006 100755 --- a/gettext-tools/tests/xgettext-desktop-1 +++ b/gettext-tools/tests/xgettext-desktop-1 @@ -75,19 +75,19 @@ msgstr "" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" -#: xg.desktop:4 +#: xg.desktop:3 msgid "Foo" msgstr "" #. This is a comment for comment #. This is a comment for comment -#: xg.desktop:7 +#: xg.desktop:6 msgid "" " This is a \n" "multiline\t comment; for testing" msgstr "" -#: xg.desktop:12 +#: xg.desktop:11 msgid "Keyword1;Keyword2;Key\\;word3;" msgstr "" EOF diff --git a/gettext-tools/tests/xgettext-desktop-2 b/gettext-tools/tests/xgettext-desktop-2 index 974e75b62..375ef78e7 100755 --- a/gettext-tools/tests/xgettext-desktop-2 +++ b/gettext-tools/tests/xgettext-desktop-2 @@ -39,11 +39,11 @@ msgstr "" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" -#: hello.desktop:3 +#: hello.desktop:2 msgid "Hello" msgstr "" -#: hello.desktop:10 +#: hello.desktop:9 msgid "Utility;" msgstr "" EOF -- 2.47.3