become smaller when statically linked.
+2001-12-21 Bruno Haible <bruno@clisp.org>
+
+ * message.h (message_merge): Remove declaration.
+ * message.c (msgfmt_check_pair_fails, message_merge): Move to
+ msgmerge.c.
+ * msgmerge.c (msgfmt_check_pair_fails, message_merge): Moved to here
+ from message.c.
+
2001-12-20 Bruno Haible <bruno@clisp.org>
* format-java.c: Include system.h.
#include "fstrcmp.h"
#include "hash.h"
-#include "format.h"
#include "xmalloc.h"
-#include "strstr.h"
-#include "system.h"
/* Prototypes for local functions. Needed to ensure compiler checking of
function argument counts despite of K&R C function definition syntax. */
-static bool msgfmt_check_pair_fails PARAMS ((const lex_pos_ty *pos,
- const char *msgid,
- const char *msgid_plural,
- const char *msgstr,
- size_t msgstr_len, size_t fmt));
static message_ty *message_list_search_fuzzy_inner PARAMS ((
message_list_ty *mlp, const char *msgid, double *best_weight_p));
}
-static bool
-msgfmt_check_pair_fails (pos, msgid, msgid_plural, msgstr, msgstr_len, fmt)
- const lex_pos_ty *pos;
- const char *msgid;
- const char *msgid_plural;
- const char *msgstr;
- size_t msgstr_len;
- size_t fmt;
-{
- bool failure;
- struct formatstring_parser *parser = formatstring_parsers[fmt];
- void *msgid_descr =
- parser->parse (msgid_plural != NULL ? msgid_plural : msgid);
-
- failure = false;
- if (msgid_descr != NULL)
- {
- const char *p_end = msgstr + msgstr_len;
- const char *p;
-
- for (p = msgstr; p < p_end; p += strlen (p) + 1)
- {
- void *msgstr_descr = parser->parse (msgstr);
-
- if (msgstr_descr != NULL)
- {
- failure = parser->check (pos, msgid_descr, msgstr_descr,
- msgid_plural == NULL, false, NULL);
- parser->free (msgstr_descr);
- }
- else
- failure = true;
-
- if (failure)
- break;
- }
-
- parser->free (msgid_descr);
- }
-
- return failure;
-}
-
-message_ty *
-message_merge (def, ref)
- message_ty *def;
- message_ty *ref;
-{
- const char *msgstr;
- size_t msgstr_len;
- message_ty *result;
- size_t j, i;
-
- /* Take the msgid from the reference. When fuzzy matches are made,
- the definition will not be unique, but the reference will be -
- usually because it has only been slightly changed. */
-
- /* Take the msgstr from the definition. The msgstr of the reference
- is usually empty, as it was generated by xgettext. If we currently
- process the header entry we have to merge the msgstr by using the
- POT-Creation-Date field from the reference. */
- if (ref->msgid[0] == '\0')
- {
- /* Oh, oh. The header entry and we have something to fill in. */
- static const struct
- {
- const char *name;
- size_t len;
- } known_fields[] =
- {
- { "Project-Id-Version:", sizeof ("Project-Id-Version:") - 1 },
-#define PROJECT_ID 0
- { "POT-Creation-Date:", sizeof ("POT-Creation-Date:") - 1 },
-#define POT_CREATION 1
- { "PO-Revision-Date:", sizeof ("PO-Revision-Date:") - 1 },
-#define PO_REVISION 2
- { "Last-Translator:", sizeof ("Last-Translator:") - 1 },
-#define LAST_TRANSLATOR 3
- { "Language-Team:", sizeof ("Language-Team:") - 1 },
-#define LANGUAGE_TEAM 4
- { "MIME-Version:", sizeof ("MIME-Version:") - 1 },
-#define MIME_VERSION 5
- { "Content-Type:", sizeof ("Content-Type:") - 1 },
-#define CONTENT_TYPE 6
- { "Content-Transfer-Encoding:",
- sizeof ("Content-Transfer-Encoding:") - 1 }
-#define CONTENT_TRANSFER 7
- };
-#define UNKNOWN 8
- struct
- {
- const char *string;
- size_t len;
- } header_fields[UNKNOWN + 1];
- const char *cp;
- char *newp;
- size_t len, cnt;
-
- /* Clear all fields. */
- memset (header_fields, '\0', sizeof (header_fields));
-
- cp = def->msgstr;
- while (*cp != '\0')
- {
- const char *endp = strchr (cp, '\n');
- int terminated = endp != NULL;
-
- if (!terminated)
- {
- /* Add a trailing newline. */
- char *copy;
- endp = strchr (cp, '\0');
-
- len = endp - cp + 1;
-
- copy = (char *) alloca (len + 1);
- stpcpy (stpcpy (copy, cp), "\n");
- cp = copy;
- }
- else
- {
- len = (endp - cp) + 1;
- ++endp;
- }
-
- /* Compare with any of the known fields. */
- for (cnt = 0;
- cnt < sizeof (known_fields) / sizeof (known_fields[0]);
- ++cnt)
- if (strncasecmp (cp, known_fields[cnt].name, known_fields[cnt].len)
- == 0)
- break;
-
- if (cnt < sizeof (known_fields) / sizeof (known_fields[0]))
- {
- header_fields[cnt].string = &cp[known_fields[cnt].len];
- header_fields[cnt].len = len - known_fields[cnt].len;
- }
- else
- {
- /* It's an unknown field. Append content to what is already
- known. */
- char *extended =
- (char *) alloca (header_fields[UNKNOWN].len + len + 1);
- memcpy (extended, header_fields[UNKNOWN].string,
- header_fields[UNKNOWN].len);
- memcpy (&extended[header_fields[UNKNOWN].len], cp, len);
- extended[header_fields[UNKNOWN].len + len] = '\0';
- header_fields[UNKNOWN].string = extended;
- header_fields[UNKNOWN].len += len;
- }
-
- cp = endp;
- }
-
- {
- const char *pot_date_ptr;
-
- pot_date_ptr = strstr (ref->msgstr, "POT-Creation-Date:");
- if (pot_date_ptr != NULL)
- {
- size_t pot_date_len;
- const char *endp;
-
- pot_date_ptr += sizeof ("POT-Creation-Date:") - 1;
-
- endp = strchr (pot_date_ptr, '\n');
- if (endp == NULL)
- {
- /* Add a trailing newline. */
- char *extended;
- endp = strchr (pot_date_ptr, '\0');
- pot_date_len = (endp - pot_date_ptr) + 1;
- extended = (char *) alloca (pot_date_len + 1);
- stpcpy (stpcpy (extended, pot_date_ptr), "\n");
- pot_date_ptr = extended;
- }
- else
- pot_date_len = (endp - pot_date_ptr) + 1;
-
- header_fields[POT_CREATION].string = pot_date_ptr;
- header_fields[POT_CREATION].len = pot_date_len;
- }
- }
-
- /* Concatenate all the various fields. */
- len = 0;
- for (cnt = 0; cnt < UNKNOWN; ++cnt)
- if (header_fields[cnt].string != NULL)
- len += known_fields[cnt].len + header_fields[cnt].len;
- len += header_fields[UNKNOWN].len;
-
- cp = newp = (char *) xmalloc (len + 1);
- newp[len] = '\0';
-
-#define IF_FILLED(idx) \
- if (header_fields[idx].string) \
- newp = stpncpy (stpcpy (newp, known_fields[idx].name), \
- header_fields[idx].string, header_fields[idx].len)
-
- IF_FILLED (PROJECT_ID);
- IF_FILLED (POT_CREATION);
- IF_FILLED (PO_REVISION);
- IF_FILLED (LAST_TRANSLATOR);
- IF_FILLED (LANGUAGE_TEAM);
- IF_FILLED (MIME_VERSION);
- IF_FILLED (CONTENT_TYPE);
- IF_FILLED (CONTENT_TRANSFER);
- if (header_fields[UNKNOWN].string != NULL)
- stpcpy (newp, header_fields[UNKNOWN].string);
-
-#undef IF_FILLED
-
- msgstr = cp;
- msgstr_len = strlen (cp) + 1;
- }
- else
- {
- msgstr = def->msgstr;
- msgstr_len = def->msgstr_len;
- }
-
- result = message_alloc (xstrdup (ref->msgid), ref->msgid_plural,
- msgstr, msgstr_len, &def->pos);
-
- /* Take the comments from the definition file. There will be none at
- all in the reference file, as it was generated by xgettext. */
- if (def->comment)
- for (j = 0; j < def->comment->nitems; ++j)
- message_comment_append (result, def->comment->item[j]);
-
- /* Take the dot comments from the reference file, as they are
- generated by xgettext. Any in the definition file are old ones
- collected by previous runs of xgettext and msgmerge. */
- if (ref->comment_dot)
- for (j = 0; j < ref->comment_dot->nitems; ++j)
- message_comment_dot_append (result, ref->comment_dot->item[j]);
-
- /* The flags are mixed in a special way. Some informations come
- from the reference message (such as format/no-format), others
- come from the definition file (fuzzy or not). */
- result->is_fuzzy = def->is_fuzzy;
-
- for (i = 0; i < NFORMATS; i++)
- {
- result->is_format[i] = ref->is_format[i];
-
- /* If the reference message is marked as being a format specifier,
- but the definition message is not, we check if the resulting
- message would pass "msgfmt -c". If yes, then all is fine. If
- not, we add a fuzzy marker, because
- 1. the message needs the translator's attention,
- 2. msgmerge must not transform a PO file which passes "msgfmt -c"
- into a PO file which doesn't. */
- if (!result->is_fuzzy
- && possible_format_p (ref->is_format[i])
- && !possible_format_p (def->is_format[i])
- && msgfmt_check_pair_fails (&def->pos, ref->msgid, ref->msgid_plural,
- msgstr, msgstr_len, i))
- result->is_fuzzy = true;
- }
-
- result->do_wrap = ref->do_wrap;
-
- /* Take the file position comments from the reference file, as they
- are generated by xgettext. Any in the definition file are old ones
- collected by previous runs of xgettext and msgmerge. */
- for (j = 0; j < ref->filepos_count; ++j)
- {
- lex_pos_ty *pp = &ref->filepos[j];
- message_comment_filepos (result, pp->file_name, pp->line_number);
- }
-
- /* Special postprocessing is needed if the reference message is a
- plural form and the definition message isn't, or vice versa. */
- if (ref->msgid_plural != NULL)
- {
- if (def->msgid_plural == NULL)
- result->used = 1;
- }
- else
- {
- if (def->msgid_plural != NULL)
- result->used = 2;
- }
-
- /* All done, return the merged message to the caller. */
- return result;
-}
-
-
message_list_ty *
message_list_alloc (use_hashtable)
bool use_hashtable;
const char *name, size_t line));
extern message_ty *
message_copy PARAMS ((message_ty *mp));
-extern message_ty *
- message_merge PARAMS ((message_ty *def, message_ty *ref));
typedef struct message_list_ty message_list_ty;
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <locale.h>
#include "dir-list.h"
#include "message.h"
#include "read-po.h"
#include "write-po.h"
+#include "format.h"
#include "xmalloc.h"
+#include "strstr.h"
#include "system.h"
#include "po.h"
#include "msgl-equal.h"
function argument counts despite of K&R C function definition syntax. */
static void usage PARAMS ((int status));
static void compendium PARAMS ((const char *filename));
+static bool msgfmt_check_pair_fails PARAMS ((const lex_pos_ty *pos,
+ const char *msgid,
+ const char *msgid_plural,
+ const char *msgstr,
+ size_t msgstr_len, size_t fmt));
+static message_ty *message_merge PARAMS ((message_ty *def, message_ty *ref));
static void match_domain PARAMS ((const char *fn1, const char *fn2,
message_list_list_ty *definitions,
message_list_ty *refmlp,
}
+static bool
+msgfmt_check_pair_fails (pos, msgid, msgid_plural, msgstr, msgstr_len, fmt)
+ const lex_pos_ty *pos;
+ const char *msgid;
+ const char *msgid_plural;
+ const char *msgstr;
+ size_t msgstr_len;
+ size_t fmt;
+{
+ bool failure;
+ struct formatstring_parser *parser = formatstring_parsers[fmt];
+ void *msgid_descr =
+ parser->parse (msgid_plural != NULL ? msgid_plural : msgid);
+
+ failure = false;
+ if (msgid_descr != NULL)
+ {
+ const char *p_end = msgstr + msgstr_len;
+ const char *p;
+
+ for (p = msgstr; p < p_end; p += strlen (p) + 1)
+ {
+ void *msgstr_descr = parser->parse (msgstr);
+
+ if (msgstr_descr != NULL)
+ {
+ failure = parser->check (pos, msgid_descr, msgstr_descr,
+ msgid_plural == NULL, false, NULL);
+ parser->free (msgstr_descr);
+ }
+ else
+ failure = true;
+
+ if (failure)
+ break;
+ }
+
+ parser->free (msgid_descr);
+ }
+
+ return failure;
+}
+
+
+static message_ty *
+message_merge (def, ref)
+ message_ty *def;
+ message_ty *ref;
+{
+ const char *msgstr;
+ size_t msgstr_len;
+ message_ty *result;
+ size_t j, i;
+
+ /* Take the msgid from the reference. When fuzzy matches are made,
+ the definition will not be unique, but the reference will be -
+ usually because it has only been slightly changed. */
+
+ /* Take the msgstr from the definition. The msgstr of the reference
+ is usually empty, as it was generated by xgettext. If we currently
+ process the header entry we have to merge the msgstr by using the
+ POT-Creation-Date field from the reference. */
+ if (ref->msgid[0] == '\0')
+ {
+ /* Oh, oh. The header entry and we have something to fill in. */
+ static const struct
+ {
+ const char *name;
+ size_t len;
+ } known_fields[] =
+ {
+ { "Project-Id-Version:", sizeof ("Project-Id-Version:") - 1 },
+#define PROJECT_ID 0
+ { "POT-Creation-Date:", sizeof ("POT-Creation-Date:") - 1 },
+#define POT_CREATION 1
+ { "PO-Revision-Date:", sizeof ("PO-Revision-Date:") - 1 },
+#define PO_REVISION 2
+ { "Last-Translator:", sizeof ("Last-Translator:") - 1 },
+#define LAST_TRANSLATOR 3
+ { "Language-Team:", sizeof ("Language-Team:") - 1 },
+#define LANGUAGE_TEAM 4
+ { "MIME-Version:", sizeof ("MIME-Version:") - 1 },
+#define MIME_VERSION 5
+ { "Content-Type:", sizeof ("Content-Type:") - 1 },
+#define CONTENT_TYPE 6
+ { "Content-Transfer-Encoding:",
+ sizeof ("Content-Transfer-Encoding:") - 1 }
+#define CONTENT_TRANSFER 7
+ };
+#define UNKNOWN 8
+ struct
+ {
+ const char *string;
+ size_t len;
+ } header_fields[UNKNOWN + 1];
+ const char *cp;
+ char *newp;
+ size_t len, cnt;
+
+ /* Clear all fields. */
+ memset (header_fields, '\0', sizeof (header_fields));
+
+ cp = def->msgstr;
+ while (*cp != '\0')
+ {
+ const char *endp = strchr (cp, '\n');
+ int terminated = endp != NULL;
+
+ if (!terminated)
+ {
+ /* Add a trailing newline. */
+ char *copy;
+ endp = strchr (cp, '\0');
+
+ len = endp - cp + 1;
+
+ copy = (char *) alloca (len + 1);
+ stpcpy (stpcpy (copy, cp), "\n");
+ cp = copy;
+ }
+ else
+ {
+ len = (endp - cp) + 1;
+ ++endp;
+ }
+
+ /* Compare with any of the known fields. */
+ for (cnt = 0;
+ cnt < sizeof (known_fields) / sizeof (known_fields[0]);
+ ++cnt)
+ if (strncasecmp (cp, known_fields[cnt].name, known_fields[cnt].len)
+ == 0)
+ break;
+
+ if (cnt < sizeof (known_fields) / sizeof (known_fields[0]))
+ {
+ header_fields[cnt].string = &cp[known_fields[cnt].len];
+ header_fields[cnt].len = len - known_fields[cnt].len;
+ }
+ else
+ {
+ /* It's an unknown field. Append content to what is already
+ known. */
+ char *extended =
+ (char *) alloca (header_fields[UNKNOWN].len + len + 1);
+ memcpy (extended, header_fields[UNKNOWN].string,
+ header_fields[UNKNOWN].len);
+ memcpy (&extended[header_fields[UNKNOWN].len], cp, len);
+ extended[header_fields[UNKNOWN].len + len] = '\0';
+ header_fields[UNKNOWN].string = extended;
+ header_fields[UNKNOWN].len += len;
+ }
+
+ cp = endp;
+ }
+
+ {
+ const char *pot_date_ptr;
+
+ pot_date_ptr = strstr (ref->msgstr, "POT-Creation-Date:");
+ if (pot_date_ptr != NULL)
+ {
+ size_t pot_date_len;
+ const char *endp;
+
+ pot_date_ptr += sizeof ("POT-Creation-Date:") - 1;
+
+ endp = strchr (pot_date_ptr, '\n');
+ if (endp == NULL)
+ {
+ /* Add a trailing newline. */
+ char *extended;
+ endp = strchr (pot_date_ptr, '\0');
+ pot_date_len = (endp - pot_date_ptr) + 1;
+ extended = (char *) alloca (pot_date_len + 1);
+ stpcpy (stpcpy (extended, pot_date_ptr), "\n");
+ pot_date_ptr = extended;
+ }
+ else
+ pot_date_len = (endp - pot_date_ptr) + 1;
+
+ header_fields[POT_CREATION].string = pot_date_ptr;
+ header_fields[POT_CREATION].len = pot_date_len;
+ }
+ }
+
+ /* Concatenate all the various fields. */
+ len = 0;
+ for (cnt = 0; cnt < UNKNOWN; ++cnt)
+ if (header_fields[cnt].string != NULL)
+ len += known_fields[cnt].len + header_fields[cnt].len;
+ len += header_fields[UNKNOWN].len;
+
+ cp = newp = (char *) xmalloc (len + 1);
+ newp[len] = '\0';
+
+#define IF_FILLED(idx) \
+ if (header_fields[idx].string) \
+ newp = stpncpy (stpcpy (newp, known_fields[idx].name), \
+ header_fields[idx].string, header_fields[idx].len)
+
+ IF_FILLED (PROJECT_ID);
+ IF_FILLED (POT_CREATION);
+ IF_FILLED (PO_REVISION);
+ IF_FILLED (LAST_TRANSLATOR);
+ IF_FILLED (LANGUAGE_TEAM);
+ IF_FILLED (MIME_VERSION);
+ IF_FILLED (CONTENT_TYPE);
+ IF_FILLED (CONTENT_TRANSFER);
+ if (header_fields[UNKNOWN].string != NULL)
+ stpcpy (newp, header_fields[UNKNOWN].string);
+
+#undef IF_FILLED
+
+ msgstr = cp;
+ msgstr_len = strlen (cp) + 1;
+ }
+ else
+ {
+ msgstr = def->msgstr;
+ msgstr_len = def->msgstr_len;
+ }
+
+ result = message_alloc (xstrdup (ref->msgid), ref->msgid_plural,
+ msgstr, msgstr_len, &def->pos);
+
+ /* Take the comments from the definition file. There will be none at
+ all in the reference file, as it was generated by xgettext. */
+ if (def->comment)
+ for (j = 0; j < def->comment->nitems; ++j)
+ message_comment_append (result, def->comment->item[j]);
+
+ /* Take the dot comments from the reference file, as they are
+ generated by xgettext. Any in the definition file are old ones
+ collected by previous runs of xgettext and msgmerge. */
+ if (ref->comment_dot)
+ for (j = 0; j < ref->comment_dot->nitems; ++j)
+ message_comment_dot_append (result, ref->comment_dot->item[j]);
+
+ /* The flags are mixed in a special way. Some informations come
+ from the reference message (such as format/no-format), others
+ come from the definition file (fuzzy or not). */
+ result->is_fuzzy = def->is_fuzzy;
+
+ for (i = 0; i < NFORMATS; i++)
+ {
+ result->is_format[i] = ref->is_format[i];
+
+ /* If the reference message is marked as being a format specifier,
+ but the definition message is not, we check if the resulting
+ message would pass "msgfmt -c". If yes, then all is fine. If
+ not, we add a fuzzy marker, because
+ 1. the message needs the translator's attention,
+ 2. msgmerge must not transform a PO file which passes "msgfmt -c"
+ into a PO file which doesn't. */
+ if (!result->is_fuzzy
+ && possible_format_p (ref->is_format[i])
+ && !possible_format_p (def->is_format[i])
+ && msgfmt_check_pair_fails (&def->pos, ref->msgid, ref->msgid_plural,
+ msgstr, msgstr_len, i))
+ result->is_fuzzy = true;
+ }
+
+ result->do_wrap = ref->do_wrap;
+
+ /* Take the file position comments from the reference file, as they
+ are generated by xgettext. Any in the definition file are old ones
+ collected by previous runs of xgettext and msgmerge. */
+ for (j = 0; j < ref->filepos_count; ++j)
+ {
+ lex_pos_ty *pp = &ref->filepos[j];
+ message_comment_filepos (result, pp->file_name, pp->line_number);
+ }
+
+ /* Special postprocessing is needed if the reference message is a
+ plural form and the definition message isn't, or vice versa. */
+ if (ref->msgid_plural != NULL)
+ {
+ if (def->msgid_plural == NULL)
+ result->used = 1;
+ }
+ else
+ {
+ if (def->msgid_plural != NULL)
+ result->used = 2;
+ }
+
+ /* All done, return the merged message to the caller. */
+ return result;
+}
+
+
#define DOT_FREQUENCY 10
static void