(root)/
gettext-0.22.4/
gettext-tools/
src/
po-xerror.c
       1  /* Error handling during reading and writing of PO files.
       2     Copyright (C) 2005-2007, 2013, 2019, 2023 Free Software Foundation, Inc.
       3     Written by Bruno Haible <bruno@clisp.org>, 2005.
       4  
       5     This program is free software: you can redistribute it and/or modify
       6     it under the terms of the GNU General Public License as published by
       7     the Free Software Foundation; either version 3 of the License, or
       8     (at your option) any later version.
       9  
      10     This program is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      13     GNU General Public License for more details.
      14  
      15     You should have received a copy of the GNU General Public License
      16     along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
      17  
      18  
      19  #ifdef HAVE_CONFIG_H
      20  # include "config.h"
      21  #endif
      22  
      23  /* Specification.  */
      24  #include "po-xerror.h"
      25  
      26  #include <error.h>
      27  #include <stdio.h>
      28  #include <stdlib.h>
      29  
      30  #include "message.h"
      31  #include "error-progname.h"
      32  #include "xalloc.h"
      33  #include "xerror.h"
      34  #include "error.h"
      35  #include "xvasprintf.h"
      36  #include "po-error.h"
      37  #if IN_LIBGETTEXTPO
      38  # define program_name getprogname ()
      39  #else
      40  # include "progname.h"
      41  #endif
      42  #include "gettext.h"
      43  
      44  #define _(str) gettext (str)
      45  
      46  
      47  static void
      48  xerror (int severity, const char *prefix_tail,
      49          const char *filename, size_t lineno, size_t column,
      50          int multiline_p, const char *message_text)
      51  {
      52    if (multiline_p)
      53      {
      54        bool old_error_with_progname = error_with_progname;
      55        char *prefix;
      56  
      57        if (filename != NULL)
      58          {
      59            if (lineno != (size_t)(-1))
      60              {
      61                if (column != (size_t)(-1))
      62                  prefix =
      63                    xasprintf ("%s:%ld:%ld: %s", filename,
      64                               (long) lineno, (long) column, prefix_tail);
      65                else
      66                  prefix =
      67                    xasprintf ("%s:%ld: %s", filename,
      68                               (long) lineno, prefix_tail);
      69              }
      70            else
      71              prefix = xasprintf ("%s: %s", filename, prefix_tail);
      72            error_with_progname = false;
      73          }
      74        else
      75          prefix = xasprintf ("%s: %s", program_name, prefix_tail);
      76  
      77        if (severity >= PO_SEVERITY_ERROR)
      78          po_multiline_error (prefix, xstrdup (message_text));
      79        else
      80          po_multiline_warning (prefix, xstrdup (message_text));
      81        error_with_progname = old_error_with_progname;
      82  
      83        if (severity == PO_SEVERITY_FATAL_ERROR)
      84          exit (EXIT_FAILURE);
      85      }
      86    else
      87      {
      88        int exit_status =
      89          (severity == PO_SEVERITY_FATAL_ERROR ? EXIT_FAILURE : 0);
      90  
      91        if (filename != NULL)
      92          {
      93            error_with_progname = false;
      94            if (lineno != (size_t)(-1))
      95              {
      96                if (column != (size_t)(-1))
      97                  po_error (exit_status, 0, "%s:%ld:%ld: %s%s",
      98                            filename, (long) lineno, (long) column,
      99                            prefix_tail, message_text);
     100                else
     101                  po_error_at_line (exit_status, 0, filename, lineno, "%s%s",
     102                                    prefix_tail, message_text);
     103              }
     104            else
     105              po_error (exit_status, 0, "%s: %s%s",
     106                        filename, prefix_tail, message_text);
     107            error_with_progname = true;
     108          }
     109        else
     110          po_error (exit_status, 0, "%s%s", prefix_tail, message_text);
     111        if (severity < PO_SEVERITY_ERROR)
     112          --error_message_count;
     113      }
     114  }
     115  
     116  /* The default error handler is based on the lower-level error handler
     117     in po-error.h, so that gettext-po.h can offer to override one or the
     118     other.  */
     119  void
     120  textmode_xerror (int severity,
     121                   const struct message_ty *message,
     122                   const char *filename, size_t lineno, size_t column,
     123                   int multiline_p, const char *message_text)
     124  {
     125    const char *prefix_tail =
     126      (severity == PO_SEVERITY_WARNING ? _("warning: ") : "");
     127  
     128    if (message != NULL && (filename == NULL || lineno == (size_t)(-1)))
     129      {
     130        filename = message->pos.file_name;
     131        lineno = message->pos.line_number;
     132        column = (size_t)(-1);
     133      }
     134  
     135    xerror (severity, prefix_tail, filename, lineno, column,
     136            multiline_p, message_text);
     137  }
     138  
     139  void
     140  textmode_xerror2 (int severity,
     141                    const struct message_ty *message1,
     142                    const char *filename1, size_t lineno1, size_t column1,
     143                    int multiline_p1, const char *message_text1,
     144                    const struct message_ty *message2,
     145                    const char *filename2, size_t lineno2, size_t column2,
     146                    int multiline_p2, const char *message_text2)
     147  {
     148    int severity1 = /* Don't exit before both texts have been output.  */
     149      (severity == PO_SEVERITY_FATAL_ERROR ? PO_SEVERITY_ERROR : severity);
     150    const char *prefix_tail =
     151      (severity == PO_SEVERITY_WARNING ? _("warning: ") : "");
     152  
     153    if (message1 != NULL && (filename1 == NULL || lineno1 == (size_t)(-1)))
     154      {
     155        filename1 = message1->pos.file_name;
     156        lineno1 = message1->pos.line_number;
     157        column1 = (size_t)(-1);
     158      }
     159  
     160    if (message2 != NULL && (filename2 == NULL || lineno2 == (size_t)(-1)))
     161      {
     162        filename2 = message2->pos.file_name;
     163        lineno2 = message2->pos.line_number;
     164        column2 = (size_t)(-1);
     165      }
     166  
     167    if (multiline_p1)
     168      xerror (severity1, prefix_tail, filename1, lineno1, column1, multiline_p1,
     169              message_text1);
     170    else
     171      {
     172        char *message_text1_extended = xasprintf ("%s...", message_text1);
     173        xerror (severity1, prefix_tail, filename1, lineno1, column1,
     174                multiline_p1, message_text1_extended);
     175        free (message_text1_extended);
     176      }
     177  
     178    {
     179      char *message_text2_extended = xasprintf ("...%s", message_text2);
     180      xerror (severity, prefix_tail, filename2, lineno2, column2,
     181              multiline_p2, message_text2_extended);
     182      free (message_text2_extended);
     183    }
     184  
     185    if (severity >= PO_SEVERITY_ERROR)
     186      /* error_message_count needs to be incremented only by 1, not by 2.  */
     187      --error_message_count;
     188  }
     189  
     190  void (*po_xerror) (int severity,
     191                     const struct message_ty *message,
     192                     const char *filename, size_t lineno, size_t column,
     193                     int multiline_p, const char *message_text)
     194    = textmode_xerror;
     195  
     196  void (*po_xerror2) (int severity,
     197                      const struct message_ty *message1,
     198                      const char *filename1, size_t lineno1, size_t column1,
     199                      int multiline_p1, const char *message_text1,
     200                      const struct message_ty *message2,
     201                      const char *filename2, size_t lineno2, size_t column2,
     202                      int multiline_p2, const char *message_text2)
     203    = textmode_xerror2;