1 /* GNU gettext - internationalization aids
2 Copyright (C) 1995-1998, 2000-2004 Free Software Foundation, Inc.
4 This file was written by Peter Miller <millerp@canb.auug.org.au>
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)
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.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
35 const char *const format_language
[NFORMATS
] =
38 /* format_objc */ "objc",
40 /* format_python */ "python",
41 /* format_lisp */ "lisp",
42 /* format_elisp */ "elisp",
43 /* format_librep */ "librep",
44 /* format_scheme */ "scheme",
45 /* format_smalltalk */ "smalltalk",
46 /* format_java */ "java",
47 /* format_csharp */ "csharp",
48 /* format_awk */ "awk",
49 /* format_pascal */ "object-pascal",
50 /* format_ycp */ "ycp",
51 /* format_tcl */ "tcl",
52 /* format_perl */ "perl",
53 /* format_perl_brace */ "perl-brace",
54 /* format_php */ "php",
55 /* format_gcc_internal */ "gcc-internal",
59 const char *const format_language_pretty
[NFORMATS
] =
62 /* format_objc */ "Objective C",
63 /* format_sh */ "Shell",
64 /* format_python */ "Python",
65 /* format_lisp */ "Lisp",
66 /* format_elisp */ "Emacs Lisp",
67 /* format_librep */ "librep",
68 /* format_scheme */ "Scheme",
69 /* format_smalltalk */ "Smalltalk",
70 /* format_java */ "Java",
71 /* format_csharp */ "C#",
72 /* format_awk */ "awk",
73 /* format_pascal */ "Object Pascal",
74 /* format_ycp */ "YCP",
75 /* format_tcl */ "Tcl",
76 /* format_perl */ "Perl",
77 /* format_perl_brace */ "Perl brace",
78 /* format_php */ "PHP",
79 /* format_gcc_internal */ "GCC internal",
85 possible_format_p (enum is_format is_format
)
87 return is_format
== possible
88 || is_format
== yes_according_to_context
94 message_alloc (const char *msgid
, const char *msgid_plural
,
95 const char *msgstr
, size_t msgstr_len
,
101 mp
= (message_ty
*) xmalloc (sizeof (message_ty
));
103 mp
->msgid_plural
= (msgid_plural
!= NULL
? xstrdup (msgid_plural
) : NULL
);
105 mp
->msgstr_len
= msgstr_len
;
108 mp
->comment_dot
= NULL
;
109 mp
->filepos_count
= 0;
111 mp
->is_fuzzy
= false;
112 for (i
= 0; i
< NFORMATS
; i
++)
113 mp
->is_format
[i
] = undecided
;
114 mp
->do_wrap
= undecided
;
116 mp
->obsolete
= false;
122 message_free (message_ty
*mp
)
126 free ((char *) mp
->msgid
);
127 if (mp
->msgid_plural
!= NULL
)
128 free ((char *) mp
->msgid_plural
);
129 free ((char *) mp
->msgstr
);
130 if (mp
->comment
!= NULL
)
131 string_list_free (mp
->comment
);
132 if (mp
->comment_dot
!= NULL
)
133 string_list_free (mp
->comment_dot
);
134 for (j
= 0; j
< mp
->filepos_count
; ++j
)
135 free ((char *) mp
->filepos
[j
].file_name
);
136 if (mp
->filepos
!= NULL
)
143 message_comment_append (message_ty
*mp
, const char *s
)
145 if (mp
->comment
== NULL
)
146 mp
->comment
= string_list_alloc ();
147 string_list_append (mp
->comment
, s
);
152 message_comment_dot_append (message_ty
*mp
, const char *s
)
154 if (mp
->comment_dot
== NULL
)
155 mp
->comment_dot
= string_list_alloc ();
156 string_list_append (mp
->comment_dot
, s
);
161 message_comment_filepos (message_ty
*mp
, const char *name
, size_t line
)
167 /* See if we have this position already. */
168 for (j
= 0; j
< mp
->filepos_count
; j
++)
170 pp
= &mp
->filepos
[j
];
171 if (strcmp (pp
->file_name
, name
) == 0 && pp
->line_number
== line
)
175 /* Extend the list so that we can add a position to it. */
176 nbytes
= (mp
->filepos_count
+ 1) * sizeof (mp
->filepos
[0]);
177 mp
->filepos
= xrealloc (mp
->filepos
, nbytes
);
179 /* Insert the position at the end. Don't sort the file positions here. */
180 pp
= &mp
->filepos
[mp
->filepos_count
++];
181 pp
->file_name
= xstrdup (name
);
182 pp
->line_number
= line
;
187 message_copy (message_ty
*mp
)
192 result
= message_alloc (xstrdup (mp
->msgid
), mp
->msgid_plural
,
193 mp
->msgstr
, mp
->msgstr_len
, &mp
->pos
);
197 for (j
= 0; j
< mp
->comment
->nitems
; ++j
)
198 message_comment_append (result
, mp
->comment
->item
[j
]);
202 for (j
= 0; j
< mp
->comment_dot
->nitems
; ++j
)
203 message_comment_dot_append (result
, mp
->comment_dot
->item
[j
]);
205 result
->is_fuzzy
= mp
->is_fuzzy
;
206 for (i
= 0; i
< NFORMATS
; i
++)
207 result
->is_format
[i
] = mp
->is_format
[i
];
208 result
->do_wrap
= mp
->do_wrap
;
209 for (j
= 0; j
< mp
->filepos_count
; ++j
)
211 lex_pos_ty
*pp
= &mp
->filepos
[j
];
212 message_comment_filepos (result
, pp
->file_name
, pp
->line_number
);
219 message_list_alloc (bool use_hashtable
)
221 message_list_ty
*mlp
;
223 mlp
= (message_list_ty
*) xmalloc (sizeof (message_list_ty
));
227 if ((mlp
->use_hashtable
= use_hashtable
))
228 init_hash (&mlp
->htable
, 10);
234 message_list_free (message_list_ty
*mlp
)
238 for (j
= 0; j
< mlp
->nitems
; ++j
)
239 message_free (mlp
->item
[j
]);
242 if (mlp
->use_hashtable
)
243 delete_hash (&mlp
->htable
);
249 message_list_append (message_list_ty
*mlp
, message_ty
*mp
)
251 if (mlp
->nitems
>= mlp
->nitems_max
)
255 mlp
->nitems_max
= mlp
->nitems_max
* 2 + 4;
256 nbytes
= mlp
->nitems_max
* sizeof (message_ty
*);
257 mlp
->item
= xrealloc (mlp
->item
, nbytes
);
259 mlp
->item
[mlp
->nitems
++] = mp
;
261 if (mlp
->use_hashtable
)
262 if (insert_entry (&mlp
->htable
, mp
->msgid
, strlen (mp
->msgid
) + 1, mp
))
263 /* A message list has duplicates, although it was allocated with the
264 assertion that it wouldn't have duplicates. It is a bug. */
270 message_list_prepend (message_list_ty
*mlp
, message_ty
*mp
)
274 if (mlp
->nitems
>= mlp
->nitems_max
)
278 mlp
->nitems_max
= mlp
->nitems_max
* 2 + 4;
279 nbytes
= mlp
->nitems_max
* sizeof (message_ty
*);
280 mlp
->item
= xrealloc (mlp
->item
, nbytes
);
282 for (j
= mlp
->nitems
; j
> 0; j
--)
283 mlp
->item
[j
] = mlp
->item
[j
- 1];
287 if (mlp
->use_hashtable
)
288 if (insert_entry (&mlp
->htable
, mp
->msgid
, strlen (mp
->msgid
) + 1, mp
))
289 /* A message list has duplicates, although it was allocated with the
290 assertion that it wouldn't have duplicates. It is a bug. */
296 message_list_insert_at (message_list_ty
*mlp
, size_t n
, message_ty
*mp
)
300 if (mlp
->nitems
>= mlp
->nitems_max
)
304 mlp
->nitems_max
= mlp
->nitems_max
* 2 + 4;
305 nbytes
= mlp
->nitems_max
* sizeof (message_ty
*);
306 mlp
->item
= xrealloc (mlp
->item
, nbytes
);
308 for (j
= mlp
->nitems
; j
> n
; j
--)
309 mlp
->item
[j
] = mlp
->item
[j
- 1];
313 if (mlp
->use_hashtable
)
314 if (insert_entry (&mlp
->htable
, mp
->msgid
, strlen (mp
->msgid
) + 1, mp
))
315 /* A message list has duplicates, although it was allocated with the
316 assertion that it wouldn't have duplicates. It is a bug. */
323 message_list_delete_nth (message_list_ty
*mlp
, size_t n
)
327 if (n
>= mlp
->nitems
)
329 message_free (mlp
->item
[n
]);
330 for (j
= n
+ 1; j
< mlp
->nitems
; ++j
)
331 mlp
->item
[j
- 1] = mlp
->item
[j
];
334 if (mlp
->use_hashtable
)
336 /* Our simple-minded hash tables don't support removal. */
337 delete_hash (&mlp
->htable
);
338 mlp
->use_hashtable
= false;
345 message_list_remove_if_not (message_list_ty
*mlp
,
346 message_predicate_ty
*predicate
)
350 for (j
= 0, i
= 0; j
< mlp
->nitems
; j
++)
351 if (predicate (mlp
->item
[j
]))
352 mlp
->item
[i
++] = mlp
->item
[j
];
353 if (mlp
->use_hashtable
&& i
< mlp
->nitems
)
355 /* Our simple-minded hash tables don't support removal. */
356 delete_hash (&mlp
->htable
);
357 mlp
->use_hashtable
= false;
364 message_list_msgids_changed (message_list_ty
*mlp
)
366 if (mlp
->use_hashtable
)
368 unsigned long int size
= mlp
->htable
.size
;
371 delete_hash (&mlp
->htable
);
372 init_hash (&mlp
->htable
, size
);
374 for (j
= 0; j
< mlp
->nitems
; j
++)
376 message_ty
*mp
= mlp
->item
[j
];
378 if (insert_entry (&mlp
->htable
, mp
->msgid
, strlen (mp
->msgid
) + 1,
380 /* A message list has duplicates, although it was allocated with
381 the assertion that it wouldn't have duplicates, and before the
382 msgids changed it indeed didn't have duplicates. */
384 delete_hash (&mlp
->htable
);
385 mlp
->use_hashtable
= false;
395 message_list_search (message_list_ty
*mlp
, const char *msgid
)
397 if (mlp
->use_hashtable
)
401 if (find_entry (&mlp
->htable
, msgid
, strlen (msgid
) + 1, &htable_value
))
404 return (message_ty
*) htable_value
;
410 for (j
= 0; j
< mlp
->nitems
; ++j
)
415 if (strcmp (msgid
, mp
->msgid
) == 0)
424 message_list_search_fuzzy_inner (message_list_ty
*mlp
, const char *msgid
,
425 double *best_weight_p
)
431 for (j
= 0; j
< mlp
->nitems
; ++j
)
437 if (mp
->msgstr
!= NULL
&& mp
->msgstr
[0] != '\0')
439 double weight
= fstrcmp (msgid
, mp
->msgid
);
440 if (weight
> *best_weight_p
)
442 *best_weight_p
= weight
;
452 message_list_search_fuzzy (message_list_ty
*mlp
, const char *msgid
)
457 return message_list_search_fuzzy_inner (mlp
, msgid
, &best_weight
);
461 message_list_list_ty
*
462 message_list_list_alloc ()
464 message_list_list_ty
*mllp
;
466 mllp
= (message_list_list_ty
*) xmalloc (sizeof (message_list_list_ty
));
468 mllp
->nitems_max
= 0;
476 message_list_list_free (message_list_list_ty
*mllp
)
480 for (j
= 0; j
< mllp
->nitems
; ++j
)
481 message_list_free (mllp
->item
[j
]);
490 message_list_list_append (message_list_list_ty
*mllp
, message_list_ty
*mlp
)
492 if (mllp
->nitems
>= mllp
->nitems_max
)
496 mllp
->nitems_max
= mllp
->nitems_max
* 2 + 4;
497 nbytes
= mllp
->nitems_max
* sizeof (message_list_ty
*);
498 mllp
->item
= xrealloc (mllp
->item
, nbytes
);
500 mllp
->item
[mllp
->nitems
++] = mlp
;
505 message_list_list_append_list (message_list_list_ty
*mllp
,
506 message_list_list_ty
*mllp2
)
510 for (j
= 0; j
< mllp2
->nitems
; ++j
)
511 message_list_list_append (mllp
, mllp2
->item
[j
]);
516 message_list_list_search (message_list_list_ty
*mllp
, const char *msgid
)
519 int best_weight
; /* 0: not found, 1: found without msgstr, 2: translated */
524 for (j
= 0; j
< mllp
->nitems
; ++j
)
526 message_list_ty
*mlp
;
530 mp
= message_list_search (mlp
, msgid
);
533 int weight
= (mp
->msgstr_len
== 1 && mp
->msgstr
[0] == '\0' ? 1 : 2);
534 if (weight
> best_weight
)
537 best_weight
= weight
;
546 message_list_list_search_fuzzy (message_list_list_ty
*mllp
, const char *msgid
)
554 for (j
= 0; j
< mllp
->nitems
; ++j
)
556 message_list_ty
*mlp
;
560 mp
= message_list_search_fuzzy_inner (mlp
, msgid
, &best_weight
);
569 msgdomain_alloc (const char *domain
, bool use_hashtable
)
573 mdp
= (msgdomain_ty
*) xmalloc (sizeof (msgdomain_ty
));
574 mdp
->domain
= domain
;
575 mdp
->messages
= message_list_alloc (use_hashtable
);
581 msgdomain_free (msgdomain_ty
*mdp
)
583 message_list_free (mdp
->messages
);
589 msgdomain_list_alloc (bool use_hashtable
)
591 msgdomain_list_ty
*mdlp
;
593 mdlp
= (msgdomain_list_ty
*) xmalloc (sizeof (msgdomain_list_ty
));
594 /* Put the default domain first, so that when we output it,
595 we can omit the 'domain' directive. */
597 mdlp
->nitems_max
= 1;
599 (msgdomain_ty
**) xmalloc (mdlp
->nitems_max
* sizeof (msgdomain_ty
*));
600 mdlp
->item
[0] = msgdomain_alloc (MESSAGE_DOMAIN_DEFAULT
, use_hashtable
);
601 mdlp
->use_hashtable
= use_hashtable
;
602 mdlp
->encoding
= NULL
;
608 msgdomain_list_free (msgdomain_list_ty
*mdlp
)
612 for (j
= 0; j
< mdlp
->nitems
; ++j
)
613 msgdomain_free (mdlp
->item
[j
]);
621 msgdomain_list_append (msgdomain_list_ty
*mdlp
, msgdomain_ty
*mdp
)
623 if (mdlp
->nitems
>= mdlp
->nitems_max
)
627 mdlp
->nitems_max
= mdlp
->nitems_max
* 2 + 4;
628 nbytes
= mdlp
->nitems_max
* sizeof (msgdomain_ty
*);
629 mdlp
->item
= xrealloc (mdlp
->item
, nbytes
);
631 mdlp
->item
[mdlp
->nitems
++] = mdp
;
637 msgdomain_list_append_list (msgdomain_list_ty
*mdlp
, msgdomain_list_ty
*mdlp2
)
641 for (j
= 0; j
< mdlp2
->nitems
; ++j
)
642 msgdomain_list_append (mdlp
, mdlp2
->item
[j
]);
648 msgdomain_list_sublist (msgdomain_list_ty
*mdlp
, const char *domain
,
653 for (j
= 0; j
< mdlp
->nitems
; j
++)
654 if (strcmp (mdlp
->item
[j
]->domain
, domain
) == 0)
655 return mdlp
->item
[j
]->messages
;
659 msgdomain_ty
*mdp
= msgdomain_alloc (domain
, mdlp
->use_hashtable
);
660 msgdomain_list_append (mdlp
, mdp
);
661 return mdp
->messages
;
670 msgdomain_list_search (msgdomain_list_ty
*mdlp
, const char *msgid
)
674 for (j
= 0; j
< mdlp
->nitems
; ++j
)
680 mp
= message_list_search (mdp
->messages
, msgid
);
691 msgdomain_list_search_fuzzy (msgdomain_list_ty
*mdlp
, const char *msgid
)
699 for (j
= 0; j
< mdlp
->nitems
; ++j
)
705 mp
= message_list_search_fuzzy_inner (mdp
->messages
, msgid
, &best_weight
);