xref: /dragonfly/contrib/diffutils/lib/gettext.h (revision 6ea1f93e)
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