1 /* Convenience header for conditional use of GNU <libintl.h>.
2 Copyright (C) 1995-1998, 2000-2002, 2004-2006, 2009-2024 Free Software
5 This file is free software: you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as
7 published by the Free Software Foundation; either version 2.1 of the
8 License, or (at your option) any later version.
10 This file is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License
16 along with this program. If not, see <https://www.gnu.org/licenses/>. */
19 #define _LIBGETTEXT_H 1
21 /* NLS can be disabled through the configure --disable-nls option
22 or through "#define ENABLE NLS 0" before including this file. */
23 #if defined ENABLE_NLS && ENABLE_NLS
25 /* Get declarations of GNU message catalog functions. */
28 /* You can set the DEFAULT_TEXT_DOMAIN macro to specify the domain used by
29 the gettext() and ngettext() macros. This is an alternative to calling
30 textdomain(), and is useful for libraries. */
31 # ifdef DEFAULT_TEXT_DOMAIN
33 # define gettext(Msgid) \
34 dgettext (DEFAULT_TEXT_DOMAIN, Msgid)
36 # define ngettext(Msgid1, Msgid2, N) \
37 dngettext (DEFAULT_TEXT_DOMAIN, Msgid1, Msgid2, N)
42 /* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which
43 chokes if dcgettext is defined as a macro. So include it now, to make
44 later inclusions of <locale.h> a NOP. We don't include <libintl.h>
45 as well because people using "gettext.h" will not include <libintl.h>,
46 and also including <libintl.h> would fail on SunOS 4, whereas <locale.h>
52 /* Many header files from the libstdc++ coming with g++ 3.3 or newer include
53 <libintl.h>, which chokes if dcgettext is defined as a macro. So include
54 it now, to make later inclusions of <libintl.h> a NOP. */
55 #if defined(__cplusplus) && defined(__GNUG__) && (__GNUC__ >= 3)
57 # if (__GLIBC__ >= 2 && !defined __UCLIBC__) || _GLIBCXX_HAVE_LIBINTL_H
63 The casts to 'const char *' serve the purpose of producing warnings
64 for invalid uses of the value returned from these functions.
65 On pre-ANSI systems without 'const', the config.h file is supposed to
66 contain "#define const". */
68 # define gettext(Msgid) ((const char *) (Msgid))
70 # define dgettext(Domainname, Msgid) ((void) (Domainname), gettext (Msgid))
72 # define dcgettext(Domainname, Msgid, Category) \
73 ((void) (Category), dgettext (Domainname, Msgid))
75 # define ngettext(Msgid1, Msgid2, N) \
77 ? ((void) (Msgid2), (const char *) (Msgid1)) \
78 : ((void) (Msgid1), (const char *) (Msgid2)))
80 # define dngettext(Domainname, Msgid1, Msgid2, N) \
81 ((void) (Domainname), ngettext (Msgid1, Msgid2, N))
83 # define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \
84 ((void) (Category), dngettext (Domainname, Msgid1, Msgid2, N))
86 # define textdomain(Domainname) ((const char *) (Domainname))
87 # undef bindtextdomain
88 # define bindtextdomain(Domainname, Dirname) \
89 ((void) (Domainname), (const char *) (Dirname))
90 # undef bind_textdomain_codeset
91 # define bind_textdomain_codeset(Domainname, Codeset) \
92 ((void) (Domainname), (const char *) (Codeset))
96 /* Prefer gnulib's setlocale override over libintl's setlocale override. */
97 #ifdef GNULIB_defined_setlocale
99 # define setlocale rpl_setlocale
102 /* A pseudo function call that serves as a marker for the automated
103 extraction of messages, but does not call gettext(). The run-time
104 translation is done at a different place in the code.
105 The argument, String, should be a literal string. Concatenated strings
106 and other string expressions won't work.
107 The macro's expansion is not parenthesized, so that it is suitable as
108 initializer for static 'char[]' or 'const char[]' variables. */
109 #define gettext_noop(String) String
111 /* The separator between msgctxt and msgid in a .mo file. */
112 #define GETTEXT_CONTEXT_GLUE "\004"
114 /* Pseudo function calls, taking a MSGCTXT and a MSGID instead of just a
115 MSGID. MSGCTXT and MSGID must be string literals. MSGCTXT should be
116 short and rarely need to change.
117 The letter 'p' stands for 'particular' or 'special'. */
118 #ifdef DEFAULT_TEXT_DOMAIN
119 # define pgettext(Msgctxt, Msgid) \
120 pgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
122 # define pgettext(Msgctxt, Msgid) \
123 pgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
125 #define dpgettext(Domainname, Msgctxt, Msgid) \
126 pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
127 #define dcpgettext(Domainname, Msgctxt, Msgid, Category) \
128 pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, Category)
129 #ifdef DEFAULT_TEXT_DOMAIN
130 # define npgettext(Msgctxt, Msgid, MsgidPlural, N) \
131 npgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
133 # define npgettext(Msgctxt, Msgid, MsgidPlural, N) \
134 npgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
136 #define dnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N) \
137 npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
138 #define dcnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N, Category) \
139 npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, Category)
141 #if defined __GNUC__ || defined __clang__
149 pgettext_aux (const char *domain
,
150 const char *msg_ctxt_id
, const char *msgid
,
153 const char *translation
= dcgettext (domain
, msg_ctxt_id
, category
);
154 if (translation
== msg_ctxt_id
)
160 #if defined __GNUC__ || defined __clang__
168 npgettext_aux (const char *domain
,
169 const char *msg_ctxt_id
, const char *msgid
,
170 const char *msgid_plural
, unsigned long int n
,
173 const char *translation
=
174 dcngettext (domain
, msg_ctxt_id
, msgid_plural
, n
, category
);
175 if (translation
== msg_ctxt_id
|| translation
== msgid_plural
)
176 return (n
== 1 ? msgid
: msgid_plural
);
181 /* The same thing extended for non-constant arguments. Here MSGCTXT and MSGID
182 can be arbitrary expressions. But for string literals these macros are
183 less efficient than those above. */
187 /* GNULIB_NO_VLA can be defined to disable use of VLAs even if supported.
188 This relates to the -Wvla and -Wvla-larger-than warnings, enabled in
189 the default GCC many warnings set. This allows programs to disable use
190 of VLAs, which may be unintended, or may be awkward to support portably,
191 or may have security implications due to non-deterministic stack usage. */
193 #if (!defined GNULIB_NO_VLA \
194 && defined __STDC_VERSION__ && 199901L <= __STDC_VERSION__ \
195 && !defined __STDC_NO_VLA__)
196 # define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS 1
198 # define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS 0
201 #if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
205 #define pgettext_expr(Msgctxt, Msgid) \
206 dcpgettext_expr (NULL, Msgctxt, Msgid, LC_MESSAGES)
207 #define dpgettext_expr(Domainname, Msgctxt, Msgid) \
208 dcpgettext_expr (Domainname, Msgctxt, Msgid, LC_MESSAGES)
210 #if defined __GNUC__ || defined __clang__
218 dcpgettext_expr (const char *domain
,
219 const char *msgctxt
, const char *msgid
,
222 size_t msgctxt_len
= strlen (msgctxt
) + 1;
223 size_t msgid_len
= strlen (msgid
) + 1;
224 const char *translation
;
225 #if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
226 char msg_ctxt_id
[msgctxt_len
+ msgid_len
];
230 (msgctxt_len
+ msgid_len
<= sizeof (buf
)
232 : (char *) malloc (msgctxt_len
+ msgid_len
));
233 if (msg_ctxt_id
!= NULL
)
236 int found_translation
;
237 memcpy (msg_ctxt_id
, msgctxt
, msgctxt_len
- 1);
238 msg_ctxt_id
[msgctxt_len
- 1] = '\004';
239 memcpy (msg_ctxt_id
+ msgctxt_len
, msgid
, msgid_len
);
240 translation
= dcgettext (domain
, msg_ctxt_id
, category
);
241 found_translation
= (translation
!= msg_ctxt_id
);
242 #if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
243 if (msg_ctxt_id
!= buf
)
246 if (found_translation
)
252 #define npgettext_expr(Msgctxt, Msgid, MsgidPlural, N) \
253 dcnpgettext_expr (NULL, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES)
254 #define dnpgettext_expr(Domainname, Msgctxt, Msgid, MsgidPlural, N) \
255 dcnpgettext_expr (Domainname, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES)
257 #if defined __GNUC__ || defined __clang__
265 dcnpgettext_expr (const char *domain
,
266 const char *msgctxt
, const char *msgid
,
267 const char *msgid_plural
, unsigned long int n
,
270 size_t msgctxt_len
= strlen (msgctxt
) + 1;
271 size_t msgid_len
= strlen (msgid
) + 1;
272 const char *translation
;
273 #if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
274 char msg_ctxt_id
[msgctxt_len
+ msgid_len
];
278 (msgctxt_len
+ msgid_len
<= sizeof (buf
)
280 : (char *) malloc (msgctxt_len
+ msgid_len
));
281 if (msg_ctxt_id
!= NULL
)
284 int found_translation
;
285 memcpy (msg_ctxt_id
, msgctxt
, msgctxt_len
- 1);
286 msg_ctxt_id
[msgctxt_len
- 1] = '\004';
287 memcpy (msg_ctxt_id
+ msgctxt_len
, msgid
, msgid_len
);
288 translation
= dcngettext (domain
, msg_ctxt_id
, msgid_plural
, n
, category
);
289 found_translation
= !(translation
== msg_ctxt_id
|| translation
== msgid_plural
);
290 #if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
291 if (msg_ctxt_id
!= buf
)
294 if (found_translation
)
297 return (n
== 1 ? msgid
: msgid_plural
);
300 #endif /* _LIBGETTEXT_H */