02110-1301, USA. */
#include <config.h>
+
#include <libpspp/message.h>
+
#include <ctype.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
-#include <libpspp/alloc.h>
+
#include <data/file-name.h>
-#include <language/line-buffer.h>
#include <language/lexer/lexer.h>
-#include <data/settings.h>
-#include <ui/terminal/read-line.h>
+#include <libpspp/alloc.h>
#include <libpspp/version.h>
-#include "exit.h"
-#include "linebreak.h"
-#include "progname.h"
-
-#include "gettext.h"
-#define _(msgid) gettext (msgid)
-#define N_(msgid) msgid
-int err_error_count;
-int err_warning_count;
+#include "progname.h"
+#include "xvasprintf.h"
-int err_already_flagged;
+/* Current command name as set by msg_set_command_name(). */
+static char *command_name;
-int err_verbosity;
+/* Message handler as set by msg_init(). */
+static void (*msg_handler) (const struct msg *);
-static char *command_name;
-\f
/* Public functions. */
/* Writes error message in CLASS, with text FORMAT, formatted with
void
msg (enum msg_class class, const char *format, ...)
{
- struct error e;
+ struct msg m;
va_list args;
- e.category = msg_class_to_category (class);
- e.severity = msg_class_to_severity (class);
- err_location (&e.where);
+ m.category = msg_class_to_category (class);
+ m.severity = msg_class_to_severity (class);
+ msg_location (&m.where);
va_start (args, format);
- e.text = xvasprintf (format, args);
+ m.text = xvasprintf (format, args);
va_end (args);
- err_msg (&e);
+ msg_emit (&m);
}
-/* Writes MESSAGE formatted with printf, to stderr, if the
- verbosity level is at least LEVEL. */
void
-verbose_msg (int level, const char *format, ...)
+msg_init (void (*handler) (const struct msg *))
{
- if (err_verbosity >= level)
- {
- va_list args;
-
- va_start (args, format);
- fprintf (stderr, "%s: ", program_name);
- vfprintf (stderr, format, args);
- putc ('\n', stderr);
- va_end (args);
- }
+ msg_handler = handler;
}
-/* Checks whether we've had so many errors that it's time to quit
- processing this syntax file. */
void
-err_check_count (void)
+msg_done (void)
{
- if (get_errorbreak() && err_error_count)
- msg (MN, _("Terminating execution of syntax file due to error."));
- else if (err_error_count > get_mxerrs() )
- msg (MN, _("Errors (%d) exceeds limit (%d)."),
- err_error_count, get_mxerrs());
- else if (err_error_count + err_warning_count > get_mxwarns() )
- msg (MN, _("Warnings (%d) exceed limit (%d)."),
- err_error_count + err_warning_count, get_mxwarns() );
- else
- return;
-
- getl_abort_noninteractive ();
}
-static void puts_stdout (int line_indent, const char *line, size_t length);
-static void dump_message (char *msg,
- void (*func) (int line_indent,
- const char *line, size_t length),
- unsigned width, unsigned indent);
-
+/* Emits M as an error message.
+ Frees allocated data in M. */
void
-err_done (void)
+msg_emit (struct msg *m)
{
- lex_done();
- getl_uninitialize ();
- readln_uninitialize();
-}
-
-/* Emits E as an error message.
- Frees `text' member in E. */
-void
-err_msg (const struct error *e)
-{
- struct category
- {
- bool show_command_name; /* Show command name with error? */
- bool show_file_location; /* Show syntax file location? */
- };
-
- static const struct category categories[] =
- {
- {false, false}, /* MSG_GENERAL. */
- {true, true}, /* MSG_SYNTAX. */
- {false, true}, /* MSG_DATA. */
- };
-
- struct severity
- {
- const char *name; /* How to identify this severity. */
- int *count; /* Number of msgs with this severity so far. */
- };
-
- static struct severity severities[] =
- {
- {N_("error"), &err_error_count}, /* MSG_ERROR. */
- {N_("warning"), &err_warning_count}, /* MSG_WARNING. */
- {NULL, NULL}, /* MSG_NOTE. */
- };
-
- const struct category *category = &categories[e->category];
- const struct severity *severity = &severities[e->severity];
- struct string msg = DS_INITIALIZER;
-
- if (category->show_file_location && e->where.file_name)
- {
- ds_printf (&msg, "%s:", e->where.file_name);
- if (e->where.line_number != -1)
- ds_printf (&msg, "%d:", e->where.line_number);
- ds_putc (&msg, ' ');
- }
-
- if (severity->name != NULL)
- ds_printf (&msg, "%s: ", gettext (severity->name));
-
- if (severity->count != NULL)
- ++*severity->count;
-
- if (category->show_command_name && command_name != NULL)
- ds_printf (&msg, "%s: ", command_name);
-
- ds_puts (&msg, e->text);
-
- /* FIXME: Check set_messages and set_errors to determine where to
- send errors and messages. */
- dump_message (ds_c_str (&msg), puts_stdout, get_viewwidth (), 8);
-
- ds_destroy (&msg);
- free (e->text);
+ msg_handler (m);
+ free (m->text);
}
\f
/* Private functions. */
-/* Write LINE_INDENT spaces, the LENGTH characters in LINE, then
- a new-line to stdout. */
-static void puts_stdout (int line_indent,
- const char *line, size_t length)
-{
- int i;
- for (i = 0; i < line_indent; i++)
- putchar (' ');
- fwrite (line, 1, length, stdout);
- putchar ('\n');
-}
-
-/* Divides MSG into lines of WIDTH width for the first line and
- WIDTH - INDENT width for each succeeding line. Each line is
- passed to FUNC as a null-terminated string (no new-line
- character is included in the string). */
-static void
-dump_message (char *msg,
- void (*func) (int line_indent, const char *line, size_t length),
- unsigned width, unsigned indent)
-{
- size_t length = strlen (msg);
- char *string, *breaks;
- int line_indent;
- size_t line_start, i;
-
- /* Allocate temporary buffers.
- If we can't get memory for them, then just dump the whole
- message. */
- string = strdup (msg);
- breaks = malloc (length);
- if (string == NULL || breaks == NULL)
- {
- free (string);
- free (breaks);
- func (0, msg, length);
- return;
- }
-
- /* Break into lines. */
- if (indent > width / 3)
- indent = width / 3;
- mbs_width_linebreaks (string, length,
- width - indent, -indent, 0,
- NULL, locale_charset (), breaks);
-
- /* Pass lines to FUNC. */
- line_start = 0;
- line_indent = 0;
- for (i = 0; i < length; i++)
- switch (breaks[i])
- {
- case UC_BREAK_POSSIBLE:
- /* Break before this character,
- and include this character in the next line. */
- func (line_indent, &string[line_start], i - line_start);
- line_start = i;
- line_indent = indent;
- break;
- case UC_BREAK_MANDATORY:
- /* Break before this character,
- but don't include this character in the next line
- (because it'string a new-line). */
- func (line_indent, &string[line_start], i - line_start);
- line_start = i + 1;
- line_indent = indent;
- break;
- default:
- break;
- }
- if (line_start < length)
- func (line_indent, &string[line_start], length - line_start);
-
- free (string);
- free (breaks);
-}
-
/* Sets COMMAND_NAME as the command name included in some kinds
of error messages. */
void
-err_set_command_name (const char *command_name_)
+msg_set_command_name (const char *command_name_)
{
free (command_name);
command_name = command_name_ ? xstrdup (command_name_) : NULL;
}
+/* Returns the current command name, or NULL if none. */
+const char *
+msg_get_command_name (void)
+{
+ return command_name;
+}
+
void
request_bug_report_and_abort(const char *msg )
{
}
void
-err_assert_fail(const char *expr, const char *file, int line)
+msg_assert_fail(const char *expr, const char *file, int line)
{
char msg[256];
snprintf(msg,256,"Assertion failed: %s:%d; (%s)",file,line,expr);