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