1 /* xgettext common functions.
2 Copyright (C) 2001-2003, 2005-2006 Free Software Foundation, Inc.
3 Written by Peter Miller <millerp@canb.auug.org.au>
4 and Bruno Haible <haible@clisp.cons.org>, 2001.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software Foundation,
18 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
19
20 #ifndef _XGETTEXT_H
21 #define _XGETTEXT_H
22
23 #include <stdbool.h>
24 #include <stddef.h>
25 #include <stdlib.h>
26
27 #if HAVE_ICONV
28 #include <iconv.h>
29 #endif
30
31 #include "message.h"
32 #include "pos.h"
33 #include "str-list.h"
34
35 /* Declare 'line_comment' and 'input_syntax'. */
36 #include "read-catalog.h"
37
38
39 #ifdef __cplusplus
40 extern "C" {
41 #endif
42
43
44 /* If true, omit the header entry.
45 If false, keep the header entry present in the input. */
46 extern int xgettext_omit_header;
47
48 extern bool substring_match;
49
50
51 /* Calling convention for a given keyword. */
52 struct callshape
53 {
54 int argnum1; /* argument number to use for msgid */
55 int argnum2; /* argument number to use for msgid_plural */
56 int argnumc; /* argument number to use for msgctxt */
57 bool argnum1_glib_context; /* argument argnum1 has the syntax "ctxt|msgid" */
58 bool argnum2_glib_context; /* argument argnum2 has the syntax "ctxt|msgid" */
59 int argtotal; /* total number of arguments */
60 string_list_ty xcomments; /* auto-extracted comments */
61 };
62
63 /* Split keyword spec into keyword, argnum1, argnum2, argnumc. */
64 extern void split_keywordspec (const char *spec, const char **endp,
65 struct callshape *shapep);
66
67 /* Set of alternative calling conventions for a given keyword. */
68 struct callshapes
69 {
70 const char *keyword; /* the keyword, not NUL terminated */
71 size_t keyword_len; /* the keyword's length */
72 size_t nshapes;
73 struct callshape shapes[1]; /* actually nshapes elements */
74 };
75
76 /* Insert a (keyword, callshape) pair into a hash table mapping keyword to
77 'struct callshapes *'. */
78 extern void insert_keyword_callshape (hash_table *table,
79 const char *keyword, size_t keyword_len,
80 const struct callshape *shape);
81
82
83 /* Context representing some flags. */
84 typedef struct flag_context_ty flag_context_ty;
85 struct flag_context_ty
86 {
87 /* Regarding the primary formatstring type. */
88 /*enum is_format*/ unsigned int is_format1 : 3;
89 /*bool*/ unsigned int pass_format1 : 1;
90 /* Regarding the secondary formatstring type. */
91 /*enum is_format*/ unsigned int is_format2 : 3;
92 /*bool*/ unsigned int pass_format2 : 1;
93 };
94 /* Null context. */
95 extern flag_context_ty null_context;
96 /* Transparent context. */
97 extern flag_context_ty passthrough_context;
98 /* Compute an inherited context.
99 The outer_context is assumed to have all pass_format* flags = false.
100 The result will then also have all pass_format* flags = false. */
101 extern flag_context_ty
102 inherited_context (flag_context_ty outer_context,
103 flag_context_ty modifier_context);
104
105 /* Context representing some flags, for each possible argument number.
106 This is a linked list, sorted according to the argument number. */
107 typedef struct flag_context_list_ty flag_context_list_ty;
108 struct flag_context_list_ty
109 {
110 int argnum; /* current argument number, > 0 */
111 flag_context_ty flags; /* flags for current argument */
112 flag_context_list_ty *next;
113 };
114
115 /* Iterator through a flag_context_list_ty. */
116 typedef struct flag_context_list_iterator_ty flag_context_list_iterator_ty;
117 struct flag_context_list_iterator_ty
118 {
119 int argnum; /* current argument number, > 0 */
120 const flag_context_list_ty* head; /* tail of list */
121 };
122 extern flag_context_list_iterator_ty null_context_list_iterator;
123 extern flag_context_list_iterator_ty passthrough_context_list_iterator;
124 extern flag_context_list_iterator_ty
125 flag_context_list_iterator (flag_context_list_ty *list);
126 extern flag_context_ty
127 flag_context_list_iterator_advance (flag_context_list_iterator_ty *iter);
128
129 /* For nearly each backend, we have a separate table mapping a keyword to
130 a flag_context_list_ty *. */
131 typedef hash_table /* char[] -> flag_context_list_ty * */
132 flag_context_list_table_ty;
133 extern flag_context_list_ty *
134 flag_context_list_table_lookup (flag_context_list_table_ty *flag_table,
135 const void *key, size_t keylen);
136 /* Record a flag in the appropriate backend's table. */
137 extern void xgettext_record_flag (const char *optionstring);
138
139
140 /* Canonicalized encoding name for all input files. */
141 extern const char *xgettext_global_source_encoding;
142
143 #if HAVE_ICONV
144 /* Converter from xgettext_global_source_encoding to UTF-8 (except from
145 ASCII or UTF-8, when this conversion is a no-op). */
146 extern iconv_t xgettext_global_source_iconv;
147 #endif
148
149 /* Canonicalized encoding name for the current input file. */
150 extern const char *xgettext_current_source_encoding;
151
152 #if HAVE_ICONV
153 /* Converter from xgettext_current_source_encoding to UTF-8 (except from
154 ASCII or UTF-8, when this conversion is a no-op). */
155 extern iconv_t xgettext_current_source_iconv;
156 #endif
157
158 /* Convert the given string from xgettext_current_source_encoding to
159 the output file encoding (i.e. ASCII or UTF-8).
160 The resulting string is either the argument string, or freshly allocated.
161 The file_name and line_number are only used for error message purposes. */
162 extern char *from_current_source_encoding (const char *string,
163 const char *file_name,
164 size_t line_number);
165
166
167 /* List of messages whose msgids must not be extracted, or NULL.
168 Used by remember_a_message(). */
169 extern message_list_ty *exclude;
170
171
172 /* Comment handling for backends which support combining adjacent strings
173 even across lines.
174 In these backends we cannot use the xgettext_comment* functions directly,
175 because in multiline string expressions like
176 "string1" +
177 "string2"
178 the newline between "string1" and "string2" would cause a call to
179 xgettext_comment_reset(), thus destroying the accumulated comments
180 that we need a little later, when we have concatenated the two strings
181 and pass them to remember_a_message().
182 Instead, we do the bookkeeping of the accumulated comments directly,
183 and save a pointer to the accumulated comments when we read "string1".
184 In order to avoid excessive copying of strings, we use reference
185 counting. */
186
187 typedef struct refcounted_string_list_ty refcounted_string_list_ty;
188 struct refcounted_string_list_ty
189 {
190 unsigned int refcount;
191 struct string_list_ty contents;
192 };
193
194 static inline refcounted_string_list_ty *
add_reference(refcounted_string_list_ty * rslp)195 add_reference (refcounted_string_list_ty *rslp)
196 {
197 if (rslp != NULL)
198 rslp->refcount++;
199 return rslp;
200 }
201
202 static inline void
drop_reference(refcounted_string_list_ty * rslp)203 drop_reference (refcounted_string_list_ty *rslp)
204 {
205 if (rslp != NULL)
206 {
207 if (rslp->refcount > 1)
208 rslp->refcount--;
209 else
210 {
211 string_list_destroy (&rslp->contents);
212 free (rslp);
213 }
214 }
215 }
216
217 extern refcounted_string_list_ty *savable_comment;
218 extern void savable_comment_add (const char *str);
219 extern void savable_comment_reset (void);
220
221
222 /* Add a message to the list of extracted messages.
223 msgctxt must be either NULL or a malloc()ed string; its ownership is passed
224 to the callee.
225 MSGID must be a malloc()ed string; its ownership is passed to the callee.
226 POS->file_name must be allocated with indefinite extent.
227 COMMENT may be savable_comment, or it may be a saved copy of savable_comment
228 (then add_reference must be used when saving it, and drop_reference while
229 dropping it). Clear savable_comment. */
230 extern message_ty *remember_a_message (message_list_ty *mlp,
231 char *msgctxt,
232 char *msgid,
233 flag_context_ty context,
234 lex_pos_ty *pos,
235 refcounted_string_list_ty *comment);
236 /* Add an msgid_plural to a message previously returned by
237 remember_a_message.
238 STRING must be a malloc()ed string; its ownership is passed to the callee.
239 POS->file_name must be allocated with indefinite extent.
240 COMMENT may be savable_comment, or it may be a saved copy of savable_comment
241 (then add_reference must be used when saving it, and drop_reference while
242 dropping it). Clear savable_comment. */
243 extern void remember_a_message_plural (message_ty *mp,
244 char *string,
245 flag_context_ty context,
246 lex_pos_ty *pos,
247 refcounted_string_list_ty *comment);
248
249
250 /* Represents the progressive parsing of an argument list w.r.t. a single
251 'struct callshape'. */
252 struct partial_call
253 {
254 int argnumc; /* number of context argument, 0 when seen */
255 int argnum1; /* number of singular argument, 0 when seen */
256 int argnum2; /* number of plural argument, 0 when seen */
257 bool argnum1_glib_context; /* argument argnum1 has the syntax "ctxt|msgid" */
258 bool argnum2_glib_context; /* argument argnum2 has the syntax "ctxt|msgid" */
259 int argtotal; /* total number of arguments, 0 if unspecified */
260 string_list_ty xcomments; /* auto-extracted comments */
261 char *msgctxt; /* context - owned string, or NULL */
262 lex_pos_ty msgctxt_pos;
263 char *msgid; /* msgid - owned string, or NULL */
264 flag_context_ty msgid_context;
265 lex_pos_ty msgid_pos;
266 refcounted_string_list_ty *msgid_comment;
267 char *msgid_plural; /* msgid_plural - owned string, or NULL */
268 flag_context_ty msgid_plural_context;
269 lex_pos_ty msgid_plural_pos;
270 };
271
272 /* Represents the progressive parsing of an argument list w.r.t. an entire
273 'struct callshapes'. */
274 struct arglist_parser
275 {
276 message_list_ty *mlp; /* list where the message shall be added */
277 const char *keyword; /* the keyword, not NUL terminated */
278 size_t keyword_len; /* the keyword's length */
279 size_t nalternatives; /* number of partial_call alternatives */
280 struct partial_call alternative[1]; /* partial_call alternatives */
281 };
282
283 /* Creates a fresh arglist_parser recognizing calls.
284 You can pass shapes = NULL for a parser not recognizing any calls. */
285 extern struct arglist_parser * arglist_parser_alloc (message_list_ty *mlp,
286 const struct callshapes *shapes);
287 /* Clones an arglist_parser. */
288 extern struct arglist_parser * arglist_parser_clone (struct arglist_parser *ap);
289 /* Adds a string argument to an arglist_parser. ARGNUM must be > 0.
290 STRING must be malloc()ed string; its ownership is passed to the callee.
291 FILE_NAME must be allocated with indefinite extent.
292 COMMENT may be savable_comment, or it may be a saved copy of savable_comment
293 (then add_reference must be used when saving it, and drop_reference while
294 dropping it). Clear savable_comment. */
295 extern void arglist_parser_remember (struct arglist_parser *ap,
296 int argnum, char *string,
297 flag_context_ty context,
298 char *file_name, size_t line_number,
299 refcounted_string_list_ty *comment);
300 /* Tests whether an arglist_parser has is not waiting for more arguments after
301 argument ARGNUM. */
302 extern bool arglist_parser_decidedp (struct arglist_parser *ap, int argnum);
303 /* Terminates the processing of an arglist_parser after argument ARGNUM and
304 deletes it. */
305 extern void arglist_parser_done (struct arglist_parser *ap, int argnum);
306
307
308 #ifdef __cplusplus
309 }
310 #endif
311
312
313 #endif /* _XGETTEXT_H */
314