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