195b7b453SJohn Marino /* Convenience header for conditional use of GNU <libintl.h>.
2*09d4459fSDaniel Fojt Copyright (C) 1995-1998, 2000-2002, 2004-2006, 2009-2020 Free Software
395b7b453SJohn Marino Foundation, Inc.
495b7b453SJohn Marino
595b7b453SJohn Marino This program is free software; you can redistribute it and/or modify
695b7b453SJohn Marino it under the terms of the GNU General Public License as published by
795b7b453SJohn Marino the Free Software Foundation; either version 3, or (at your option)
895b7b453SJohn Marino any later version.
995b7b453SJohn Marino
1095b7b453SJohn Marino This program is distributed in the hope that it will be useful,
1195b7b453SJohn Marino but WITHOUT ANY WARRANTY; without even the implied warranty of
1295b7b453SJohn Marino MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1395b7b453SJohn Marino GNU General Public License for more details.
1495b7b453SJohn Marino
1595b7b453SJohn Marino You should have received a copy of the GNU General Public License along
16*09d4459fSDaniel Fojt with this program; if not, see <https://www.gnu.org/licenses/>. */
1795b7b453SJohn Marino
1895b7b453SJohn Marino #ifndef _LIBGETTEXT_H
1995b7b453SJohn Marino #define _LIBGETTEXT_H 1
2095b7b453SJohn Marino
21*09d4459fSDaniel Fojt /* NLS can be disabled through the configure --disable-nls option
22*09d4459fSDaniel Fojt or through "#define ENABLE NLS 0" before including this file. */
23*09d4459fSDaniel Fojt #if defined ENABLE_NLS && ENABLE_NLS
2495b7b453SJohn Marino
2595b7b453SJohn Marino /* Get declarations of GNU message catalog functions. */
2695b7b453SJohn Marino # include <libintl.h>
2795b7b453SJohn Marino
2895b7b453SJohn Marino /* You can set the DEFAULT_TEXT_DOMAIN macro to specify the domain used by
2995b7b453SJohn Marino the gettext() and ngettext() macros. This is an alternative to calling
3095b7b453SJohn Marino textdomain(), and is useful for libraries. */
3195b7b453SJohn Marino # ifdef DEFAULT_TEXT_DOMAIN
3295b7b453SJohn Marino # undef gettext
3395b7b453SJohn Marino # define gettext(Msgid) \
3495b7b453SJohn Marino dgettext (DEFAULT_TEXT_DOMAIN, Msgid)
3595b7b453SJohn Marino # undef ngettext
3695b7b453SJohn Marino # define ngettext(Msgid1, Msgid2, N) \
3795b7b453SJohn Marino dngettext (DEFAULT_TEXT_DOMAIN, Msgid1, Msgid2, N)
3895b7b453SJohn Marino # endif
3995b7b453SJohn Marino
4095b7b453SJohn Marino #else
4195b7b453SJohn Marino
4295b7b453SJohn Marino /* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which
4395b7b453SJohn Marino chokes if dcgettext is defined as a macro. So include it now, to make
4495b7b453SJohn Marino later inclusions of <locale.h> a NOP. We don't include <libintl.h>
4595b7b453SJohn Marino as well because people using "gettext.h" will not include <libintl.h>,
4695b7b453SJohn Marino and also including <libintl.h> would fail on SunOS 4, whereas <locale.h>
4795b7b453SJohn Marino is OK. */
4895b7b453SJohn Marino #if defined(__sun)
4995b7b453SJohn Marino # include <locale.h>
5095b7b453SJohn Marino #endif
5195b7b453SJohn Marino
5295b7b453SJohn Marino /* Many header files from the libstdc++ coming with g++ 3.3 or newer include
5395b7b453SJohn Marino <libintl.h>, which chokes if dcgettext is defined as a macro. So include
5495b7b453SJohn Marino it now, to make later inclusions of <libintl.h> a NOP. */
5595b7b453SJohn Marino #if defined(__cplusplus) && defined(__GNUG__) && (__GNUC__ >= 3)
5695b7b453SJohn Marino # include <cstdlib>
57200fbe8dSJohn Marino # if (__GLIBC__ >= 2 && !defined __UCLIBC__) || _GLIBCXX_HAVE_LIBINTL_H
5895b7b453SJohn Marino # include <libintl.h>
5995b7b453SJohn Marino # endif
6095b7b453SJohn Marino #endif
6195b7b453SJohn Marino
6295b7b453SJohn Marino /* Disabled NLS.
6395b7b453SJohn Marino The casts to 'const char *' serve the purpose of producing warnings
6495b7b453SJohn Marino for invalid uses of the value returned from these functions.
6595b7b453SJohn Marino On pre-ANSI systems without 'const', the config.h file is supposed to
6695b7b453SJohn Marino contain "#define const". */
6795b7b453SJohn Marino # undef gettext
6895b7b453SJohn Marino # define gettext(Msgid) ((const char *) (Msgid))
6995b7b453SJohn Marino # undef dgettext
7095b7b453SJohn Marino # define dgettext(Domainname, Msgid) ((void) (Domainname), gettext (Msgid))
7195b7b453SJohn Marino # undef dcgettext
7295b7b453SJohn Marino # define dcgettext(Domainname, Msgid, Category) \
7395b7b453SJohn Marino ((void) (Category), dgettext (Domainname, Msgid))
7495b7b453SJohn Marino # undef ngettext
7595b7b453SJohn Marino # define ngettext(Msgid1, Msgid2, N) \
7695b7b453SJohn Marino ((N) == 1 \
7795b7b453SJohn Marino ? ((void) (Msgid2), (const char *) (Msgid1)) \
7895b7b453SJohn Marino : ((void) (Msgid1), (const char *) (Msgid2)))
7995b7b453SJohn Marino # undef dngettext
8095b7b453SJohn Marino # define dngettext(Domainname, Msgid1, Msgid2, N) \
8195b7b453SJohn Marino ((void) (Domainname), ngettext (Msgid1, Msgid2, N))
8295b7b453SJohn Marino # undef dcngettext
8395b7b453SJohn Marino # define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \
8495b7b453SJohn Marino ((void) (Category), dngettext (Domainname, Msgid1, Msgid2, N))
8595b7b453SJohn Marino # undef textdomain
8695b7b453SJohn Marino # define textdomain(Domainname) ((const char *) (Domainname))
8795b7b453SJohn Marino # undef bindtextdomain
8895b7b453SJohn Marino # define bindtextdomain(Domainname, Dirname) \
8995b7b453SJohn Marino ((void) (Domainname), (const char *) (Dirname))
9095b7b453SJohn Marino # undef bind_textdomain_codeset
9195b7b453SJohn Marino # define bind_textdomain_codeset(Domainname, Codeset) \
9295b7b453SJohn Marino ((void) (Domainname), (const char *) (Codeset))
9395b7b453SJohn Marino
9495b7b453SJohn Marino #endif
9595b7b453SJohn Marino
96200fbe8dSJohn Marino /* Prefer gnulib's setlocale override over libintl's setlocale override. */
97200fbe8dSJohn Marino #ifdef GNULIB_defined_setlocale
98200fbe8dSJohn Marino # undef setlocale
99200fbe8dSJohn Marino # define setlocale rpl_setlocale
100200fbe8dSJohn Marino #endif
101200fbe8dSJohn Marino
10295b7b453SJohn Marino /* A pseudo function call that serves as a marker for the automated
10395b7b453SJohn Marino extraction of messages, but does not call gettext(). The run-time
10495b7b453SJohn Marino translation is done at a different place in the code.
10595b7b453SJohn Marino The argument, String, should be a literal string. Concatenated strings
10695b7b453SJohn Marino and other string expressions won't work.
10795b7b453SJohn Marino The macro's expansion is not parenthesized, so that it is suitable as
10895b7b453SJohn Marino initializer for static 'char[]' or 'const char[]' variables. */
10995b7b453SJohn Marino #define gettext_noop(String) String
11095b7b453SJohn Marino
11195b7b453SJohn Marino /* The separator between msgctxt and msgid in a .mo file. */
11295b7b453SJohn Marino #define GETTEXT_CONTEXT_GLUE "\004"
11395b7b453SJohn Marino
11495b7b453SJohn Marino /* Pseudo function calls, taking a MSGCTXT and a MSGID instead of just a
11595b7b453SJohn Marino MSGID. MSGCTXT and MSGID must be string literals. MSGCTXT should be
11695b7b453SJohn Marino short and rarely need to change.
11795b7b453SJohn Marino The letter 'p' stands for 'particular' or 'special'. */
11895b7b453SJohn Marino #ifdef DEFAULT_TEXT_DOMAIN
11995b7b453SJohn Marino # define pgettext(Msgctxt, Msgid) \
12095b7b453SJohn Marino pgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
12195b7b453SJohn Marino #else
12295b7b453SJohn Marino # define pgettext(Msgctxt, Msgid) \
12395b7b453SJohn Marino pgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
12495b7b453SJohn Marino #endif
12595b7b453SJohn Marino #define dpgettext(Domainname, Msgctxt, Msgid) \
12695b7b453SJohn Marino pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
12795b7b453SJohn Marino #define dcpgettext(Domainname, Msgctxt, Msgid, Category) \
12895b7b453SJohn Marino pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, Category)
12995b7b453SJohn Marino #ifdef DEFAULT_TEXT_DOMAIN
13095b7b453SJohn Marino # define npgettext(Msgctxt, Msgid, MsgidPlural, N) \
13195b7b453SJohn Marino npgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
13295b7b453SJohn Marino #else
13395b7b453SJohn Marino # define npgettext(Msgctxt, Msgid, MsgidPlural, N) \
13495b7b453SJohn Marino npgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
13595b7b453SJohn Marino #endif
13695b7b453SJohn Marino #define dnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N) \
13795b7b453SJohn Marino npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
13895b7b453SJohn Marino #define dcnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N, Category) \
13995b7b453SJohn Marino npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, Category)
14095b7b453SJohn Marino
14195b7b453SJohn Marino #ifdef __GNUC__
14295b7b453SJohn Marino __inline
14395b7b453SJohn Marino #else
14495b7b453SJohn Marino #ifdef __cplusplus
14595b7b453SJohn Marino inline
14695b7b453SJohn Marino #endif
14795b7b453SJohn Marino #endif
14895b7b453SJohn Marino static const char *
pgettext_aux(const char * domain,const char * msg_ctxt_id,const char * msgid,int category)14995b7b453SJohn Marino pgettext_aux (const char *domain,
15095b7b453SJohn Marino const char *msg_ctxt_id, const char *msgid,
15195b7b453SJohn Marino int category)
15295b7b453SJohn Marino {
15395b7b453SJohn Marino const char *translation = dcgettext (domain, msg_ctxt_id, category);
15495b7b453SJohn Marino if (translation == msg_ctxt_id)
15595b7b453SJohn Marino return msgid;
15695b7b453SJohn Marino else
15795b7b453SJohn Marino return translation;
15895b7b453SJohn Marino }
15995b7b453SJohn Marino
16095b7b453SJohn Marino #ifdef __GNUC__
16195b7b453SJohn Marino __inline
16295b7b453SJohn Marino #else
16395b7b453SJohn Marino #ifdef __cplusplus
16495b7b453SJohn Marino inline
16595b7b453SJohn Marino #endif
16695b7b453SJohn Marino #endif
16795b7b453SJohn 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)16895b7b453SJohn Marino npgettext_aux (const char *domain,
16995b7b453SJohn Marino const char *msg_ctxt_id, const char *msgid,
17095b7b453SJohn Marino const char *msgid_plural, unsigned long int n,
17195b7b453SJohn Marino int category)
17295b7b453SJohn Marino {
17395b7b453SJohn Marino const char *translation =
17495b7b453SJohn Marino dcngettext (domain, msg_ctxt_id, msgid_plural, n, category);
17595b7b453SJohn Marino if (translation == msg_ctxt_id || translation == msgid_plural)
17695b7b453SJohn Marino return (n == 1 ? msgid : msgid_plural);
17795b7b453SJohn Marino else
17895b7b453SJohn Marino return translation;
17995b7b453SJohn Marino }
18095b7b453SJohn Marino
18195b7b453SJohn Marino /* The same thing extended for non-constant arguments. Here MSGCTXT and MSGID
18295b7b453SJohn Marino can be arbitrary expressions. But for string literals these macros are
18395b7b453SJohn Marino less efficient than those above. */
18495b7b453SJohn Marino
18595b7b453SJohn Marino #include <string.h>
18695b7b453SJohn Marino
187*09d4459fSDaniel Fojt /* GNULIB_NO_VLA can be defined to disable use of VLAs even if supported.
188*09d4459fSDaniel Fojt This relates to the -Wvla and -Wvla-larger-than warnings, enabled in
189*09d4459fSDaniel Fojt the default GCC many warnings set. This allows programs to disable use
190*09d4459fSDaniel Fojt of VLAs, which may be unintended, or may be awkward to support portably,
191*09d4459fSDaniel Fojt or may have security implications due to non-deterministic stack usage. */
192*09d4459fSDaniel Fojt
193*09d4459fSDaniel Fojt #if (!defined GNULIB_NO_VLA \
194*09d4459fSDaniel Fojt && (((__GNUC__ >= 3 || __GNUG__ >= 2) && !defined __STRICT_ANSI__) \
195*09d4459fSDaniel Fojt /* || (__STDC_VERSION__ == 199901L && !defined __HP_cc)
196*09d4459fSDaniel Fojt || (__STDC_VERSION__ >= 201112L && !defined __STDC_NO_VLA__) */ ))
197a8597f6cSJohn Marino # define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS 1
198a8597f6cSJohn Marino #else
199a8597f6cSJohn Marino # define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS 0
200a8597f6cSJohn Marino #endif
20195b7b453SJohn Marino
20295b7b453SJohn Marino #if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
20395b7b453SJohn Marino #include <stdlib.h>
20495b7b453SJohn Marino #endif
20595b7b453SJohn Marino
20695b7b453SJohn Marino #define pgettext_expr(Msgctxt, Msgid) \
20795b7b453SJohn Marino dcpgettext_expr (NULL, Msgctxt, Msgid, LC_MESSAGES)
20895b7b453SJohn Marino #define dpgettext_expr(Domainname, Msgctxt, Msgid) \
20995b7b453SJohn Marino dcpgettext_expr (Domainname, Msgctxt, Msgid, LC_MESSAGES)
21095b7b453SJohn Marino
21195b7b453SJohn Marino #ifdef __GNUC__
21295b7b453SJohn Marino __inline
21395b7b453SJohn Marino #else
21495b7b453SJohn Marino #ifdef __cplusplus
21595b7b453SJohn Marino inline
21695b7b453SJohn Marino #endif
21795b7b453SJohn Marino #endif
21895b7b453SJohn Marino static const char *
dcpgettext_expr(const char * domain,const char * msgctxt,const char * msgid,int category)21995b7b453SJohn Marino dcpgettext_expr (const char *domain,
22095b7b453SJohn Marino const char *msgctxt, const char *msgid,
22195b7b453SJohn Marino int category)
22295b7b453SJohn Marino {
22395b7b453SJohn Marino size_t msgctxt_len = strlen (msgctxt) + 1;
22495b7b453SJohn Marino size_t msgid_len = strlen (msgid) + 1;
22595b7b453SJohn Marino const char *translation;
22695b7b453SJohn Marino #if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
22795b7b453SJohn Marino char msg_ctxt_id[msgctxt_len + msgid_len];
22895b7b453SJohn Marino #else
22995b7b453SJohn Marino char buf[1024];
23095b7b453SJohn Marino char *msg_ctxt_id =
23195b7b453SJohn Marino (msgctxt_len + msgid_len <= sizeof (buf)
23295b7b453SJohn Marino ? buf
23395b7b453SJohn Marino : (char *) malloc (msgctxt_len + msgid_len));
23495b7b453SJohn Marino if (msg_ctxt_id != NULL)
23595b7b453SJohn Marino #endif
23695b7b453SJohn Marino {
237*09d4459fSDaniel Fojt int found_translation;
23895b7b453SJohn Marino memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1);
23995b7b453SJohn Marino msg_ctxt_id[msgctxt_len - 1] = '\004';
24095b7b453SJohn Marino memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len);
24195b7b453SJohn Marino translation = dcgettext (domain, msg_ctxt_id, category);
242*09d4459fSDaniel Fojt found_translation = (translation != msg_ctxt_id);
24395b7b453SJohn Marino #if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
24495b7b453SJohn Marino if (msg_ctxt_id != buf)
24595b7b453SJohn Marino free (msg_ctxt_id);
24695b7b453SJohn Marino #endif
247*09d4459fSDaniel Fojt if (found_translation)
24895b7b453SJohn Marino return translation;
24995b7b453SJohn Marino }
25095b7b453SJohn Marino return msgid;
25195b7b453SJohn Marino }
25295b7b453SJohn Marino
25395b7b453SJohn Marino #define npgettext_expr(Msgctxt, Msgid, MsgidPlural, N) \
25495b7b453SJohn Marino dcnpgettext_expr (NULL, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES)
25595b7b453SJohn Marino #define dnpgettext_expr(Domainname, Msgctxt, Msgid, MsgidPlural, N) \
25695b7b453SJohn Marino dcnpgettext_expr (Domainname, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES)
25795b7b453SJohn Marino
25895b7b453SJohn Marino #ifdef __GNUC__
25995b7b453SJohn Marino __inline
26095b7b453SJohn Marino #else
26195b7b453SJohn Marino #ifdef __cplusplus
26295b7b453SJohn Marino inline
26395b7b453SJohn Marino #endif
26495b7b453SJohn Marino #endif
26595b7b453SJohn 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)26695b7b453SJohn Marino dcnpgettext_expr (const char *domain,
26795b7b453SJohn Marino const char *msgctxt, const char *msgid,
26895b7b453SJohn Marino const char *msgid_plural, unsigned long int n,
26995b7b453SJohn Marino int category)
27095b7b453SJohn Marino {
27195b7b453SJohn Marino size_t msgctxt_len = strlen (msgctxt) + 1;
27295b7b453SJohn Marino size_t msgid_len = strlen (msgid) + 1;
27395b7b453SJohn Marino const char *translation;
27495b7b453SJohn Marino #if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
27595b7b453SJohn Marino char msg_ctxt_id[msgctxt_len + msgid_len];
27695b7b453SJohn Marino #else
27795b7b453SJohn Marino char buf[1024];
27895b7b453SJohn Marino char *msg_ctxt_id =
27995b7b453SJohn Marino (msgctxt_len + msgid_len <= sizeof (buf)
28095b7b453SJohn Marino ? buf
28195b7b453SJohn Marino : (char *) malloc (msgctxt_len + msgid_len));
28295b7b453SJohn Marino if (msg_ctxt_id != NULL)
28395b7b453SJohn Marino #endif
28495b7b453SJohn Marino {
285*09d4459fSDaniel Fojt int found_translation;
28695b7b453SJohn Marino memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1);
28795b7b453SJohn Marino msg_ctxt_id[msgctxt_len - 1] = '\004';
28895b7b453SJohn Marino memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len);
28995b7b453SJohn Marino translation = dcngettext (domain, msg_ctxt_id, msgid_plural, n, category);
290*09d4459fSDaniel Fojt found_translation = !(translation == msg_ctxt_id || translation == msgid_plural);
29195b7b453SJohn Marino #if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
29295b7b453SJohn Marino if (msg_ctxt_id != buf)
29395b7b453SJohn Marino free (msg_ctxt_id);
29495b7b453SJohn Marino #endif
295*09d4459fSDaniel Fojt if (found_translation)
29695b7b453SJohn Marino return translation;
29795b7b453SJohn Marino }
29895b7b453SJohn Marino return (n == 1 ? msgid : msgid_plural);
29995b7b453SJohn Marino }
30095b7b453SJohn Marino
30195b7b453SJohn Marino #endif /* _LIBGETTEXT_H */
302