diff options
Diffstat (limited to 'gettext-tools')
26 files changed, 851 insertions, 429 deletions
diff --git a/gettext-tools/src/ChangeLog b/gettext-tools/src/ChangeLog index 49346ba..c7db86f 100644 --- a/gettext-tools/src/ChangeLog +++ b/gettext-tools/src/ChangeLog @@ -1,3 +1,65 @@ +2005-09-17 Bruno Haible <bruno@clisp.org> + + New, higher-level error message output primitives. + * po-xerror.h: New file. + * po-xerror.c: New file. + * open-po.c: Include xerror.h, po-xerror.h, not error.h. + (open_po_file): Use po_xerror instead of error. + * po-charset.c: Include po-xerror.h, not po-error.h. + (po_lex_charset_set): Use po_xerror instead of po_multiline_warning. + * po-lex.c: Include xerror.h, po-error.h, po-xerror.h. + (po_gram_error, po_gram_error_at_line): Use po_xerror instead of + po_error or po_error_at_line. Don't decrement error_message_count; + let the caller do this instead. + (mbfile_getc, lex_getc): Use po_xerror instead of po_error. + * po-lex.h: Don't include po-error.h. + (po_gram_error, po_gram_error_at_line): Remove optimized macros. + * read-po-abstract.c: Include xerror.h, po-xerror.h. + (po_scan): Use po_xerror instead of po_error. + * read-po.c: Include po-xerror.h. + (default_add_message): Use po_xerror2 instead of po_gram_error_at_line + pair. + * read-properties.c: Include xerror.h, po-xerror.h, not exit.h. + (phase1_getc, phase4_getuc): Use po_xerror instead of error. + * read-stringtable.c: Include xerror.h, po-xerror.h, not exit.h. + (phase1_getc, read_string, stringtable_parse): Use po_xerror instead of + error. + * write-po.c: Include po-xerror.h, not exit.h, po-error.h. + (wrap): Pass the entire message as argument. Use po_xerror instead of + po_error. + (message_print, message_print_obsolete): Update. Use po_xerror instead + of po_multiline_warning. + (msgdomain_list_print): Use po_xerror instead of po_error or + po_error_at_line. + * msgl-iconv.h (struct conversion_context): Add 'message' field. + * msgl-iconv.c: Include xerror.h, po-xerror.h, not error.h, exit.h. + (conversion_error): Use po_xerror instead of error. + (iconv_message_list): Likewise. Set the entire message in the + conversion context before calling convert_*. + (iconv_msgdomain_list): Use po_xerror instead of error. + * xgettext.c (from_current_source_encoding): Set context.message. + * msgfmt.c: Include po-xerror.h. + (check_plural_eval): Pass the entire header as argument. Use po_xerror + instead of error_at_line. + (plural_help): New function, extracted from check_plural. + (check_plural): Change type of local variables has_plural, min_pos, + max_pos. Use po_xerror2 instead of error_at_line pairs. Use po_xerror + instead of error_at_line. + (curr_mp): New variable. + (formatstring_error_logger): Use po_xerror instead of vfprintf. + (check_pair): Take the entire message as argument. Use po_xerror + instead of error_at_line. Set curr_mp before calling + check_msgid_msgstr_format. + (check_header_entry): Take the entire header message as argument. Use + po_xerror instead of multiline_error. + (msgfmt_frob_new_message): Update. + * msgcmp.c (match_domain): Decrement error_message_count between two + error messages that belong together. + * msgmerge.c (match_domain): Decrement error_message_count between two + error messages that belong together. + * Makefile.am (noinst_HEADERS): Add po-xerror.h. + (COMMON_SOURCE): Add po-xerror.c. + 2005-09-16 Bruno Haible <bruno@clisp.org> * gettext-po.c (po_file_read): Set gram_max_allowed_errors to a large diff --git a/gettext-tools/src/FILES b/gettext-tools/src/FILES index ceee7cb..0ab3c8f 100644 --- a/gettext-tools/src/FILES +++ b/gettext-tools/src/FILES @@ -34,6 +34,8 @@ msgl-ascii.c po-error.h po-error.c +po-xerror.h +po-xerror.c Error handling during writing and reading of PO files. write-po.h diff --git a/gettext-tools/src/Makefile.am b/gettext-tools/src/Makefile.am index b41f07c..46a882c 100644 --- a/gettext-tools/src/Makefile.am +++ b/gettext-tools/src/Makefile.am @@ -34,7 +34,7 @@ lib_LTLIBRARIES = libgettextsrc.la libgettextpo.la include_HEADERS = gettext-po.h -noinst_HEADERS = pos.h message.h po-error.h po-gram.h po-charset.h \ +noinst_HEADERS = pos.h message.h po-error.h po-xerror.h po-gram.h po-charset.h \ po-lex.h open-po.h \ read-po-abstract.h read-po.h read-properties.h read-stringtable.h \ str-list.h \ @@ -98,7 +98,7 @@ CSHARPCOMPFLAGS = -O -g # (read-po-abstract.c <--> po-gram-gen.y <--> po-lex.c) -> open-po.c -> dir-list.c -> str-list.c. # (read-po-abstract.c <--> po-gram-gen.y <--> po-lex.c) -> po-charset.c. # (read-po-abstract.c <--> po-gram-gen.y <--> po-lex.c) -> message.c -> str-list.c. -COMMON_SOURCE = message.c po-error.c \ +COMMON_SOURCE = message.c po-error.c po-xerror.c \ read-po-abstract.c po-lex.c po-gram-gen.y po-charset.c \ read-properties.c read-stringtable.c open-po.c dir-list.c str-list.c diff --git a/gettext-tools/src/msgcmp.c b/gettext-tools/src/msgcmp.c index 2c5bb0e..6f0962c 100644 --- a/gettext-tools/src/msgcmp.c +++ b/gettext-tools/src/msgcmp.c @@ -284,6 +284,7 @@ match_domain (const char *fn1, const char *fn2, { po_gram_error_at_line (&refmsg->pos, _("\ this message is used but not defined...")); + error_message_count--; po_gram_error_at_line (&defmsg->pos, _("\ ...but this definition is similar")); defmsg->used = 1; diff --git a/gettext-tools/src/msgfmt.c b/gettext-tools/src/msgfmt.c index 7d6c81e..4c5bf8e 100644 --- a/gettext-tools/src/msgfmt.c +++ b/gettext-tools/src/msgfmt.c @@ -39,6 +39,7 @@ #include "relocatable.h" #include "basename.h" #include "xerror.h" +#include "po-xerror.h" #include "format.h" #include "xalloc.h" #include "plural-exp.h" @@ -873,7 +874,7 @@ uninstall_sigfpe_handler () static void check_plural_eval (struct expression *plural_expr, unsigned long nplurals_value, - const lex_pos_ty *header_pos) + const message_ty *header) { if (sigsetjmp (sigfpe_exit, 1) == 0) { @@ -891,25 +892,22 @@ check_plural_eval (struct expression *plural_expr, /* End of protection against arithmetic exceptions. */ uninstall_sigfpe_handler (); - error_with_progname = false; - error_at_line (0, 0, - header_pos->file_name, header_pos->line_number, - _("plural expression can produce negative values")); - error_with_progname = true; + po_xerror (PO_SEVERITY_ERROR, header, NULL, 0, 0, false, + _("plural expression can produce negative values")); exit_status = EXIT_FAILURE; return; } else if (val >= nplurals_value) { + char *msg; + /* End of protection against arithmetic exceptions. */ uninstall_sigfpe_handler (); - error_with_progname = false; - error_at_line (0, 0, - header_pos->file_name, header_pos->line_number, - _("nplurals = %lu but plural expression can produce values as large as %lu"), - nplurals_value, val); - error_with_progname = true; + msg = xasprintf (_("nplurals = %lu but plural expression can produce values as large as %lu"), + nplurals_value, val); + po_xerror (PO_SEVERITY_ERROR, header, NULL, 0, 0, false, msg); + free (msg); exit_status = EXIT_FAILURE; return; } @@ -933,39 +931,65 @@ check_plural_eval (struct expression *plural_expr, #if USE_SIGINFO # ifdef FPE_INTDIV case FPE_INTDIV: - /* xgettext: c-format */ msg = _("plural expression can produce division by zero"); break; # endif # ifdef FPE_INTOVF case FPE_INTOVF: - /* xgettext: c-format */ msg = _("plural expression can produce integer overflow"); break; # endif default: #endif - /* xgettext: c-format */ msg = _("plural expression can produce arithmetic exceptions, possibly division by zero"); } - error_with_progname = false; - error_at_line (0, 0, header_pos->file_name, header_pos->line_number, msg); - error_with_progname = true; + po_xerror (PO_SEVERITY_ERROR, header, NULL, 0, 0, false, msg); exit_status = EXIT_FAILURE; } } +/* Try to help the translator by looking up the right plural formula for her. + Return a freshly allocated multiline help string, or NULL. */ +static char * +plural_help (const char *nullentry) +{ + const char *language; + size_t j; + + language = strstr (nullentry, "Language-Team: "); + if (language != NULL) + { + language += 15; + for (j = 0; j < plural_table_size; j++) + if (strncmp (language, + plural_table[j].language, + strlen (plural_table[j].language)) == 0) + { + char *helpline1 = + xasprintf (_("Try using the following, valid for %s:"), + plural_table[j].language); + char *help = + xasprintf ("%s\n\"Plural-Forms: %s\\n\"\n", + helpline1, plural_table[j].value); + free (helpline1); + return help; + } + } + return NULL; +} + + /* Perform plural expression checking. */ static void check_plural (message_list_ty *mlp) { - const lex_pos_ty *has_plural; + const message_ty *has_plural; unsigned long min_nplurals; - const lex_pos_ty *min_pos; + const message_ty *min_pos; unsigned long max_nplurals; - const lex_pos_ty *max_pos; + const message_ty *max_pos; size_t j; message_ty *header; @@ -986,7 +1010,7 @@ check_plural (message_list_ty *mlp) unsigned long n; if (has_plural == NULL) - has_plural = &mp->pos; + has_plural = mp; n = 0; for (p = mp->msgstr, p_end = p + mp->msgstr_len; @@ -996,12 +1020,12 @@ check_plural (message_list_ty *mlp) if (min_nplurals > n) { min_nplurals = n; - min_pos = &mp->pos; + min_pos = mp; } if (max_nplurals > n) { max_nplurals = n; - min_pos = &mp->pos; + min_pos = mp; } } } @@ -1014,7 +1038,6 @@ check_plural (message_list_ty *mlp) const char *nullentry; const char *plural; const char *nplurals; - bool try_to_help = false; nullentry = header->msgstr; @@ -1022,26 +1045,50 @@ check_plural (message_list_ty *mlp) nplurals = strstr (nullentry, "nplurals="); if (plural == NULL && has_plural != NULL) { - error_with_progname = false; - error_at_line (0, 0, has_plural->file_name, has_plural->line_number, - _("message catalog has plural form translations...")); - --error_message_count; - error_at_line (0, 0, header->pos.file_name, header->pos.line_number, - _("...but header entry lacks a \"plural=EXPRESSION\" attribute")); - error_with_progname = true; - try_to_help = true; + const char *msg1 = + _("message catalog has plural form translations"); + const char *msg2 = + _("but header entry lacks a \"plural=EXPRESSION\" attribute"); + char *help = plural_help (nullentry); + + if (help != NULL) + { + char *msg2ext = xasprintf ("%s\n%s", msg2, help); + po_xerror2 (PO_SEVERITY_ERROR, + has_plural, NULL, 0, 0, false, msg1, + header, NULL, 0, 0, true, msg2ext); + free (msg2ext); + free (help); + } + else + po_xerror2 (PO_SEVERITY_ERROR, + has_plural, NULL, 0, 0, false, msg1, + header, NULL, 0, 0, false, msg2); + exit_status = EXIT_FAILURE; } if (nplurals == NULL && has_plural != NULL) { - error_with_progname = false; - error_at_line (0, 0, has_plural->file_name, has_plural->line_number, - _("message catalog has plural form translations...")); - --error_message_count; - error_at_line (0, 0, header->pos.file_name, header->pos.line_number, - _("...but header entry lacks a \"nplurals=INTEGER\" attribute")); - error_with_progname = true; - try_to_help = true; + const char *msg1 = + _("message catalog has plural form translations"); + const char *msg2 = + _("but header entry lacks a \"nplurals=INTEGER\" attribute"); + char *help = plural_help (nullentry); + + if (help != NULL) + { + char *msg2ext = xasprintf ("%s\n%s", msg2, help); + po_xerror2 (PO_SEVERITY_ERROR, + has_plural, NULL, 0, 0, false, msg1, + header, NULL, 0, 0, true, msg2ext); + free (msg2ext); + free (help); + } + else + po_xerror2 (PO_SEVERITY_ERROR, + has_plural, NULL, 0, 0, false, msg1, + header, NULL, 0, 0, false, msg2); + exit_status = EXIT_FAILURE; } if (plural != NULL && nplurals != NULL) @@ -1061,12 +1108,20 @@ check_plural (message_list_ty *mlp) nplurals_value = strtoul (nplurals, (char **) &endp, 10); if (nplurals == endp) { - error_with_progname = false; - error_at_line (0, 0, - header->pos.file_name, header->pos.line_number, - _("invalid nplurals value")); - error_with_progname = true; - try_to_help = true; + const char *msg = _("invalid nplurals value"); + char *help = plural_help (nullentry); + + if (help != NULL) + { + char *msgext = xasprintf ("%s\n%s", msg, help); + po_xerror (PO_SEVERITY_ERROR, header, NULL, 0, 0, true, + msgext); + free (msgext); + free (help); + } + else + po_xerror (PO_SEVERITY_ERROR, header, NULL, 0, 0, false, msg); + exit_status = EXIT_FAILURE; } @@ -1075,51 +1130,61 @@ check_plural (message_list_ty *mlp) args.cp = plural; if (parse_plural_expression (&args) != 0) { - error_with_progname = false; - error_at_line (0, 0, - header->pos.file_name, header->pos.line_number, - _("invalid plural expression")); - error_with_progname = true; - try_to_help = true; + const char *msg = _("invalid plural expression"); + char *help = plural_help (nullentry); + + if (help != NULL) + { + char *msgext = xasprintf ("%s\n%s", msg, help); + po_xerror (PO_SEVERITY_ERROR, header, NULL, 0, 0, true, + msgext); + free (msgext); + free (help); + } + else + po_xerror (PO_SEVERITY_ERROR, header, NULL, 0, 0, false, msg); + exit_status = EXIT_FAILURE; } plural_expr = args.res; /* See whether nplurals and plural fit together. */ if (exit_status != EXIT_FAILURE) - check_plural_eval (plural_expr, nplurals_value, &header->pos); + check_plural_eval (plural_expr, nplurals_value, header); /* Check the number of plurals of the translations. */ if (exit_status != EXIT_FAILURE) { if (min_nplurals < nplurals_value) { - error_with_progname = false; - error_at_line (0, 0, - header->pos.file_name, header->pos.line_number, - _("nplurals = %lu..."), nplurals_value); - --error_message_count; - error_at_line (0, 0, min_pos->file_name, min_pos->line_number, - ngettext ("...but some messages have only one plural form", - "...but some messages have only %lu plural forms", - min_nplurals), - min_nplurals); - error_with_progname = true; + char *msg1 = + xasprintf (_("nplurals = %lu"), nplurals_value); + char *msg2 = + xasprintf (ngettext ("but some messages have only one plural form", + "but some messages have only %lu plural forms", + min_nplurals), + min_nplurals); + po_xerror2 (PO_SEVERITY_ERROR, + header, NULL, 0, 0, false, msg1, + min_pos, NULL, 0, 0, false, msg2); + free (msg2); + free (msg1); exit_status = EXIT_FAILURE; } else if (max_nplurals > nplurals_value) { - error_with_progname = false; - error_at_line (0, 0, - header->pos.file_name, header->pos.line_number, - _("nplurals = %lu..."), nplurals_value); - --error_message_count; - error_at_line (0, 0, max_pos->file_name, max_pos->line_number, - ngettext ("...but some messages have one plural form", - "...but some messages have %lu plural forms", - max_nplurals), - max_nplurals); - error_with_progname = true; + char *msg1 = + xasprintf (_("nplurals = %lu"), nplurals_value); + char *msg2 = + xasprintf (ngettext ("but some messages have one plural form", + "but some messages have %lu plural forms", + max_nplurals), + max_nplurals); + po_xerror2 (PO_SEVERITY_ERROR, + header, NULL, 0, 0, false, msg1, + max_pos, NULL, 0, 0, false, msg2); + free (msg2); + free (msg1); exit_status = EXIT_FAILURE; } /* The only valid case is max_nplurals <= n <= min_nplurals, @@ -1127,70 +1192,45 @@ check_plural (message_list_ty *mlp) max_nplurals = n = min_nplurals. */ } } - /* Try to help the translator by looking up the right plural formula - for her. */ - if (try_to_help) - { - const char *language; - - language = strstr (nullentry, "Language-Team: "); - if (language != NULL) - { - language += 15; - for (j = 0; j < plural_table_size; j++) - if (strncmp (language, - plural_table[j].language, - strlen (plural_table[j].language)) == 0) - { - char *recommended = - xasprintf ("Plural-Forms: %s\\n", plural_table[j].value); - fprintf (stderr, - _("Try using the following, valid for %s:\n"), - plural_table[j].language); - fprintf (stderr, "\"%s\"\n", recommended); - free (recommended); - break; - } - } - } } else if (has_plural != NULL) { - error_with_progname = false; - error_at_line (0, 0, has_plural->file_name, has_plural->line_number, - _("message catalog has plural form translations, but lacks a header entry with \"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\"")); - error_with_progname = true; + po_xerror (PO_SEVERITY_ERROR, has_plural, NULL, 0, 0, false, + _("message catalog has plural form translations, but lacks a header entry with \"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\"")); exit_status = EXIT_FAILURE; } } /* Signal an error when checking format strings. */ +static const message_ty *curr_mp; static lex_pos_ty curr_msgid_pos; static void formatstring_error_logger (const char *format, ...) { va_list args; + char *msg; va_start (args, format); - fprintf (stderr, "%s:%lu: ", - curr_msgid_pos.file_name, - (unsigned long) curr_msgid_pos.line_number); - vfprintf (stderr, format, args); - putc ('\n', stderr); - fflush (stderr); + if (vasprintf (&msg, format, args) < 0) + error (EXIT_FAILURE, 0, _("memory exhausted")); va_end (args); - ++error_message_count; + po_xerror (PO_SEVERITY_ERROR, + curr_mp, curr_msgid_pos.file_name, curr_msgid_pos.line_number, + (size_t)(-1), false, msg); + free (msg); } /* Perform miscellaneous checks on a message. */ static void -check_pair (const char *msgid, +check_pair (const message_ty *mp, + const char *msgid, const lex_pos_ty *msgid_pos, const char *msgid_plural, const char *msgstr, size_t msgstr_len, - const lex_pos_ty *msgstr_pos, enum is_format is_format[NFORMATS]) + const lex_pos_ty *msgstr_pos, + enum is_format is_format[NFORMATS]) { int has_newline; unsigned int j; @@ -1208,21 +1248,22 @@ check_pair (const char *msgid, { if (TEST_NEWLINE(msgid_plural) != has_newline) { - error_with_progname = false; - error_at_line (0, 0, msgid_pos->file_name, msgid_pos->line_number, - _("\ + po_xerror (PO_SEVERITY_ERROR, + mp, msgid_pos->file_name, msgid_pos->line_number, + (size_t)(-1), false, _("\ `msgid' and `msgid_plural' entries do not both begin with '\\n'")); - error_with_progname = true; exit_status = EXIT_FAILURE; } for (p = msgstr, j = 0; p < msgstr + msgstr_len; p += strlen (p) + 1, j++) if (TEST_NEWLINE(p) != has_newline) { - error_with_progname = false; - error_at_line (0, 0, msgid_pos->file_name, msgid_pos->line_number, - _("\ + char *msg = + xasprintf (_("\ `msgid' and `msgstr[%u]' entries do not both begin with '\\n'"), j); - error_with_progname = true; + po_xerror (PO_SEVERITY_ERROR, + mp, msgid_pos->file_name, msgid_pos->line_number, + (size_t)(-1), false, msg); + free (msg); exit_status = EXIT_FAILURE; } } @@ -1230,11 +1271,10 @@ check_pair (const char *msgid, { if (TEST_NEWLINE(msgstr) != has_newline) { - error_with_progname = false; - error_at_line (0, 0, msgid_pos->file_name, msgid_pos->line_number, - _("\ + po_xerror (PO_SEVERITY_ERROR, + mp, msgid_pos->file_name, msgid_pos->line_number, + (size_t)(-1), false, _("\ `msgid' and `msgstr' entries do not both begin with '\\n'")); - error_with_progname = true; exit_status = EXIT_FAILURE; } } @@ -1247,21 +1287,22 @@ check_pair (const char *msgid, { if (TEST_NEWLINE(msgid_plural) != has_newline) { - error_with_progname = false; - error_at_line (0, 0, msgid_pos->file_name, msgid_pos->line_number, - _("\ + po_xerror (PO_SEVERITY_ERROR, + mp, msgid_pos->file_name, msgid_pos->line_number, + (size_t)(-1), false, _("\ `msgid' and `msgid_plural' entries do not both end with '\\n'")); - error_with_progname = true; exit_status = EXIT_FAILURE; } for (p = msgstr, j = 0; p < msgstr + msgstr_len; p += strlen (p) + 1, j++) if (TEST_NEWLINE(p) != has_newline) { - error_with_progname = false; - error_at_line (0, 0, msgid_pos->file_name, msgid_pos->line_number, - _("\ + char *msg = + xasprintf (_("\ `msgid' and `msgstr[%u]' entries do not both end with '\\n'"), j); - error_with_progname = true; + po_xerror (PO_SEVERITY_ERROR, + mp, msgid_pos->file_name, msgid_pos->line_number, + (size_t)(-1), false, msg); + free (msg); exit_status = EXIT_FAILURE; } } @@ -1269,11 +1310,10 @@ check_pair (const char *msgid, { if (TEST_NEWLINE(msgstr) != has_newline) { - error_with_progname = false; - error_at_line (0, 0, msgid_pos->file_name, msgid_pos->line_number, - _("\ + po_xerror (PO_SEVERITY_ERROR, + mp, msgid_pos->file_name, msgid_pos->line_number, + (size_t)(-1), false, _("\ `msgid' and `msgstr' entries do not both end with '\\n'")); - error_with_progname = true; exit_status = EXIT_FAILURE; } } @@ -1281,10 +1321,10 @@ check_pair (const char *msgid, if (check_compatibility && msgid_plural != NULL) { - error_with_progname = false; - error_at_line (0, 0, msgid_pos->file_name, msgid_pos->line_number, - _("plural handling is a GNU gettext extension")); - error_with_progname = true; + po_xerror (PO_SEVERITY_ERROR, + mp, msgid_pos->file_name, msgid_pos->line_number, + (size_t)(-1), false, _("\ +plural handling is a GNU gettext extension")); exit_status = EXIT_FAILURE; } @@ -1292,6 +1332,7 @@ check_pair (const char *msgid, /* Test 3: Check whether both formats strings contain the same number of format specifications. */ { + curr_mp = mp; curr_msgid_pos = *msgid_pos; if (check_msgid_msgstr_format (msgid, msgid_plural, msgstr, msgstr_len, is_format, formatstring_error_logger)) @@ -1322,19 +1363,23 @@ check_pair (const char *msgid, if (count == 0) { - error_with_progname = false; - error_at_line (0, 0, msgid_pos->file_name, msgid_pos->line_number, - _("msgstr lacks the keyboard accelerator mark '%c'"), - accelerator_char); - error_with_progname = true; + char *msg = + xasprintf (_("msgstr lacks the keyboard accelerator mark '%c'"), + accelerator_char); + po_xerror (PO_SEVERITY_ERROR, + mp, msgid_pos->file_name, msgid_pos->line_number, + (size_t)(-1), false, msg); + free (msg); } else if (count > 1) { - error_with_progname = false; - error_at_line (0, 0, msgid_pos->file_name, msgid_pos->line_number, - _("msgstr has too many keyboard accelerator marks '%c'"), - accelerator_char); - error_with_progname = true; + char *msg = + xasprintf (_("msgstr has too many keyboard accelerator marks '%c'"), + accelerator_char); + po_xerror (PO_SEVERITY_ERROR, + mp, msgid_pos->file_name, msgid_pos->line_number, + (size_t)(-1), false, msg); + free (msg); } } } @@ -1343,7 +1388,7 @@ check_pair (const char *msgid, /* Perform miscellaneous checks on a header entry. */ static void -check_header_entry (const char *msgstr_string) +check_header_entry (const message_ty *mp, const char *msgstr_string) { static const char *required_fields[] = { @@ -1365,14 +1410,24 @@ check_header_entry (const char *msgstr_string) char *endp = strstr (msgstr_string, required_fields[cnt]); if (endp == NULL) - multiline_error (xasprintf ("%s: ", gram_pos.file_name), - xasprintf (_("headerfield `%s' missing in header\n"), - required_fields[cnt])); + { + char *msg = + xasprintf (_("headerfield `%s' missing in header\n"), + required_fields[cnt]); + po_xerror (PO_SEVERITY_ERROR, mp, gram_pos.file_name, (size_t)(-1), + (size_t)(-1), true, msg); + free (msg); + } else if (endp != msgstr_string && endp[-1] != '\n') - multiline_error (xasprintf ("%s: ", gram_pos.file_name), - xasprintf (_("\ + { + char *msg = + xasprintf (_("\ header field `%s' should start at beginning of line\n"), - required_fields[cnt])); + required_fields[cnt]); + po_xerror (PO_SEVERITY_ERROR, mp, gram_pos.file_name, (size_t)(-1), + (size_t)(-1), true, msg); + free (msg); + } else if (default_values[cnt] != NULL && strncmp (default_values[cnt], endp + strlen (required_fields[cnt]) + 2, @@ -1380,9 +1435,10 @@ header field `%s' should start at beginning of line\n"), { if (initial != -1) { - multiline_error (xasprintf ("%s: ", gram_pos.file_name), - xstrdup (_("\ -some header fields still have the initial default value\n"))); + po_xerror (PO_SEVERITY_ERROR, + mp, gram_pos.file_name, (size_t)(-1), (size_t)(-1), + true, _("\ +some header fields still have the initial default value\n")); initial = -1; break; } @@ -1392,10 +1448,14 @@ some header fields still have the initial default value\n"))); } if (initial != -1) - multiline_error (xasprintf ("%s: ", gram_pos.file_name), - xasprintf (_("\ -field `%s' still has initial default value\n"), - required_fields[initial])); + { + char *msg = + xasprintf (_("field `%s' still has initial default value\n"), + required_fields[initial]); + po_xerror (PO_SEVERITY_ERROR, mp, gram_pos.file_name, (size_t)(-1), + (size_t)(-1), true, msg); + free (msg); + } } @@ -1587,7 +1647,7 @@ msgfmt_frob_new_message (default_po_reader_ty *that, message_ty *mp, /* Do some more tests on the contents of the header entry. */ if (check_header) - check_header_entry (mp->msgstr); + check_header_entry (mp, mp->msgstr); } else /* We don't count the header entry in the statistic so place @@ -1598,7 +1658,8 @@ msgfmt_frob_new_message (default_po_reader_ty *that, message_ty *mp, ++msgs_translated; /* Do some more checks on both strings. */ - check_pair (mp->msgid, msgid_pos, mp->msgid_plural, + check_pair (mp, + mp->msgid, msgid_pos, mp->msgid_plural, mp->msgstr, mp->msgstr_len, msgstr_pos, mp->is_format); } diff --git a/gettext-tools/src/msgl-iconv.c b/gettext-tools/src/msgl-iconv.c index f7aadc3..ad44f0c 100644 --- a/gettext-tools/src/msgl-iconv.c +++ b/gettext-tools/src/msgl-iconv.c @@ -34,7 +34,6 @@ # include <iconv.h> #endif -#include "error.h" #include "progname.h" #include "basename.h" #include "message.h" @@ -43,7 +42,8 @@ #include "xalloc.h" #include "xallocsa.h" #include "strstr.h" -#include "exit.h" +#include "xerror.h" +#include "po-xerror.h" #include "gettext.h" #define _(str) gettext (str) @@ -181,12 +181,15 @@ conversion_error (const struct conversion_context* context) { if (context->to_code == po_charset_utf8) /* If a conversion to UTF-8 fails, the problem lies in the input. */ - error (EXIT_FAILURE, 0, _("%s: input is not valid in \"%s\" encoding"), - context->from_filename, context->from_code); + po_xerror (PO_SEVERITY_FATAL_ERROR, context->message, NULL, 0, 0, false, + xasprintf (_("%s: input is not valid in \"%s\" encoding"), + context->from_filename, context->from_code)); else - error (EXIT_FAILURE, 0, - _("%s: error while converting from \"%s\" encoding to \"%s\" encoding"), - context->from_filename, context->from_code, context->to_code); + po_xerror (PO_SEVERITY_FATAL_ERROR, context->message, NULL, 0, 0, false, + xasprintf (_("\ +%s: error while converting from \"%s\" encoding to \"%s\" encoding"), + context->from_filename, context->from_code, + context->to_code)); /* NOTREACHED */ abort (); } @@ -325,10 +328,10 @@ iconv_message_list (message_list_ty *mlp, && strcmp (charset, "CHARSET") == 0) canon_charset = po_charset_ascii; else - error (EXIT_FAILURE, 0, - _("\ + po_xerror (PO_SEVERITY_FATAL_ERROR, NULL, NULL, 0, 0, + false, xasprintf (_("\ present charset \"%s\" is not a portable encoding name"), - charset); + charset)); } } else @@ -336,10 +339,11 @@ present charset \"%s\" is not a portable encoding name"), if (canon_from_code == NULL) canon_from_code = canon_charset; else if (canon_from_code != canon_charset) - error (EXIT_FAILURE, 0, - _("\ + po_xerror (PO_SEVERITY_FATAL_ERROR, NULL, NULL, 0, 0, + false, + xasprintf (_("\ two different charsets \"%s\" and \"%s\" in input file"), - canon_from_code, canon_charset); + canon_from_code, canon_charset)); } freesa (charset); @@ -360,7 +364,8 @@ two different charsets \"%s\" and \"%s\" in input file"), if (is_ascii_message_list (mlp)) canon_from_code = po_charset_ascii; else - error (EXIT_FAILURE, 0, _("\ + po_xerror (PO_SEVERITY_FATAL_ERROR, NULL, NULL, 0, 0, false, + _("\ input file doesn't contain a header entry with a charset specification")); } @@ -380,10 +385,12 @@ input file doesn't contain a header entry with a charset specification")); # endif cd = iconv_open (canon_to_code, canon_from_code); if (cd == (iconv_t)(-1)) - error (EXIT_FAILURE, 0, _("\ + po_xerror (PO_SEVERITY_FATAL_ERROR, NULL, NULL, 0, 0, false, + xasprintf (_("\ Cannot convert from \"%s\" to \"%s\". %s relies on iconv(), \ and iconv() does not support this conversion."), - canon_from_code, canon_to_code, basename (program_name)); + canon_from_code, canon_to_code, + basename (program_name))); context.from_code = canon_from_code; context.to_code = canon_to_code; @@ -396,6 +403,7 @@ and iconv() does not support this conversion."), if (!is_ascii_string (mp->msgid)) msgids_changed = true; + context.message = mp; convert_string_list (cd, mp->comment, &context); convert_string_list (cd, mp->comment_dot, &context); convert_msgid (cd, mp, &context); @@ -406,15 +414,18 @@ and iconv() does not support this conversion."), if (msgids_changed) if (message_list_msgids_changed (mlp)) - error (EXIT_FAILURE, 0, _("\ + po_xerror (PO_SEVERITY_FATAL_ERROR, NULL, NULL, 0, 0, false, + xasprintf (_("\ Conversion from \"%s\" to \"%s\" introduces duplicates: \ some different msgids become equal."), - canon_from_code, canon_to_code); + canon_from_code, canon_to_code)); #else - error (EXIT_FAILURE, 0, _("\ + po_xerror (PO_SEVERITY_FATAL_ERROR, NULL, NULL, 0, 0, false, + xasprintf (_("\ Cannot convert from \"%s\" to \"%s\". %s relies on iconv(). \ This version was built without iconv()."), - canon_from_code, canon_to_code, basename (program_name)); + canon_from_code, canon_to_code, + basename (program_name)); #endif } } @@ -430,9 +441,10 @@ iconv_msgdomain_list (msgdomain_list_ty *mdlp, /* Canonicalize target encoding. */ canon_to_code = po_charset_canonicalize (to_code); if (canon_to_code == NULL) - error (EXIT_FAILURE, 0, - _("target charset \"%s\" is not a portable encoding name."), - to_code); + po_xerror (PO_SEVERITY_FATAL_ERROR, NULL, NULL, 0, 0, false, + xasprintf (_("\ +target charset \"%s\" is not a portable encoding name."), + to_code)); for (k = 0; k < mdlp->nitems; k++) iconv_message_list (mdlp->item[k]->messages, mdlp->encoding, canon_to_code, diff --git a/gettext-tools/src/msgl-iconv.h b/gettext-tools/src/msgl-iconv.h index 14f549b..6d4a361 100644 --- a/gettext-tools/src/msgl-iconv.h +++ b/gettext-tools/src/msgl-iconv.h @@ -39,6 +39,7 @@ struct conversion_context const char *from_code; /* canonicalized encoding name for input */ const char *to_code; /* canonicalized encoding name for output */ const char *from_filename; /* file name where the input comes from */ + const message_ty *message; /* message being converted, or NULL */ }; /* Converts the STRING through the conversion descriptor CD. */ diff --git a/gettext-tools/src/msgmerge.c b/gettext-tools/src/msgmerge.c index 89d1d3e..0e45221 100644 --- a/gettext-tools/src/msgmerge.c +++ b/gettext-tools/src/msgmerge.c @@ -964,6 +964,7 @@ match_domain (const char *fn1, const char *fn2, { po_gram_error_at_line (&refmsg->pos, _("\ this message is used but not defined...")); + error_message_count--; po_gram_error_at_line (&defmsg->pos, _("\ ...but this definition is similar")); } diff --git a/gettext-tools/src/open-po.c b/gettext-tools/src/open-po.c index 29c2199..079954b 100644 --- a/gettext-tools/src/open-po.c +++ b/gettext-tools/src/open-po.c @@ -1,5 +1,5 @@ /* open-po - search for .po file along search path list and open for reading - Copyright (C) 1995-1996, 2000-2003 Free Software Foundation, Inc. + Copyright (C) 1995-1996, 2000-2003, 2005 Free Software Foundation, Inc. Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, April 1995. This program is free software; you can redistribute it and/or modify @@ -32,7 +32,8 @@ #include "dir-list.h" #include "pathname.h" #include "xalloc.h" -#include "error.h" +#include "xerror.h" +#include "po-xerror.h" #include "gettext.h" #define _(str) gettext (str) @@ -114,8 +115,14 @@ open_po_file (const char *input_name, char **real_file_name_p, FILE *fp = try_open_po_file (input_name, real_file_name_p); if (fp == NULL && exit_on_error) - error (EXIT_FAILURE, errno, - _("error while opening \"%s\" for reading"), *real_file_name_p); + { + const char *errno_description = strerror (errno); + po_xerror (PO_SEVERITY_FATAL_ERROR, NULL, NULL, 0, 0, false, + xasprintf ("%s: %s", + xasprintf (_("error while opening \"%s\" for reading"), + *real_file_name_p), + errno_description)); + } return fp; } diff --git a/gettext-tools/src/po-charset.c b/gettext-tools/src/po-charset.c index 81759c3..cff5826 100644 --- a/gettext-tools/src/po-charset.c +++ b/gettext-tools/src/po-charset.c @@ -30,7 +30,7 @@ #include "xallocsa.h" #include "xerror.h" -#include "po-error.h" +#include "po-xerror.h" #include "basename.h" #include "progname.h" #include "strstr.h" @@ -223,11 +223,17 @@ po_lex_charset_set (const char *header_entry, const char *filename) if (!(filenamelen >= 4 && memcmp (filename + filenamelen - 4, ".pot", 4) == 0 && strcmp (charset, "CHARSET") == 0)) - po_multiline_warning (xasprintf (_("%s: warning: "), filename), - xasprintf (_("\ + { + char *warning_message = + xasprintf (_("\ Charset \"%s\" is not a portable encoding name.\n\ Message conversion to user's charset might not work.\n"), - charset)); + charset); + po_xerror (PO_SEVERITY_WARNING, NULL, + filename, (size_t)(-1), (size_t)(-1), true, + warning_message); + free (warning_message); + } } else { @@ -280,7 +286,25 @@ Message conversion to user's charset might not work.\n"), po_lex_iconv = iconv_open ("UTF-8", po_lex_charset); if (po_lex_iconv == (iconv_t)(-1)) { + char *warning_message; + const char *recommendation; const char *note; + char *whole_message; + + warning_message = + xasprintf (_("\ +Charset \"%s\" is not supported. %s relies on iconv(),\n\ +and iconv() does not support \"%s\".\n"), + po_lex_charset, basename (program_name), + po_lex_charset); + +# if !defined _LIBICONV_VERSION + recommendation = _("\ +Installing GNU libiconv and then reinstalling GNU gettext\n\ +would fix this problem.\n"); +# else + recommendation = ""; +# endif /* Test for a charset which has double-byte characters ending in 0x5C. For these encodings, the string parser @@ -293,22 +317,16 @@ Message conversion to user's charset might not work.\n"), else note = _("Continuing anyway."); - po_multiline_warning (xasprintf (_("%s: warning: "), filename), - xasprintf (_("\ -Charset \"%s\" is not supported. %s relies on iconv(),\n\ -and iconv() does not support \"%s\".\n"), - po_lex_charset, - basename (program_name), - po_lex_charset)); + whole_message = + xasprintf ("%s%s%s\n", + warning_message, recommendation, note); -# if !defined _LIBICONV_VERSION - po_multiline_warning (NULL, - xasprintf (_("\ -Installing GNU libiconv and then reinstalling GNU gettext\n\ -would fix this problem.\n"))); -# endif + po_xerror (PO_SEVERITY_WARNING, NULL, + filename, (size_t)(-1), (size_t)(-1), true, + whole_message); - po_multiline_warning (NULL, xasprintf (_("%s\n"), note)); + free (whole_message); + free (warning_message); } #else /* Test for a charset which has double-byte characters @@ -318,22 +336,33 @@ would fix this problem.\n"))); po_lex_weird_cjk = po_is_charset_weird_cjk (po_lex_charset); if (po_is_charset_weird (po_lex_charset) && !po_lex_weird_cjk) { - const char *note = - _("Continuing anyway, expect parse errors."); + char *warning_message; + const char *recommendation; + const char *note; + char *whole_message; - po_multiline_warning (xasprintf (_("%s: warning: "), filename), - xasprintf (_("\ + warning_message = + xasprintf (_("\ Charset \"%s\" is not supported. %s relies on iconv().\n\ This version was built without iconv().\n"), - po_lex_charset, - basename (program_name))); + po_lex_charset, basename (program_name)); - po_multiline_warning (NULL, - xasprintf (_("\ + recommendation = _("\ Installing GNU libiconv and then reinstalling GNU gettext\n\ -would fix this problem.\n"))); +would fix this problem.\n"); + + note = _("Continuing anyway, expect parse errors."); + + whole_message = + xasprintf ("%s%s%s\n", + warning_message, recommendation, note); + + po_xerror (PO_SEVERITY_WARNING, NULL, + filename, (size_t)(-1), (size_t)(-1), true, + whole_message); - po_multiline_warning (NULL, xasprintf (_("%s\n"), note)); + free (whole_message); + free (warning_message); } #endif } @@ -348,10 +377,11 @@ would fix this problem.\n"))); if (!(filenamelen >= 4 && memcmp (filename + filenamelen - 4, ".pot", 4) == 0)) - po_multiline_warning (xasprintf (_("%s: warning: "), filename), - xasprintf (_("\ + po_xerror (PO_SEVERITY_WARNING, + NULL, filename, (size_t)(-1), (size_t)(-1), true, + _("\ Charset missing in header.\n\ -Message conversion to user's charset will not work.\n"))); +Message conversion to user's charset will not work.\n")); } } diff --git a/gettext-tools/src/po-lex.c b/gettext-tools/src/po-lex.c index 6a4fee8..9fc38b5 100644 --- a/gettext-tools/src/po-lex.c +++ b/gettext-tools/src/po-lex.c @@ -46,6 +46,9 @@ #include "exit.h" #include "error.h" #include "error-progname.h" +#include "xerror.h" +#include "po-error.h" +#include "po-xerror.h" #include "pos.h" #include "str-list.h" #include "po-gram-gen2.h" @@ -70,13 +73,6 @@ int gram_pos_column; /* Error handling during the parsing of a PO file. These functions can access gram_pos and gram_pos_column. */ -#if !(__STDC__ && \ - ((defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L && !defined __DECC) \ - || (defined __GNUC__ && __GNUC__ >= 2 && !(__APPLE_CC__ > 1)))) - -/* CAUTION: If you change this function, you must also make identical - changes to the macro of the same name in src/po-lex.h */ - /* VARARGS1 */ void po_gram_error (const char *fmt, ...) @@ -88,24 +84,14 @@ po_gram_error (const char *fmt, ...) if (vasprintf (&buffer, fmt, ap) < 0) error (EXIT_FAILURE, 0, _("memory exhausted")); va_end (ap); - error_with_progname = false; - po_error (0, 0, "%s:%lu:%d: %s", gram_pos.file_name, - (unsigned long) gram_pos.line_number, gram_pos_column + 1, buffer); - error_with_progname = true; + po_xerror (PO_SEVERITY_ERROR, NULL, gram_pos.file_name, gram_pos.line_number, + gram_pos_column + 1, false, buffer); free (buffer); - /* Some messages need more than one line. Continuation lines are - indicated by using "..." at the start of the string. We don't - increment the error counter for these continuation lines. */ - if (*fmt == '.') - --error_message_count; - else if (error_message_count >= gram_max_allowed_errors) + if (error_message_count >= gram_max_allowed_errors) po_error (EXIT_FAILURE, 0, _("too many errors, aborting")); } -/* CAUTION: If you change this function, you must also make identical - changes to the macro of the same name in src/po-lex.h */ - /* VARARGS2 */ void po_gram_error_at_line (const lex_pos_ty *pp, const char *fmt, ...) @@ -117,23 +103,14 @@ po_gram_error_at_line (const lex_pos_ty *pp, const char *fmt, ...) if (vasprintf (&buffer, fmt, ap) < 0) error (EXIT_FAILURE, 0, _("memory exhausted")); va_end (ap); - error_with_progname = false; - po_error_at_line (0, 0, pp->file_name, pp->line_number, "%s", buffer); - error_with_progname = true; + po_xerror (PO_SEVERITY_ERROR, NULL, pp->file_name, pp->line_number, + (size_t)(-1), false, buffer); free (buffer); - /* Some messages need more than one line, or more than one location. - Continuation lines are indicated by using "..." at the start of the - string. We don't increment the error counter for these - continuation lines. */ - if (*fmt == '.') - --error_message_count; - else if (error_message_count >= gram_max_allowed_errors) + if (error_message_count >= gram_max_allowed_errors) po_error (EXIT_FAILURE, 0, _("too many errors, aborting")); } -#endif - /* The lowest level of PO file parsing converts bytes to multibyte characters. This is needed @@ -505,7 +482,13 @@ incomplete multibyte sequence at end of line")); } } else - po_error (EXIT_FAILURE, errno, _("iconv failure")); + { + const char *errno_description = strerror (errno); + po_xerror (PO_SEVERITY_FATAL_ERROR, NULL, NULL, 0, 0, false, + xasprintf ("%s: %s", + _("iconv failure"), + errno_description)); + } } else { @@ -665,10 +648,14 @@ lex_getc (mbchar_t mbc) if (mb_iseof (mbc)) { if (ferror (mbf->fp)) + bomb: { - bomb: - po_error (EXIT_FAILURE, errno, _("error while reading \"%s\""), - gram_pos.file_name); + const char *errno_description = strerror (errno); + po_xerror (PO_SEVERITY_FATAL_ERROR, NULL, NULL, 0, 0, false, + xasprintf ("%s: %s", + xasprintf (_("error while reading \"%s\""), + gram_pos.file_name), + errno_description)); } break; } diff --git a/gettext-tools/src/po-lex.h b/gettext-tools/src/po-lex.h index 185a24c..17adace 100644 --- a/gettext-tools/src/po-lex.h +++ b/gettext-tools/src/po-lex.h @@ -26,7 +26,6 @@ #include "error.h" #include "error-progname.h" #include "xerror.h" -#include "po-error.h" #include "pos.h" @@ -70,83 +69,8 @@ extern void po_lex_pass_comments (bool flag); Switch this on or off. */ extern void po_lex_pass_obsolete_entries (bool flag); - -/* ISO C 99 is smart enough to allow optimizations like this. - Note: OpenVMS 7.3 cc pretends to support ISO C 99 but chokes on '...'. */ -#if __STDC__ && (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L && !defined __DECC) - -/* CAUTION: If you change this macro, you must also make identical - changes to the function of the same name in src/po-lex.c */ - -# define po_gram_error(fmt, ...) \ - do { \ - char *totalfmt = xasprintf ("%s%s", "%s:%lu:%d: ", fmt); \ - error_with_progname = false; \ - po_error (0, 0, totalfmt, gram_pos.file_name, \ - (unsigned long) gram_pos.line_number, gram_pos_column + 1, \ - __VA_ARGS__ + 0); \ - error_with_progname = true; \ - free (totalfmt); \ - if (*fmt == '.') \ - --error_message_count; \ - else if (error_message_count >= gram_max_allowed_errors) \ - po_error (1, 0, _("too many errors, aborting")); \ - } while (0) - -/* CAUTION: If you change this macro, you must also make identical - changes to the function of the same name in src/po-lex.c */ - -# define po_gram_error_at_line(pos, fmt, ...) \ - do { \ - error_with_progname = false; \ - po_error_at_line (0, 0, (pos)->file_name, (pos)->line_number, \ - fmt, __VA_ARGS__ + 0); \ - error_with_progname = true; \ - if (*fmt == '.') \ - --error_message_count; \ - else if (error_message_count >= gram_max_allowed_errors) \ - po_error (1, 0, _("too many errors, aborting")); \ - } while (0) - -/* GCC is also smart enough to allow optimizations like this. */ -#elif __STDC__ && defined __GNUC__ && __GNUC__ >= 2 && !(__APPLE_CC__ > 1) - -/* CAUTION: If you change this macro, you must also make identical - changes to the function of the same name in src/po-lex.c */ - -# define po_gram_error(fmt, args...) \ - do { \ - char *totalfmt = xasprintf ("%s%s", "%s:%d:%d: ", fmt); \ - error_with_progname = false; \ - po_error (0, 0, totalfmt, gram_pos.file_name, gram_pos.line_number, \ - gram_pos_column + 1 , ## args); \ - error_with_progname = true; \ - free (totalfmt); \ - if (*fmt == '.') \ - --error_message_count; \ - else if (error_message_count >= gram_max_allowed_errors) \ - po_error (1, 0, _("too many errors, aborting")); \ - } while (0) - -/* CAUTION: If you change this macro, you must also make identical - changes to the function of the same name in src/po-lex.c */ - -# define po_gram_error_at_line(pos, fmt, args...) \ - do { \ - error_with_progname = false; \ - po_error_at_line (0, 0, (pos)->file_name, (pos)->line_number, \ - fmt , ## args); \ - error_with_progname = true; \ - if (*fmt == '.') \ - --error_message_count; \ - else if (error_message_count >= gram_max_allowed_errors) \ - po_error (1, 0, _("too many errors, aborting")); \ - } while (0) - -#else extern void po_gram_error (const char *fmt, ...); extern void po_gram_error_at_line (const lex_pos_ty *pos, const char *fmt, ...); -#endif /* Contains information about the definition of one translation. */ diff --git a/gettext-tools/src/po-xerror.c b/gettext-tools/src/po-xerror.c new file mode 100644 index 0000000..0e5de27 --- /dev/null +++ b/gettext-tools/src/po-xerror.c @@ -0,0 +1,199 @@ +/* Error handling during reading and writing of PO files. + Copyright (C) 2005 Free Software Foundation, Inc. + Written by Bruno Haible <bruno@clisp.org>, 2005. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +/* Specification. */ +#include "po-xerror.h" + +#include <error.h> +#include <stdio.h> +#include <stdlib.h> + +#include "exit.h" +#include "message.h" +#include "progname.h" +#include "error-progname.h" +#include "xalloc.h" +#include "xerror.h" +#include "po-error.h" +#include "gettext.h" + +#define _(str) gettext (str) + + +static void +xerror (int severity, const char *prefix_tail, + const char *filename, size_t lineno, size_t column, + int multiline_p, const char *message_text) +{ + if (multiline_p) + { + bool old_error_with_progname = error_with_progname; + char *prefix; + + if (filename != NULL) + { + if (lineno != (size_t)(-1)) + { + if (column != (size_t)(-1)) + prefix = + xasprintf ("%s:%ld:%ld: %s", filename, + (long) lineno, (long) column, prefix_tail); + else + prefix = + xasprintf ("%s:%ld: %s", filename, + (long) lineno, prefix_tail); + } + else + prefix = xasprintf ("%s: %s", filename, prefix_tail); + error_with_progname = false; + } + else + prefix = xasprintf ("%s: %s", program_name, prefix_tail); + + if (severity >= PO_SEVERITY_ERROR) + po_multiline_error (prefix, xstrdup (message_text)); + else + po_multiline_warning (prefix, xstrdup (message_text)); + error_with_progname = old_error_with_progname; + + if (severity == PO_SEVERITY_FATAL_ERROR) + exit (EXIT_FAILURE); + } + else + { + int exit_status = + (severity == PO_SEVERITY_FATAL_ERROR ? EXIT_FAILURE : 0); + + if (filename != NULL) + { + error_with_progname = false; + if (lineno != (size_t)(-1)) + { + if (column != (size_t)(-1)) + po_error (exit_status, 0, "%s:%ld:%ld: %s%s", + filename, (long) lineno, (long) column, + prefix_tail, message_text); + else + po_error_at_line (exit_status, 0, filename, lineno, "%s%s", + prefix_tail, message_text); + } + else + po_error (exit_status, 0, "%s: %s%s", + filename, prefix_tail, message_text); + error_with_progname = true; + } + else + po_error (exit_status, 0, "%s%s", prefix_tail, message_text); + if (severity < PO_SEVERITY_ERROR) + --error_message_count; + } +} + +/* The default error handler is based on the lower-level error handler + in po-error.h, so that gettext-po.h can offer to override one or the + other. */ +void +textmode_xerror (int severity, + const struct message_ty *message, + const char *filename, size_t lineno, size_t column, + int multiline_p, const char *message_text) +{ + const char *prefix_tail = + (severity == PO_SEVERITY_WARNING ? _("warning: ") : ""); + + if (message != NULL && (filename == NULL || lineno == (size_t)(-1))) + { + filename = message->pos.file_name; + lineno = message->pos.line_number; + column = (size_t)(-1); + } + + xerror (severity, prefix_tail, filename, lineno, column, + multiline_p, message_text); +} + +void +textmode_xerror2 (int severity, + const struct message_ty *message1, + const char *filename1, size_t lineno1, size_t column1, + int multiline_p1, const char *message_text1, + const struct message_ty *message2, + const char *filename2, size_t lineno2, size_t column2, + int multiline_p2, const char *message_text2) +{ + int severity1 = /* Don't exit before both texts have been output. */ + (severity == PO_SEVERITY_FATAL_ERROR ? PO_SEVERITY_ERROR : severity); + const char *prefix_tail = + (severity == PO_SEVERITY_WARNING ? _("warning: ") : ""); + + if (message1 != NULL && (filename1 == NULL || lineno1 == (size_t)(-1))) + { + filename1 = message1->pos.file_name; + lineno1 = message1->pos.line_number; + column1 = (size_t)(-1); + } + + if (message2 != NULL && (filename2 == NULL || lineno2 == (size_t)(-1))) + { + filename2 = message2->pos.file_name; + lineno2 = message2->pos.line_number; + column2 = (size_t)(-1); + } + + if (multiline_p1) + xerror (severity1, prefix_tail, filename1, lineno1, column1, multiline_p1, + message_text1); + else + { + char *message_text1_extended = xasprintf ("%s...", message_text1); + xerror (severity1, prefix_tail, filename1, lineno1, column1, + multiline_p1, message_text1_extended); + free (message_text1_extended); + } + + { + char *message_text2_extended = xasprintf ("...%s", message_text2); + xerror (severity, prefix_tail, filename2, lineno2, column2, + multiline_p2, message_text2_extended); + free (message_text2_extended); + } + + if (severity >= PO_SEVERITY_ERROR) + /* error_message_count needs to be incremented only by 1, not by 2. */ + --error_message_count; +} + +void (*po_xerror) (int severity, + const struct message_ty *message, + const char *filename, size_t lineno, size_t column, + int multiline_p, const char *message_text) + = textmode_xerror; + +void (*po_xerror2) (int severity, + const struct message_ty *message1, + const char *filename1, size_t lineno1, size_t column1, + int multiline_p1, const char *message_text1, + const struct message_ty *message2, + const char *filename2, size_t lineno2, size_t column2, + int multiline_p2, const char *message_text2) + = textmode_xerror2; diff --git a/gettext-tools/src/po-xerror.h b/gettext-tools/src/po-xerror.h new file mode 100644 index 0000000..03a3438 --- /dev/null +++ b/gettext-tools/src/po-xerror.h @@ -0,0 +1,83 @@ +/* Error handling during reading and writing of PO files. + Copyright (C) 2005 Free Software Foundation, Inc. + Written by Bruno Haible <bruno@clisp.org>, 2005. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#ifndef _PO_XERROR_H +#define _PO_XERROR_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stddef.h> + +struct message_ty; + + +/* A higher-level error handler than the one in po-error.h. */ + +/* These values must be the same as those in gettext-po.h. */ +#define PO_SEVERITY_WARNING 0 /* just a warning, tell the user */ +#define PO_SEVERITY_ERROR 1 /* an error, the operation cannot complete */ +#define PO_SEVERITY_FATAL_ERROR 2 /* an error, the operation must be aborted */ + +/* Signal a problem of the given severity. + MESSAGE and/or FILENAME + LINENO indicate where the problem occurred. + If FILENAME is NULL, FILENAME and LINENO and COLUMN should be ignored. + If LINENO is (size_t)(-1), LINENO and COLUMN should be ignored. + If COLUMN is (size_t)(-1), it should be ignored. + MESSAGE_TEXT is the problem description (if MULTILINE_P is true, + multiple lines of text, each terminated with a newline, otherwise + usually a single line). + Must not return if SEVERITY is PO_SEVERITY_FATAL_ERROR. */ +extern DLL_VARIABLE + void (*po_xerror) (int severity, + const struct message_ty *message, + const char *filename, size_t lineno, size_t column, + int multiline_p, const char *message_text); + +/* Signal a problem that refers to two messages. + Similar to two calls to po_xerror. + If possible, a "..." can be appended to MESSAGE_TEXT1 and prepended to + MESSAGE_TEXT2. */ +extern DLL_VARIABLE + void (*po_xerror2) (int severity, + const struct message_ty *message1, + const char *filename1, size_t lineno1, size_t column1, + int multiline_p1, const char *message_text1, + const struct message_ty *message2, + const char *filename2, size_t lineno2, size_t column2, + int multiline_p2, const char *message_text2); + +/* The default error handler. */ +extern void textmode_xerror (int severity, + const struct message_ty *message, + const char *filename, size_t lineno, size_t column, + int multiline_p, const char *message_text); +extern void textmode_xerror2 (int severity, + const struct message_ty *message1, + const char *filename1, size_t lineno1, size_t column1, + int multiline_p1, const char *message_text1, + const struct message_ty *message2, + const char *filename2, size_t lineno2, size_t column2, + int multiline_p2, const char *message_text2); + +#ifdef __cplusplus +} +#endif + +#endif /* _PO_XERROR_H */ diff --git a/gettext-tools/src/read-po-abstract.c b/gettext-tools/src/read-po-abstract.c index 29f0573..bb99740 100644 --- a/gettext-tools/src/read-po-abstract.c +++ b/gettext-tools/src/read-po-abstract.c @@ -32,6 +32,8 @@ #include "read-properties.h" #include "read-stringtable.h" #include "xalloc.h" +#include "xerror.h" +#include "po-xerror.h" #include "gettext.h" /* Local variables. */ @@ -187,10 +189,12 @@ po_scan (abstract_po_reader_ty *pop, FILE *fp, } if (error_message_count > 0) - po_error (EXIT_FAILURE, 0, - ngettext ("found %d fatal error", "found %d fatal errors", - error_message_count), - error_message_count); + po_xerror (PO_SEVERITY_FATAL_ERROR, NULL, + /*real_filename*/ NULL, (size_t)(-1), (size_t)(-1), false, + xasprintf (ngettext ("found %d fatal error", + "found %d fatal errors", + error_message_count), + error_message_count)); error_message_count = 0; } diff --git a/gettext-tools/src/read-po.c b/gettext-tools/src/read-po.c index 84a2001..4b37081 100644 --- a/gettext-tools/src/read-po.c +++ b/gettext-tools/src/read-po.c @@ -1,5 +1,5 @@ /* Reading PO files. - Copyright (C) 1995-1998, 2000-2003 Free Software Foundation, Inc. + Copyright (C) 1995-1998, 2000-2003, 2005 Free Software Foundation, Inc. This file was written by Peter Miller <millerp@canb.auug.org.au> This program is free software; you can redistribute it and/or modify @@ -29,6 +29,7 @@ #include "open-po.h" #include "po-charset.h" +#include "po-xerror.h" #include "xalloc.h" #include "gettext.h" @@ -354,9 +355,11 @@ default_add_message (default_po_reader_ty *this, translations are equal or different. This is for consistency with msgmerge, msgcat and others. The user can use the msguniq program to get rid of duplicates. */ - po_gram_error_at_line (msgid_pos, _("duplicate message definition")); - po_gram_error_at_line (&mp->pos, _("\ -...this is the location of the first definition")); + po_xerror2 (PO_SEVERITY_ERROR, + NULL, msgid_pos->file_name, msgid_pos->line_number, + (size_t)(-1), false, _("duplicate message definition"), + mp, NULL, 0, 0, false, + _("this is the location of the first definition")); } /* We don't need the just constructed entries' parameter string (allocated in po-gram-gen.y). */ diff --git a/gettext-tools/src/read-properties.c b/gettext-tools/src/read-properties.c index 3a110a8..4e22d9e 100644 --- a/gettext-tools/src/read-properties.c +++ b/gettext-tools/src/read-properties.c @@ -1,5 +1,5 @@ /* Reading Java .properties files. - Copyright (C) 2003 Free Software Foundation, Inc. + Copyright (C) 2003, 2005 Free Software Foundation, Inc. Written by Bruno Haible <bruno@clisp.org>, 2003. This program is free software; you can redistribute it and/or modify @@ -35,7 +35,8 @@ #include "message.h" #include "read-po-abstract.h" #include "xalloc.h" -#include "exit.h" +#include "xerror.h" +#include "po-xerror.h" #include "msgl-ascii.h" #include "utf16-ucs4.h" #include "ucs4-utf8.h" @@ -77,8 +78,14 @@ phase1_getc () if (c == EOF) { if (ferror (fp)) - error (EXIT_FAILURE, errno, _("error while reading \"%s\""), - real_file_name); + { + const char *errno_description = strerror (errno); + po_xerror (PO_SEVERITY_FATAL_ERROR, NULL, NULL, 0, 0, false, + xasprintf ("%s: %s", + xasprintf (_("error while reading \"%s\""), + real_file_name), + errno_description)); + } return EOF; } @@ -211,10 +218,9 @@ phase4_getuc () else { phase3_ungetc (c1); - error_with_progname = false; - error (0, 0, _("%s:%lu: warning: invalid \\uxxxx syntax for Unicode character"), - real_file_name, (unsigned long) gram_pos.line_number); - error_with_progname = true; + po_xerror (PO_SEVERITY_ERROR, NULL, + real_file_name, gram_pos.line_number, (size_t)(-1), + false, _("warning: invalid \\uxxxx syntax for Unicode character")); return 'u'; } } diff --git a/gettext-tools/src/read-stringtable.c b/gettext-tools/src/read-stringtable.c index c841c49..081e582 100644 --- a/gettext-tools/src/read-stringtable.c +++ b/gettext-tools/src/read-stringtable.c @@ -34,7 +34,8 @@ #include "error-progname.h" #include "read-po-abstract.h" #include "xalloc.h" -#include "exit.h" +#include "xerror.h" +#include "po-xerror.h" #include "utf8-ucs4.h" #include "ucs4-utf8.h" #include "gettext.h" @@ -92,8 +93,14 @@ phase1_getc () if (c == EOF) { if (ferror (fp)) - error (EXIT_FAILURE, errno, _("error while reading \"%s\""), - real_file_name); + { + const char *errno_description = strerror (errno); + po_xerror (PO_SEVERITY_FATAL_ERROR, NULL, NULL, 0, 0, false, + xasprintf ("%s: %s", + xasprintf (_("error while reading \"%s\""), + real_file_name), + errno_description)); + } return EOF; } @@ -792,23 +799,17 @@ read_string (lex_pos_ty *pos) buffer[buflen++] = c; } if (c == UEOF) - { - error_with_progname = false; - error (0, 0, _("%s:%lu: warning: unterminated string"), - real_file_name, (unsigned long) gram_pos.line_number); - error_with_progname = true; - } + po_xerror (PO_SEVERITY_ERROR, NULL, + real_file_name, gram_pos.line_number, (size_t)(-1), false, + _("warning: unterminated string")); } else { /* Read a token outside quotes. */ if (is_quotable (c)) - { - error_with_progname = false; - error (0, 0, _("%s:%lu: warning: syntax error"), - real_file_name, (unsigned long) gram_pos.line_number); - error_with_progname = true; - } + po_xerror (PO_SEVERITY_ERROR, NULL, + real_file_name, gram_pos.line_number, (size_t)(-1), false, + _("warning: syntax error")); for (; c != UEOF && !is_quotable (c); c = phase4_getc ()) { if (buflen >= bufmax) @@ -867,10 +868,9 @@ stringtable_parse (abstract_po_reader_ty *pop, FILE *file, /* Expect a '=' or ';'. */ if (c == UEOF) { - error_with_progname = false; - error (0, 0, _("%s:%lu: warning: unterminated key/value pair"), - real_file_name, (unsigned long) gram_pos.line_number); - error_with_progname = true; + po_xerror (PO_SEVERITY_ERROR, NULL, + real_file_name, gram_pos.line_number, (size_t)(-1), false, + _("warning: unterminated key/value pair")); break; } if (c == ';') @@ -889,10 +889,9 @@ stringtable_parse (abstract_po_reader_ty *pop, FILE *file, msgstr = read_string (&msgstr_pos); if (msgstr == NULL) { - error_with_progname = false; - error (0, 0, _("%s:%lu: warning: unterminated key/value pair"), - real_file_name, (unsigned long) gram_pos.line_number); - error_with_progname = true; + po_xerror (PO_SEVERITY_ERROR, NULL, + real_file_name, gram_pos.line_number, (size_t)(-1), + false, _("warning: unterminated key/value pair")); break; } @@ -935,21 +934,19 @@ stringtable_parse (abstract_po_reader_ty *pop, FILE *file, } else { - error_with_progname = false; - error (0, 0, _("\ -%s:%lu: warning: syntax error, expected ';' after string"), - real_file_name, (unsigned long) gram_pos.line_number); - error_with_progname = true; + po_xerror (PO_SEVERITY_ERROR, NULL, + real_file_name, gram_pos.line_number, (size_t)(-1), + false, _("\ +warning: syntax error, expected ';' after string")); break; } } else { - error_with_progname = false; - error (0, 0, _("\ -%s:%lu: warning: syntax error, expected '=' or ';' after string"), - real_file_name, (unsigned long) gram_pos.line_number); - error_with_progname = true; + po_xerror (PO_SEVERITY_ERROR, NULL, + real_file_name, gram_pos.line_number, (size_t)(-1), false, + _("\ +warning: syntax error, expected '=' or ';' after string")); break; } } diff --git a/gettext-tools/src/write-po.c b/gettext-tools/src/write-po.c index cebfd6a..b1a0b56 100644 --- a/gettext-tools/src/write-po.c +++ b/gettext-tools/src/write-po.c @@ -45,10 +45,9 @@ #include "xallocsa.h" #include "strstr.h" #include "fwriteerror.h" -#include "exit.h" #include "error-progname.h" #include "xerror.h" -#include "po-error.h" +#include "po-xerror.h" #include "gettext.h" /* Our regular abbreviation. */ @@ -419,8 +418,9 @@ memcpy_small (void *dst, const void *src, size_t n) static void -wrap (FILE *fp, const char *line_prefix, const char *name, const char *value, - enum is_wrap do_wrap, const char *charset) +wrap (const message_ty *mp, FILE *fp, const char *line_prefix, + const char *name, const char *value, enum is_wrap do_wrap, + const char *charset) { const char *canon_charset; const char *s; @@ -550,7 +550,8 @@ wrap (FILE *fp, const char *line_prefix, const char *name, const char *value, { if (errno == EILSEQ) { - po_error (0, 0, _("invalid multibyte sequence")); + po_xerror (PO_SEVERITY_ERROR, mp, NULL, 0, 0, false, + _("invalid multibyte sequence")); continue; } else @@ -603,9 +604,15 @@ wrap (FILE *fp, const char *line_prefix, const char *name, const char *value, /* We warn about any use of escape sequences beside '\n' and '\t'. */ if (c != 'n' && c != 't') - po_error (0, 0, _("\ + { + char *error_message = + xasprintf (_("\ internationalized messages should not contain the `\\%c' escape sequence"), - c); + c); + po_xerror (PO_SEVERITY_ERROR, mp, NULL, 0, 0, false, + error_message); + free (error_message); + } } else if (escape && !c_isprint ((unsigned char) c)) { @@ -658,7 +665,8 @@ internationalized messages should not contain the `\\%c' escape sequence"), { if (errno == EILSEQ) { - po_error (0, 0, _("invalid multibyte sequence")); + po_xerror (PO_SEVERITY_ERROR, mp, NULL, 0, 0, + false, _("invalid multibyte sequence")); continue; } else @@ -848,18 +856,22 @@ message_print (const message_ty *mp, FILE *fp, const char *charset, this domain, emit an empty string. */ if (!is_ascii_string (mp->msgid) && po_charset_canonicalize (charset) != po_charset_utf8) - po_multiline_warning (xasprintf (_("warning: ")), - xasprintf (_("\ + { + char *warning_message = + xasprintf (_("\ The following msgid contains non-ASCII characters.\n\ This will cause problems to translators who use a character encoding\n\ different from yours. Consider using a pure ASCII msgid instead.\n\ -%s\n"), mp->msgid)); - wrap (fp, NULL, "msgid", mp->msgid, mp->do_wrap, charset); +%s\n"), mp->msgid); + po_xerror (PO_SEVERITY_WARNING, mp, NULL, 0, 0, true, warning_message); + free (warning_message); + } + wrap (mp, fp, NULL, "msgid", mp->msgid, mp->do_wrap, charset); if (mp->msgid_plural != NULL) - wrap (fp, NULL, "msgid_plural", mp->msgid_plural, mp->do_wrap, charset); + wrap (mp, fp, NULL, "msgid_plural", mp->msgid_plural, mp->do_wrap, charset); if (mp->msgid_plural == NULL) - wrap (fp, NULL, "msgstr", mp->msgstr, mp->do_wrap, charset); + wrap (mp, fp, NULL, "msgstr", mp->msgstr, mp->do_wrap, charset); else { char prefix_buf[20]; @@ -871,7 +883,7 @@ different from yours. Consider using a pure ASCII msgid instead.\n\ p += strlen (p) + 1, i++) { sprintf (prefix_buf, "msgstr[%u]", i); - wrap (fp, NULL, prefix_buf, p, mp->do_wrap, charset); + wrap (mp, fp, NULL, prefix_buf, p, mp->do_wrap, charset); } } } @@ -914,18 +926,23 @@ message_print_obsolete (const message_ty *mp, FILE *fp, const char *charset, are as readable as possible. */ if (!is_ascii_string (mp->msgid) && po_charset_canonicalize (charset) != po_charset_utf8) - po_multiline_warning (xasprintf (_("warning: ")), - xasprintf (_("\ + { + char *warning_message = + xasprintf (_("\ The following msgid contains non-ASCII characters.\n\ This will cause problems to translators who use a character encoding\n\ different from yours. Consider using a pure ASCII msgid instead.\n\ -%s\n"), mp->msgid)); - wrap (fp, "#~ ", "msgid", mp->msgid, mp->do_wrap, charset); +%s\n"), mp->msgid); + po_xerror (PO_SEVERITY_WARNING, mp, NULL, 0, 0, true, warning_message); + free (warning_message); + } + wrap (mp, fp, "#~ ", "msgid", mp->msgid, mp->do_wrap, charset); if (mp->msgid_plural != NULL) - wrap (fp, "#~ ", "msgid_plural", mp->msgid_plural, mp->do_wrap, charset); + wrap (mp, fp, "#~ ", "msgid_plural", mp->msgid_plural, mp->do_wrap, + charset); if (mp->msgid_plural == NULL) - wrap (fp, "#~ ", "msgstr", mp->msgstr, mp->do_wrap, charset); + wrap (mp, fp, "#~ ", "msgstr", mp->msgstr, mp->do_wrap, charset); else { char prefix_buf[20]; @@ -937,7 +954,7 @@ different from yours. Consider using a pure ASCII msgid instead.\n\ p += strlen (p) + 1, i++) { sprintf (prefix_buf, "msgstr[%u]", i); - wrap (fp, "#~ ", prefix_buf, p, mp->do_wrap, charset); + wrap (mp, fp, "#~ ", prefix_buf, p, mp->do_wrap, charset); } } } @@ -1060,9 +1077,11 @@ msgdomain_list_print (msgdomain_list_ty *mdlp, const char *filename, if (mdlp->nitems > 1) { if (use_syntax_properties) - po_error (EXIT_FAILURE, 0, _("Cannot output multiple translation domains into a single file with Java .properties syntax. Try using PO file syntax instead.")); + po_xerror (PO_SEVERITY_FATAL_ERROR, NULL, NULL, 0, 0, false, _("\ +Cannot output multiple translation domains into a single file with Java .properties syntax. Try using PO file syntax instead.")); if (use_syntax_stringtable) - po_error (EXIT_FAILURE, 0, _("Cannot output multiple translation domains into a single file with NeXTstep/GNUstep .strings syntax.")); + po_xerror (PO_SEVERITY_FATAL_ERROR, NULL, NULL, 0, 0, false, _("\ +Cannot output multiple translation domains into a single file with NeXTstep/GNUstep .strings syntax.")); } if (mdlp->nitems == 1) { @@ -1086,13 +1105,15 @@ msgdomain_list_print (msgdomain_list_ty *mdlp, const char *filename, { error_with_progname = false; if (use_syntax_properties) - po_error_at_line (EXIT_FAILURE, 0, - has_plural->file_name, has_plural->line_number, - _("message catalog has plural form translations, but the output format does not support them. Try generating a Java class using \"msgfmt --java\", instead of a properties file.")); + po_xerror (PO_SEVERITY_FATAL_ERROR, NULL, + has_plural->file_name, has_plural->line_number, + (size_t)(-1), false, _("\ +message catalog has plural form translations, but the output format does not support them. Try generating a Java class using \"msgfmt --java\", instead of a properties file.")); if (use_syntax_stringtable) - po_error_at_line (EXIT_FAILURE, 0, - has_plural->file_name, has_plural->line_number, - _("message catalog has plural form translations, but the output format does not support them.")); + po_xerror (PO_SEVERITY_FATAL_ERROR, NULL, + has_plural->file_name, has_plural->line_number, + (size_t)(-1), false, _("\ +message catalog has plural form translations, but the output format does not support them.")); error_with_progname = true; } } @@ -1104,8 +1125,14 @@ msgdomain_list_print (msgdomain_list_ty *mdlp, const char *filename, { fp = fopen (filename, "w"); if (fp == NULL) - po_error (EXIT_FAILURE, errno, _("cannot create output file \"%s\""), - filename); + { + const char *errno_description = strerror (errno); + po_xerror (PO_SEVERITY_FATAL_ERROR, NULL, NULL, 0, 0, false, + xasprintf ("%s: %s", + xasprintf (_("cannot create output file \"%s\""), + filename), + errno_description)); + } } else { @@ -1123,8 +1150,14 @@ msgdomain_list_print (msgdomain_list_ty *mdlp, const char *filename, /* Make sure nothing went wrong. */ if (fwriteerror (fp)) - po_error (EXIT_FAILURE, errno, _("error while writing \"%s\" file"), - filename); + { + const char *errno_description = strerror (errno); + po_xerror (PO_SEVERITY_FATAL_ERROR, NULL, NULL, 0, 0, false, + xasprintf ("%s: %s", + xasprintf (_("error while writing \"%s\" file"), + filename), + errno_description)); + } } diff --git a/gettext-tools/src/xgettext.c b/gettext-tools/src/xgettext.c index be4d8b3..260577f 100644 --- a/gettext-tools/src/xgettext.c +++ b/gettext-tools/src/xgettext.c @@ -1676,6 +1676,7 @@ Please specify the source encoding through --from-code.\n"), context.from_code = xgettext_current_source_encoding; context.to_code = po_charset_utf8; context.from_filename = file_name; + context.message = NULL; string = convert_string (xgettext_current_source_iconv, string, &context); #else diff --git a/gettext-tools/tests/ChangeLog b/gettext-tools/tests/ChangeLog index fc88890..aeb2d1c 100644 --- a/gettext-tools/tests/ChangeLog +++ b/gettext-tools/tests/ChangeLog @@ -1,3 +1,11 @@ +2005-09-17 Bruno Haible <bruno@clisp.org> + + * msgfmt-7: Update after slight change in error message. + * msgfmt-8: Likewise. + * msgfmt-9: Likewise. + * msgmerge-2: Likewise. + * msgmerge-9: Likewise. + 2005-08-26 Bruno Haible <bruno@clisp.org> * plural-2: Add test for Romanian plural formula. diff --git a/gettext-tools/tests/msgfmt-7 b/gettext-tools/tests/msgfmt-7 index 002cf6d..f399d6c 100755 --- a/gettext-tools/tests/msgfmt-7 +++ b/gettext-tools/tests/msgfmt-7 @@ -34,7 +34,7 @@ ${MSGFMT} --verbose --check mf-test7.in1 -o /dev/null \ tmpfiles="$tmpfiles mf-test7.ok" cat << EOF > mf-test7.ok -mf-test7.in1:17: duplicate message definition +mf-test7.in1:17: duplicate message definition... mf-test7.in1:16: ...this is the location of the first definition msgfmt: found 1 fatal error EOF diff --git a/gettext-tools/tests/msgfmt-8 b/gettext-tools/tests/msgfmt-8 index c5467ed..515ff58 100755 --- a/gettext-tools/tests/msgfmt-8 +++ b/gettext-tools/tests/msgfmt-8 @@ -34,7 +34,7 @@ ${MSGFMT} --verbose --check mf-test8.in1 -o /dev/null \ tmpfiles="$tmpfiles mf-test8.ok" cat << EOF > mf-test8.ok -mf-test8.in1:17: duplicate message definition +mf-test8.in1:17: duplicate message definition... mf-test8.in1:16: ...this is the location of the first definition msgfmt: found 1 fatal error EOF diff --git a/gettext-tools/tests/msgfmt-9 b/gettext-tools/tests/msgfmt-9 index 1574916..1a897d1 100755 --- a/gettext-tools/tests/msgfmt-9 +++ b/gettext-tools/tests/msgfmt-9 @@ -37,7 +37,7 @@ ${MSGFMT} --verbose --check mf-test9.in1 -o /dev/null \ tmpfiles="$tmpfiles mf-test9.ok" cat << EOF > mf-test9.ok -mf-test9.in1:17: duplicate message definition +mf-test9.in1:17: duplicate message definition... mf-test9.in1:15: ...this is the location of the first definition msgfmt: found 1 fatal error EOF diff --git a/gettext-tools/tests/msgmerge-2 b/gettext-tools/tests/msgmerge-2 index 9580df5..e79b145 100755 --- a/gettext-tools/tests/msgmerge-2 +++ b/gettext-tools/tests/msgmerge-2 @@ -26,7 +26,7 @@ ${MSGMERGE} -q mm-test2.in1 mm-test2.in2 -o /dev/stdout \ tmpfiles="$tmpfiles mm-test2.ok" cat << EOF > mm-test2.ok -mm-test2.in1:3: duplicate message definition +mm-test2.in1:3: duplicate message definition... mm-test2.in1:1: ...this is the location of the first definition msgmerge: found 1 fatal error EOF diff --git a/gettext-tools/tests/msgmerge-9 b/gettext-tools/tests/msgmerge-9 index 872dc9f..c2197e9 100755 --- a/gettext-tools/tests/msgmerge-9 +++ b/gettext-tools/tests/msgmerge-9 @@ -29,7 +29,7 @@ ${MSGMERGE} -q mm-test9.in1 mm-test9.in2 -o /dev/null \ tmpfiles="$tmpfiles mm-test9.ok" cat << EOF > mm-test9.ok -mm-test9.in1:3: duplicate message definition +mm-test9.in1:3: duplicate message definition... mm-test9.in1:1: ...this is the location of the first definition msgmerge: found 1 fatal error EOF |