1855caec6SPeter Avalos /* Convenience header for conditional use of GNU <libintl.h>.
2*6ea1f93eSDaniel Fojt Copyright (C) 1995-1998, 2000-2002, 2004-2006, 2009-2018 Free Software
344b87433SJohn Marino Foundation, Inc.
4855caec6SPeter Avalos
5855caec6SPeter Avalos This program is free software; you can redistribute it and/or modify
6855caec6SPeter Avalos it under the terms of the GNU General Public License as published by
744b87433SJohn Marino the Free Software Foundation; either version 3, or (at your option)
8855caec6SPeter Avalos any later version.
9855caec6SPeter Avalos
10855caec6SPeter Avalos This program is distributed in the hope that it will be useful,
11855caec6SPeter Avalos but WITHOUT ANY WARRANTY; without even the implied warranty of
12855caec6SPeter Avalos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13855caec6SPeter Avalos GNU General Public License for more details.
14855caec6SPeter Avalos
15855caec6SPeter Avalos You should have received a copy of the GNU General Public License along
16*6ea1f93eSDaniel Fojt with this program; if not, see <https://www.gnu.org/licenses/>. */
17855caec6SPeter Avalos
18855caec6SPeter Avalos #ifndef _LIBGETTEXT_H
19855caec6SPeter Avalos #define _LIBGETTEXT_H 1
20855caec6SPeter Avalos
21*6ea1f93eSDaniel Fojt /* NLS can be disabled through the configure --disable-nls option
22*6ea1f93eSDaniel Fojt or through "#define ENABLE NLS 0" before including this file. */
23*6ea1f93eSDaniel Fojt #if defined ENABLE_NLS && ENABLE_NLS
24855caec6SPeter Avalos
25855caec6SPeter Avalos /* Get declarations of GNU message catalog functions. */
26855caec6SPeter Avalos # include <libintl.h>
27855caec6SPeter Avalos
2844b87433SJohn Marino /* You can set the DEFAULT_TEXT_DOMAIN macro to specify the domain used by
2944b87433SJohn Marino the gettext() and ngettext() macros. This is an alternative to calling
3044b87433SJohn Marino textdomain(), and is useful for libraries. */
3144b87433SJohn Marino # ifdef DEFAULT_TEXT_DOMAIN
3244b87433SJohn Marino # undef gettext
3344b87433SJohn Marino # define gettext(Msgid) \
3444b87433SJohn Marino dgettext (DEFAULT_TEXT_DOMAIN, Msgid)
3544b87433SJohn Marino # undef ngettext
3644b87433SJohn Marino # define ngettext(Msgid1, Msgid2, N) \
3744b87433SJohn Marino dngettext (DEFAULT_TEXT_DOMAIN, Msgid1, Msgid2, N)
3844b87433SJohn Marino # endif
3944b87433SJohn Marino
40855caec6SPeter Avalos #else
41855caec6SPeter Avalos
42855caec6SPeter Avalos /* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which
43855caec6SPeter Avalos chokes if dcgettext is defined as a macro. So include it now, to make
44855caec6SPeter Avalos later inclusions of <locale.h> a NOP. We don't include <libintl.h>
45855caec6SPeter Avalos as well because people using "gettext.h" will not include <libintl.h>,
46855caec6SPeter Avalos and also including <libintl.h> would fail on SunOS 4, whereas <locale.h>
47855caec6SPeter Avalos is OK. */
48855caec6SPeter Avalos #if defined(__sun)
49855caec6SPeter Avalos # include <locale.h>
50855caec6SPeter Avalos #endif
51855caec6SPeter Avalos
5244b87433SJohn Marino /* Many header files from the libstdc++ coming with g++ 3.3 or newer include
5344b87433SJohn Marino <libintl.h>, which chokes if dcgettext is defined as a macro. So include
5444b87433SJohn Marino it now, to make later inclusions of <libintl.h> a NOP. */
5544b87433SJohn Marino #if defined(__cplusplus) && defined(__GNUG__) && (__GNUC__ >= 3)
5644b87433SJohn Marino # include <cstdlib>
57008e37b6SJohn Marino # if (__GLIBC__ >= 2 && !defined __UCLIBC__) || _GLIBCXX_HAVE_LIBINTL_H
5844b87433SJohn Marino # include <libintl.h>
5944b87433SJohn Marino # endif
6044b87433SJohn Marino #endif
6144b87433SJohn Marino
62855caec6SPeter Avalos /* Disabled NLS.
63855caec6SPeter Avalos The casts to 'const char *' serve the purpose of producing warnings
64855caec6SPeter Avalos for invalid uses of the value returned from these functions.
65855caec6SPeter Avalos On pre-ANSI systems without 'const', the config.h file is supposed to
66855caec6SPeter Avalos contain "#define const". */
6744b87433SJohn Marino # undef gettext
68855caec6SPeter Avalos # define gettext(Msgid) ((const char *) (Msgid))
6944b87433SJohn Marino # undef dgettext
7044b87433SJohn Marino # define dgettext(Domainname, Msgid) ((void) (Domainname), gettext (Msgid))
7144b87433SJohn Marino # undef dcgettext
7244b87433SJohn Marino # define dcgettext(Domainname, Msgid, Category) \
7344b87433SJohn Marino ((void) (Category), dgettext (Domainname, Msgid))
7444b87433SJohn Marino # undef ngettext
75855caec6SPeter Avalos # define ngettext(Msgid1, Msgid2, N) \
7644b87433SJohn Marino ((N) == 1 \
7744b87433SJohn Marino ? ((void) (Msgid2), (const char *) (Msgid1)) \
7844b87433SJohn Marino : ((void) (Msgid1), (const char *) (Msgid2)))
7944b87433SJohn Marino # undef dngettext
80855caec6SPeter Avalos # define dngettext(Domainname, Msgid1, Msgid2, N) \
8144b87433SJohn Marino ((void) (Domainname), ngettext (Msgid1, Msgid2, N))
8244b87433SJohn Marino # undef dcngettext
83855caec6SPeter Avalos # define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \
8444b87433SJohn Marino ((void) (Category), dngettext (Domainname, Msgid1, Msgid2, N))
8544b87433SJohn Marino # undef textdomain
86855caec6SPeter Avalos # define textdomain(Domainname) ((const char *) (Domainname))
8744b87433SJohn Marino # undef bindtextdomain
8844b87433SJohn Marino # define bindtextdomain(Domainname, Dirname) \
8944b87433SJohn Marino ((void) (Domainname), (const char *) (Dirname))
9044b87433SJohn Marino # undef bind_textdomain_codeset
9144b87433SJohn Marino # define bind_textdomain_codeset(Domainname, Codeset) \
9244b87433SJohn Marino ((void) (Domainname), (const char *) (Codeset))
93855caec6SPeter Avalos
94855caec6SPeter Avalos #endif
95855caec6SPeter Avalos
96008e37b6SJohn Marino /* Prefer gnulib's setlocale override over libintl's setlocale override. */
97008e37b6SJohn Marino #ifdef GNULIB_defined_setlocale
98008e37b6SJohn Marino # undef setlocale
99008e37b6SJohn Marino # define setlocale rpl_setlocale
100008e37b6SJohn Marino #endif
101008e37b6SJohn Marino
102855caec6SPeter Avalos /* A pseudo function call that serves as a marker for the automated
103855caec6SPeter Avalos extraction of messages, but does not call gettext(). The run-time
104855caec6SPeter Avalos translation is done at a different place in the code.
105855caec6SPeter Avalos The argument, String, should be a literal string. Concatenated strings
106855caec6SPeter Avalos and other string expressions won't work.
107855caec6SPeter Avalos The macro's expansion is not parenthesized, so that it is suitable as
108855caec6SPeter Avalos initializer for static 'char[]' or 'const char[]' variables. */
109855caec6SPeter Avalos #define gettext_noop(String) String
110855caec6SPeter Avalos
11144b87433SJohn Marino /* The separator between msgctxt and msgid in a .mo file. */
11244b87433SJohn Marino #define GETTEXT_CONTEXT_GLUE "\004"
11344b87433SJohn Marino
11444b87433SJohn Marino /* Pseudo function calls, taking a MSGCTXT and a MSGID instead of just a
11544b87433SJohn Marino MSGID. MSGCTXT and MSGID must be string literals. MSGCTXT should be
11644b87433SJohn Marino short and rarely need to change.
11744b87433SJohn Marino The letter 'p' stands for 'particular' or 'special'. */
11844b87433SJohn Marino #ifdef DEFAULT_TEXT_DOMAIN
11944b87433SJohn Marino # define pgettext(Msgctxt, Msgid) \
12044b87433SJohn Marino pgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
12144b87433SJohn Marino #else
12244b87433SJohn Marino # define pgettext(Msgctxt, Msgid) \
12344b87433SJohn Marino pgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
12444b87433SJohn Marino #endif
12544b87433SJohn Marino #define dpgettext(Domainname, Msgctxt, Msgid) \
12644b87433SJohn Marino pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
12744b87433SJohn Marino #define dcpgettext(Domainname, Msgctxt, Msgid, Category) \
12844b87433SJohn Marino pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, Category)
12944b87433SJohn Marino #ifdef DEFAULT_TEXT_DOMAIN
13044b87433SJohn Marino # define npgettext(Msgctxt, Msgid, MsgidPlural, N) \
13144b87433SJohn Marino npgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
13244b87433SJohn Marino #else
13344b87433SJohn Marino # define npgettext(Msgctxt, Msgid, MsgidPlural, N) \
13444b87433SJohn Marino npgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
13544b87433SJohn Marino #endif
13644b87433SJohn Marino #define dnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N) \
13744b87433SJohn Marino npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
13844b87433SJohn Marino #define dcnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N, Category) \
13944b87433SJohn Marino npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, Category)
14044b87433SJohn Marino
14144b87433SJohn Marino #ifdef __GNUC__
14244b87433SJohn Marino __inline
14344b87433SJohn Marino #else
14444b87433SJohn Marino #ifdef __cplusplus
14544b87433SJohn Marino inline
14644b87433SJohn Marino #endif
14744b87433SJohn Marino #endif
14844b87433SJohn Marino static const char *
pgettext_aux(const char * domain,const char * msg_ctxt_id,const char * msgid,int category)14944b87433SJohn Marino pgettext_aux (const char *domain,
15044b87433SJohn Marino const char *msg_ctxt_id, const char *msgid,
15144b87433SJohn Marino int category)
15244b87433SJohn Marino {
15344b87433SJohn Marino const char *translation = dcgettext (domain, msg_ctxt_id, category);
15444b87433SJohn Marino if (translation == msg_ctxt_id)
15544b87433SJohn Marino return msgid;
15644b87433SJohn Marino else
15744b87433SJohn Marino return translation;
15844b87433SJohn Marino }
15944b87433SJohn Marino
16044b87433SJohn Marino #ifdef __GNUC__
16144b87433SJohn Marino __inline
16244b87433SJohn Marino #else
16344b87433SJohn Marino #ifdef __cplusplus
16444b87433SJohn Marino inline
16544b87433SJohn Marino #endif
16644b87433SJohn Marino #endif
16744b87433SJohn Marino 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)16844b87433SJohn Marino npgettext_aux (const char *domain,
16944b87433SJohn Marino const char *msg_ctxt_id, const char *msgid,
17044b87433SJohn Marino const char *msgid_plural, unsigned long int n,
17144b87433SJohn Marino int category)
17244b87433SJohn Marino {
17344b87433SJohn Marino const char *translation =
17444b87433SJohn Marino dcngettext (domain, msg_ctxt_id, msgid_plural, n, category);
17544b87433SJohn Marino if (translation == msg_ctxt_id || translation == msgid_plural)
17644b87433SJohn Marino return (n == 1 ? msgid : msgid_plural);
17744b87433SJohn Marino else
17844b87433SJohn Marino return translation;
17944b87433SJohn Marino }
18044b87433SJohn Marino
18144b87433SJohn Marino /* The same thing extended for non-constant arguments. Here MSGCTXT and MSGID
18244b87433SJohn Marino can be arbitrary expressions. But for string literals these macros are
18344b87433SJohn Marino less efficient than those above. */
18444b87433SJohn Marino
18544b87433SJohn Marino #include <string.h>
18644b87433SJohn Marino
1874536c563SJohn Marino #if (((__GNUC__ >= 3 || __GNUG__ >= 2) && !defined __STRICT_ANSI__) \
188*6ea1f93eSDaniel Fojt /* || (__STDC_VERSION__ == 199901L && !defined __HP_cc)
189*6ea1f93eSDaniel Fojt || (__STDC_VERSION__ >= 201112L && !defined __STDC_NO_VLA__) */ )
1904536c563SJohn Marino # define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS 1
1914536c563SJohn Marino #else
1924536c563SJohn Marino # define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS 0
1934536c563SJohn Marino #endif
19444b87433SJohn Marino
19544b87433SJohn Marino #if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
19644b87433SJohn Marino #include <stdlib.h>
19744b87433SJohn Marino #endif
19844b87433SJohn Marino
19944b87433SJohn Marino #define pgettext_expr(Msgctxt, Msgid) \
20044b87433SJohn Marino dcpgettext_expr (NULL, Msgctxt, Msgid, LC_MESSAGES)
20144b87433SJohn Marino #define dpgettext_expr(Domainname, Msgctxt, Msgid) \
20244b87433SJohn Marino dcpgettext_expr (Domainname, Msgctxt, Msgid, LC_MESSAGES)
20344b87433SJohn Marino
20444b87433SJohn Marino #ifdef __GNUC__
20544b87433SJohn Marino __inline
20644b87433SJohn Marino #else
20744b87433SJohn Marino #ifdef __cplusplus
20844b87433SJohn Marino inline
20944b87433SJohn Marino #endif
21044b87433SJohn Marino #endif
21144b87433SJohn Marino static const char *
dcpgettext_expr(const char * domain,const char * msgctxt,const char * msgid,int category)21244b87433SJohn Marino dcpgettext_expr (const char *domain,
21344b87433SJohn Marino const char *msgctxt, const char *msgid,
21444b87433SJohn Marino int category)
21544b87433SJohn Marino {
21644b87433SJohn Marino size_t msgctxt_len = strlen (msgctxt) + 1;
21744b87433SJohn Marino size_t msgid_len = strlen (msgid) + 1;
21844b87433SJohn Marino const char *translation;
21944b87433SJohn Marino #if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
22044b87433SJohn Marino char msg_ctxt_id[msgctxt_len + msgid_len];
22144b87433SJohn Marino #else
22244b87433SJohn Marino char buf[1024];
22344b87433SJohn Marino char *msg_ctxt_id =
22444b87433SJohn Marino (msgctxt_len + msgid_len <= sizeof (buf)
22544b87433SJohn Marino ? buf
22644b87433SJohn Marino : (char *) malloc (msgctxt_len + msgid_len));
22744b87433SJohn Marino if (msg_ctxt_id != NULL)
22844b87433SJohn Marino #endif
22944b87433SJohn Marino {
230*6ea1f93eSDaniel Fojt int found_translation;
23144b87433SJohn Marino memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1);
23244b87433SJohn Marino msg_ctxt_id[msgctxt_len - 1] = '\004';
23344b87433SJohn Marino memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len);
23444b87433SJohn Marino translation = dcgettext (domain, msg_ctxt_id, category);
235*6ea1f93eSDaniel Fojt found_translation = (translation != msg_ctxt_id);
23644b87433SJohn Marino #if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
23744b87433SJohn Marino if (msg_ctxt_id != buf)
23844b87433SJohn Marino free (msg_ctxt_id);
23944b87433SJohn Marino #endif
240*6ea1f93eSDaniel Fojt if (found_translation)
24144b87433SJohn Marino return translation;
24244b87433SJohn Marino }
24344b87433SJohn Marino return msgid;
24444b87433SJohn Marino }
24544b87433SJohn Marino
24644b87433SJohn Marino #define npgettext_expr(Msgctxt, Msgid, MsgidPlural, N) \
24744b87433SJohn Marino dcnpgettext_expr (NULL, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES)
24844b87433SJohn Marino #define dnpgettext_expr(Domainname, Msgctxt, Msgid, MsgidPlural, N) \
24944b87433SJohn Marino dcnpgettext_expr (Domainname, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES)
25044b87433SJohn Marino
25144b87433SJohn Marino #ifdef __GNUC__
25244b87433SJohn Marino __inline
25344b87433SJohn Marino #else
25444b87433SJohn Marino #ifdef __cplusplus
25544b87433SJohn Marino inline
25644b87433SJohn Marino #endif
25744b87433SJohn Marino #endif
25844b87433SJohn Marino static const char *
dcnpgettext_expr(const char * domain,const char * msgctxt,const char * msgid,const char * msgid_plural,unsigned long int n,int category)25944b87433SJohn Marino dcnpgettext_expr (const char *domain,
26044b87433SJohn Marino const char *msgctxt, const char *msgid,
26144b87433SJohn Marino const char *msgid_plural, unsigned long int n,
26244b87433SJohn Marino int category)
26344b87433SJohn Marino {
26444b87433SJohn Marino size_t msgctxt_len = strlen (msgctxt) + 1;
26544b87433SJohn Marino size_t msgid_len = strlen (msgid) + 1;
26644b87433SJohn Marino const char *translation;
26744b87433SJohn Marino #if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
26844b87433SJohn Marino char msg_ctxt_id[msgctxt_len + msgid_len];
26944b87433SJohn Marino #else
27044b87433SJohn Marino char buf[1024];
27144b87433SJohn Marino char *msg_ctxt_id =
27244b87433SJohn Marino (msgctxt_len + msgid_len <= sizeof (buf)
27344b87433SJohn Marino ? buf
27444b87433SJohn Marino : (char *) malloc (msgctxt_len + msgid_len));
27544b87433SJohn Marino if (msg_ctxt_id != NULL)
27644b87433SJohn Marino #endif
27744b87433SJohn Marino {
278*6ea1f93eSDaniel Fojt int found_translation;
27944b87433SJohn Marino memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1);
28044b87433SJohn Marino msg_ctxt_id[msgctxt_len - 1] = '\004';
28144b87433SJohn Marino memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len);
28244b87433SJohn Marino translation = dcngettext (domain, msg_ctxt_id, msgid_plural, n, category);
283*6ea1f93eSDaniel Fojt found_translation = !(translation == msg_ctxt_id || translation == msgid_plural);
28444b87433SJohn Marino #if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
28544b87433SJohn Marino if (msg_ctxt_id != buf)
28644b87433SJohn Marino free (msg_ctxt_id);
28744b87433SJohn Marino #endif
288*6ea1f93eSDaniel Fojt if (found_translation)
28944b87433SJohn Marino return translation;
29044b87433SJohn Marino }
29144b87433SJohn Marino return (n == 1 ? msgid : msgid_plural);
29244b87433SJohn Marino }
29344b87433SJohn Marino
294855caec6SPeter Avalos #endif /* _LIBGETTEXT_H */
295