From: Bruno Haible Date: Thu, 3 Jul 2025 06:48:44 +0000 (+0200) Subject: msggrep: Add new options -W and -S. X-Git-Tag: v0.26~32 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=efb20317fbeae73b2be3a8e6e2a3ce6f0693459a;p=thirdparty%2Fgettext.git msggrep: Add new options -W and -S. Reported at . * gettext-tools/src/msggrep.c (workflow_flags, sticky_flags): New variables. (main): Initialize them. Handle the options -W and -S. (usage): Document the -W and -S options. (is_message_selected_no_invert): Return true if one of the specified workflow flags or one of the specified sticky flags is set. * gettext-tools/tests/msggrep-12: New file. * gettext-tools/tests/Makefile.am (TESTS): Add it. * gettext-tools/doc/msggrep.texi: Document the -W and -S options. * NEWS: Mention the change. --- diff --git a/NEWS b/NEWS index be95b6ba4..4cbcd9ba4 100644 --- a/NEWS +++ b/NEWS @@ -22,6 +22,11 @@ Version 0.26 - July 2025 - xgettext now recognizes the \c, \u, and \U escape sequences in dollar- single-quoted strings $'...'. +# Improvements for translators: + * msggrep: + - msggrep accepts two new options -W/--workflow-flags and -S/--sticky-flags + that allow to select only messages that have a specified flag. + # Bug fixes: - The AM_GNU_GETTEXT macro now rejects the dysfunctional gettext() function in libc of Solaris 11.[0-3], Solaris OpenIndiana, and Solaris OmniOS. diff --git a/gettext-tools/doc/msggrep.texi b/gettext-tools/doc/msggrep.texi index 1673d29d3..c77ec97e7 100644 --- a/gettext-tools/doc/msggrep.texi +++ b/gettext-tools/doc/msggrep.texi @@ -50,6 +50,7 @@ or if it is @samp{-}. [-N @var{sourcefile}]... [-M @var{domainname}]... [-J @var{msgctxt-pattern}] [-K @var{msgid-pattern}] [-T @var{msgstr-pattern}] [-C @var{comment-pattern}] [-X @var{extracted-comment-pattern}] + [-W @var{workflow-flag}] [-S @var{sticky-flag}] @end example A message is selected if @@ -65,7 +66,9 @@ A message is selected if @item or if @samp{-C} is given and the translator's comment matches @var{comment-pattern}, @item or if @samp{-X} is given and the extracted comment matches -@var{extracted-comment-pattern}. +@var{extracted-comment-pattern}, +@item or if @samp{-W} is given and its flags contain @var{workflow-flag}, +@item or if @samp{-S} is given and its flags contain @var{sticky-flag}. @end itemize When more than one selection criterion is specified, the set of selected @@ -152,6 +155,20 @@ Obtain @var{pattern} from @var{file}. @opindex --ignore-case@r{, @code{msggrep} option} Ignore case distinctions. +@item -W @var{workflow-flag} +@itemx --workflow-flag=@var{workflow-flag} +@opindex -W@r{, @code{msggrep} option} +@opindex --workflow-flag@r{, @code{msggrep} option} +Select messages with @var{workflow-flag}. +Workflow flags are defined in @ref{Workflow flags}. + +@item -S @var{sticky-flag} +@itemx --sticky-flag=@var{sticky-flag} +@opindex -S@r{, @code{msggrep} option} +@opindex --sticky-flag@r{, @code{msggrep} option} +Select messages with @var{sticky-flag}. +Sticky flags are defined in @ref{Sticky flags}. + @item -v @itemx --invert-match @opindex -v@r{, @code{msggrep} option} diff --git a/gettext-tools/src/msggrep.c b/gettext-tools/src/msggrep.c index b31b6f757..94054dcd3 100644 --- a/gettext-tools/src/msggrep.c +++ b/gettext-tools/src/msggrep.c @@ -91,6 +91,12 @@ struct grep_task { }; static struct grep_task grep_task[5]; +/* Selected workflow flags. */ +static string_list_ty *workflow_flags; + +/* Selected sticky flags. */ +static string_list_ty *sticky_flags; + /* Forward declaration of local functions. */ _GL_NORETURN_FUNC static void no_pass (int opt); @@ -138,6 +144,8 @@ main (int argc, char **argv) grep_pass = -1; location_files = string_list_alloc (); domain_names = string_list_alloc (); + workflow_flags = string_list_alloc (); + sticky_flags = string_list_alloc (); for (i = 0; i < 5; i++) { @@ -183,12 +191,14 @@ main (int argc, char **argv) { "regexp", 'e', required_argument }, { "sort-by-file", CHAR_MAX + 4, no_argument }, { "sort-output", CHAR_MAX + 5, no_argument }, + { "sticky-flag", 'S', required_argument }, { "strict", CHAR_MAX + 12, no_argument }, { "stringtable-input", CHAR_MAX + 7, no_argument }, { "stringtable-output", CHAR_MAX + 8, no_argument }, { "style", CHAR_MAX + 10, required_argument }, { "version", 'V', no_argument }, { "width", 'w', required_argument }, + { "workflow-flag", 'W', required_argument }, }; END_ALLOW_OMITTING_FIELD_INITIALIZERS start_options (argc, argv, options, MOVE_OPTIONS_FIRST, 0); @@ -331,6 +341,10 @@ main (int argc, char **argv) message_print_style_uniforum (); break; + case 'S': + string_list_append (sticky_flags, optarg); + break; + case 'T': grep_pass = 2; break; @@ -353,6 +367,10 @@ main (int argc, char **argv) } break; + case 'W': + string_list_append (workflow_flags, optarg); + break; + case 'X': grep_pass = 4; break; @@ -547,13 +565,16 @@ Message selection:\n\ [-N SOURCEFILE]... [-M DOMAINNAME]...\n\ [-J MSGCTXT-PATTERN] [-K MSGID-PATTERN] [-T MSGSTR-PATTERN]\n\ [-C COMMENT-PATTERN] [-X EXTRACTED-COMMENT-PATTERN]\n\ + [-W WORKFLOW-FLAG] [-S STICKY-FLAG]\n\ A message is selected if it comes from one of the specified source files,\n\ or if it comes from one of the specified domains,\n\ or if -J is given and its context (msgctxt) matches MSGCTXT-PATTERN,\n\ or if -K is given and its key (msgid or msgid_plural) matches MSGID-PATTERN,\n\ or if -T is given and its translation (msgstr) matches MSGSTR-PATTERN,\n\ or if -C is given and the translator's comment matches COMMENT-PATTERN,\n\ -or if -X is given and the extracted comment matches EXTRACTED-COMMENT-PATTERN.\n\ +or if -X is given and the extracted comment matches EXTRACTED-COMMENT-PATTERN,\n\ +or if -W is given and its flags contain WORKFLOW-FLAG,\n\ +or if -S is given and its flags contain STICKY-FLAG.\n\ \n\ When more than one selection criterion is specified, the set of selected\n\ messages is the union of the selected messages of each criterion.\n\ @@ -576,6 +597,8 @@ expressions if -E is given, or fixed strings if -F is given.\n\ -e, --regexp=PATTERN use PATTERN as a regular expression\n\ -f, --file=FILE obtain PATTERN from FILE\n\ -i, --ignore-case ignore case distinctions\n\ + -W, --workflow-flag=FLAG select messages with FLAG\n\ + -S, --sticky-flag=FLAG select messages with FLAG\n\ -v, --invert-match output only the messages that do not match any\n\ selection criterion\n\ ")); @@ -697,6 +720,41 @@ is_message_selected_no_invert (const message_ty *mp) if (filename_list_match (location_files, mp->filepos[i].file_name)) return true; + /* Test whether one of the workflow flags is selected. */ + if (mp->is_fuzzy && string_list_member (workflow_flags, "fuzzy")) + return true; + + /* Test whether one of the sticky flags is selected. */ + /* Recognize flag "[no-]wrap". */ + if ((mp->do_wrap == yes && string_list_member (sticky_flags, "wrap")) + || (mp->do_wrap == no && string_list_member (sticky_flags, "no-wrap"))) + return true; + /* Recognize flag "[no-]-format". */ + for (i = 0; i < sticky_flags->nitems; i++) + { + const char *flag = sticky_flags->item[i]; + size_t flag_len = strlen (flag); + if (flag_len >= 7 && memcmp (flag + flag_len - 7, "-format", 7) == 0) + { + flag_len -= 7; + bool has_no_prefix = (flag_len >= 3 && memcmp (flag, "no-", 3) == 0); + if (has_no_prefix) + { + flag += 3; + flag_len -= 3; + } + size_t j; + for (j = 0; j < NFORMATS; j++) + if (strlen (format_language[j]) == flag_len + && memcmp (format_language[j], flag, flag_len) == 0) + { + /* The value of the flag is stored in mp->is_format[j]. */ + if (mp->is_format[j] == (has_no_prefix ? no : yes)) + return true; + } + } + } + /* Test msgctxt using the --msgctxt arguments. */ if (mp->msgctxt != NULL && is_string_selected (0, mp->msgctxt, strlen (mp->msgctxt))) diff --git a/gettext-tools/tests/Makefile.am b/gettext-tools/tests/Makefile.am index 54127ba9d..6f02cc69c 100644 --- a/gettext-tools/tests/Makefile.am +++ b/gettext-tools/tests/Makefile.am @@ -59,7 +59,7 @@ TESTS = gettext-1 gettext-2 \ msgfmt-desktop-1 msgfmt-desktop-2 msgfmt-desktop-3 msgfmt-desktop-4 \ msgfmt-xml-1 msgfmt-xml-2 msgfmt-xml-3 msgfmt-xml-4 msgfmt-xml-5 \ msggrep-1 msggrep-2 msggrep-3 msggrep-4 msggrep-5 msggrep-6 msggrep-7 \ - msggrep-8 msggrep-9 msggrep-10 msggrep-11 \ + msggrep-8 msggrep-9 msggrep-10 msggrep-11 msggrep-12 \ msginit-1 msginit-2 msginit-3 msginit-4 msginit-5 \ msgmerge-1 msgmerge-2 msgmerge-3 msgmerge-4 msgmerge-5 msgmerge-6 \ msgmerge-7 msgmerge-8 msgmerge-9 msgmerge-10 msgmerge-11 msgmerge-12 \ diff --git a/gettext-tools/tests/msggrep-12 b/gettext-tools/tests/msggrep-12 new file mode 100755 index 000000000..c2ed17046 --- /dev/null +++ b/gettext-tools/tests/msggrep-12 @@ -0,0 +1,311 @@ +#! /bin/sh +. "${srcdir=.}/init.sh"; path_prepend_ . ../src + +# Test --workflow-flag and --sticky-flag options. + +cat <<\EOF > mg-test12.po +# German translations for GNU gettext package. +# Copyright (C) 1995, 1996, 1997, 2001 Free Software Foundation, Inc. +msgid "" +msgstr "" +"Project-Id-Version: GNU gettext 0.11-pre1\n" +"POT-Creation-Date: 2001-12-08 20:33+0100\n" +"PO-Revision-Date: 2001-11-04 12:25+0100\n" +"Last-Translator: Karl Eichwalder \n" +"Language-Team: German \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=ISO-8859-1\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: argmatch.c:141 +#, c-format +msgid "invalid argument `%s' for `%s'" +msgstr "ungültiges Argument »%s« für »%s«" + +#: argmatch.c:142 +#, c-format +msgid "ambiguous argument `%s' for `%s'" +msgstr "mehrdeutiges Argument »%s« für »%s«" + +#: argmatch.c:162 +msgid "Valid arguments are:" +msgstr "Gültige Argumente sind:" + +#: copy-file.c:60 +#, c-format +msgid "error while opening \"%s\" for reading" +msgstr "Öffnen der Datei »%s« zum Lesen fehlgeschlagen" + +#: copy-file.c:67 +#, c-format +msgid "cannot open backup file \"%s\" for writing" +msgstr "Öffnen der Sicherungsdatei »%s« zum Schreiben fehlgeschlagen" + +#: copy-file.c:80 +#, c-format +msgid "error reading \"%s\"" +msgstr "Fehler beim Lesen von »%s«" + +#: copy-file.c:86 copy-file.c:90 +#, c-format +msgid "error writing \"%s\"" +msgstr "Fehler beim Schreiben von »%s«" + +#: copy-file.c:92 +#, fuzzy, c-format +msgid "error after reading \"%s\"" +msgstr "Fehler nach dem Lesen von »%s«" + +#: error.c:115 +#, fuzzy +msgid "Unknown system error" +msgstr "Unbekannter Systemfehler" + +#: execute.c:170 execute.c:205 pipe-bidi.c:156 pipe-bidi.c:191 pipe-in.c:169 +#: pipe-in.c:205 pipe-out.c:169 pipe-out.c:205 wait-process.c:136 +#, c-format +msgid "%s subprocess failed" +msgstr "Subprozess %s fehlgeschlagen" + +#: getopt.c:691 +#, c-format +msgid "%s: option `%s' is ambiguous\n" +msgstr "%s: Option »%s« ist mehrdeutig\n" + +#: getopt.c:716 +#, c-format +msgid "%s: option `--%s' doesn't allow an argument\n" +msgstr "%s: Option »--%s« erwartet kein Argument\n" + +#: getopt.c:721 +#, c-format +msgid "%s: option `%c%s' doesn't allow an argument\n" +msgstr "%s: Option »%c%s« erwartet kein Argument\n" + +#: getopt.c:739 getopt.c:912 +#, c-format +msgid "%s: option `%s' requires an argument\n" +msgstr "%s: Option »%s« erwartet ein Argument\n" + +#: getopt.c:768 +#, c-format +msgid "%s: unrecognized option `--%s'\n" +msgstr "%s: unbekannte Option »--%s«\n" + +#: getopt.c:772 +#, c-format +msgid "%s: unrecognized option `%c%s'\n" +msgstr "%s: unbekannte Option »%c%s«\n" + +# Möchte mal gerne wissen, was der Unterschied zwischen +# "unzulässig" und "ungültig" ist. +# Übrigens ist im Englischen "illegal" falsch. +#: getopt.c:798 +#, c-format +msgid "%s: illegal option -- %c\n" +msgstr "%s: unzulässige Option -- %c\n" + +#: getopt.c:801 +#, c-format +msgid "%s: invalid option -- %c\n" +msgstr "%s: ungültige Option -- %c\n" + +#: getopt.c:831 getopt.c:961 +#, c-format +msgid "%s: option requires an argument -- %c\n" +msgstr "%s: Option erwartet ein Argument -- %c\n" + +#: getopt.c:878 +#, c-format +msgid "%s: option `-W %s' is ambiguous\n" +msgstr "%s: Option »-W %s« ist mehrdeutig\n" + +#: getopt.c:896 +#, c-format +msgid "%s: option `-W %s' doesn't allow an argument\n" +msgstr "%s: Option »-W %s« erwartet kein Argument\n" + +#: javacomp.c:465 +msgid "Java compiler not found, try installing gcj or set $JAVAC" +msgstr "" +"Java-Compiler nicht gefunden; bitte »gcj« installieren oder $JAVAC setzen" + +#: javaexec.c:404 +#, fuzzy +msgid "Java virtual machine not found, try installing gij or set $JAVA" +msgstr "" +"Virtuelle Java-Maschine nicht gefunden; bitte »gcj« installieren oder\n" +"$JAVA setzen" + +#: obstack.c:474 xerror.c:75 xmalloc.c:56 +#, objc-format +msgid "memory exhausted" +msgstr "virtueller Speicher erschöpft" + +# Auch "Pipe" eindeutschen. +#: pipe-bidi.c:119 pipe-bidi.c:121 pipe-in.c:136 pipe-out.c:136 +msgid "cannot create pipe" +msgstr "Es ist nicht möglich, eine Pipe zu erzeugen" + +#: wait-process.c:117 +#, c-format +msgid "%s subprocess" +msgstr "Subprozess %s" + +#: wait-process.c:129 +#, c-format +msgid "%s subprocess got fatal signal" +msgstr "Subprozess %s hat ein fatales Signal erhalten" +EOF + +: ${MSGGREP=msggrep} +LC_MESSAGES=C LC_ALL= \ +${MSGGREP} -W fuzzy -S c-format -o mg-test12.tmp mg-test12.po >mg-test12.err 2>&1 +result=$? +cat mg-test12.err | grep -v 'warning: Locale charset' | grep -v '^ ' +test $result = 0 || { Exit 1; } +LC_ALL=C tr -d '\r' < mg-test12.tmp > mg-test12.out || Exit 1 + +cat <<\EOF > mg-test12.ok +# German translations for GNU gettext package. +# Copyright (C) 1995, 1996, 1997, 2001 Free Software Foundation, Inc. +msgid "" +msgstr "" +"Project-Id-Version: GNU gettext 0.11-pre1\n" +"POT-Creation-Date: 2001-12-08 20:33+0100\n" +"PO-Revision-Date: 2001-11-04 12:25+0100\n" +"Last-Translator: Karl Eichwalder \n" +"Language-Team: German \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=ISO-8859-1\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: argmatch.c:141 +#, c-format +msgid "invalid argument `%s' for `%s'" +msgstr "ungültiges Argument »%s« für »%s«" + +#: argmatch.c:142 +#, c-format +msgid "ambiguous argument `%s' for `%s'" +msgstr "mehrdeutiges Argument »%s« für »%s«" + +#: copy-file.c:60 +#, c-format +msgid "error while opening \"%s\" for reading" +msgstr "Öffnen der Datei »%s« zum Lesen fehlgeschlagen" + +#: copy-file.c:67 +#, c-format +msgid "cannot open backup file \"%s\" for writing" +msgstr "Öffnen der Sicherungsdatei »%s« zum Schreiben fehlgeschlagen" + +#: copy-file.c:80 +#, c-format +msgid "error reading \"%s\"" +msgstr "Fehler beim Lesen von »%s«" + +#: copy-file.c:86 copy-file.c:90 +#, c-format +msgid "error writing \"%s\"" +msgstr "Fehler beim Schreiben von »%s«" + +#: copy-file.c:92 +#, fuzzy, c-format +msgid "error after reading \"%s\"" +msgstr "Fehler nach dem Lesen von »%s«" + +#: error.c:115 +#, fuzzy +msgid "Unknown system error" +msgstr "Unbekannter Systemfehler" + +#: execute.c:170 execute.c:205 pipe-bidi.c:156 pipe-bidi.c:191 pipe-in.c:169 +#: pipe-in.c:205 pipe-out.c:169 pipe-out.c:205 wait-process.c:136 +#, c-format +msgid "%s subprocess failed" +msgstr "Subprozess %s fehlgeschlagen" + +#: getopt.c:691 +#, c-format +msgid "%s: option `%s' is ambiguous\n" +msgstr "%s: Option »%s« ist mehrdeutig\n" + +#: getopt.c:716 +#, c-format +msgid "%s: option `--%s' doesn't allow an argument\n" +msgstr "%s: Option »--%s« erwartet kein Argument\n" + +#: getopt.c:721 +#, c-format +msgid "%s: option `%c%s' doesn't allow an argument\n" +msgstr "%s: Option »%c%s« erwartet kein Argument\n" + +#: getopt.c:739 getopt.c:912 +#, c-format +msgid "%s: option `%s' requires an argument\n" +msgstr "%s: Option »%s« erwartet ein Argument\n" + +#: getopt.c:768 +#, c-format +msgid "%s: unrecognized option `--%s'\n" +msgstr "%s: unbekannte Option »--%s«\n" + +#: getopt.c:772 +#, c-format +msgid "%s: unrecognized option `%c%s'\n" +msgstr "%s: unbekannte Option »%c%s«\n" + +# Möchte mal gerne wissen, was der Unterschied zwischen +# "unzulässig" und "ungültig" ist. +# Übrigens ist im Englischen "illegal" falsch. +#: getopt.c:798 +#, c-format +msgid "%s: illegal option -- %c\n" +msgstr "%s: unzulässige Option -- %c\n" + +#: getopt.c:801 +#, c-format +msgid "%s: invalid option -- %c\n" +msgstr "%s: ungültige Option -- %c\n" + +#: getopt.c:831 getopt.c:961 +#, c-format +msgid "%s: option requires an argument -- %c\n" +msgstr "%s: Option erwartet ein Argument -- %c\n" + +#: getopt.c:878 +#, c-format +msgid "%s: option `-W %s' is ambiguous\n" +msgstr "%s: Option »-W %s« ist mehrdeutig\n" + +#: getopt.c:896 +#, c-format +msgid "%s: option `-W %s' doesn't allow an argument\n" +msgstr "%s: Option »-W %s« erwartet kein Argument\n" + +#: javaexec.c:404 +#, fuzzy +msgid "Java virtual machine not found, try installing gij or set $JAVA" +msgstr "" +"Virtuelle Java-Maschine nicht gefunden; bitte »gcj« installieren oder\n" +"$JAVA setzen" + +#: wait-process.c:117 +#, c-format +msgid "%s subprocess" +msgstr "Subprozess %s" + +#: wait-process.c:129 +#, c-format +msgid "%s subprocess got fatal signal" +msgstr "Subprozess %s hat ein fatales Signal erhalten" +EOF + +: ${DIFF=diff} +${DIFF} mg-test12.ok mg-test12.out +result=$? + +exit $result