1275970Scy/* Convenience header for conditional use of GNU <libintl.h>. 2285169Scy Copyright (C) 1995-1998, 2000-2002, 2004-2006, 2009-2015 Free Software 3275970Scy Foundation, Inc. 4275970Scy 5275970Scy This program is free software; you can redistribute it and/or modify 6275970Scy it under the terms of the GNU Lesser General Public License as published by 7275970Scy the Free Software Foundation; either version 2.1, or (at your option) 8275970Scy any later version. 9275970Scy 10275970Scy This program is distributed in the hope that it will be useful, 11275970Scy but WITHOUT ANY WARRANTY; without even the implied warranty of 12275970Scy MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13275970Scy GNU Lesser General Public License for more details. 14275970Scy 15275970Scy You should have received a copy of the GNU Lesser General Public License along 16275970Scy with this program; if not, see <http://www.gnu.org/licenses/>. */ 17275970Scy 18275970Scy#ifndef _LIBGETTEXT_H 19275970Scy#define _LIBGETTEXT_H 1 20275970Scy 21275970Scy/* NLS can be disabled through the configure --disable-nls option. */ 22275970Scy#if ENABLE_NLS 23275970Scy 24275970Scy/* Get declarations of GNU message catalog functions. */ 25275970Scy# include <libintl.h> 26275970Scy 27275970Scy/* You can set the DEFAULT_TEXT_DOMAIN macro to specify the domain used by 28275970Scy the gettext() and ngettext() macros. This is an alternative to calling 29275970Scy textdomain(), and is useful for libraries. */ 30275970Scy# ifdef DEFAULT_TEXT_DOMAIN 31275970Scy# undef gettext 32275970Scy# define gettext(Msgid) \ 33275970Scy dgettext (DEFAULT_TEXT_DOMAIN, Msgid) 34275970Scy# undef ngettext 35275970Scy# define ngettext(Msgid1, Msgid2, N) \ 36275970Scy dngettext (DEFAULT_TEXT_DOMAIN, Msgid1, Msgid2, N) 37275970Scy# endif 38275970Scy 39275970Scy#else 40275970Scy 41275970Scy/* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which 42275970Scy chokes if dcgettext is defined as a macro. So include it now, to make 43275970Scy later inclusions of <locale.h> a NOP. We don't include <libintl.h> 44275970Scy as well because people using "gettext.h" will not include <libintl.h>, 45275970Scy and also including <libintl.h> would fail on SunOS 4, whereas <locale.h> 46275970Scy is OK. */ 47275970Scy#if defined(__sun) 48275970Scy# include <locale.h> 49275970Scy#endif 50275970Scy 51275970Scy/* Many header files from the libstdc++ coming with g++ 3.3 or newer include 52275970Scy <libintl.h>, which chokes if dcgettext is defined as a macro. So include 53275970Scy it now, to make later inclusions of <libintl.h> a NOP. */ 54275970Scy#if defined(__cplusplus) && defined(__GNUG__) && (__GNUC__ >= 3) 55275970Scy# include <cstdlib> 56275970Scy# if (__GLIBC__ >= 2 && !defined __UCLIBC__) || _GLIBCXX_HAVE_LIBINTL_H 57275970Scy# include <libintl.h> 58275970Scy# endif 59275970Scy#endif 60275970Scy 61275970Scy/* Disabled NLS. 62275970Scy The casts to 'const char *' serve the purpose of producing warnings 63275970Scy for invalid uses of the value returned from these functions. 64275970Scy On pre-ANSI systems without 'const', the config.h file is supposed to 65275970Scy contain "#define const". */ 66275970Scy# undef gettext 67275970Scy# define gettext(Msgid) ((const char *) (Msgid)) 68275970Scy# undef dgettext 69275970Scy# define dgettext(Domainname, Msgid) ((void) (Domainname), gettext (Msgid)) 70275970Scy# undef dcgettext 71275970Scy# define dcgettext(Domainname, Msgid, Category) \ 72275970Scy ((void) (Category), dgettext (Domainname, Msgid)) 73275970Scy# undef ngettext 74275970Scy# define ngettext(Msgid1, Msgid2, N) \ 75275970Scy ((N) == 1 \ 76275970Scy ? ((void) (Msgid2), (const char *) (Msgid1)) \ 77275970Scy : ((void) (Msgid1), (const char *) (Msgid2))) 78275970Scy# undef dngettext 79275970Scy# define dngettext(Domainname, Msgid1, Msgid2, N) \ 80275970Scy ((void) (Domainname), ngettext (Msgid1, Msgid2, N)) 81275970Scy# undef dcngettext 82275970Scy# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \ 83275970Scy ((void) (Category), dngettext (Domainname, Msgid1, Msgid2, N)) 84275970Scy# undef textdomain 85275970Scy# define textdomain(Domainname) ((const char *) (Domainname)) 86275970Scy# undef bindtextdomain 87275970Scy# define bindtextdomain(Domainname, Dirname) \ 88275970Scy ((void) (Domainname), (const char *) (Dirname)) 89275970Scy# undef bind_textdomain_codeset 90275970Scy# define bind_textdomain_codeset(Domainname, Codeset) \ 91275970Scy ((void) (Domainname), (const char *) (Codeset)) 92275970Scy 93275970Scy#endif 94275970Scy 95275970Scy/* Prefer gnulib's setlocale override over libintl's setlocale override. */ 96275970Scy#ifdef GNULIB_defined_setlocale 97275970Scy# undef setlocale 98275970Scy# define setlocale rpl_setlocale 99275970Scy#endif 100275970Scy 101275970Scy/* A pseudo function call that serves as a marker for the automated 102275970Scy extraction of messages, but does not call gettext(). The run-time 103275970Scy translation is done at a different place in the code. 104275970Scy The argument, String, should be a literal string. Concatenated strings 105275970Scy and other string expressions won't work. 106275970Scy The macro's expansion is not parenthesized, so that it is suitable as 107275970Scy initializer for static 'char[]' or 'const char[]' variables. */ 108275970Scy#define gettext_noop(String) String 109275970Scy 110275970Scy/* The separator between msgctxt and msgid in a .mo file. */ 111275970Scy#define GETTEXT_CONTEXT_GLUE "\004" 112275970Scy 113275970Scy/* Pseudo function calls, taking a MSGCTXT and a MSGID instead of just a 114275970Scy MSGID. MSGCTXT and MSGID must be string literals. MSGCTXT should be 115275970Scy short and rarely need to change. 116275970Scy The letter 'p' stands for 'particular' or 'special'. */ 117275970Scy#ifdef DEFAULT_TEXT_DOMAIN 118275970Scy# define pgettext(Msgctxt, Msgid) \ 119275970Scy pgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES) 120275970Scy#else 121275970Scy# define pgettext(Msgctxt, Msgid) \ 122275970Scy pgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES) 123275970Scy#endif 124275970Scy#define dpgettext(Domainname, Msgctxt, Msgid) \ 125275970Scy pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES) 126275970Scy#define dcpgettext(Domainname, Msgctxt, Msgid, Category) \ 127275970Scy pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, Category) 128275970Scy#ifdef DEFAULT_TEXT_DOMAIN 129275970Scy# define npgettext(Msgctxt, Msgid, MsgidPlural, N) \ 130275970Scy npgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES) 131275970Scy#else 132275970Scy# define npgettext(Msgctxt, Msgid, MsgidPlural, N) \ 133275970Scy npgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES) 134275970Scy#endif 135275970Scy#define dnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N) \ 136275970Scy npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES) 137275970Scy#define dcnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N, Category) \ 138275970Scy npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, Category) 139275970Scy 140275970Scy#ifdef __GNUC__ 141275970Scy__inline 142275970Scy#else 143275970Scy#ifdef __cplusplus 144275970Scyinline 145275970Scy#endif 146275970Scy#endif 147275970Scystatic const char * 148275970Scypgettext_aux (const char *domain, 149275970Scy const char *msg_ctxt_id, const char *msgid, 150275970Scy int category) 151275970Scy{ 152275970Scy const char *translation = dcgettext (domain, msg_ctxt_id, category); 153275970Scy if (translation == msg_ctxt_id) 154275970Scy return msgid; 155275970Scy else 156275970Scy return translation; 157275970Scy} 158275970Scy 159275970Scy#ifdef __GNUC__ 160275970Scy__inline 161275970Scy#else 162275970Scy#ifdef __cplusplus 163275970Scyinline 164275970Scy#endif 165275970Scy#endif 166275970Scystatic const char * 167275970Scynpgettext_aux (const char *domain, 168275970Scy const char *msg_ctxt_id, const char *msgid, 169275970Scy const char *msgid_plural, unsigned long int n, 170275970Scy int category) 171275970Scy{ 172275970Scy const char *translation = 173275970Scy dcngettext (domain, msg_ctxt_id, msgid_plural, n, category); 174275970Scy if (translation == msg_ctxt_id || translation == msgid_plural) 175275970Scy return (n == 1 ? msgid : msgid_plural); 176275970Scy else 177275970Scy return translation; 178275970Scy} 179275970Scy 180275970Scy/* The same thing extended for non-constant arguments. Here MSGCTXT and MSGID 181275970Scy can be arbitrary expressions. But for string literals these macros are 182275970Scy less efficient than those above. */ 183275970Scy 184275970Scy#include <string.h> 185275970Scy 186275970Scy#if (((__GNUC__ >= 3 || __GNUG__ >= 2) && !defined __STRICT_ANSI__) \ 187275970Scy /* || __STDC_VERSION__ >= 199901L */ ) 188275970Scy# define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS 1 189275970Scy#else 190275970Scy# define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS 0 191275970Scy#endif 192275970Scy 193275970Scy#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS 194275970Scy#include <stdlib.h> 195275970Scy#endif 196275970Scy 197275970Scy#define pgettext_expr(Msgctxt, Msgid) \ 198275970Scy dcpgettext_expr (NULL, Msgctxt, Msgid, LC_MESSAGES) 199275970Scy#define dpgettext_expr(Domainname, Msgctxt, Msgid) \ 200275970Scy dcpgettext_expr (Domainname, Msgctxt, Msgid, LC_MESSAGES) 201275970Scy 202275970Scy#ifdef __GNUC__ 203275970Scy__inline 204275970Scy#else 205275970Scy#ifdef __cplusplus 206275970Scyinline 207275970Scy#endif 208275970Scy#endif 209275970Scystatic const char * 210275970Scydcpgettext_expr (const char *domain, 211275970Scy const char *msgctxt, const char *msgid, 212275970Scy int category) 213275970Scy{ 214275970Scy size_t msgctxt_len = strlen (msgctxt) + 1; 215275970Scy size_t msgid_len = strlen (msgid) + 1; 216275970Scy const char *translation; 217275970Scy#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS 218275970Scy char msg_ctxt_id[msgctxt_len + msgid_len]; 219275970Scy#else 220275970Scy char buf[1024]; 221275970Scy char *msg_ctxt_id = 222275970Scy (msgctxt_len + msgid_len <= sizeof (buf) 223275970Scy ? buf 224275970Scy : (char *) malloc (msgctxt_len + msgid_len)); 225275970Scy if (msg_ctxt_id != NULL) 226275970Scy#endif 227275970Scy { 228275970Scy memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1); 229275970Scy msg_ctxt_id[msgctxt_len - 1] = '\004'; 230275970Scy memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len); 231275970Scy translation = dcgettext (domain, msg_ctxt_id, category); 232275970Scy#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS 233275970Scy if (msg_ctxt_id != buf) 234275970Scy free (msg_ctxt_id); 235275970Scy#endif 236275970Scy if (translation != msg_ctxt_id) 237275970Scy return translation; 238275970Scy } 239275970Scy return msgid; 240275970Scy} 241275970Scy 242275970Scy#define npgettext_expr(Msgctxt, Msgid, MsgidPlural, N) \ 243275970Scy dcnpgettext_expr (NULL, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES) 244275970Scy#define dnpgettext_expr(Domainname, Msgctxt, Msgid, MsgidPlural, N) \ 245275970Scy dcnpgettext_expr (Domainname, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES) 246275970Scy 247275970Scy#ifdef __GNUC__ 248275970Scy__inline 249275970Scy#else 250275970Scy#ifdef __cplusplus 251275970Scyinline 252275970Scy#endif 253275970Scy#endif 254275970Scystatic const char * 255275970Scydcnpgettext_expr (const char *domain, 256275970Scy const char *msgctxt, const char *msgid, 257275970Scy const char *msgid_plural, unsigned long int n, 258275970Scy int category) 259275970Scy{ 260275970Scy size_t msgctxt_len = strlen (msgctxt) + 1; 261275970Scy size_t msgid_len = strlen (msgid) + 1; 262275970Scy const char *translation; 263275970Scy#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS 264275970Scy char msg_ctxt_id[msgctxt_len + msgid_len]; 265275970Scy#else 266275970Scy char buf[1024]; 267275970Scy char *msg_ctxt_id = 268275970Scy (msgctxt_len + msgid_len <= sizeof (buf) 269275970Scy ? buf 270275970Scy : (char *) malloc (msgctxt_len + msgid_len)); 271275970Scy if (msg_ctxt_id != NULL) 272275970Scy#endif 273275970Scy { 274275970Scy memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1); 275275970Scy msg_ctxt_id[msgctxt_len - 1] = '\004'; 276275970Scy memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len); 277275970Scy translation = dcngettext (domain, msg_ctxt_id, msgid_plural, n, category); 278275970Scy#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS 279275970Scy if (msg_ctxt_id != buf) 280275970Scy free (msg_ctxt_id); 281275970Scy#endif 282275970Scy if (!(translation == msg_ctxt_id || translation == msgid_plural)) 283275970Scy return translation; 284275970Scy } 285275970Scy return (n == 1 ? msgid : msgid_plural); 286275970Scy} 287275970Scy 288275970Scy#endif /* _LIBGETTEXT_H */ 289