1/* Convenience header for conditional use of GNU <libintl.h>.
2 SPDX-FileCopyrightText: 1995-1998, 2000-2002, 2004-2006 Free Software Foundation, Inc.
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6// clang-format off
7#ifndef _LIBGETTEXT_H
8#define _LIBGETTEXT_H 1
9
10/* Get declarations of GNU message catalog functions. */
11# include <libintl.h>
12// libintl.h redefines inline which causes MSVC to abort compilation with the message
13// fatal error C1189: #error : The C++ Standard Library forbids macroizing keywords
14#undef inline
15
16/* You can set the DEFAULT_TEXT_DOMAIN macro to specify the domain used by
17 the gettext() and ngettext() macros. This is an alternative to calling
18 textdomain(), and is useful for libraries. */
19# ifdef DEFAULT_TEXT_DOMAIN
20# undef gettext
21# define gettext(Msgid) \
22 dgettext (DEFAULT_TEXT_DOMAIN, Msgid)
23# undef ngettext
24# define ngettext(Msgid1, Msgid2, N) \
25 dngettext (DEFAULT_TEXT_DOMAIN, Msgid1, Msgid2, N)
26# endif
27
28/* The separator between msgctxt and msgid in a .mo file. */
29#define GETTEXT_CONTEXT_GLUE "\004"
30
31/* Pseudo function calls, taking a MSGCTXT and a MSGID instead of just a
32 MSGID. MSGCTXT and MSGID must be string literals. MSGCTXT should be
33 short and rarely need to change.
34 The letter 'p' stands for 'particular' or 'special'. */
35#ifdef DEFAULT_TEXT_DOMAIN
36# define pgettext(Msgctxt, Msgid) \
37 pgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid)
38#else
39# define pgettext(Msgctxt, Msgid) \
40 pgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid)
41#endif
42#define dpgettext(Domainname, Msgctxt, Msgid) \
43 pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid)
44
45#ifdef __GNUC__
46__inline
47#else
48#ifdef __cplusplus
49inline
50#endif
51#endif
52static const char *
53pgettext_aux(const char *domain,
54 const char *msg_ctxt_id, const char *msgid)
55{
56 const char *translation = dgettext(domainname: domain, msgid: msg_ctxt_id);
57 if (translation == msg_ctxt_id) {
58 return msgid;
59 } else {
60 return translation;
61 }
62}
63
64/* The same thing extended for non-constant arguments. Here MSGCTXT and MSGID
65 can be arbitrary expressions. But for string literals these macros are
66 less efficient than those above. */
67
68#include <string.h>
69
70#ifndef __STRICT_ANSI__
71#define __STRICT_ANSI__
72#define __STRICT_ANSI_FORCED__
73#endif
74
75#define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS \
76 (__STRICT_ANSI__ - 0 == 0) && (__GNUC__ >= 3 || __GNUG__ >= 2 /* || __STDC_VERSION__ >= 199901L */ )
77
78#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
79#include <stdlib.h>
80#endif
81
82#define pgettext_expr(Msgctxt, Msgid) \
83 dpgettext_expr (NULL, Msgctxt, Msgid)
84#define dpgettext_expr(Domainname, Msgctxt, Msgid) \
85 dpgettext_expr (Domainname, Msgctxt, Msgid)
86
87#ifdef __GNUC__
88__inline
89#else
90#ifdef __cplusplus
91inline
92#endif
93#endif
94static const char *
95dpgettext_expr(const char *domain,
96 const char *msgctxt, const char *msgid)
97{
98 size_t msgctxt_len = strlen(s: msgctxt) + 1;
99 size_t msgid_len = strlen(s: msgid) + 1;
100 const char *translation;
101 int translation_found;
102#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
103 char msg_ctxt_id[msgctxt_len + msgid_len];
104#else
105 char buf[1024];
106 char *msg_ctxt_id =
107 (msgctxt_len + msgid_len <= sizeof(buf)
108 ? buf
109 : (char *) malloc(size: msgctxt_len + msgid_len));
110 if (msg_ctxt_id != nullptr)
111#endif
112 {
113 memcpy(dest: msg_ctxt_id, src: msgctxt, n: msgctxt_len - 1);
114 msg_ctxt_id[msgctxt_len - 1] = '\004';
115 memcpy(dest: msg_ctxt_id + msgctxt_len, src: msgid, n: msgid_len);
116 translation = dgettext(domainname: domain, msgid: msg_ctxt_id);
117 /* Test must occur before msg_ctxt_id freed */
118 translation_found = translation != msg_ctxt_id;
119#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
120 if (msg_ctxt_id != buf) {
121 free(ptr: msg_ctxt_id);
122 }
123#endif
124 if (translation_found) {
125 return translation;
126 }
127 }
128 return msgid;
129}
130
131#define npgettext_expr(Msgctxt, Msgid, MsgidPlural, N) \
132 dnpgettext_expr (NULL, Msgctxt, Msgid, MsgidPlural, N)
133#define dnpgettext_expr(Domainname, Msgctxt, Msgid, MsgidPlural, N) \
134 dnpgettext_expr (Domainname, Msgctxt, Msgid, MsgidPlural, N)
135
136#ifdef __GNUC__
137__inline
138#else
139#ifdef __cplusplus
140inline
141#endif
142#endif
143static const char *
144dnpgettext_expr(const char *domain,
145 const char *msgctxt, const char *msgid,
146 const char *msgid_plural, unsigned long int n)
147{
148 size_t msgctxt_len = strlen(s: msgctxt) + 1;
149 size_t msgid_len = strlen(s: msgid) + 1;
150 const char *translation;
151 int translation_found;
152#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
153 char msg_ctxt_id[msgctxt_len + msgid_len];
154#else
155 char buf[1024];
156 char *msg_ctxt_id =
157 (msgctxt_len + msgid_len <= sizeof(buf)
158 ? buf
159 : (char *) malloc(size: msgctxt_len + msgid_len));
160 if (msg_ctxt_id != nullptr)
161#endif
162 {
163 memcpy(dest: msg_ctxt_id, src: msgctxt, n: msgctxt_len - 1);
164 msg_ctxt_id[msgctxt_len - 1] = '\004';
165 memcpy(dest: msg_ctxt_id + msgctxt_len, src: msgid, n: msgid_len);
166 translation = dngettext(domainname: domain, msgid1: msg_ctxt_id, msgid2: msgid_plural, n: n);
167 /* Test must occur before msg_ctxt_id freed */
168 translation_found = !(translation == msg_ctxt_id || translation == msgid_plural);
169#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
170 if (msg_ctxt_id != buf) {
171 free(ptr: msg_ctxt_id);
172 }
173#endif
174 if (translation_found) {
175 return translation;
176 }
177 }
178 return (n == 1 ? msgid : msgid_plural);
179}
180
181#ifdef __STRICT_ANSI_FORCED__
182#undef __STRICT_ANSI__
183#undef __STRICT_ANSI_FORCED__
184#endif
185
186#endif /* _LIBGETTEXT_H */
187// clang-format on
188

source code of ki18n/src/i18n/gettext.h