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