diff options
Diffstat (limited to 'patches/argp-domain.patch')
-rw-r--r-- | patches/argp-domain.patch | 278 |
1 files changed, 278 insertions, 0 deletions
diff --git a/patches/argp-domain.patch b/patches/argp-domain.patch new file mode 100644 index 0000000..3297a32 --- /dev/null +++ b/patches/argp-domain.patch @@ -0,0 +1,278 @@ +commit a304ab22b12f41712dbcd41b6ff001feb062b03f +Author: Colin Watson <cjwatson@debian.org> +Date: Mon May 28 17:41:05 2018 +0100 + + Fix domain handling in argp + + man-db sets its default text domain to "man-db", and keeps all Gnulib's + strings in a separate "man-db-gnulib" domain, using 'gnulib-tool + --po-domain=man-db' which results in + -DDEFAULT_TEXT_DOMAIN=\"man-db-gnulib\". (I checked this general + approach with Bruno a while back and he said it was fine.) + + However, Gnulib's argp implementation has three bugs which cause this + not to work properly: + + * It hardcodes "libc" as a domain in two places. This is obviously + wrong in Gnulib. + + * It uses argp_domain as both the domain used to translate its own + strings (i.e. string literals in lib/argp-*.c) and the domain used + to translate strings provided by the user, which normally have to + use gettext_noop so that they can be used as 'struct argp_option' + initialisers. This is dreadfully inconvenient because you have to + copy strings about all over the place and keep your POT file up to + date as the argp implementation changes. If argp is in libc then + this is obviously impossible. + + Instead, argp should use DEFAULT_TEXT_DOMAIN to translate its own + string literals (falling back to the default program domain if that + is not set), and should reserve argp_domain for translating strings + that appear in that argp structure. + + * In a number of places, argp uses the domain of the root argp + structure when translating text from a child argp structure. This is + the direct cause of Robert's bug, because the standard --help and + --version options are implemented as a child argp structure with its + own domain. + + My patch changes this to use argp_domain from the child instead. + However, on reflection, I'm not certain that this is correct; + arguably it needs to walk up the tree until it finds a domain to + use. This depends on whether you think that argp_domain == NULL + means "use default program domain" or "use same domain as parent + argp structure". + + https://lists.gnu.org/r/bug-gnulib/2008-03/msg00144.html + +diff --git a/gl/lib/argp-help.c b/gl/lib/argp-help.c +index 80cdb44937..4e600f269d 100644 +--- a/gl/lib/argp-help.c ++++ b/gl/lib/argp-help.c +@@ -49,6 +49,16 @@ + # include "gettext.h" + #endif + ++#ifdef _LIBC ++# define ARGP_TEXT_DOMAIN "libc" ++#else ++# ifdef DEFAULT_TEXT_DOMAIN ++# define ARGP_TEXT_DOMAIN DEFAULT_TEXT_DOMAIN ++# else ++# define ARGP_TEXT_DOMAIN NULL ++# endif ++#endif ++ + #include "argp.h" + #include "argp-fmtstream.h" + #include "argp-namefrob.h" +@@ -148,7 +158,7 @@ validate_uparams (const struct argp_state *state, struct uparams *upptr) + { + __argp_failure (state, 0, 0, + dgettext (state == NULL ? NULL +- : state->root_argp->argp_domain, ++ : ARGP_TEXT_DOMAIN, + "\ + ARGP_HELP_FMT: %s value is less than or equal to %s"), + "rmargin", up->name); +@@ -224,7 +234,7 @@ fill_in_uparams (const struct argp_state *state) + if (unspec && !un->is_bool) + __argp_failure (state, 0, 0, + dgettext (state == NULL ? NULL +- : state->root_argp->argp_domain, ++ : ARGP_TEXT_DOMAIN, + "\ + %.*s: ARGP_HELP_FMT parameter requires a value"), + (int) var_len, var); +@@ -235,7 +245,7 @@ fill_in_uparams (const struct argp_state *state) + if (un == uparam_names + nuparam_names) + __argp_failure (state, 0, 0, + dgettext (state == NULL ? NULL +- : state->root_argp->argp_domain, "\ ++ : ARGP_TEXT_DOMAIN, "\ + %.*s: Unknown ARGP_HELP_FMT parameter"), + (int) var_len, var); + +@@ -247,7 +257,7 @@ fill_in_uparams (const struct argp_state *state) + { + __argp_failure (state, 0, 0, + dgettext (state == NULL ? NULL +- : state->root_argp->argp_domain, ++ : ARGP_TEXT_DOMAIN, + "Garbage in ARGP_HELP_FMT: %s"), var); + break; + } +@@ -1256,7 +1266,7 @@ hol_entry_help (struct hol_entry *entry, const struct argp_state *state, + __argp_fmtstream_putc (stream, *so); + if (!have_long_opt || uparams.dup_args) + arg (real, " %s", "[%s]", +- state == NULL ? NULL : state->root_argp->argp_domain, ++ state == NULL ? NULL : entry->argp->argp_domain, + stream); + else if (real->arg) + hhstate->suppressed_dup_arg = 1; +@@ -1278,7 +1288,7 @@ hol_entry_help (struct hol_entry *entry, const struct argp_state *state, + should be pretty rare anyway... */ + __argp_fmtstream_puts (stream, + dgettext (state == NULL ? NULL +- : state->root_argp->argp_domain, ++ : entry->argp->argp_domain, + opt->name)); + } + } +@@ -1292,7 +1302,7 @@ hol_entry_help (struct hol_entry *entry, const struct argp_state *state, + comma (uparams.long_opt_col, &pest); + __argp_fmtstream_printf (stream, "--%s", opt->name); + arg (real, "=%s", "[=%s]", +- state == NULL ? NULL : state->root_argp->argp_domain, stream); ++ state == NULL ? NULL : entry->argp->argp_domain, stream); + } + } + +@@ -1312,7 +1322,7 @@ hol_entry_help (struct hol_entry *entry, const struct argp_state *state, + else + { + const char *tstr = real->doc ? dgettext (state == NULL ? NULL +- : state->root_argp->argp_domain, ++ : entry->argp->argp_domain, + real->doc) : 0; + const char *fstr = filter_doc (tstr, real->key, entry->argp, state); + if (fstr && *fstr) +@@ -1361,7 +1371,7 @@ hol_help (struct hol *hol, const struct argp_state *state, + if (hhstate.suppressed_dup_arg && uparams.dup_args_note) + { + const char *tstr = dgettext (state == NULL ? NULL +- : state->root_argp->argp_domain, "\ ++ : ARGP_TEXT_DOMAIN, "\ + Mandatory or optional arguments to long options are also mandatory or \ + optional for any corresponding short options."); + const char *fstr = filter_doc (tstr, ARGP_KEY_HELP_DUP_ARGS_NOTE, +@@ -1727,11 +1737,11 @@ _help (const struct argp *argp, const struct argp_state *state, FILE *stream, + + if (first_pattern) + __argp_fmtstream_printf (fs, "%s %s", +- dgettext (argp->argp_domain, "Usage:"), ++ dgettext (ARGP_TEXT_DOMAIN, "Usage:"), + name); + else + __argp_fmtstream_printf (fs, "%s %s", +- dgettext (argp->argp_domain, " or: "), ++ dgettext (ARGP_TEXT_DOMAIN, " or: "), + name); + + /* We set the lmargin as well as the wmargin, because hol_usage +@@ -1742,7 +1752,7 @@ _help (const struct argp *argp, const struct argp_state *state, FILE *stream, + /* Just show where the options go. */ + { + if (hol->num_entries > 0) +- __argp_fmtstream_puts (fs, dgettext (argp->argp_domain, ++ __argp_fmtstream_puts (fs, dgettext (ARGP_TEXT_DOMAIN, + " [OPTION...]")); + } + else +@@ -1770,7 +1780,7 @@ _help (const struct argp *argp, const struct argp_state *state, FILE *stream, + + if (flags & ARGP_HELP_SEE) + { +- __argp_fmtstream_printf (fs, dgettext (argp->argp_domain, "\ ++ __argp_fmtstream_printf (fs, dgettext (ARGP_TEXT_DOMAIN, "\ + Try '%s --help' or '%s --usage' for more information.\n"), + name, name); + anything = 1; +@@ -1797,7 +1807,7 @@ Try '%s --help' or '%s --usage' for more information.\n"), + { + if (anything) + __argp_fmtstream_putc (fs, '\n'); +- __argp_fmtstream_printf (fs, dgettext (argp->argp_domain, ++ __argp_fmtstream_printf (fs, dgettext (ARGP_TEXT_DOMAIN, + "Report bugs to %s.\n"), + argp_program_bug_address); + anything = 1; +@@ -1998,8 +2008,7 @@ __argp_failure (const struct argp_state *state, int status, int errnum, + # endif + # endif + if (! s && ! (s = strerror (errnum))) +- s = dgettext (state->root_argp->argp_domain, +- "Unknown system error"); ++ s = dgettext (ARGP_TEXT_DOMAIN, "Unknown system error"); + fputs_unlocked (s, stream); + #endif + } +diff --git a/gl/lib/argp-parse.c b/gl/lib/argp-parse.c +index 053495ec03..23f54f3aa7 100644 +--- a/gl/lib/argp-parse.c ++++ b/gl/lib/argp-parse.c +@@ -40,6 +40,16 @@ + #endif + #define N_(msgid) msgid + ++#ifdef _LIBC ++# define ARGP_TEXT_DOMAIN "libc" ++#else ++# ifdef DEFAULT_TEXT_DOMAIN ++# define ARGP_TEXT_DOMAIN DEFAULT_TEXT_DOMAIN ++# else ++# define ARGP_TEXT_DOMAIN NULL ++# endif ++#endif ++ + #include "argp.h" + #include "argp-namefrob.h" + +@@ -135,7 +145,8 @@ argp_default_parser (int key, char *arg, struct argp_state *state) + } + + static const struct argp argp_default_argp = +- {argp_default_options, &argp_default_parser, NULL, NULL, NULL, NULL, "libc"}; ++ {argp_default_options, &argp_default_parser, NULL, NULL, NULL, NULL, ++ ARGP_TEXT_DOMAIN}; + + + static const struct argp_option argp_version_options[] = +@@ -156,7 +167,7 @@ argp_version_parser (int key, char *arg, struct argp_state *state) + fprintf (state->out_stream, "%s\n", argp_program_version); + else + __argp_error (state, "%s", +- dgettext (state->root_argp->argp_domain, ++ dgettext (ARGP_TEXT_DOMAIN, + "(PROGRAM ERROR) No version known!?")); + if (! (state->flags & ARGP_NO_EXIT)) + exit (0); +@@ -168,7 +179,8 @@ argp_version_parser (int key, char *arg, struct argp_state *state) + } + + static const struct argp argp_version_argp = +- {argp_version_options, &argp_version_parser, NULL, NULL, NULL, NULL, "libc"}; ++ {argp_version_options, &argp_version_parser, NULL, NULL, NULL, NULL, ++ ARGP_TEXT_DOMAIN}; + + /* Returns the offset into the getopt long options array LONG_OPTIONS of a + long option with called NAME, or -1 if none is found. Passing NULL as +@@ -609,8 +621,7 @@ parser_finalize (struct parser *parser, + if (!(parser->state.flags & ARGP_NO_ERRS) + && parser->state.err_stream) + fprintf (parser->state.err_stream, +- dgettext (parser->argp->argp_domain, +- "%s: Too many arguments\n"), ++ dgettext (ARGP_TEXT_DOMAIN, "%s: Too many arguments\n"), + parser->state.name); + err = EBADKEY; + } +@@ -759,7 +770,7 @@ parser_parse_opt (struct parser *parser, int opt, char *val) + N_("(PROGRAM ERROR) Option should have been recognized!?"); + if (group_key == 0) + __argp_error (&parser->state, "-%c: %s", opt, +- dgettext (parser->argp->argp_domain, bad_key_err)); ++ dgettext (ARGP_TEXT_DOMAIN, bad_key_err)); + else + { + struct option *long_opt = parser->long_opts; +@@ -767,7 +778,7 @@ parser_parse_opt (struct parser *parser, int opt, char *val) + long_opt++; + __argp_error (&parser->state, "--%s: %s", + long_opt->name ? long_opt->name : "???", +- dgettext (parser->argp->argp_domain, bad_key_err)); ++ dgettext (ARGP_TEXT_DOMAIN, bad_key_err)); + } + } + |