]> git.ipfire.org Git - thirdparty/gettext.git/commitdiff
New, higher-level error and warning message output primitives.
authorBruno Haible <bruno@clisp.org>
Mon, 19 Sep 2005 16:06:40 +0000 (16:06 +0000)
committerBruno Haible <bruno@clisp.org>
Tue, 23 Jun 2009 10:12:50 +0000 (12:12 +0200)
26 files changed:
gettext-tools/src/ChangeLog
gettext-tools/src/FILES
gettext-tools/src/Makefile.am
gettext-tools/src/msgcmp.c
gettext-tools/src/msgfmt.c
gettext-tools/src/msgl-iconv.c
gettext-tools/src/msgl-iconv.h
gettext-tools/src/msgmerge.c
gettext-tools/src/open-po.c
gettext-tools/src/po-charset.c
gettext-tools/src/po-lex.c
gettext-tools/src/po-lex.h
gettext-tools/src/po-xerror.c [new file with mode: 0644]
gettext-tools/src/po-xerror.h [new file with mode: 0644]
gettext-tools/src/read-po-abstract.c
gettext-tools/src/read-po.c
gettext-tools/src/read-properties.c
gettext-tools/src/read-stringtable.c
gettext-tools/src/write-po.c
gettext-tools/src/xgettext.c
gettext-tools/tests/ChangeLog
gettext-tools/tests/msgfmt-7
gettext-tools/tests/msgfmt-8
gettext-tools/tests/msgfmt-9
gettext-tools/tests/msgmerge-2
gettext-tools/tests/msgmerge-9

index 49346bad757f65cab421432bcf7b0baff1ab58dd..c7db86f6b1460571a5a86dc38b1d03a6908d4f59 100644 (file)
@@ -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
index ceee7cb16c7366baec05884805a09c787133a14e..0ab3c8f6d7cd792326d1dc0e7f22b2f974ba70f6 100644 (file)
@@ -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
index b41f07c8d933da2e8f00fbcdc37f4fd778b5a247..46a882c9bbdb30085935db871a398db814f0c456 100644 (file)
@@ -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
 
index 2c5bb0e024241e227134ffe3d98298d7ae494b22..6f0962c159fc4b2c622f8806f71faaacfa7c0a97 100644 (file)
@@ -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;
index 7d6c81e9aeab2e5fc78e61e67fe9969a928cf939..4c5bf8ebc35a83075fb509f2c1bd104d025ddb5c 100644 (file)
@@ -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);
        }
index f7aadc343ef1372eff57195856cd6026106d1db9..ad44f0ce64715c65133c37417c5777b0ccfcc65c 100644 (file)
@@ -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,
index 14f549bf513f61f6c1d25603383b89d147f2f393..6d4a361ee0e96fe707852c5986ae66661eeed4ff 100644 (file)
@@ -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.  */
index 89d1d3ee4f928c485c0f56accb64ce4a7947752a..0e45221a83383e4657ae34d80ae79a82e95078fc 100644 (file)
@@ -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"));
                }
index 29c21991fd77adb59ace1ebb199ec8e4ae6efa80..079954bc551bdc9f94135dcc06e46952c0df60e9 100644 (file)
@@ -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;
 }
index 81759c38303f679c6aa7999ae0c49aaafca89a72..cff58264e624bdfb13050a51c45fc59232d523e4 100644 (file)
@@ -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"));
     }
 }
 
index 6a4fee8b8819f1628c98e74bfb34c769871f6473..9fc38b585754d645c9949d16471d36d685b6bde7 100644 (file)
@@ -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;
        }
index 185a24c2aabc467769eaed5ab18c752420429da6..17adace6620e7108d124960294f6d8ac57bd3fed 100644 (file)
@@ -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 (file)
index 0000000..0e5de27
--- /dev/null
@@ -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 (file)
index 0000000..03a3438
--- /dev/null
@@ -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 */
index 29f0573947389714aae1d21b5c17eb240d892654..bb9974034d37cfec7d65c2969d61dbd37be15f50 100644 (file)
@@ -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;
 }
 
index 84a2001ef676296297a569a3468325a79ded4982..4b3708147193dc6b277befbb1b7b596b63b2a9d7 100644 (file)
@@ -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).  */
index 3a110a84917ea3809edd61bcc841042788850473..4e22d9eba51218f63cb6ae99f5276dddc355b669 100644 (file)
@@ -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';
                }
            }
index c841c49a5dd665b4be052dccd5e3582ccb897fc6..081e5829dc1cdc5803b2ec7eda63e1115e41cd11 100644 (file)
@@ -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;
        }
     }
index cebfd6aedc88515ff9b3beed1c695a917ecd60a3..b1a0b56a0168462c2c9c287a8846bf328f70966b 100644 (file)
 #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));
+    }
 }
 
 
index be4d8b30cf644755fd6de4b1bcd94994b5f835c9..260577f3a6c092f05852edbdf9ce4839f8b89c28 100644 (file)
@@ -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
index fc888907f61d808bf95b3a963eaf46c61a4eefd0..aeb2d1cc61f92e1d65c124e2a68d2f85146790e4 100644 (file)
@@ -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.
index 002cf6dc0aa1b59446dacc88d7c424b21c2dfabb..f399d6c4a831e72f81c9601c59a0450033df4f3e 100755 (executable)
@@ -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
index c5467edcae6ab01832700105f2f0af30153e6f20..515ff58cbd065bb6b041fee76dc587c653a17f96 100755 (executable)
@@ -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
index 1574916b06ed3e0cf91e906eb8c67c716464359a..1a897d1055da5c4ad5f1342d94dc1a079c694653 100755 (executable)
@@ -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
index 9580df5fffc711cd0903884a4dc8cb19d0dc9e04..e79b14599dbb25a090f68af065bb83385f4e68bc 100755 (executable)
@@ -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
index 872dc9f1a11033d491525a952de1a6b69e894fe5..c2197e91c053a8e5aa8f0b2549c59e48c7910ac2 100755 (executable)
@@ -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