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