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