X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Flibpspp%2Fmessage.c;h=e40b34c93c9a7b959ca03e06793b3d763f8f20bd;hb=5af2d8e4450d82bdb660de801e2a8961750442fa;hp=de3dab8df754efb40cd357ee1311cbc3223cb7a3;hpb=a353919df75c25331144602421353a856f4236d6;p=pspp diff --git a/src/libpspp/message.c b/src/libpspp/message.c index de3dab8df7..e40b34c93c 100644 --- a/src/libpspp/message.c +++ b/src/libpspp/message.c @@ -33,6 +33,7 @@ #include "gl/minmax.h" #include "gl/progname.h" +#include "gl/relocatable.h" #include "gl/xalloc.h" #include "gl/xvasprintf.h" @@ -267,24 +268,26 @@ msg_ui_any_errors (void) } -static int entrances = 0; - static void ship_message (struct msg *m) { - entrances++; - if ( ! m->shipped ) - { - if (msg_handler && entrances <= 1) - msg_handler (m, msg_aux); - else - { - fwrite (m->text, 1, strlen (m->text), stderr); - fwrite ("\n", 1, 1, stderr); - } - } - m->shipped = true; - entrances--; + enum { MAX_STACK = 4 }; + static struct msg *stack[MAX_STACK]; + static size_t n; + + /* If we're recursing on a given message, or recursing deeply, drop it. */ + if (n >= MAX_STACK) + return; + for (size_t i = 0; i < n; i++) + if (stack[i] == m) + return; + + stack[n++] = m; + if (msg_handler && n <= 1) + msg_handler (m, msg_aux); + else + fprintf (stderr, "%s\n", m->text); + n--; } static void @@ -309,7 +312,7 @@ process_msg (struct msg *m) if (too_many_errors || (too_many_notes && m->severity == MSG_S_NOTE) - || (warnings_off && m->severity == MSG_S_WARNING) ) + || (warnings_off && m->severity == MSG_S_WARNING)) return; ship_message (m); @@ -347,7 +350,6 @@ process_msg (struct msg *m) void msg_emit (struct msg *m) { - m->shipped = false; if (!messages_disabled) process_msg (m); @@ -375,28 +377,75 @@ msg_enable (void) /* Private functions. */ -void -request_bug_report (const char *msg) +static char fatal_error_message[1024]; +static int fatal_error_message_bytes = 0; + +static char diagnostic_information[1024]; +static int diagnostic_information_bytes = 0; + +static int +append_message (char *msg, int bytes_used, const char *fmt, ...) +{ + va_list va; + va_start (va, fmt); + int ret = vsnprintf (msg + bytes_used, 1024 - bytes_used, fmt, va); + va_end (va); + assert (ret >= 0); + + return ret; +} + + +/* Generate a row of asterisks held in statically allocated memory */ +static struct substring +generate_banner (void) +{ + static struct substring banner; + if (!banner.string) + banner = ss_cstr ("******************************************************\n"); + return banner; +} + +const char * +prepare_fatal_error_message (void) +{ + fatal_error_message_bytes += append_message (fatal_error_message, fatal_error_message_bytes, generate_banner ().string); + + fatal_error_message_bytes += append_message (fatal_error_message, fatal_error_message_bytes, "You have discovered a bug in PSPP. Please report this\n"); + fatal_error_message_bytes += append_message (fatal_error_message, fatal_error_message_bytes, "to " PACKAGE_BUGREPORT ". Please include this entire\n"); + fatal_error_message_bytes += append_message (fatal_error_message, fatal_error_message_bytes, "message, *plus* several lines of output just above it.\n"); + fatal_error_message_bytes += append_message (fatal_error_message, fatal_error_message_bytes, "For the best chance at having the bug fixed, also\n"); + fatal_error_message_bytes += append_message (fatal_error_message, fatal_error_message_bytes, "include the syntax file that triggered it and a sample\n"); + fatal_error_message_bytes += append_message (fatal_error_message, fatal_error_message_bytes, "of any data file used for input.\n"); + return fatal_error_message; +} + +const char * +prepare_diagnostic_information (void) { - fprintf (stderr, "******************************************************\n"); - fprintf (stderr, "You have discovered a bug in PSPP. Please report this\n"); - fprintf (stderr, "to " PACKAGE_BUGREPORT ". Please include this entire\n"); - fprintf (stderr, "message, *plus* several lines of output just above it.\n"); - fprintf (stderr, "For the best chance at having the bug fixed, also\n"); - fprintf (stderr, "include the syntax file that triggered it and a sample\n"); - fprintf (stderr, "of any data file used for input.\n"); - fprintf (stderr, "proximate cause: %s\n", msg); - fprintf (stderr, "version: %s\n", version); - fprintf (stderr, "host_system: %s\n", host_system); - fprintf (stderr, "build_system: %s\n", build_system); - fprintf (stderr, "locale_dir: %s\n", locale_dir); - fprintf (stderr, "compiler version: %s\n", + diagnostic_information_bytes += append_message (diagnostic_information, diagnostic_information_bytes, "version: %s\n", version); + diagnostic_information_bytes += append_message (diagnostic_information, diagnostic_information_bytes, "host_system: %s\n", host_system); + diagnostic_information_bytes += append_message (diagnostic_information, diagnostic_information_bytes, "build_system: %s\n", build_system); + diagnostic_information_bytes += append_message (diagnostic_information, diagnostic_information_bytes, "locale_dir: %s\n", relocate (locale_dir)); + diagnostic_information_bytes += append_message (diagnostic_information, diagnostic_information_bytes, "compiler version: %s\n", #ifdef __VERSION__ __VERSION__ #else "Unknown" #endif - ); - fprintf (stderr, "******************************************************\n"); +); + + return diagnostic_information; } +void +request_bug_report (const char *msg) +{ + write (STDERR_FILENO, fatal_error_message, fatal_error_message_bytes); + write (STDERR_FILENO, "proximate cause: ", 21); + write (STDERR_FILENO, msg, strlen (msg)); + write (STDERR_FILENO, "\n", 1); + write (STDERR_FILENO, diagnostic_information, diagnostic_information_bytes); + const struct substring banner = generate_banner (); + write (STDERR_FILENO, banner.string, banner.length); +}