1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
|
/* GNU gettext - internationalization aids
Copyright (C) 1995-1998, 2000-2009, 2015-2016 Free Software Foundation, Inc.
This file was written by Peter Miller <millerp@canb.auug.org.au>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#ifndef _MESSAGE_H
#define _MESSAGE_H
#include "str-list.h"
#include "pos.h"
#include "hash.h"
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/* According to Sun's Uniforum proposal the default message domain is
named 'messages'. */
#define MESSAGE_DOMAIN_DEFAULT "messages"
/* Separator between msgctxt and msgid in .mo files. */
#define MSGCTXT_SEPARATOR '\004' /* EOT */
/* Kinds of format strings. */
enum format_type
{
format_c,
format_objc,
format_sh,
format_python,
format_python_brace,
format_lisp,
format_elisp,
format_librep,
format_scheme,
format_smalltalk,
format_java,
format_csharp,
format_awk,
format_pascal,
format_ycp,
format_tcl,
format_perl,
format_perl_brace,
format_php,
format_gcc_internal,
format_gfc_internal,
format_qt,
format_qt_plural,
format_kde,
format_kde_kuit,
format_boost,
format_lua,
format_javascript
};
#define NFORMATS 28 /* Number of format_type enum values. */
extern DLL_VARIABLE const char *const format_language[NFORMATS];
extern DLL_VARIABLE const char *const format_language_pretty[NFORMATS];
/* Is current msgid a format string? */
enum is_format
{
undecided,
yes,
no,
yes_according_to_context,
possible,
impossible
};
extern bool
possible_format_p (enum is_format);
/* Range of an unsigned integer argument. */
struct argument_range
{
int min;
int max;
};
/* Tests whether a range is present. */
#define has_range_p(range) ((range).min >= 0 && (range).max >= 0)
/* Is current msgid wrappable? */
#if 0
enum is_wrap
{
undecided,
yes,
no
};
#else /* HACK - C's enum concept is so stupid */
#define is_wrap is_format
#endif
/* Kinds of syntax checks which apply to strings. */
enum syntax_check_type
{
sc_ellipsis_unicode,
sc_space_ellipsis,
sc_quote_unicode
};
#define NSYNTAXCHECKS 3
extern DLL_VARIABLE const char *const syntax_check_name[NSYNTAXCHECKS];
/* Is current msgid subject to a syntax check? */
#if 0
enum is_syntax_check
{
undecided,
yes,
no
};
#else /* HACK - C's enum concept is so stupid */
#define is_syntax_check is_format
#endif
struct altstr
{
const char *msgstr;
size_t msgstr_len;
const char *msgstr_end;
string_list_ty *comment;
string_list_ty *comment_dot;
char *id;
};
typedef struct message_ty message_ty;
struct message_ty
{
/* The msgctxt string, if present. */
const char *msgctxt;
/* The msgid string. */
const char *msgid;
/* The msgid's plural, if present. */
const char *msgid_plural;
/* The msgstr strings. */
const char *msgstr;
/* The number of bytes in msgstr, including the terminating NUL. */
size_t msgstr_len;
/* Position in the source PO file. */
lex_pos_ty pos;
/* Plain comments (#) appearing before the message. */
string_list_ty *comment;
/* Extracted comments (#.) appearing before the message. */
string_list_ty *comment_dot;
/* File position comments (#:) appearing before the message, one for
each unique file position instance, sorted by file name and then
by line. */
size_t filepos_count;
lex_pos_ty *filepos;
/* Informations from special comments (#,).
Some of them come from extracted comments. They are manipulated by
the tools, e.g. msgmerge. */
/* Fuzzy means "needs translator review". */
bool is_fuzzy;
/* Designation of format string syntax requirements for specific
programming languages. */
enum is_format is_format[NFORMATS];
/* Lower and upper bound for the argument whose format directive can be
omitted in specific cases of singular or plural. */
struct argument_range range;
/* Do we want the string to be wrapped in the emitted PO file? */
enum is_wrap do_wrap;
/* Do we want to apply extra syntax checks on the string? */
enum is_syntax_check do_syntax_check[NSYNTAXCHECKS];
/* The prev_msgctxt, prev_msgid and prev_msgid_plural strings appearing
before the message, if present. Generated by msgmerge. */
const char *prev_msgctxt;
const char *prev_msgid;
const char *prev_msgid_plural;
/* If set the message is obsolete and while writing out it should be
commented out. */
bool obsolete;
/* Used for checking that messages have been used, in the msgcmp,
msgmerge, msgcomm and msgcat programs. */
int used;
/* Used for looking up the target message, in the msgcat program. */
message_ty *tmp;
/* Used for combining alternative translations, in the msgcat program. */
int alternative_count;
struct altstr *alternative;
};
extern message_ty *
message_alloc (const char *msgctxt,
const char *msgid, const char *msgid_plural,
const char *msgstr, size_t msgstr_len,
const lex_pos_ty *pp);
#define is_header(mp) ((mp)->msgctxt == NULL && (mp)->msgid[0] == '\0')
extern void
message_free (message_ty *mp);
extern void
message_comment_append (message_ty *mp, const char *comment);
extern void
message_comment_dot_append (message_ty *mp, const char *comment);
extern void
message_comment_filepos (message_ty *mp, const char *name, size_t line);
extern message_ty *
message_copy (message_ty *mp);
typedef struct message_list_ty message_list_ty;
struct message_list_ty
{
message_ty **item;
size_t nitems;
size_t nitems_max;
bool use_hashtable;
hash_table htable; /* Table mapping msgid to 'message_ty *'. */
};
/* Create a fresh message list.
If USE_HASHTABLE is true, a hash table will be used to speed up
message_list_search(). USE_HASHTABLE can only be set to true if it is
known that the message list will not contain duplicate msgids. */
extern message_list_ty *
message_list_alloc (bool use_hashtable);
/* Free a message list.
If keep_messages = 0, also free the messages. If keep_messages = 1, don't
free the messages. */
extern void
message_list_free (message_list_ty *mlp, int keep_messages);
extern void
message_list_append (message_list_ty *mlp, message_ty *mp);
extern void
message_list_prepend (message_list_ty *mlp, message_ty *mp);
extern void
message_list_insert_at (message_list_ty *mlp, size_t n, message_ty *mp);
extern void
message_list_delete_nth (message_list_ty *mlp, size_t n);
typedef bool message_predicate_ty (const message_ty *mp);
extern void
message_list_remove_if_not (message_list_ty *mlp,
message_predicate_ty *predicate);
/* Recompute the hash table of a message list after the msgids or msgctxts
changed. */
extern bool
message_list_msgids_changed (message_list_ty *mlp);
/* Copy a message list.
If copy_level = 0, also copy the messages. If copy_level = 1, share the
messages. */
extern message_list_ty *
message_list_copy (message_list_ty *mlp, int copy_level);
extern message_ty *
message_list_search (message_list_ty *mlp,
const char *msgctxt, const char *msgid);
/* Return the message in MLP which maximizes the fuzzy_search_goal_function.
Only messages with a fuzzy_search_goal_function > FUZZY_THRESHOLD are
considered. In case of several messages with the same goal function value,
the one with the smaller index is returned. */
extern message_ty *
message_list_search_fuzzy (message_list_ty *mlp,
const char *msgctxt, const char *msgid);
typedef struct message_list_list_ty message_list_list_ty;
struct message_list_list_ty
{
message_list_ty **item;
size_t nitems;
size_t nitems_max;
};
extern message_list_list_ty *
message_list_list_alloc (void);
/* Free a list of message lists.
If keep_level = 0, also free the messages. If keep_level = 1, don't free
the messages but free the lists. If keep_level = 2, don't free the
the messages and the lists. */
extern void
message_list_list_free (message_list_list_ty *mllp, int keep_level);
extern void
message_list_list_append (message_list_list_ty *mllp,
message_list_ty *mlp);
extern void
message_list_list_append_list (message_list_list_ty *mllp,
message_list_list_ty *mllp2);
extern message_ty *
message_list_list_search (message_list_list_ty *mllp,
const char *msgctxt, const char *msgid);
extern message_ty *
message_list_list_search_fuzzy (message_list_list_ty *mllp,
const char *msgctxt, const char *msgid);
typedef struct msgdomain_ty msgdomain_ty;
struct msgdomain_ty
{
const char *domain;
message_list_ty *messages;
};
extern msgdomain_ty *
msgdomain_alloc (const char *domain, bool use_hashtable);
extern void
msgdomain_free (msgdomain_ty *mdp);
typedef struct msgdomain_list_ty msgdomain_list_ty;
struct msgdomain_list_ty
{
msgdomain_ty **item;
size_t nitems;
size_t nitems_max;
bool use_hashtable;
const char *encoding; /* canonicalized encoding or NULL if unknown */
};
extern msgdomain_list_ty *
msgdomain_list_alloc (bool use_hashtable);
extern void
msgdomain_list_free (msgdomain_list_ty *mdlp);
extern void
msgdomain_list_append (msgdomain_list_ty *mdlp, msgdomain_ty *mdp);
extern void
msgdomain_list_append_list (msgdomain_list_ty *mdlp,
msgdomain_list_ty *mdlp2);
extern message_list_ty *
msgdomain_list_sublist (msgdomain_list_ty *mdlp, const char *domain,
bool create);
/* Copy a message domain list.
If copy_level = 0, also copy the messages. If copy_level = 1, share the
messages but copy the domains. If copy_level = 2, share the domains. */
extern msgdomain_list_ty *
msgdomain_list_copy (msgdomain_list_ty *mdlp, int copy_level);
extern message_ty *
msgdomain_list_search (msgdomain_list_ty *mdlp,
const char *msgctxt, const char *msgid);
extern message_ty *
msgdomain_list_search_fuzzy (msgdomain_list_ty *mdlp,
const char *msgctxt, const char *msgid);
/* The goal function used in fuzzy search.
Higher values indicate a closer match.
If the result is < LOWER_BOUND, an arbitrary other value < LOWER_BOUND can
be returned. */
extern double
fuzzy_search_goal_function (const message_ty *mp,
const char *msgctxt, const char *msgid,
double lower_bound);
/* The threshold for fuzzy-searching.
A message is considered only if
fuzzy_search_goal_function (mp, given, 0.0) > FUZZY_THRESHOLD. */
#define FUZZY_THRESHOLD 0.6
#ifdef __cplusplus
}
#endif
#endif /* message.h */
|