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