Home | History | Annotate | Line # | Download | only in import
gettext.h revision 1.1
      1  1.1  christos /* Convenience header for conditional use of GNU <libintl.h>.
      2  1.1  christos    Copyright (C) 1995-1998, 2000-2002, 2004-2006, 2009-2020 Free Software
      3  1.1  christos    Foundation, Inc.
      4  1.1  christos 
      5  1.1  christos    This program is free software; you can redistribute it and/or modify
      6  1.1  christos    it under the terms of the GNU General Public License as published by
      7  1.1  christos    the Free Software Foundation; either version 3, or (at your option)
      8  1.1  christos    any later version.
      9  1.1  christos 
     10  1.1  christos    This program is distributed in the hope that it will be useful,
     11  1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13  1.1  christos    GNU General Public License for more details.
     14  1.1  christos 
     15  1.1  christos    You should have received a copy of the GNU General Public License along
     16  1.1  christos    with this program; if not, see <https://www.gnu.org/licenses/>.  */
     17  1.1  christos 
     18  1.1  christos #ifndef _LIBGETTEXT_H
     19  1.1  christos #define _LIBGETTEXT_H 1
     20  1.1  christos 
     21  1.1  christos /* NLS can be disabled through the configure --disable-nls option
     22  1.1  christos    or through "#define ENABLE NLS 0" before including this file.  */
     23  1.1  christos #if defined ENABLE_NLS && ENABLE_NLS
     24  1.1  christos 
     25  1.1  christos /* Get declarations of GNU message catalog functions.  */
     26  1.1  christos # include <libintl.h>
     27  1.1  christos 
     28  1.1  christos /* You can set the DEFAULT_TEXT_DOMAIN macro to specify the domain used by
     29  1.1  christos    the gettext() and ngettext() macros.  This is an alternative to calling
     30  1.1  christos    textdomain(), and is useful for libraries.  */
     31  1.1  christos # ifdef DEFAULT_TEXT_DOMAIN
     32  1.1  christos #  undef gettext
     33  1.1  christos #  define gettext(Msgid) \
     34  1.1  christos      dgettext (DEFAULT_TEXT_DOMAIN, Msgid)
     35  1.1  christos #  undef ngettext
     36  1.1  christos #  define ngettext(Msgid1, Msgid2, N) \
     37  1.1  christos      dngettext (DEFAULT_TEXT_DOMAIN, Msgid1, Msgid2, N)
     38  1.1  christos # endif
     39  1.1  christos 
     40  1.1  christos #else
     41  1.1  christos 
     42  1.1  christos /* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which
     43  1.1  christos    chokes if dcgettext is defined as a macro.  So include it now, to make
     44  1.1  christos    later inclusions of <locale.h> a NOP.  We don't include <libintl.h>
     45  1.1  christos    as well because people using "gettext.h" will not include <libintl.h>,
     46  1.1  christos    and also including <libintl.h> would fail on SunOS 4, whereas <locale.h>
     47  1.1  christos    is OK.  */
     48  1.1  christos #if defined(__sun)
     49  1.1  christos # include <locale.h>
     50  1.1  christos #endif
     51  1.1  christos 
     52  1.1  christos /* Many header files from the libstdc++ coming with g++ 3.3 or newer include
     53  1.1  christos    <libintl.h>, which chokes if dcgettext is defined as a macro.  So include
     54  1.1  christos    it now, to make later inclusions of <libintl.h> a NOP.  */
     55  1.1  christos #if defined(__cplusplus) && defined(__GNUG__) && (__GNUC__ >= 3)
     56  1.1  christos # include <cstdlib>
     57  1.1  christos # if (__GLIBC__ >= 2 && !defined __UCLIBC__) || _GLIBCXX_HAVE_LIBINTL_H
     58  1.1  christos #  include <libintl.h>
     59  1.1  christos # endif
     60  1.1  christos #endif
     61  1.1  christos 
     62  1.1  christos /* Disabled NLS.
     63  1.1  christos    The casts to 'const char *' serve the purpose of producing warnings
     64  1.1  christos    for invalid uses of the value returned from these functions.
     65  1.1  christos    On pre-ANSI systems without 'const', the config.h file is supposed to
     66  1.1  christos    contain "#define const".  */
     67  1.1  christos # undef gettext
     68  1.1  christos # define gettext(Msgid) ((const char *) (Msgid))
     69  1.1  christos # undef dgettext
     70  1.1  christos # define dgettext(Domainname, Msgid) ((void) (Domainname), gettext (Msgid))
     71  1.1  christos # undef dcgettext
     72  1.1  christos # define dcgettext(Domainname, Msgid, Category) \
     73  1.1  christos     ((void) (Category), dgettext (Domainname, Msgid))
     74  1.1  christos # undef ngettext
     75  1.1  christos # define ngettext(Msgid1, Msgid2, N) \
     76  1.1  christos     ((N) == 1 \
     77  1.1  christos      ? ((void) (Msgid2), (const char *) (Msgid1)) \
     78  1.1  christos      : ((void) (Msgid1), (const char *) (Msgid2)))
     79  1.1  christos # undef dngettext
     80  1.1  christos # define dngettext(Domainname, Msgid1, Msgid2, N) \
     81  1.1  christos     ((void) (Domainname), ngettext (Msgid1, Msgid2, N))
     82  1.1  christos # undef dcngettext
     83  1.1  christos # define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \
     84  1.1  christos     ((void) (Category), dngettext (Domainname, Msgid1, Msgid2, N))
     85  1.1  christos # undef textdomain
     86  1.1  christos # define textdomain(Domainname) ((const char *) (Domainname))
     87  1.1  christos # undef bindtextdomain
     88  1.1  christos # define bindtextdomain(Domainname, Dirname) \
     89  1.1  christos     ((void) (Domainname), (const char *) (Dirname))
     90  1.1  christos # undef bind_textdomain_codeset
     91  1.1  christos # define bind_textdomain_codeset(Domainname, Codeset) \
     92  1.1  christos     ((void) (Domainname), (const char *) (Codeset))
     93  1.1  christos 
     94  1.1  christos #endif
     95  1.1  christos 
     96  1.1  christos /* Prefer gnulib's setlocale override over libintl's setlocale override.  */
     97  1.1  christos #ifdef GNULIB_defined_setlocale
     98  1.1  christos # undef setlocale
     99  1.1  christos # define setlocale rpl_setlocale
    100  1.1  christos #endif
    101  1.1  christos 
    102  1.1  christos /* A pseudo function call that serves as a marker for the automated
    103  1.1  christos    extraction of messages, but does not call gettext().  The run-time
    104  1.1  christos    translation is done at a different place in the code.
    105  1.1  christos    The argument, String, should be a literal string.  Concatenated strings
    106  1.1  christos    and other string expressions won't work.
    107  1.1  christos    The macro's expansion is not parenthesized, so that it is suitable as
    108  1.1  christos    initializer for static 'char[]' or 'const char[]' variables.  */
    109  1.1  christos #define gettext_noop(String) String
    110  1.1  christos 
    111  1.1  christos /* The separator between msgctxt and msgid in a .mo file.  */
    112  1.1  christos #define GETTEXT_CONTEXT_GLUE "\004"
    113  1.1  christos 
    114  1.1  christos /* Pseudo function calls, taking a MSGCTXT and a MSGID instead of just a
    115  1.1  christos    MSGID.  MSGCTXT and MSGID must be string literals.  MSGCTXT should be
    116  1.1  christos    short and rarely need to change.
    117  1.1  christos    The letter 'p' stands for 'particular' or 'special'.  */
    118  1.1  christos #ifdef DEFAULT_TEXT_DOMAIN
    119  1.1  christos # define pgettext(Msgctxt, Msgid) \
    120  1.1  christos    pgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
    121  1.1  christos #else
    122  1.1  christos # define pgettext(Msgctxt, Msgid) \
    123  1.1  christos    pgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
    124  1.1  christos #endif
    125  1.1  christos #define dpgettext(Domainname, Msgctxt, Msgid) \
    126  1.1  christos   pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
    127  1.1  christos #define dcpgettext(Domainname, Msgctxt, Msgid, Category) \
    128  1.1  christos   pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, Category)
    129  1.1  christos #ifdef DEFAULT_TEXT_DOMAIN
    130  1.1  christos # define npgettext(Msgctxt, Msgid, MsgidPlural, N) \
    131  1.1  christos    npgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
    132  1.1  christos #else
    133  1.1  christos # define npgettext(Msgctxt, Msgid, MsgidPlural, N) \
    134  1.1  christos    npgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
    135  1.1  christos #endif
    136  1.1  christos #define dnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N) \
    137  1.1  christos   npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
    138  1.1  christos #define dcnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N, Category) \
    139  1.1  christos   npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, Category)
    140  1.1  christos 
    141  1.1  christos #ifdef __GNUC__
    142  1.1  christos __inline
    143  1.1  christos #else
    144  1.1  christos #ifdef __cplusplus
    145  1.1  christos inline
    146  1.1  christos #endif
    147  1.1  christos #endif
    148  1.1  christos static const char *
    149  1.1  christos pgettext_aux (const char *domain,
    150  1.1  christos               const char *msg_ctxt_id, const char *msgid,
    151  1.1  christos               int category)
    152  1.1  christos {
    153  1.1  christos   const char *translation = dcgettext (domain, msg_ctxt_id, category);
    154  1.1  christos   if (translation == msg_ctxt_id)
    155  1.1  christos     return msgid;
    156  1.1  christos   else
    157  1.1  christos     return translation;
    158  1.1  christos }
    159  1.1  christos 
    160  1.1  christos #ifdef __GNUC__
    161  1.1  christos __inline
    162  1.1  christos #else
    163  1.1  christos #ifdef __cplusplus
    164  1.1  christos inline
    165  1.1  christos #endif
    166  1.1  christos #endif
    167  1.1  christos static const char *
    168  1.1  christos npgettext_aux (const char *domain,
    169  1.1  christos                const char *msg_ctxt_id, const char *msgid,
    170  1.1  christos                const char *msgid_plural, unsigned long int n,
    171  1.1  christos                int category)
    172  1.1  christos {
    173  1.1  christos   const char *translation =
    174  1.1  christos     dcngettext (domain, msg_ctxt_id, msgid_plural, n, category);
    175  1.1  christos   if (translation == msg_ctxt_id || translation == msgid_plural)
    176  1.1  christos     return (n == 1 ? msgid : msgid_plural);
    177  1.1  christos   else
    178  1.1  christos     return translation;
    179  1.1  christos }
    180  1.1  christos 
    181  1.1  christos /* The same thing extended for non-constant arguments.  Here MSGCTXT and MSGID
    182  1.1  christos    can be arbitrary expressions.  But for string literals these macros are
    183  1.1  christos    less efficient than those above.  */
    184  1.1  christos 
    185  1.1  christos #include <string.h>
    186  1.1  christos 
    187  1.1  christos /* GNULIB_NO_VLA can be defined to disable use of VLAs even if supported.
    188  1.1  christos    This relates to the -Wvla and -Wvla-larger-than warnings, enabled in
    189  1.1  christos    the default GCC many warnings set.  This allows programs to disable use
    190  1.1  christos    of VLAs, which may be unintended, or may be awkward to support portably,
    191  1.1  christos    or may have security implications due to non-deterministic stack usage.  */
    192  1.1  christos 
    193  1.1  christos #if (!defined GNULIB_NO_VLA \
    194  1.1  christos      && (((__GNUC__ >= 3 || __GNUG__ >= 2) && !defined __STRICT_ANSI__) \
    195  1.1  christos      /*  || (__STDC_VERSION__ == 199901L && !defined __HP_cc)
    196  1.1  christos          || (__STDC_VERSION__ >= 201112L && !defined __STDC_NO_VLA__) */ ))
    197  1.1  christos # define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS 1
    198  1.1  christos #else
    199  1.1  christos # define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS 0
    200  1.1  christos #endif
    201  1.1  christos 
    202  1.1  christos #if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
    203  1.1  christos #include <stdlib.h>
    204  1.1  christos #endif
    205  1.1  christos 
    206  1.1  christos #define pgettext_expr(Msgctxt, Msgid) \
    207  1.1  christos   dcpgettext_expr (NULL, Msgctxt, Msgid, LC_MESSAGES)
    208  1.1  christos #define dpgettext_expr(Domainname, Msgctxt, Msgid) \
    209  1.1  christos   dcpgettext_expr (Domainname, Msgctxt, Msgid, LC_MESSAGES)
    210  1.1  christos 
    211  1.1  christos #ifdef __GNUC__
    212  1.1  christos __inline
    213  1.1  christos #else
    214  1.1  christos #ifdef __cplusplus
    215  1.1  christos inline
    216  1.1  christos #endif
    217  1.1  christos #endif
    218  1.1  christos static const char *
    219  1.1  christos dcpgettext_expr (const char *domain,
    220  1.1  christos                  const char *msgctxt, const char *msgid,
    221  1.1  christos                  int category)
    222  1.1  christos {
    223  1.1  christos   size_t msgctxt_len = strlen (msgctxt) + 1;
    224  1.1  christos   size_t msgid_len = strlen (msgid) + 1;
    225  1.1  christos   const char *translation;
    226  1.1  christos #if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
    227  1.1  christos   char msg_ctxt_id[msgctxt_len + msgid_len];
    228  1.1  christos #else
    229  1.1  christos   char buf[1024];
    230  1.1  christos   char *msg_ctxt_id =
    231  1.1  christos     (msgctxt_len + msgid_len <= sizeof (buf)
    232  1.1  christos      ? buf
    233  1.1  christos      : (char *) malloc (msgctxt_len + msgid_len));
    234  1.1  christos   if (msg_ctxt_id != NULL)
    235  1.1  christos #endif
    236  1.1  christos     {
    237  1.1  christos       int found_translation;
    238  1.1  christos       memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1);
    239  1.1  christos       msg_ctxt_id[msgctxt_len - 1] = '\004';
    240  1.1  christos       memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len);
    241  1.1  christos       translation = dcgettext (domain, msg_ctxt_id, category);
    242  1.1  christos       found_translation = (translation != msg_ctxt_id);
    243  1.1  christos #if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
    244  1.1  christos       if (msg_ctxt_id != buf)
    245  1.1  christos         free (msg_ctxt_id);
    246  1.1  christos #endif
    247  1.1  christos       if (found_translation)
    248  1.1  christos         return translation;
    249  1.1  christos     }
    250  1.1  christos   return msgid;
    251  1.1  christos }
    252  1.1  christos 
    253  1.1  christos #define npgettext_expr(Msgctxt, Msgid, MsgidPlural, N) \
    254  1.1  christos   dcnpgettext_expr (NULL, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES)
    255  1.1  christos #define dnpgettext_expr(Domainname, Msgctxt, Msgid, MsgidPlural, N) \
    256  1.1  christos   dcnpgettext_expr (Domainname, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES)
    257  1.1  christos 
    258  1.1  christos #ifdef __GNUC__
    259  1.1  christos __inline
    260  1.1  christos #else
    261  1.1  christos #ifdef __cplusplus
    262  1.1  christos inline
    263  1.1  christos #endif
    264  1.1  christos #endif
    265  1.1  christos static const char *
    266  1.1  christos dcnpgettext_expr (const char *domain,
    267  1.1  christos                   const char *msgctxt, const char *msgid,
    268  1.1  christos                   const char *msgid_plural, unsigned long int n,
    269  1.1  christos                   int category)
    270  1.1  christos {
    271  1.1  christos   size_t msgctxt_len = strlen (msgctxt) + 1;
    272  1.1  christos   size_t msgid_len = strlen (msgid) + 1;
    273  1.1  christos   const char *translation;
    274  1.1  christos #if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
    275  1.1  christos   char msg_ctxt_id[msgctxt_len + msgid_len];
    276  1.1  christos #else
    277  1.1  christos   char buf[1024];
    278  1.1  christos   char *msg_ctxt_id =
    279  1.1  christos     (msgctxt_len + msgid_len <= sizeof (buf)
    280  1.1  christos      ? buf
    281  1.1  christos      : (char *) malloc (msgctxt_len + msgid_len));
    282  1.1  christos   if (msg_ctxt_id != NULL)
    283  1.1  christos #endif
    284  1.1  christos     {
    285  1.1  christos       int found_translation;
    286  1.1  christos       memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1);
    287  1.1  christos       msg_ctxt_id[msgctxt_len - 1] = '\004';
    288  1.1  christos       memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len);
    289  1.1  christos       translation = dcngettext (domain, msg_ctxt_id, msgid_plural, n, category);
    290  1.1  christos       found_translation = !(translation == msg_ctxt_id || translation == msgid_plural);
    291  1.1  christos #if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
    292  1.1  christos       if (msg_ctxt_id != buf)
    293  1.1  christos         free (msg_ctxt_id);
    294  1.1  christos #endif
    295  1.1  christos       if (found_translation)
    296  1.1  christos         return translation;
    297  1.1  christos     }
    298  1.1  christos   return (n == 1 ? msgid : msgid_plural);
    299  1.1  christos }
    300  1.1  christos 
    301  1.1  christos #endif /* _LIBGETTEXT_H */
    302