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