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 |
49 | inline |
50 | #endif |
51 | #endif |
52 | static const char * |
53 | pgettext_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 |
91 | inline |
92 | #endif |
93 | #endif |
94 | static const char * |
95 | dpgettext_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 |
140 | inline |
141 | #endif |
142 | #endif |
143 | static const char * |
144 | dnpgettext_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 | |