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
40extern "C" {
41#endif
42
43
44/* If true, omit the header entry.
45   If false, keep the header entry present in the input.  */
46extern int xgettext_omit_header;
47
48extern bool substring_match;
49
50
51/* Calling convention for a given keyword.  */
52struct 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.  */
64extern void split_keywordspec (const char *spec, const char **endp,
65			       struct callshape *shapep);
66
67/* Set of alternative calling conventions for a given keyword.  */
68struct 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 *'.  */
78extern 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.  */
84typedef struct flag_context_ty flag_context_ty;
85struct 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.  */
95extern flag_context_ty null_context;
96/* Transparent context.  */
97extern 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.  */
101extern 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.  */
107typedef struct flag_context_list_ty flag_context_list_ty;
108struct 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.  */
116typedef struct flag_context_list_iterator_ty flag_context_list_iterator_ty;
117struct flag_context_list_iterator_ty
118{
119  int argnum;				/* current argument number, > 0 */
120  const flag_context_list_ty* head;	/* tail of list */
121};
122extern flag_context_list_iterator_ty null_context_list_iterator;
123extern flag_context_list_iterator_ty passthrough_context_list_iterator;
124extern flag_context_list_iterator_ty
125       flag_context_list_iterator (flag_context_list_ty *list);
126extern 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 *.  */
131typedef hash_table /* char[] -> flag_context_list_ty * */
132        flag_context_list_table_ty;
133extern 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.  */
137extern void xgettext_record_flag (const char *optionstring);
138
139
140/* Canonicalized encoding name for all input files.  */
141extern 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).  */
146extern iconv_t xgettext_global_source_iconv;
147#endif
148
149/* Canonicalized encoding name for the current input file.  */
150extern 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).  */
155extern 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.  */
162extern 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().  */
169extern 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
187typedef struct refcounted_string_list_ty refcounted_string_list_ty;
188struct refcounted_string_list_ty
189{
190  unsigned int refcount;
191  struct string_list_ty contents;
192};
193
194static inline refcounted_string_list_ty *
195add_reference (refcounted_string_list_ty *rslp)
196{
197  if (rslp != NULL)
198    rslp->refcount++;
199  return rslp;
200}
201
202static inline void
203drop_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
217extern refcounted_string_list_ty *savable_comment;
218extern void savable_comment_add (const char *str);
219extern 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.  */
230extern 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.  */
243extern 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'.  */
252struct 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'.  */
274struct 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.  */
285extern struct arglist_parser * arglist_parser_alloc (message_list_ty *mlp,
286						     const struct callshapes *shapes);
287/* Clones an arglist_parser.  */
288extern 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.  */
295extern 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.  */
302extern 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.  */
305extern 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