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