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