12b15cb3dSCy Schubert /* Convenience header for conditional use of GNU <libintl.h>.
2*a466cc55SCy Schubert Copyright (C) 1995-1998, 2000-2002, 2004-2006, 2009-2018 Free Software
32b15cb3dSCy Schubert Foundation, Inc.
42b15cb3dSCy Schubert
52b15cb3dSCy Schubert This program is free software; you can redistribute it and/or modify
62b15cb3dSCy Schubert it under the terms of the GNU Lesser General Public License as published by
72b15cb3dSCy Schubert the Free Software Foundation; either version 2.1, or (at your option)
82b15cb3dSCy Schubert any later version.
92b15cb3dSCy Schubert
102b15cb3dSCy Schubert This program is distributed in the hope that it will be useful,
112b15cb3dSCy Schubert but WITHOUT ANY WARRANTY; without even the implied warranty of
122b15cb3dSCy Schubert MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
132b15cb3dSCy Schubert GNU Lesser General Public License for more details.
142b15cb3dSCy Schubert
152b15cb3dSCy Schubert You should have received a copy of the GNU Lesser General Public License along
16*a466cc55SCy Schubert with this program; if not, see <https://www.gnu.org/licenses/>. */
172b15cb3dSCy Schubert
182b15cb3dSCy Schubert #ifndef _LIBGETTEXT_H
192b15cb3dSCy Schubert #define _LIBGETTEXT_H 1
202b15cb3dSCy Schubert
21*a466cc55SCy Schubert /* NLS can be disabled through the configure --disable-nls option
22*a466cc55SCy Schubert or through "#define ENABLE NLS 0" before including this file. */
23*a466cc55SCy Schubert #if defined ENABLE_NLS && ENABLE_NLS
242b15cb3dSCy Schubert
252b15cb3dSCy Schubert /* Get declarations of GNU message catalog functions. */
262b15cb3dSCy Schubert # include <libintl.h>
272b15cb3dSCy Schubert
282b15cb3dSCy Schubert /* You can set the DEFAULT_TEXT_DOMAIN macro to specify the domain used by
292b15cb3dSCy Schubert the gettext() and ngettext() macros. This is an alternative to calling
302b15cb3dSCy Schubert textdomain(), and is useful for libraries. */
312b15cb3dSCy Schubert # ifdef DEFAULT_TEXT_DOMAIN
322b15cb3dSCy Schubert # undef gettext
332b15cb3dSCy Schubert # define gettext(Msgid) \
342b15cb3dSCy Schubert dgettext (DEFAULT_TEXT_DOMAIN, Msgid)
352b15cb3dSCy Schubert # undef ngettext
362b15cb3dSCy Schubert # define ngettext(Msgid1, Msgid2, N) \
372b15cb3dSCy Schubert dngettext (DEFAULT_TEXT_DOMAIN, Msgid1, Msgid2, N)
382b15cb3dSCy Schubert # endif
392b15cb3dSCy Schubert
402b15cb3dSCy Schubert #else
412b15cb3dSCy Schubert
422b15cb3dSCy Schubert /* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which
432b15cb3dSCy Schubert chokes if dcgettext is defined as a macro. So include it now, to make
442b15cb3dSCy Schubert later inclusions of <locale.h> a NOP. We don't include <libintl.h>
452b15cb3dSCy Schubert as well because people using "gettext.h" will not include <libintl.h>,
462b15cb3dSCy Schubert and also including <libintl.h> would fail on SunOS 4, whereas <locale.h>
472b15cb3dSCy Schubert is OK. */
482b15cb3dSCy Schubert #if defined(__sun)
492b15cb3dSCy Schubert # include <locale.h>
502b15cb3dSCy Schubert #endif
512b15cb3dSCy Schubert
522b15cb3dSCy Schubert /* Many header files from the libstdc++ coming with g++ 3.3 or newer include
532b15cb3dSCy Schubert <libintl.h>, which chokes if dcgettext is defined as a macro. So include
542b15cb3dSCy Schubert it now, to make later inclusions of <libintl.h> a NOP. */
552b15cb3dSCy Schubert #if defined(__cplusplus) && defined(__GNUG__) && (__GNUC__ >= 3)
562b15cb3dSCy Schubert # include <cstdlib>
572b15cb3dSCy Schubert # if (__GLIBC__ >= 2 && !defined __UCLIBC__) || _GLIBCXX_HAVE_LIBINTL_H
582b15cb3dSCy Schubert # include <libintl.h>
592b15cb3dSCy Schubert # endif
602b15cb3dSCy Schubert #endif
612b15cb3dSCy Schubert
622b15cb3dSCy Schubert /* Disabled NLS.
632b15cb3dSCy Schubert The casts to 'const char *' serve the purpose of producing warnings
642b15cb3dSCy Schubert for invalid uses of the value returned from these functions.
652b15cb3dSCy Schubert On pre-ANSI systems without 'const', the config.h file is supposed to
662b15cb3dSCy Schubert contain "#define const". */
672b15cb3dSCy Schubert # undef gettext
682b15cb3dSCy Schubert # define gettext(Msgid) ((const char *) (Msgid))
692b15cb3dSCy Schubert # undef dgettext
702b15cb3dSCy Schubert # define dgettext(Domainname, Msgid) ((void) (Domainname), gettext (Msgid))
712b15cb3dSCy Schubert # undef dcgettext
722b15cb3dSCy Schubert # define dcgettext(Domainname, Msgid, Category) \
732b15cb3dSCy Schubert ((void) (Category), dgettext (Domainname, Msgid))
742b15cb3dSCy Schubert # undef ngettext
752b15cb3dSCy Schubert # define ngettext(Msgid1, Msgid2, N) \
762b15cb3dSCy Schubert ((N) == 1 \
772b15cb3dSCy Schubert ? ((void) (Msgid2), (const char *) (Msgid1)) \
782b15cb3dSCy Schubert : ((void) (Msgid1), (const char *) (Msgid2)))
792b15cb3dSCy Schubert # undef dngettext
802b15cb3dSCy Schubert # define dngettext(Domainname, Msgid1, Msgid2, N) \
812b15cb3dSCy Schubert ((void) (Domainname), ngettext (Msgid1, Msgid2, N))
822b15cb3dSCy Schubert # undef dcngettext
832b15cb3dSCy Schubert # define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \
842b15cb3dSCy Schubert ((void) (Category), dngettext (Domainname, Msgid1, Msgid2, N))
852b15cb3dSCy Schubert # undef textdomain
862b15cb3dSCy Schubert # define textdomain(Domainname) ((const char *) (Domainname))
872b15cb3dSCy Schubert # undef bindtextdomain
882b15cb3dSCy Schubert # define bindtextdomain(Domainname, Dirname) \
892b15cb3dSCy Schubert ((void) (Domainname), (const char *) (Dirname))
902b15cb3dSCy Schubert # undef bind_textdomain_codeset
912b15cb3dSCy Schubert # define bind_textdomain_codeset(Domainname, Codeset) \
922b15cb3dSCy Schubert ((void) (Domainname), (const char *) (Codeset))
932b15cb3dSCy Schubert
942b15cb3dSCy Schubert #endif
952b15cb3dSCy Schubert
962b15cb3dSCy Schubert /* Prefer gnulib's setlocale override over libintl's setlocale override. */
972b15cb3dSCy Schubert #ifdef GNULIB_defined_setlocale
982b15cb3dSCy Schubert # undef setlocale
992b15cb3dSCy Schubert # define setlocale rpl_setlocale
1002b15cb3dSCy Schubert #endif
1012b15cb3dSCy Schubert
1022b15cb3dSCy Schubert /* A pseudo function call that serves as a marker for the automated
1032b15cb3dSCy Schubert extraction of messages, but does not call gettext(). The run-time
1042b15cb3dSCy Schubert translation is done at a different place in the code.
1052b15cb3dSCy Schubert The argument, String, should be a literal string. Concatenated strings
1062b15cb3dSCy Schubert and other string expressions won't work.
1072b15cb3dSCy Schubert The macro's expansion is not parenthesized, so that it is suitable as
1082b15cb3dSCy Schubert initializer for static 'char[]' or 'const char[]' variables. */
1092b15cb3dSCy Schubert #define gettext_noop(String) String
1102b15cb3dSCy Schubert
1112b15cb3dSCy Schubert /* The separator between msgctxt and msgid in a .mo file. */
1122b15cb3dSCy Schubert #define GETTEXT_CONTEXT_GLUE "\004"
1132b15cb3dSCy Schubert
1142b15cb3dSCy Schubert /* Pseudo function calls, taking a MSGCTXT and a MSGID instead of just a
1152b15cb3dSCy Schubert MSGID. MSGCTXT and MSGID must be string literals. MSGCTXT should be
1162b15cb3dSCy Schubert short and rarely need to change.
1172b15cb3dSCy Schubert The letter 'p' stands for 'particular' or 'special'. */
1182b15cb3dSCy Schubert #ifdef DEFAULT_TEXT_DOMAIN
1192b15cb3dSCy Schubert # define pgettext(Msgctxt, Msgid) \
1202b15cb3dSCy Schubert pgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
1212b15cb3dSCy Schubert #else
1222b15cb3dSCy Schubert # define pgettext(Msgctxt, Msgid) \
1232b15cb3dSCy Schubert pgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
1242b15cb3dSCy Schubert #endif
1252b15cb3dSCy Schubert #define dpgettext(Domainname, Msgctxt, Msgid) \
1262b15cb3dSCy Schubert pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
1272b15cb3dSCy Schubert #define dcpgettext(Domainname, Msgctxt, Msgid, Category) \
1282b15cb3dSCy Schubert pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, Category)
1292b15cb3dSCy Schubert #ifdef DEFAULT_TEXT_DOMAIN
1302b15cb3dSCy Schubert # define npgettext(Msgctxt, Msgid, MsgidPlural, N) \
1312b15cb3dSCy Schubert npgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
1322b15cb3dSCy Schubert #else
1332b15cb3dSCy Schubert # define npgettext(Msgctxt, Msgid, MsgidPlural, N) \
1342b15cb3dSCy Schubert npgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
1352b15cb3dSCy Schubert #endif
1362b15cb3dSCy Schubert #define dnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N) \
1372b15cb3dSCy Schubert npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
1382b15cb3dSCy Schubert #define dcnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N, Category) \
1392b15cb3dSCy Schubert npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, Category)
1402b15cb3dSCy Schubert
1412b15cb3dSCy Schubert #ifdef __GNUC__
1422b15cb3dSCy Schubert __inline
1432b15cb3dSCy Schubert #else
1442b15cb3dSCy Schubert #ifdef __cplusplus
1452b15cb3dSCy Schubert inline
1462b15cb3dSCy Schubert #endif
1472b15cb3dSCy Schubert #endif
1482b15cb3dSCy Schubert static const char *
pgettext_aux(const char * domain,const char * msg_ctxt_id,const char * msgid,int category)1492b15cb3dSCy Schubert pgettext_aux (const char *domain,
1502b15cb3dSCy Schubert const char *msg_ctxt_id, const char *msgid,
1512b15cb3dSCy Schubert int category)
1522b15cb3dSCy Schubert {
1532b15cb3dSCy Schubert const char *translation = dcgettext (domain, msg_ctxt_id, category);
1542b15cb3dSCy Schubert if (translation == msg_ctxt_id)
1552b15cb3dSCy Schubert return msgid;
1562b15cb3dSCy Schubert else
1572b15cb3dSCy Schubert return translation;
1582b15cb3dSCy Schubert }
1592b15cb3dSCy Schubert
1602b15cb3dSCy Schubert #ifdef __GNUC__
1612b15cb3dSCy Schubert __inline
1622b15cb3dSCy Schubert #else
1632b15cb3dSCy Schubert #ifdef __cplusplus
1642b15cb3dSCy Schubert inline
1652b15cb3dSCy Schubert #endif
1662b15cb3dSCy Schubert #endif
1672b15cb3dSCy Schubert static const char *
npgettext_aux(const char * domain,const char * msg_ctxt_id,const char * msgid,const char * msgid_plural,unsigned long int n,int category)1682b15cb3dSCy Schubert npgettext_aux (const char *domain,
1692b15cb3dSCy Schubert const char *msg_ctxt_id, const char *msgid,
1702b15cb3dSCy Schubert const char *msgid_plural, unsigned long int n,
1712b15cb3dSCy Schubert int category)
1722b15cb3dSCy Schubert {
1732b15cb3dSCy Schubert const char *translation =
1742b15cb3dSCy Schubert dcngettext (domain, msg_ctxt_id, msgid_plural, n, category);
1752b15cb3dSCy Schubert if (translation == msg_ctxt_id || translation == msgid_plural)
1762b15cb3dSCy Schubert return (n == 1 ? msgid : msgid_plural);
1772b15cb3dSCy Schubert else
1782b15cb3dSCy Schubert return translation;
1792b15cb3dSCy Schubert }
1802b15cb3dSCy Schubert
1812b15cb3dSCy Schubert /* The same thing extended for non-constant arguments. Here MSGCTXT and MSGID
1822b15cb3dSCy Schubert can be arbitrary expressions. But for string literals these macros are
1832b15cb3dSCy Schubert less efficient than those above. */
1842b15cb3dSCy Schubert
1852b15cb3dSCy Schubert #include <string.h>
1862b15cb3dSCy Schubert
1872b15cb3dSCy Schubert #if (((__GNUC__ >= 3 || __GNUG__ >= 2) && !defined __STRICT_ANSI__) \
188*a466cc55SCy Schubert /* || __STDC_VERSION__ == 199901L
189*a466cc55SCy Schubert || (__STDC_VERSION__ >= 201112L && !defined __STDC_NO_VLA__) */ )
1902b15cb3dSCy Schubert # define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS 1
1912b15cb3dSCy Schubert #else
1922b15cb3dSCy Schubert # define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS 0
1932b15cb3dSCy Schubert #endif
1942b15cb3dSCy Schubert
1952b15cb3dSCy Schubert #if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
1962b15cb3dSCy Schubert #include <stdlib.h>
1972b15cb3dSCy Schubert #endif
1982b15cb3dSCy Schubert
1992b15cb3dSCy Schubert #define pgettext_expr(Msgctxt, Msgid) \
2002b15cb3dSCy Schubert dcpgettext_expr (NULL, Msgctxt, Msgid, LC_MESSAGES)
2012b15cb3dSCy Schubert #define dpgettext_expr(Domainname, Msgctxt, Msgid) \
2022b15cb3dSCy Schubert dcpgettext_expr (Domainname, Msgctxt, Msgid, LC_MESSAGES)
2032b15cb3dSCy Schubert
2042b15cb3dSCy Schubert #ifdef __GNUC__
2052b15cb3dSCy Schubert __inline
2062b15cb3dSCy Schubert #else
2072b15cb3dSCy Schubert #ifdef __cplusplus
2082b15cb3dSCy Schubert inline
2092b15cb3dSCy Schubert #endif
2102b15cb3dSCy Schubert #endif
2112b15cb3dSCy Schubert static const char *
dcpgettext_expr(const char * domain,const char * msgctxt,const char * msgid,int category)2122b15cb3dSCy Schubert dcpgettext_expr (const char *domain,
2132b15cb3dSCy Schubert const char *msgctxt, const char *msgid,
2142b15cb3dSCy Schubert int category)
2152b15cb3dSCy Schubert {
2162b15cb3dSCy Schubert size_t msgctxt_len = strlen (msgctxt) + 1;
2172b15cb3dSCy Schubert size_t msgid_len = strlen (msgid) + 1;
2182b15cb3dSCy Schubert const char *translation;
2192b15cb3dSCy Schubert #if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
2202b15cb3dSCy Schubert char msg_ctxt_id[msgctxt_len + msgid_len];
2212b15cb3dSCy Schubert #else
2222b15cb3dSCy Schubert char buf[1024];
2232b15cb3dSCy Schubert char *msg_ctxt_id =
2242b15cb3dSCy Schubert (msgctxt_len + msgid_len <= sizeof (buf)
2252b15cb3dSCy Schubert ? buf
2262b15cb3dSCy Schubert : (char *) malloc (msgctxt_len + msgid_len));
2272b15cb3dSCy Schubert if (msg_ctxt_id != NULL)
2282b15cb3dSCy Schubert #endif
2292b15cb3dSCy Schubert {
230*a466cc55SCy Schubert int found_translation;
2312b15cb3dSCy Schubert memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1);
2322b15cb3dSCy Schubert msg_ctxt_id[msgctxt_len - 1] = '\004';
2332b15cb3dSCy Schubert memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len);
2342b15cb3dSCy Schubert translation = dcgettext (domain, msg_ctxt_id, category);
235*a466cc55SCy Schubert found_translation = (translation != msg_ctxt_id);
2362b15cb3dSCy Schubert #if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
2372b15cb3dSCy Schubert if (msg_ctxt_id != buf)
2382b15cb3dSCy Schubert free (msg_ctxt_id);
2392b15cb3dSCy Schubert #endif
240*a466cc55SCy Schubert if (found_translation)
2412b15cb3dSCy Schubert return translation;
2422b15cb3dSCy Schubert }
2432b15cb3dSCy Schubert return msgid;
2442b15cb3dSCy Schubert }
2452b15cb3dSCy Schubert
2462b15cb3dSCy Schubert #define npgettext_expr(Msgctxt, Msgid, MsgidPlural, N) \
2472b15cb3dSCy Schubert dcnpgettext_expr (NULL, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES)
2482b15cb3dSCy Schubert #define dnpgettext_expr(Domainname, Msgctxt, Msgid, MsgidPlural, N) \
2492b15cb3dSCy Schubert dcnpgettext_expr (Domainname, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES)
2502b15cb3dSCy Schubert
2512b15cb3dSCy Schubert #ifdef __GNUC__
2522b15cb3dSCy Schubert __inline
2532b15cb3dSCy Schubert #else
2542b15cb3dSCy Schubert #ifdef __cplusplus
2552b15cb3dSCy Schubert inline
2562b15cb3dSCy Schubert #endif
2572b15cb3dSCy Schubert #endif
2582b15cb3dSCy Schubert static const char *
dcnpgettext_expr(const char * domain,const char * msgctxt,const char * msgid,const char * msgid_plural,unsigned long int n,int category)2592b15cb3dSCy Schubert dcnpgettext_expr (const char *domain,
2602b15cb3dSCy Schubert const char *msgctxt, const char *msgid,
2612b15cb3dSCy Schubert const char *msgid_plural, unsigned long int n,
2622b15cb3dSCy Schubert int category)
2632b15cb3dSCy Schubert {
2642b15cb3dSCy Schubert size_t msgctxt_len = strlen (msgctxt) + 1;
2652b15cb3dSCy Schubert size_t msgid_len = strlen (msgid) + 1;
2662b15cb3dSCy Schubert const char *translation;
2672b15cb3dSCy Schubert #if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
2682b15cb3dSCy Schubert char msg_ctxt_id[msgctxt_len + msgid_len];
2692b15cb3dSCy Schubert #else
2702b15cb3dSCy Schubert char buf[1024];
2712b15cb3dSCy Schubert char *msg_ctxt_id =
2722b15cb3dSCy Schubert (msgctxt_len + msgid_len <= sizeof (buf)
2732b15cb3dSCy Schubert ? buf
2742b15cb3dSCy Schubert : (char *) malloc (msgctxt_len + msgid_len));
2752b15cb3dSCy Schubert if (msg_ctxt_id != NULL)
2762b15cb3dSCy Schubert #endif
2772b15cb3dSCy Schubert {
278*a466cc55SCy Schubert int found_translation;
2792b15cb3dSCy Schubert memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1);
2802b15cb3dSCy Schubert msg_ctxt_id[msgctxt_len - 1] = '\004';
2812b15cb3dSCy Schubert memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len);
2822b15cb3dSCy Schubert translation = dcngettext (domain, msg_ctxt_id, msgid_plural, n, category);
283*a466cc55SCy Schubert found_translation = !(translation == msg_ctxt_id || translation == msgid_plural);
2842b15cb3dSCy Schubert #if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
2852b15cb3dSCy Schubert if (msg_ctxt_id != buf)
2862b15cb3dSCy Schubert free (msg_ctxt_id);
2872b15cb3dSCy Schubert #endif
288*a466cc55SCy Schubert if (found_translation)
2892b15cb3dSCy Schubert return translation;
2902b15cb3dSCy Schubert }
2912b15cb3dSCy Schubert return (n == 1 ? msgid : msgid_plural);
2922b15cb3dSCy Schubert }
2932b15cb3dSCy Schubert
2942b15cb3dSCy Schubert #endif /* _LIBGETTEXT_H */
295