xref: /netbsd-src/external/gpl2/gettext/dist/gettext-tools/src/po-xerror.c (revision 946379e7b37692fc43f68eb0d1c10daa0a7f3b6c)
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@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
xerror(int severity,const char * prefix_tail,const char * filename,size_t lineno,size_t column,int multiline_p,const char * message_text)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
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)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
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)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