xref: /netbsd-src/external/gpl2/gettext/dist/gettext-tools/src/xgettext.h (revision 946379e7b37692fc43f68eb0d1c10daa0a7f3b6c)
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