[PATCH v2 6/7] posix: let the getopt caller choose the textdomain for translation
Vivien Kraus
vivien@planete-kraus.eu
Thu May 29 17:28:01 GMT 2025
Using the same solution as for the option translation context, a new
opttextdomain variable is defined.
---
manual/getopt.texi | 11 +++++++++--
posix/Versions | 2 +-
posix/bits/getopt_core.h | 5 +++++
posix/getopt.c | 28 ++++++++++++++++++++--------
posix/getopt_int.h | 1 +
posix/tstgetoptl.c | 9 +++------
6 files changed, 39 insertions(+), 17 deletions(-)
diff --git a/manual/getopt.texi b/manual/getopt.texi
index 3eb44849f0..af2c65347b 100644
--- a/manual/getopt.texi
+++ b/manual/getopt.texi
@@ -59,8 +59,15 @@ names in the current textdomain. Since option names may be short words
instead of long sentences, they may have different translations in
other places of the program. @xref{Contexts, , Using contexts for
solving ambiguities, gettext, the GNU Gettext manual}, for more
-information. If this is @code{NULL}, then the translations will be
-retrieved without a context.
+information. If this is @code{NULL} (the default), then the
+translations will be retrieved without a context.
+@end deftypevar
+
+@deftypevar {const char *} opttextdomain
+Option names may be translated in a textdomain that is not currently
+the default (@pxref{Interface to gettext, , The Interface, gettext,
+the GNU Gettext manual}). If this is @code{NULL} (the default), the
+translation will be searched in the current text domain.
@end deftypevar
@deftypefun int getopt (int @var{argc}, char *const *@var{argv}, const char *@var{options})
diff --git a/posix/Versions b/posix/Versions
index 3ef3609711..0fe3d103f3 100644
--- a/posix/Versions
+++ b/posix/Versions
@@ -18,7 +18,7 @@ libc {
__environ; _environ;
# variables in normal name space
- environ; optarg; opterr; optind; optopt; optctxt;
+ environ; optarg; opterr; optind; optopt; optctxt; opttextdomain;
re_max_failures; re_syntax_options;
# a*
diff --git a/posix/bits/getopt_core.h b/posix/bits/getopt_core.h
index 32bf787491..6d651d099a 100644
--- a/posix/bits/getopt_core.h
+++ b/posix/bits/getopt_core.h
@@ -64,6 +64,11 @@ extern int optopt;
extern const char *optctxt;
+/* Callers store the textdomain to use to retrieve option names, or
+ NULL to use the current textdomain. */
+
+extern const char *opttextdomain;
+
/* Get definitions and prototypes for functions to process the
arguments in ARGV (ARGC of them, minus the program name) for
options given in OPTS.
diff --git a/posix/getopt.c b/posix/getopt.c
index 62a2486002..632c063805 100644
--- a/posix/getopt.c
+++ b/posix/getopt.c
@@ -118,6 +118,11 @@ int optopt = '?';
const char *optctxt = NULL;
+/* Callers store the textdomain in which the option names are to be
+ looked up. */
+
+const char *opttextdomain = NULL;
+
/* Keep a global copy of all internal members of getopt_data. */
static struct _getopt_data getopt_data;
@@ -188,7 +193,8 @@ exchange (char **argv, struct _getopt_data *d)
/* FIXME: use pgettext_expr when available. */
static const char *
-translate_option_name (const char *context, const char *long_option_name)
+translate_option_name (const char *context, const char *textdomain,
+ const char *long_option_name)
{
char *msgid;
const char *translated = long_option_name;
@@ -201,7 +207,7 @@ translate_option_name (const char *context, const char *long_option_name)
strcpy (msgid, context);
msgid[strlen (context)] = '\004';
strcpy (msgid + strlen (context) + 1, long_option_name);
- translated = gettext (msgid);
+ translated = dgettext (textdomain, msgid);
if (!strcmp (translated, msgid))
{
translated = long_option_name;
@@ -210,12 +216,13 @@ translate_option_name (const char *context, const char *long_option_name)
free (msgid);
}
else
- translated = gettext (long_option_name);
+ translated = dgettext (textdomain, long_option_name);
return translated;
}
-/* Return 1 iff a translation for opt_name has been found and it
- matches the substring from argument, length argument_length.
+/* Return 1 iff a translation for opt_name in opt_textdomain has been
+ found and it matches the substring from argument, length
+ argument_length.
The translation is disambiguated iff translation_context is not
NULL.
@@ -223,9 +230,11 @@ translate_option_name (const char *context, const char *long_option_name)
static const int
match_translated_option_name (const char *argument, size_t argument_length,
const char *translation_context,
+ const char *opt_textdomain,
const char *opt_name)
{
- const char *translated = translate_option_name (translation_context, opt_name);
+ const char *translated =
+ translate_option_name (translation_context, opt_textdomain, opt_name);
return (!strncmp (translated, argument, argument_length)
&& argument_length == strlen (translated));
}
@@ -274,7 +283,8 @@ process_long_option (int argc, char **argv, const char *optstring,
names. */
for (p = longopts, option_index = 0; p->name; p++, option_index++)
if (match_translated_option_name (d->__nextchar, namelen,
- d->optctxt, p->name))
+ d->optctxt, d->opttextdomain,
+ p->name))
{
/* Exact match found with translation. */
pfound = p;
@@ -398,7 +408,8 @@ process_long_option (int argc, char **argv, const char *optstring,
/* We have found a matching long option. Consume it. */
d->optind++;
d->__nextchar = NULL;
- translated_option_name = translate_option_name (d->optctxt, pfound->name);
+ translated_option_name =
+ translate_option_name (d->optctxt, d->opttextdomain, pfound->name);
if (*nameend)
{
/* Don't test has_arg with >, because some C compilers don't
@@ -802,6 +813,7 @@ _getopt_internal (int argc, char **argv, const char *optstring,
getopt_data.optind = optind;
getopt_data.opterr = opterr;
getopt_data.optctxt = optctxt;
+ getopt_data.opttextdomain = opttextdomain;
result = _getopt_internal_r (argc, argv, optstring, longopts,
longind, long_only, &getopt_data,
diff --git a/posix/getopt_int.h b/posix/getopt_int.h
index 5c10d7b99e..e93f8921d9 100644
--- a/posix/getopt_int.h
+++ b/posix/getopt_int.h
@@ -68,6 +68,7 @@ struct _getopt_data
int optopt;
char *optarg;
const char *optctxt;
+ const char *opttextdomain;
/* Internal members. */
diff --git a/posix/tstgetoptl.c b/posix/tstgetoptl.c
index 5e7fa9c402..03a2911c43 100644
--- a/posix/tstgetoptl.c
+++ b/posix/tstgetoptl.c
@@ -129,13 +129,8 @@ prepare_localedir (void)
fputs ("Cannot call bindtextdomain.\n", stderr);
return -1;
}
- if (textdomain ("tstgetoptl") == NULL)
- {
- fputs ("Cannot call textdomain.\n", stderr);
- return -1;
- }
/* Check that the catalog is OK: */
- if (strcmp (gettext (TRANSLATION_CONTEXT "\004" "color"), "colour") != 0)
+ if (strcmp (dgettext ("tstgetoptl", TRANSLATION_CONTEXT "\004" "color"), "colour") != 0)
{
fputs ("The mo file does not work.\n", stderr);
return -1;
@@ -147,6 +142,7 @@ int
main (int argc, char **argv)
{
static const char *translation_context = TRANSLATION_CONTEXT;
+ static const char *translation_textdomain = "tstgetoptl";
static const struct option options[] =
{
{"required", required_argument, NULL, 'r'},
@@ -172,6 +168,7 @@ main (int argc, char **argv)
return 1;
}
optctxt = translation_context;
+ opttextdomain = translation_textdomain;
while ((c = getopt_long (argc, argv, "abc:", options, NULL)) >= 0)
switch (c)
{
--
2.49.0
More information about the Libc-alpha
mailing list