Home | History | Annotate | Line # | Download | only in gnulib-lib
      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 Free Software Foundation, Inc.
      3  1.1  christos 
      4  1.1  christos    This program is free software; you can redistribute it and/or modify it
      5  1.1  christos    under the terms of the GNU Library General Public License as published
      6  1.1  christos    by the Free Software Foundation; either version 2, or (at your option)
      7  1.1  christos    any later version.
      8  1.1  christos 
      9  1.1  christos    This program is distributed in the hope that it will be useful,
     10  1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     11  1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     12  1.1  christos    Library General Public License for more details.
     13  1.1  christos 
     14  1.1  christos    You should have received a copy of the GNU Library General Public
     15  1.1  christos    License along with this program; if not, write to the Free Software
     16  1.1  christos    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
     17  1.1  christos    USA.  */
     18  1.1  christos 
     19  1.1  christos #ifndef _LIBGETTEXT_H
     20  1.1  christos #define _LIBGETTEXT_H 1
     21  1.1  christos 
     22  1.1  christos /* NLS can be disabled through the configure --disable-nls option.  */
     23  1.1  christos #if 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) || _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 # define gettext(Msgid) ((const char *) (Msgid))
     68  1.1  christos # define dgettext(Domainname, Msgid) ((const char *) (Msgid))
     69  1.1  christos # define dcgettext(Domainname, Msgid, Category) ((const char *) (Msgid))
     70  1.1  christos # define ngettext(Msgid1, Msgid2, N) \
     71  1.1  christos     ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
     72  1.1  christos # define dngettext(Domainname, Msgid1, Msgid2, N) \
     73  1.1  christos     ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
     74  1.1  christos # define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \
     75  1.1  christos     ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
     76  1.1  christos # define textdomain(Domainname) ((const char *) (Domainname))
     77  1.1  christos # define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname))
     78  1.1  christos # define bind_textdomain_codeset(Domainname, Codeset) ((const char *) (Codeset))
     79  1.1  christos 
     80  1.1  christos #endif
     81  1.1  christos 
     82  1.1  christos /* A pseudo function call that serves as a marker for the automated
     83  1.1  christos    extraction of messages, but does not call gettext().  The run-time
     84  1.1  christos    translation is done at a different place in the code.
     85  1.1  christos    The argument, String, should be a literal string.  Concatenated strings
     86  1.1  christos    and other string expressions won't work.
     87  1.1  christos    The macro's expansion is not parenthesized, so that it is suitable as
     88  1.1  christos    initializer for static 'char[]' or 'const char[]' variables.  */
     89  1.1  christos #define gettext_noop(String) String
     90  1.1  christos 
     91  1.1  christos /* The separator between msgctxt and msgid in a .mo file.  */
     92  1.1  christos #define GETTEXT_CONTEXT_GLUE "\004"
     93  1.1  christos 
     94  1.1  christos /* Pseudo function calls, taking a MSGCTXT and a MSGID instead of just a
     95  1.1  christos    MSGID.  MSGCTXT and MSGID must be string literals.  MSGCTXT should be
     96  1.1  christos    short and rarely need to change.
     97  1.1  christos    The letter 'p' stands for 'particular' or 'special'.  */
     98  1.1  christos #ifdef DEFAULT_TEXT_DOMAIN
     99  1.1  christos # define pgettext(Msgctxt, Msgid) \
    100  1.1  christos    pgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
    101  1.1  christos #else
    102  1.1  christos # define pgettext(Msgctxt, Msgid) \
    103  1.1  christos    pgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
    104  1.1  christos #endif
    105  1.1  christos #define dpgettext(Domainname, Msgctxt, Msgid) \
    106  1.1  christos   pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
    107  1.1  christos #define dcpgettext(Domainname, Msgctxt, Msgid, Category) \
    108  1.1  christos   pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, Category)
    109  1.1  christos #ifdef DEFAULT_TEXT_DOMAIN
    110  1.1  christos # define npgettext(Msgctxt, Msgid, MsgidPlural, N) \
    111  1.1  christos    npgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
    112  1.1  christos #else
    113  1.1  christos # define npgettext(Msgctxt, Msgid, MsgidPlural, N) \
    114  1.1  christos    npgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
    115  1.1  christos #endif
    116  1.1  christos #define dnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N) \
    117  1.1  christos   npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
    118  1.1  christos #define dcnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N, Category) \
    119  1.1  christos   npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, Category)
    120  1.1  christos 
    121  1.1  christos #ifdef __GNUC__
    122  1.1  christos __inline
    123  1.1  christos #else
    124  1.1  christos #ifdef __cplusplus
    125  1.1  christos inline
    126  1.1  christos #endif
    127  1.1  christos #endif
    128  1.1  christos static const char *
    129  1.1  christos pgettext_aux (const char *domain,
    130  1.1  christos 	      const char *msg_ctxt_id, const char *msgid,
    131  1.1  christos 	      int category)
    132  1.1  christos {
    133  1.1  christos   const char *translation = dcgettext (domain, msg_ctxt_id, category);
    134  1.1  christos   if (translation == msg_ctxt_id)
    135  1.1  christos     return msgid;
    136  1.1  christos   else
    137  1.1  christos     return translation;
    138  1.1  christos }
    139  1.1  christos 
    140  1.1  christos #ifdef __GNUC__
    141  1.1  christos __inline
    142  1.1  christos #else
    143  1.1  christos #ifdef __cplusplus
    144  1.1  christos inline
    145  1.1  christos #endif
    146  1.1  christos #endif
    147  1.1  christos static const char *
    148  1.1  christos npgettext_aux (const char *domain,
    149  1.1  christos 	       const char *msg_ctxt_id, const char *msgid,
    150  1.1  christos 	       const char *msgid_plural, unsigned long int n,
    151  1.1  christos 	       int category)
    152  1.1  christos {
    153  1.1  christos   const char *translation =
    154  1.1  christos     dcngettext (domain, msg_ctxt_id, msgid_plural, n, category);
    155  1.1  christos   if (translation == msg_ctxt_id || translation == msgid_plural)
    156  1.1  christos     return (n == 1 ? msgid : msgid_plural);
    157  1.1  christos   else
    158  1.1  christos     return translation;
    159  1.1  christos }
    160  1.1  christos 
    161  1.1  christos /* The same thing extended for non-constant arguments.  Here MSGCTXT and MSGID
    162  1.1  christos    can be arbitrary expressions.  But for string literals these macros are
    163  1.1  christos    less efficient than those above.  */
    164  1.1  christos 
    165  1.1  christos #include <string.h>
    166  1.1  christos 
    167  1.1  christos #define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS \
    168  1.1  christos   (__GNUC__ >= 3 || __GNUG__ >= 2 /* || __STDC_VERSION__ >= 199901L */ )
    169  1.1  christos 
    170  1.1  christos #if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
    171  1.1  christos #include <stdlib.h>
    172  1.1  christos #endif
    173  1.1  christos 
    174  1.1  christos #define pgettext_expr(Msgctxt, Msgid) \
    175  1.1  christos   dcpgettext_expr (NULL, Msgctxt, Msgid, LC_MESSAGES)
    176  1.1  christos #define dpgettext_expr(Domainname, Msgctxt, Msgid) \
    177  1.1  christos   dcpgettext_expr (Domainname, Msgctxt, Msgid, LC_MESSAGES)
    178  1.1  christos 
    179  1.1  christos #ifdef __GNUC__
    180  1.1  christos __inline
    181  1.1  christos #else
    182  1.1  christos #ifdef __cplusplus
    183  1.1  christos inline
    184  1.1  christos #endif
    185  1.1  christos #endif
    186  1.1  christos static const char *
    187  1.1  christos dcpgettext_expr (const char *domain,
    188  1.1  christos 		 const char *msgctxt, const char *msgid,
    189  1.1  christos 		 int category)
    190  1.1  christos {
    191  1.1  christos   size_t msgctxt_len = strlen (msgctxt) + 1;
    192  1.1  christos   size_t msgid_len = strlen (msgid) + 1;
    193  1.1  christos   const char *translation;
    194  1.1  christos #if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
    195  1.1  christos   char msg_ctxt_id[msgctxt_len + msgid_len];
    196  1.1  christos #else
    197  1.1  christos   char buf[1024];
    198  1.1  christos   char *msg_ctxt_id =
    199  1.1  christos     (msgctxt_len + msgid_len <= sizeof (buf)
    200  1.1  christos      ? buf
    201  1.1  christos      : (char *) malloc (msgctxt_len + msgid_len));
    202  1.1  christos   if (msg_ctxt_id != NULL)
    203  1.1  christos #endif
    204  1.1  christos     {
    205  1.1  christos       memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1);
    206  1.1  christos       msg_ctxt_id[msgctxt_len - 1] = '\004';
    207  1.1  christos       memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len);
    208  1.1  christos       translation = dcgettext (domain, msg_ctxt_id, category);
    209  1.1  christos #if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
    210  1.1  christos       if (msg_ctxt_id != buf)
    211  1.1  christos 	free (msg_ctxt_id);
    212  1.1  christos #endif
    213  1.1  christos       if (translation != msg_ctxt_id)
    214  1.1  christos 	return translation;
    215  1.1  christos     }
    216  1.1  christos   return msgid;
    217  1.1  christos }
    218  1.1  christos 
    219  1.1  christos #define npgettext_expr(Msgctxt, Msgid, MsgidPlural, N) \
    220  1.1  christos   dcnpgettext_expr (NULL, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES)
    221  1.1  christos #define dnpgettext_expr(Domainname, Msgctxt, Msgid, MsgidPlural, N) \
    222  1.1  christos   dcnpgettext_expr (Domainname, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES)
    223  1.1  christos 
    224  1.1  christos #ifdef __GNUC__
    225  1.1  christos __inline
    226  1.1  christos #else
    227  1.1  christos #ifdef __cplusplus
    228  1.1  christos inline
    229  1.1  christos #endif
    230  1.1  christos #endif
    231  1.1  christos static const char *
    232  1.1  christos dcnpgettext_expr (const char *domain,
    233  1.1  christos 		  const char *msgctxt, const char *msgid,
    234  1.1  christos 		  const char *msgid_plural, unsigned long int n,
    235  1.1  christos 		  int category)
    236  1.1  christos {
    237  1.1  christos   size_t msgctxt_len = strlen (msgctxt) + 1;
    238  1.1  christos   size_t msgid_len = strlen (msgid) + 1;
    239  1.1  christos   const char *translation;
    240  1.1  christos #if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
    241  1.1  christos   char msg_ctxt_id[msgctxt_len + msgid_len];
    242  1.1  christos #else
    243  1.1  christos   char buf[1024];
    244  1.1  christos   char *msg_ctxt_id =
    245  1.1  christos     (msgctxt_len + msgid_len <= sizeof (buf)
    246  1.1  christos      ? buf
    247  1.1  christos      : (char *) malloc (msgctxt_len + msgid_len));
    248  1.1  christos   if (msg_ctxt_id != NULL)
    249  1.1  christos #endif
    250  1.1  christos     {
    251  1.1  christos       memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1);
    252  1.1  christos       msg_ctxt_id[msgctxt_len - 1] = '\004';
    253  1.1  christos       memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len);
    254  1.1  christos       translation = dcngettext (domain, msg_ctxt_id, msgid_plural, n, category);
    255  1.1  christos #if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
    256  1.1  christos       if (msg_ctxt_id != buf)
    257  1.1  christos 	free (msg_ctxt_id);
    258  1.1  christos #endif
    259  1.1  christos       if (!(translation == msg_ctxt_id || translation == msgid_plural))
    260  1.1  christos 	return translation;
    261  1.1  christos     }
    262  1.1  christos   return (n == 1 ? msgid : msgid_plural);
    263  1.1  christos }
    264  1.1  christos 
    265  1.1  christos #endif /* _LIBGETTEXT_H */
    266