File indexing completed on 2024-04-28 11:40:00

0001 /*  Convenience header for conditional use of GNU <libintl.h>.
0002     SPDX-FileCopyrightText: 1995-1998, 2000-2002, 2004-2006 Free Software Foundation, Inc.
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 // clang-format off
0007 #ifndef _LIBGETTEXT_H
0008 #define _LIBGETTEXT_H 1
0009 
0010 /* Get declarations of GNU message catalog functions.  */
0011 # include <libintl.h>
0012 // libintl.h redefines inline which causes MSVC to abort compilation with the message
0013 // fatal error C1189: #error :  The C++ Standard Library forbids macroizing keywords
0014 #undef inline
0015 
0016 /* You can set the DEFAULT_TEXT_DOMAIN macro to specify the domain used by
0017    the gettext() and ngettext() macros.  This is an alternative to calling
0018    textdomain(), and is useful for libraries.  */
0019 # ifdef DEFAULT_TEXT_DOMAIN
0020 #  undef gettext
0021 #  define gettext(Msgid) \
0022     dgettext (DEFAULT_TEXT_DOMAIN, Msgid)
0023 #  undef ngettext
0024 #  define ngettext(Msgid1, Msgid2, N) \
0025     dngettext (DEFAULT_TEXT_DOMAIN, Msgid1, Msgid2, N)
0026 # endif
0027 
0028 /* The separator between msgctxt and msgid in a .mo file.  */
0029 #define GETTEXT_CONTEXT_GLUE "\004"
0030 
0031 /* Pseudo function calls, taking a MSGCTXT and a MSGID instead of just a
0032    MSGID.  MSGCTXT and MSGID must be string literals.  MSGCTXT should be
0033    short and rarely need to change.
0034    The letter 'p' stands for 'particular' or 'special'.  */
0035 #ifdef DEFAULT_TEXT_DOMAIN
0036 # define pgettext(Msgctxt, Msgid) \
0037     pgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid)
0038 #else
0039 # define pgettext(Msgctxt, Msgid) \
0040     pgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid)
0041 #endif
0042 #define dpgettext(Domainname, Msgctxt, Msgid) \
0043     pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid)
0044 
0045 #ifdef __GNUC__
0046 __inline
0047 #else
0048 #ifdef __cplusplus
0049 inline
0050 #endif
0051 #endif
0052 static const char *
0053 pgettext_aux(const char *domain,
0054              const char *msg_ctxt_id, const char *msgid)
0055 {
0056     const char *translation = dgettext(domain, msg_ctxt_id);
0057     if (translation == msg_ctxt_id) {
0058         return msgid;
0059     } else {
0060         return translation;
0061     }
0062 }
0063 
0064 /* The same thing extended for non-constant arguments.  Here MSGCTXT and MSGID
0065    can be arbitrary expressions.  But for string literals these macros are
0066    less efficient than those above.  */
0067 
0068 #include <string.h>
0069 
0070 #ifndef __STRICT_ANSI__
0071 #define __STRICT_ANSI__
0072 #define __STRICT_ANSI_FORCED__
0073 #endif
0074 
0075 #define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS \
0076     (__STRICT_ANSI__ - 0 == 0) && (__GNUC__ >= 3 || __GNUG__ >= 2 /* || __STDC_VERSION__ >= 199901L */ )
0077 
0078 #if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
0079 #include <stdlib.h>
0080 #endif
0081 
0082 #define pgettext_expr(Msgctxt, Msgid) \
0083     dpgettext_expr (NULL, Msgctxt, Msgid)
0084 #define dpgettext_expr(Domainname, Msgctxt, Msgid) \
0085     dpgettext_expr (Domainname, Msgctxt, Msgid)
0086 
0087 #ifdef __GNUC__
0088 __inline
0089 #else
0090 #ifdef __cplusplus
0091 inline
0092 #endif
0093 #endif
0094 static const char *
0095 dpgettext_expr(const char *domain,
0096                 const char *msgctxt, const char *msgid)
0097 {
0098     size_t msgctxt_len = strlen(msgctxt) + 1;
0099     size_t msgid_len = strlen(msgid) + 1;
0100     const char *translation;
0101     int translation_found;
0102 #if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
0103     char msg_ctxt_id[msgctxt_len + msgid_len];
0104 #else
0105     char buf[1024];
0106     char *msg_ctxt_id =
0107         (msgctxt_len + msgid_len <= sizeof(buf)
0108          ? buf
0109          : (char *) malloc(msgctxt_len + msgid_len));
0110     if (msg_ctxt_id != nullptr)
0111 #endif
0112     {
0113         memcpy(msg_ctxt_id, msgctxt, msgctxt_len - 1);
0114         msg_ctxt_id[msgctxt_len - 1] = '\004';
0115         memcpy(msg_ctxt_id + msgctxt_len, msgid, msgid_len);
0116         translation = dgettext(domain, msg_ctxt_id);
0117         /* Test must occur before msg_ctxt_id freed */
0118         translation_found = translation != msg_ctxt_id;
0119 #if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
0120         if (msg_ctxt_id != buf) {
0121             free(msg_ctxt_id);
0122         }
0123 #endif
0124         if (translation_found) {
0125             return translation;
0126         }
0127     }
0128     return msgid;
0129 }
0130 
0131 #define npgettext_expr(Msgctxt, Msgid, MsgidPlural, N) \
0132     dnpgettext_expr (NULL, Msgctxt, Msgid, MsgidPlural, N)
0133 #define dnpgettext_expr(Domainname, Msgctxt, Msgid, MsgidPlural, N) \
0134     dnpgettext_expr (Domainname, Msgctxt, Msgid, MsgidPlural, N)
0135 
0136 #ifdef __GNUC__
0137 __inline
0138 #else
0139 #ifdef __cplusplus
0140 inline
0141 #endif
0142 #endif
0143 static const char *
0144 dnpgettext_expr(const char *domain,
0145                  const char *msgctxt, const char *msgid,
0146                  const char *msgid_plural, unsigned long int n)
0147 {
0148     size_t msgctxt_len = strlen(msgctxt) + 1;
0149     size_t msgid_len = strlen(msgid) + 1;
0150     const char *translation;
0151     int translation_found;
0152 #if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
0153     char msg_ctxt_id[msgctxt_len + msgid_len];
0154 #else
0155     char buf[1024];
0156     char *msg_ctxt_id =
0157         (msgctxt_len + msgid_len <= sizeof(buf)
0158          ? buf
0159          : (char *) malloc(msgctxt_len + msgid_len));
0160     if (msg_ctxt_id != nullptr)
0161 #endif
0162     {
0163         memcpy(msg_ctxt_id, msgctxt, msgctxt_len - 1);
0164         msg_ctxt_id[msgctxt_len - 1] = '\004';
0165         memcpy(msg_ctxt_id + msgctxt_len, msgid, msgid_len);
0166         translation = dngettext(domain, msg_ctxt_id, msgid_plural, n);
0167         /* Test must occur before msg_ctxt_id freed */
0168         translation_found = !(translation == msg_ctxt_id || translation == msgid_plural);
0169 #if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
0170         if (msg_ctxt_id != buf) {
0171             free(msg_ctxt_id);
0172         }
0173 #endif
0174         if (translation_found) {
0175             return translation;
0176         }
0177     }
0178     return (n == 1 ? msgid : msgid_plural);
0179 }
0180 
0181 #ifdef __STRICT_ANSI_FORCED__
0182 #undef __STRICT_ANSI__
0183 #undef __STRICT_ANSI_FORCED__
0184 #endif
0185 
0186 #endif /* _LIBGETTEXT_H */
0187 // clang-format on