xref: /freebsd/contrib/ntp/sntp/libopts/gettext.h (revision a466cc55)
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