Coverage Report

Created: 2026-07-30 07:17

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ki18n/src/i18n/gettext.h
Line
Count
Source
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
0
{
56
0
    const char *translation = dgettext(domain, msg_ctxt_id);
57
0
    if (translation == msg_ctxt_id) {
58
0
        return msgid;
59
0
    } else {
60
0
        return translation;
61
0
    }
62
0
}
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
0
    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
0
{
98
0
    size_t msgctxt_len = strlen(msgctxt) + 1;
99
0
    size_t msgid_len = strlen(msgid) + 1;
100
0
    const char *translation;
101
0
    int translation_found;
102
#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
103
    char msg_ctxt_id[msgctxt_len + msgid_len];
104
#else
105
0
    char buf[1024];
106
0
    char *msg_ctxt_id =
107
0
        (msgctxt_len + msgid_len <= sizeof(buf)
108
0
         ? buf
109
0
         : (char *) malloc(msgctxt_len + msgid_len));
110
0
    if (msg_ctxt_id != nullptr)
111
0
#endif
112
0
    {
113
0
        memcpy(msg_ctxt_id, msgctxt, msgctxt_len - 1);
114
0
        msg_ctxt_id[msgctxt_len - 1] = '\004';
115
0
        memcpy(msg_ctxt_id + msgctxt_len, msgid, msgid_len);
116
0
        translation = dgettext(domain, msg_ctxt_id);
117
        /* Test must occur before msg_ctxt_id freed */
118
0
        translation_found = translation != msg_ctxt_id;
119
0
#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
120
0
        if (msg_ctxt_id != buf) {
121
0
            free(msg_ctxt_id);
122
0
        }
123
0
#endif
124
0
        if (translation_found) {
125
0
            return translation;
126
0
        }
127
0
    }
128
0
    return msgid;
129
0
}
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
0
    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
0
{
148
0
    size_t msgctxt_len = strlen(msgctxt) + 1;
149
0
    size_t msgid_len = strlen(msgid) + 1;
150
0
    const char *translation;
151
0
    int translation_found;
152
#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
153
    char msg_ctxt_id[msgctxt_len + msgid_len];
154
#else
155
0
    char buf[1024];
156
0
    char *msg_ctxt_id =
157
0
        (msgctxt_len + msgid_len <= sizeof(buf)
158
0
         ? buf
159
0
         : (char *) malloc(msgctxt_len + msgid_len));
160
0
    if (msg_ctxt_id != nullptr)
161
0
#endif
162
0
    {
163
0
        memcpy(msg_ctxt_id, msgctxt, msgctxt_len - 1);
164
0
        msg_ctxt_id[msgctxt_len - 1] = '\004';
165
0
        memcpy(msg_ctxt_id + msgctxt_len, msgid, msgid_len);
166
0
        translation = dngettext(domain, msg_ctxt_id, msgid_plural, n);
167
        /* Test must occur before msg_ctxt_id freed */
168
0
        translation_found = !(translation == msg_ctxt_id || translation == msgid_plural);
169
0
#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
170
0
        if (msg_ctxt_id != buf) {
171
0
            free(msg_ctxt_id);
172
0
        }
173
0
#endif
174
0
        if (translation_found) {
175
0
            return translation;
176
0
        }
177
0
    }
178
0
    return (n == 1 ? msgid : msgid_plural);
179
0
}
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