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