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