1 /* xgettext common functions. 2 Copyright (C) 2001-2003, 2005-2006 Free Software Foundation, Inc. 3 Written by Peter Miller <millerp (at) canb.auug.org.au> 4 and Bruno Haible <haible (at) 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 * 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 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