From: Bruno Haible Date: Fri, 21 Dec 2001 16:42:10 +0000 (+0000) Subject: Move some code from message.c to msgmerge.c, so that other msg* programs X-Git-Tag: v0.11~148 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=28ad6ac5b520cd1af22a2ca9d1a8be6aa01639c4;p=thirdparty%2Fgettext.git Move some code from message.c to msgmerge.c, so that other msg* programs become smaller when statically linked. --- diff --git a/src/ChangeLog b/src/ChangeLog index 63d850f86..2d7362f34 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,11 @@ +2001-12-21 Bruno Haible + + * 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 * format-java.c: Include system.h. diff --git a/src/message.c b/src/message.c index 83e27fea6..d80df089d 100644 --- a/src/message.c +++ b/src/message.c @@ -29,19 +29,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #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)); @@ -216,297 +208,6 @@ message_copy (mp) } -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; diff --git a/src/message.h b/src/message.h index a1f6100a4..3e1fdc68d 100644 --- a/src/message.h +++ b/src/message.h @@ -151,8 +151,6 @@ extern void 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; diff --git a/src/msgmerge.c b/src/msgmerge.c index a7272ff3a..c14ae39db 100644 --- a/src/msgmerge.c +++ b/src/msgmerge.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include "dir-list.h" @@ -34,7 +35,9 @@ #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" @@ -108,6 +111,12 @@ struct statistics 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, @@ -485,6 +494,298 @@ compendium (filename) } +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