1 /* GNU gettext - internationalization aids 2 Copyright (C) 1995-1998, 2000-2010, 2012-2013, 2015-2016, 2019-2020 Free Software Foundation, Inc. 3 4 This file was written by Peter Miller <millerp@canb.auug.org.au> 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 <https://www.gnu.org/licenses/>. */ 18 19 #ifndef _MESSAGE_H 20 #define _MESSAGE_H 21 22 #include "str-list.h" 23 #include "pos.h" 24 #include "mem-hash-map.h" 25 26 #include <stdbool.h> 27 28 29 #ifdef __cplusplus 30 extern "C" { 31 #endif 32 33 34 /* According to Sun's Uniforum proposal the default message domain is 35 named 'messages'. */ 36 #define MESSAGE_DOMAIN_DEFAULT "messages" 37 38 39 /* Separator between msgctxt and msgid in .mo files. */ 40 #define MSGCTXT_SEPARATOR '\004' /* EOT */ 41 42 43 /* Kinds of format strings. */ 44 enum format_type 45 { 46 format_c, 47 format_objc, 48 format_python, 49 format_python_brace, 50 format_java, 51 format_java_printf, 52 format_csharp, 53 format_javascript, 54 format_scheme, 55 format_lisp, 56 format_elisp, 57 format_librep, 58 format_ruby, 59 format_sh, 60 format_awk, 61 format_lua, 62 format_pascal, 63 format_smalltalk, 64 format_qt, 65 format_qt_plural, 66 format_kde, 67 format_kde_kuit, 68 format_boost, 69 format_tcl, 70 format_perl, 71 format_perl_brace, 72 format_php, 73 format_gcc_internal, 74 format_gfc_internal, 75 format_ycp 76 }; 77 #define NFORMATS 30 /* Number of format_type enum values. */ 78 extern DLL_VARIABLE const char *const format_language[NFORMATS]; 79 extern DLL_VARIABLE const char *const format_language_pretty[NFORMATS]; 80 81 /* Is current msgid a format string? */ 82 enum is_format 83 { 84 undecided, 85 yes, 86 no, 87 yes_according_to_context, 88 possible, 89 impossible 90 }; 91 92 extern bool 93 possible_format_p (enum is_format); 94 95 96 /* Range of an unsigned integer argument. */ 97 struct argument_range 98 { 99 int min; 100 int max; 101 }; 102 103 /* Tests whether a range is present. */ 104 #define has_range_p(range) ((range).min >= 0 && (range).max >= 0) 105 106 107 /* Is current msgid wrappable? */ 108 #if 0 109 enum is_wrap 110 { 111 undecided, 112 yes, 113 no 114 }; 115 #else /* HACK - C's enum concept is so stupid */ 116 #define is_wrap is_format 117 #endif 118 119 120 /* Kinds of syntax checks which apply to strings. */ 121 enum syntax_check_type 122 { 123 sc_ellipsis_unicode, 124 sc_space_ellipsis, 125 sc_quote_unicode, 126 sc_bullet_unicode 127 }; 128 #define NSYNTAXCHECKS 4 129 extern DLL_VARIABLE const char *const syntax_check_name[NSYNTAXCHECKS]; 130 131 /* Is current msgid subject to a syntax check? */ 132 #if 0 133 enum is_syntax_check 134 { 135 undecided, 136 yes, 137 no 138 }; 139 #else /* HACK - C's enum concept is so stupid */ 140 #define is_syntax_check is_format 141 #endif 142 143 144 struct altstr 145 { 146 const char *msgstr; 147 size_t msgstr_len; 148 const char *msgstr_end; 149 string_list_ty *comment; 150 string_list_ty *comment_dot; 151 char *id; 152 }; 153 154 155 typedef struct message_ty message_ty; 156 struct message_ty 157 { 158 /* The msgctxt string, if present. */ 159 const char *msgctxt; 160 161 /* The msgid string. */ 162 const char *msgid; 163 164 /* The msgid's plural, if present. */ 165 const char *msgid_plural; 166 167 /* The msgstr strings. */ 168 const char *msgstr; 169 /* The number of bytes in msgstr, including the terminating NUL. */ 170 size_t msgstr_len; 171 172 /* Position in the source PO file. */ 173 lex_pos_ty pos; 174 175 /* Plain comments (#) appearing before the message. */ 176 string_list_ty *comment; 177 178 /* Extracted comments (#.) appearing before the message. */ 179 string_list_ty *comment_dot; 180 181 /* File position comments (#:) appearing before the message, one for 182 each unique file position instance, sorted by file name and then 183 by line. */ 184 size_t filepos_count; 185 lex_pos_ty *filepos; 186 187 /* Informations from special comments (#,). 188 Some of them come from extracted comments. They are manipulated by 189 the tools, e.g. msgmerge. */ 190 191 /* Fuzzy means "needs translator review". */ 192 bool is_fuzzy; 193 194 /* Designation of format string syntax requirements for specific 195 programming languages. */ 196 enum is_format is_format[NFORMATS]; 197 198 /* Lower and upper bound for the argument whose format directive can be 199 omitted in specific cases of singular or plural. */ 200 struct argument_range range; 201 202 /* Do we want the string to be wrapped in the emitted PO file? */ 203 enum is_wrap do_wrap; 204 205 /* Do we want to apply extra syntax checks on the string? */ 206 enum is_syntax_check do_syntax_check[NSYNTAXCHECKS]; 207 208 /* The prev_msgctxt, prev_msgid and prev_msgid_plural strings appearing 209 before the message, if present. Generated by msgmerge. */ 210 const char *prev_msgctxt; 211 const char *prev_msgid; 212 const char *prev_msgid_plural; 213 214 /* If set the message is obsolete and while writing out it should be 215 commented out. */ 216 bool obsolete; 217 218 /* Used for checking that messages have been used, in the msgcmp, 219 msgmerge, msgcomm and msgcat programs. */ 220 int used; 221 222 /* Used for looking up the target message, in the msgcat program. */ 223 message_ty *tmp; 224 225 /* Used for combining alternative translations, in the msgcat program. */ 226 int alternative_count; 227 struct altstr *alternative; 228 }; 229 230 extern message_ty * 231 message_alloc (const char *msgctxt, 232 const char *msgid, const char *msgid_plural, 233 const char *msgstr, size_t msgstr_len, 234 const lex_pos_ty *pp); 235 #define is_header(mp) ((mp)->msgctxt == NULL && (mp)->msgid[0] == '\0') 236 extern void 237 message_free (message_ty *mp); 238 extern void 239 message_comment_append (message_ty *mp, const char *comment); 240 extern void 241 message_comment_dot_append (message_ty *mp, const char *comment); 242 extern void 243 message_comment_filepos (message_ty *mp, const char *name, size_t line); 244 extern message_ty * 245 message_copy (message_ty *mp); 246 247 248 typedef struct message_list_ty message_list_ty; 249 struct message_list_ty 250 { 251 message_ty **item; 252 size_t nitems; 253 size_t nitems_max; 254 bool use_hashtable; 255 hash_table htable; /* Table mapping msgid to 'message_ty *'. */ 256 }; 257 258 /* Create a fresh message list. 259 If USE_HASHTABLE is true, a hash table will be used to speed up 260 message_list_search(). USE_HASHTABLE can only be set to true if it is 261 known that the message list will not contain duplicate msgids. */ 262 extern message_list_ty * 263 message_list_alloc (bool use_hashtable); 264 /* Free a message list. 265 If keep_messages = 0, also free the messages. If keep_messages = 1, don't 266 free the messages. */ 267 extern void 268 message_list_free (message_list_ty *mlp, int keep_messages); 269 extern void 270 message_list_append (message_list_ty *mlp, message_ty *mp); 271 extern void 272 message_list_prepend (message_list_ty *mlp, message_ty *mp); 273 extern void 274 message_list_insert_at (message_list_ty *mlp, size_t n, message_ty *mp); 275 extern void 276 message_list_delete_nth (message_list_ty *mlp, size_t n); 277 typedef bool message_predicate_ty (const message_ty *mp); 278 extern void 279 message_list_remove_if_not (message_list_ty *mlp, 280 message_predicate_ty *predicate); 281 /* Recompute the hash table of a message list after the msgids or msgctxts 282 changed. */ 283 extern bool 284 message_list_msgids_changed (message_list_ty *mlp); 285 /* Copy a message list. 286 If copy_level = 0, also copy the messages. If copy_level = 1, share the 287 messages. */ 288 extern message_list_ty * 289 message_list_copy (message_list_ty *mlp, int copy_level); 290 extern message_ty * 291 message_list_search (message_list_ty *mlp, 292 const char *msgctxt, const char *msgid); 293 /* Return the message in MLP which maximizes the fuzzy_search_goal_function. 294 Only messages with a fuzzy_search_goal_function > FUZZY_THRESHOLD are 295 considered. In case of several messages with the same goal function value, 296 the one with the smaller index is returned. */ 297 extern message_ty * 298 message_list_search_fuzzy (message_list_ty *mlp, 299 const char *msgctxt, const char *msgid); 300 301 302 typedef struct message_list_list_ty message_list_list_ty; 303 struct message_list_list_ty 304 { 305 message_list_ty **item; 306 size_t nitems; 307 size_t nitems_max; 308 }; 309 310 extern message_list_list_ty * 311 message_list_list_alloc (void); 312 /* Free a list of message lists. 313 If keep_level = 0, also free the messages. If keep_level = 1, don't free 314 the messages but free the lists. If keep_level = 2, don't free the 315 the messages and the lists. */ 316 extern void 317 message_list_list_free (message_list_list_ty *mllp, int keep_level); 318 extern void 319 message_list_list_append (message_list_list_ty *mllp, 320 message_list_ty *mlp); 321 extern void 322 message_list_list_append_list (message_list_list_ty *mllp, 323 message_list_list_ty *mllp2); 324 extern message_ty * 325 message_list_list_search (message_list_list_ty *mllp, 326 const char *msgctxt, const char *msgid); 327 extern message_ty * 328 message_list_list_search_fuzzy (message_list_list_ty *mllp, 329 const char *msgctxt, const char *msgid); 330 331 332 typedef struct msgdomain_ty msgdomain_ty; 333 struct msgdomain_ty 334 { 335 const char *domain; 336 message_list_ty *messages; 337 }; 338 339 extern msgdomain_ty * 340 msgdomain_alloc (const char *domain, bool use_hashtable); 341 extern void 342 msgdomain_free (msgdomain_ty *mdp); 343 344 345 typedef struct msgdomain_list_ty msgdomain_list_ty; 346 struct msgdomain_list_ty 347 { 348 msgdomain_ty **item; 349 size_t nitems; 350 size_t nitems_max; 351 bool use_hashtable; 352 const char *encoding; /* canonicalized encoding or NULL if unknown */ 353 }; 354 355 extern msgdomain_list_ty * 356 msgdomain_list_alloc (bool use_hashtable); 357 extern void 358 msgdomain_list_free (msgdomain_list_ty *mdlp); 359 extern void 360 msgdomain_list_append (msgdomain_list_ty *mdlp, msgdomain_ty *mdp); 361 extern void 362 msgdomain_list_append_list (msgdomain_list_ty *mdlp, 363 msgdomain_list_ty *mdlp2); 364 extern message_list_ty * 365 msgdomain_list_sublist (msgdomain_list_ty *mdlp, const char *domain, 366 bool create); 367 /* Copy a message domain list. 368 If copy_level = 0, also copy the messages. If copy_level = 1, share the 369 messages but copy the domains. If copy_level = 2, share the domains. */ 370 extern msgdomain_list_ty * 371 msgdomain_list_copy (msgdomain_list_ty *mdlp, int copy_level); 372 extern message_ty * 373 msgdomain_list_search (msgdomain_list_ty *mdlp, 374 const char *msgctxt, const char *msgid); 375 extern message_ty * 376 msgdomain_list_search_fuzzy (msgdomain_list_ty *mdlp, 377 const char *msgctxt, const char *msgid); 378 379 380 /* The goal function used in fuzzy search. 381 Higher values indicate a closer match. 382 If the result is < LOWER_BOUND, an arbitrary other value < LOWER_BOUND can 383 be returned. */ 384 extern double 385 fuzzy_search_goal_function (const message_ty *mp, 386 const char *msgctxt, const char *msgid, 387 double lower_bound); 388 389 /* The threshold for fuzzy-searching. 390 A message is considered only if 391 fuzzy_search_goal_function (mp, given, 0.0) > FUZZY_THRESHOLD. */ 392 #define FUZZY_THRESHOLD 0.6 393 394 395 #ifdef __cplusplus 396 } 397 #endif 398 399 400 #endif /* message.h */ 401