blob: d916d2a370265961632257849e9eb3a071625d5b [file] [log] [blame]
/* Error handling during reading and writing of PO files.
Copyright (C) 2005-2007, 2013, 2019 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2005.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
/* Specification. */
#include "po-xerror.h"
#include <error.h>
#include <stdio.h>
#include <stdlib.h>
#include "message.h"
#include "error-progname.h"
#include "xalloc.h"
#include "xerror.h"
#include "error.h"
#include "xvasprintf.h"
#include "po-error.h"
#if IN_LIBGETTEXTPO
# include "getprogname.h"
# define program_name getprogname ()
#else
# include "progname.h"
#endif
#include "gettext.h"
#define _(str) gettext (str)
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)
{
if (multiline_p)
{
bool old_error_with_progname = error_with_progname;
char *prefix;
if (filename != NULL)
{
if (lineno != (size_t)(-1))
{
if (column != (size_t)(-1))
prefix =
xasprintf ("%s:%ld:%ld: %s", filename,
(long) lineno, (long) column, prefix_tail);
else
prefix =
xasprintf ("%s:%ld: %s", filename,
(long) lineno, prefix_tail);
}
else
prefix = xasprintf ("%s: %s", filename, prefix_tail);
error_with_progname = false;
}
else
prefix = xasprintf ("%s: %s", program_name, prefix_tail);
if (severity >= PO_SEVERITY_ERROR)
po_multiline_error (prefix, xstrdup (message_text));
else
po_multiline_warning (prefix, xstrdup (message_text));
error_with_progname = old_error_with_progname;
if (severity == PO_SEVERITY_FATAL_ERROR)
exit (EXIT_FAILURE);
}
else
{
int exit_status =
(severity == PO_SEVERITY_FATAL_ERROR ? EXIT_FAILURE : 0);
if (filename != NULL)
{
error_with_progname = false;
if (lineno != (size_t)(-1))
{
if (column != (size_t)(-1))
po_error (exit_status, 0, "%s:%ld:%ld: %s%s",
filename, (long) lineno, (long) column,
prefix_tail, message_text);
else
po_error_at_line (exit_status, 0, filename, lineno, "%s%s",
prefix_tail, message_text);
}
else
po_error (exit_status, 0, "%s: %s%s",
filename, prefix_tail, message_text);
error_with_progname = true;
}
else
po_error (exit_status, 0, "%s%s", prefix_tail, message_text);
if (severity < PO_SEVERITY_ERROR)
--error_message_count;
}
}
/* The default error handler is based on the lower-level error handler
in po-error.h, so that gettext-po.h can offer to override one or the
other. */
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)
{
const char *prefix_tail =
(severity == PO_SEVERITY_WARNING ? _("warning: ") : "");
if (message != NULL && (filename == NULL || lineno == (size_t)(-1)))
{
filename = message->pos.file_name;
lineno = message->pos.line_number;
column = (size_t)(-1);
}
xerror (severity, prefix_tail, filename, lineno, column,
multiline_p, message_text);
}
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)
{
int severity1 = /* Don't exit before both texts have been output. */
(severity == PO_SEVERITY_FATAL_ERROR ? PO_SEVERITY_ERROR : severity);
const char *prefix_tail =
(severity == PO_SEVERITY_WARNING ? _("warning: ") : "");
if (message1 != NULL && (filename1 == NULL || lineno1 == (size_t)(-1)))
{
filename1 = message1->pos.file_name;
lineno1 = message1->pos.line_number;
column1 = (size_t)(-1);
}
if (message2 != NULL && (filename2 == NULL || lineno2 == (size_t)(-1)))
{
filename2 = message2->pos.file_name;
lineno2 = message2->pos.line_number;
column2 = (size_t)(-1);
}
if (multiline_p1)
xerror (severity1, prefix_tail, filename1, lineno1, column1, multiline_p1,
message_text1);
else
{
char *message_text1_extended = xasprintf ("%s...", message_text1);
xerror (severity1, prefix_tail, filename1, lineno1, column1,
multiline_p1, message_text1_extended);
free (message_text1_extended);
}
{
char *message_text2_extended = xasprintf ("...%s", message_text2);
xerror (severity, prefix_tail, filename2, lineno2, column2,
multiline_p2, message_text2_extended);
free (message_text2_extended);
}
if (severity >= PO_SEVERITY_ERROR)
/* error_message_count needs to be incremented only by 1, not by 2. */
--error_message_count;
}
void (*po_xerror) (int severity,
const struct message_ty *message,
const char *filename, size_t lineno, size_t column,
int multiline_p, const char *message_text)
= textmode_xerror;
void (*po_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)
= textmode_xerror2;