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 44static void 45xerror (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. */ 116void 117textmode_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 136void 137textmode_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 187void (*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 193void (*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