xref: /dflybsd-src/contrib/grep/lib/gettext.h (revision 91b9ed38d3db6a8a8ac5b66da1d43e6e331e259a)
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