Fix compilation with old g++ 3.3.5 and debian-sarge.
[wvstreams.git] / utils / wvcrashbase.cc
blob3b839593dcf9130014ebead864fc53d7166266ab
1 /*
2 * Worldvisions Weaver Software:
3 * Copyright (C) 2005 Net Integration Technologies, Inc.
5 * Routines to save messages that can be logged when a program crashes.
6 */
7 #include "wvcrash.h"
9 #include <errno.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
14 IWvStream *WvCrashInfo::in_stream = NULL;
15 const char *WvCrashInfo::in_stream_id = NULL;
16 enum WvCrashInfo::InStreamState WvCrashInfo::in_stream_state = UNUSED;
18 // FIXME: this file mostly only works in Linux
19 #ifdef __linux
21 #ifdef __USE_GNU
22 static const char *argv0 = program_invocation_short_name;
23 #else
24 static const char *argv0 = "UNKNOWN";
25 #endif // __USE_GNU
27 // Reserve enough buffer for a screenful of programme.
28 static const int buffer_size = 2048;
29 static char will_msg[buffer_size];
30 static char assert_msg[buffer_size];
32 static const int ring_buffer_order = wvcrash_ring_buffer_order;
33 static const int ring_buffer_size = wvcrash_ring_buffer_size;
34 static const int ring_buffer_mask = ring_buffer_size - 1;
35 static char ring_buffer[ring_buffer_size+1];
36 static int ring_buffer_start = 0, ring_buffer_used = 0;
38 extern "C"
40 // Support assert().
41 void __assert_fail(const char *__assertion, const char *__file,
42 unsigned int __line, const char *__function)
44 // Set the assert message that WvCrash will dump.
45 snprintf(assert_msg, buffer_size,
46 "%s: %s:%u: %s: Assertion `%s' failed.\n",
47 argv0, __file, __line, __function, __assertion);
48 assert_msg[buffer_size - 1] = '\0';
50 // Emulate the GNU C library's __assert_fail().
51 fprintf(stderr, "%s: %s:%u: %s: Assertion `%s' failed.\n",
52 argv0, __file, __line, __function, __assertion);
53 abort();
57 // Wrapper for standards compliance.
58 void __assert(const char *__assertion, const char *__file,
59 unsigned int __line, const char *__function)
61 __assert_fail(__assertion, __file, __line, __function);
65 // Support the GNU assert_perror() extension.
66 void __assert_perror_fail(int __errnum, const char *__file,
67 unsigned int __line, const char *__function)
69 // Set the assert message that WvCrash will dump.
70 snprintf(assert_msg, buffer_size,
71 "%s: %s:%u: %s: Unexpected error: %s.\n",
72 argv0, __file, __line, __function, strerror(__errnum));
73 assert_msg[buffer_size - 1] = '\0';
75 // Emulate the GNU C library's __assert_perror_fail().
76 fprintf(stderr, "%s: %s:%u: %s: Unexpected error: %s.\n",
77 argv0, __file, __line, __function, strerror(__errnum));
78 abort();
80 } // extern "C"
83 // This function is meant to support people who wish to leave a last will
84 // and testament in the WvCrash.
85 void wvcrash_leave_will(const char *will)
87 if (will)
89 strncpy(will_msg, will, buffer_size);
90 will_msg[buffer_size - 1] = '\0';
92 else
93 will_msg[0] = '\0';
97 const char *wvcrash_read_will()
99 return will_msg;
103 const char *wvcrash_read_assert()
105 return assert_msg;
109 void wvcrash_ring_buffer_put(const char *str)
111 wvcrash_ring_buffer_put(str, strlen(str));
115 void wvcrash_ring_buffer_put(const char *str, size_t len)
117 while (len > 0)
119 int pos = (ring_buffer_start + ring_buffer_used) & ring_buffer_mask;
120 ring_buffer[pos] = *str++;
121 --len;
122 if (ring_buffer_used == ring_buffer_size)
123 ring_buffer_start = (ring_buffer_start + 1) & ring_buffer_mask;
124 else
125 ++ring_buffer_used;
130 const char *wvcrash_ring_buffer_get()
132 if (ring_buffer_used == 0)
133 return NULL;
134 const char *result;
135 if (ring_buffer_start + ring_buffer_used >= ring_buffer_size)
137 ring_buffer[ring_buffer_size] = '\0';
138 result = &ring_buffer[ring_buffer_start];
139 ring_buffer_used -= ring_buffer_size - ring_buffer_start;
140 ring_buffer_start = 0;
142 else
144 ring_buffer[ring_buffer_start + ring_buffer_used] = '\0';
145 result = &ring_buffer[ring_buffer_start];
146 ring_buffer_start += ring_buffer_used;
147 ring_buffer_used = 0;
149 return result;
153 void __wvcrash_init_buffers(const char *program_name)
155 if (program_name)
156 argv0 = program_name;
157 will_msg[0] = '\0';
158 assert_msg[0] = '\0';
162 #else // __linux
164 void wvcrash_leave_will(const char *will) {}
165 const char *wvcrash_read_will() { return NULL; }
167 #endif // __linux