Home | History | Annotate | Line # | Download | only in src
      1 /* Error handling during reading and writing of PO files.
      2    Copyright (C) 2005-2006 Free Software Foundation, Inc.
      3    Written by Bruno Haible <bruno (at) 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 2, or (at your option)
      8    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, write to the Free Software Foundation,
     17    Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
     18 
     19 
     20 #ifdef HAVE_CONFIG_H
     21 # include "config.h"
     22 #endif
     23 
     24 /* Specification.  */
     25 #include "po-xerror.h"
     26 
     27 #include <error.h>
     28 #include <stdio.h>
     29 #include <stdlib.h>
     30 
     31 #include "exit.h"
     32 #include "message.h"
     33 #include "progname.h"
     34 #include "error-progname.h"
     35 #include "xalloc.h"
     36 #include "xerror.h"
     37 #include "xvasprintf.h"
     38 #include "po-error.h"
     39 #include "gettext.h"
     40 
     41 #define _(str) gettext (str)
     42 
     43 
     44 static void
     45 xerror (int severity, const char *prefix_tail,
     46 	const char *filename, size_t lineno, size_t column,
     47 	int multiline_p, const char *message_text)
     48 {
     49   if (multiline_p)
     50     {
     51       bool old_error_with_progname = error_with_progname;
     52       char *prefix;
     53 
     54       if (filename != NULL)
     55 	{
     56 	  if (lineno != (size_t)(-1))
     57 	    {
     58 	      if (column != (size_t)(-1))
     59 		prefix =
     60 		  xasprintf ("%s:%ld:%ld: %s", filename,
     61 			     (long) lineno, (long) column, prefix_tail);
     62 	      else
     63 		prefix =
     64 		  xasprintf ("%s:%ld: %s", filename,
     65 			     (long) lineno, prefix_tail);
     66 	    }
     67 	  else
     68 	    prefix = xasprintf ("%s: %s", filename, prefix_tail);
     69 	  error_with_progname = false;
     70 	}
     71       else
     72 	prefix = xasprintf ("%s: %s", program_name, prefix_tail);
     73 
     74       if (severity >= PO_SEVERITY_ERROR)
     75 	po_multiline_error (prefix, xstrdup (message_text));
     76       else
     77 	po_multiline_warning (prefix, xstrdup (message_text));
     78       error_with_progname = old_error_with_progname;
     79 
     80       if (severity == PO_SEVERITY_FATAL_ERROR)
     81 	exit (EXIT_FAILURE);
     82     }
     83   else
     84     {
     85       int exit_status =
     86 	(severity == PO_SEVERITY_FATAL_ERROR ? EXIT_FAILURE : 0);
     87 
     88       if (filename != NULL)
     89 	{
     90 	  error_with_progname = false;
     91 	  if (lineno != (size_t)(-1))
     92 	    {
     93 	      if (column != (size_t)(-1))
     94 		po_error (exit_status, 0, "%s:%ld:%ld: %s%s",
     95 			  filename, (long) lineno, (long) column,
     96 			  prefix_tail, message_text);
     97 	      else
     98 		po_error_at_line (exit_status, 0, filename, lineno, "%s%s",
     99 				  prefix_tail, message_text);
    100 	    }
    101 	  else
    102 	    po_error (exit_status, 0, "%s: %s%s",
    103 		      filename, prefix_tail, message_text);
    104 	  error_with_progname = true;
    105 	}
    106       else
    107 	po_error (exit_status, 0, "%s%s", prefix_tail, message_text);
    108       if (severity < PO_SEVERITY_ERROR)
    109 	--error_message_count;
    110     }
    111 }
    112 
    113 /* The default error handler is based on the lower-level error handler
    114    in po-error.h, so that gettext-po.h can offer to override one or the
    115    other.  */
    116 void
    117 textmode_xerror (int severity,
    118 		 const struct message_ty *message,
    119 		 const char *filename, size_t lineno, size_t column,
    120 		 int multiline_p, const char *message_text)
    121 {
    122   const char *prefix_tail =
    123     (severity == PO_SEVERITY_WARNING ? _("warning: ") : "");
    124 
    125   if (message != NULL && (filename == NULL || lineno == (size_t)(-1)))
    126     {
    127       filename = message->pos.file_name;
    128       lineno = message->pos.line_number;
    129       column = (size_t)(-1);
    130     }
    131 
    132   xerror (severity, prefix_tail, filename, lineno, column,
    133 	  multiline_p, message_text);
    134 }
    135 
    136 void
    137 textmode_xerror2 (int severity,
    138 		  const struct message_ty *message1,
    139 		  const char *filename1, size_t lineno1, size_t column1,
    140 		  int multiline_p1, const char *message_text1,
    141 		  const struct message_ty *message2,
    142 		  const char *filename2, size_t lineno2, size_t column2,
    143 		  int multiline_p2, const char *message_text2)
    144 {
    145   int severity1 = /* Don't exit before both texts have been output.  */
    146     (severity == PO_SEVERITY_FATAL_ERROR ? PO_SEVERITY_ERROR : severity);
    147   const char *prefix_tail =
    148     (severity == PO_SEVERITY_WARNING ? _("warning: ") : "");
    149 
    150   if (message1 != NULL && (filename1 == NULL || lineno1 == (size_t)(-1)))
    151     {
    152       filename1 = message1->pos.file_name;
    153       lineno1 = message1->pos.line_number;
    154       column1 = (size_t)(-1);
    155     }
    156 
    157   if (message2 != NULL && (filename2 == NULL || lineno2 == (size_t)(-1)))
    158     {
    159       filename2 = message2->pos.file_name;
    160       lineno2 = message2->pos.line_number;
    161       column2 = (size_t)(-1);
    162     }
    163 
    164   if (multiline_p1)
    165     xerror (severity1, prefix_tail, filename1, lineno1, column1, multiline_p1,
    166 	    message_text1);
    167   else
    168     {
    169       char *message_text1_extended = xasprintf ("%s...", message_text1);
    170       xerror (severity1, prefix_tail, filename1, lineno1, column1,
    171 	      multiline_p1, message_text1_extended);
    172       free (message_text1_extended);
    173     }
    174 
    175   {
    176     char *message_text2_extended = xasprintf ("...%s", message_text2);
    177     xerror (severity, prefix_tail, filename2, lineno2, column2,
    178 	    multiline_p2, message_text2_extended);
    179     free (message_text2_extended);
    180   }
    181 
    182   if (severity >= PO_SEVERITY_ERROR)
    183     /* error_message_count needs to be incremented only by 1, not by 2.  */
    184     --error_message_count;
    185 }
    186 
    187 void (*po_xerror) (int severity,
    188 		   const struct message_ty *message,
    189 		   const char *filename, size_t lineno, size_t column,
    190 		   int multiline_p, const char *message_text)
    191   = textmode_xerror;
    192 
    193 void (*po_xerror2) (int severity,
    194 		    const struct message_ty *message1,
    195 		    const char *filename1, size_t lineno1, size_t column1,
    196 		    int multiline_p1, const char *message_text1,
    197 		    const struct message_ty *message2,
    198 		    const char *filename2, size_t lineno2, size_t column2,
    199 		    int multiline_p2, const char *message_text2)
    200   = textmode_xerror2;
    201