00001
00002
00003
00004
00005
00006
00007 #include "wvcrash.h"
00008
00009 #include <errno.h>
00010 #include <stdio.h>
00011 #include <stdlib.h>
00012 #include <string.h>
00013
00014
00015 #ifdef __linux
00016
00017 #ifdef __USE_GNU
00018 static const char *argv0 = program_invocation_short_name;
00019 #else
00020 static const char *argv0 = "UNKNOWN";
00021 #endif // __USE_GNU
00022
00023
00024 static const int buffer_size = 2048;
00025 static char will_msg[buffer_size];
00026 static char assert_msg[buffer_size];
00027
00028 static const int ring_buffer_order = wvcrash_ring_buffer_order;
00029 static const int ring_buffer_size = wvcrash_ring_buffer_size;
00030 static const int ring_buffer_mask = ring_buffer_size - 1;
00031 static char ring_buffer[ring_buffer_size+1];
00032 static int ring_buffer_start = 0, ring_buffer_used = 0;
00033
00034 extern "C"
00035 {
00036
00037 void __assert_fail(const char *__assertion, const char *__file,
00038 unsigned int __line, const char *__function)
00039 {
00040
00041 snprintf(assert_msg, buffer_size,
00042 "%s: %s:%u: %s: Assertion `%s' failed.\n",
00043 argv0, __file, __line, __function, __assertion);
00044 assert_msg[buffer_size - 1] = '\0';
00045
00046
00047 fprintf(stderr, "%s: %s:%u: %s: Assertion `%s' failed.\n",
00048 argv0, __file, __line, __function, __assertion);
00049 abort();
00050 }
00051
00052
00053
00054 void __assert(const char *__assertion, const char *__file,
00055 unsigned int __line, const char *__function)
00056 {
00057 __assert_fail(__assertion, __file, __line, __function);
00058 }
00059
00060
00061
00062 void __assert_perror_fail(int __errnum, const char *__file,
00063 unsigned int __line, const char *__function)
00064 {
00065
00066 snprintf(assert_msg, buffer_size,
00067 "%s: %s:%u: %s: Unexpected error: %s.\n",
00068 argv0, __file, __line, __function, strerror(__errnum));
00069 assert_msg[buffer_size - 1] = '\0';
00070
00071
00072 fprintf(stderr, "%s: %s:%u: %s: Unexpected error: %s.\n",
00073 argv0, __file, __line, __function, strerror(__errnum));
00074 abort();
00075 }
00076 }
00077
00078
00079
00080
00081 void wvcrash_leave_will(const char *will)
00082 {
00083 if (will)
00084 {
00085 strncpy(will_msg, will, buffer_size);
00086 will_msg[buffer_size - 1] = '\0';
00087 }
00088 else
00089 will_msg[0] = '\0';
00090 }
00091
00092
00093 const char *wvcrash_read_will()
00094 {
00095 return will_msg;
00096 }
00097
00098
00099 const char *wvcrash_read_assert()
00100 {
00101 return assert_msg;
00102 }
00103
00104
00105 void wvcrash_ring_buffer_put(const char *str)
00106 {
00107 wvcrash_ring_buffer_put(str, strlen(str));
00108 }
00109
00110
00111 void wvcrash_ring_buffer_put(const char *str, size_t len)
00112 {
00113 while (len > 0)
00114 {
00115 int pos = (ring_buffer_start + ring_buffer_used) & ring_buffer_mask;
00116 ring_buffer[pos] = *str++;
00117 --len;
00118 if (ring_buffer_used == ring_buffer_size)
00119 ring_buffer_start = (ring_buffer_start + 1) & ring_buffer_mask;
00120 else
00121 ++ring_buffer_used;
00122 }
00123 }
00124
00125
00126 const char *wvcrash_ring_buffer_get()
00127 {
00128 if (ring_buffer_used == 0)
00129 return NULL;
00130 const char *result;
00131 if (ring_buffer_start + ring_buffer_used >= ring_buffer_size)
00132 {
00133 ring_buffer[ring_buffer_size] = '\0';
00134 result = &ring_buffer[ring_buffer_start];
00135 ring_buffer_used -= ring_buffer_size - ring_buffer_start;
00136 ring_buffer_start = 0;
00137 }
00138 else
00139 {
00140 ring_buffer[ring_buffer_start + ring_buffer_used] = '\0';
00141 result = &ring_buffer[ring_buffer_start];
00142 ring_buffer_start += ring_buffer_used;
00143 ring_buffer_used = 0;
00144 }
00145 return result;
00146 }
00147
00148
00149 void __wvcrash_init_buffers(const char *program_name)
00150 {
00151 if (program_name)
00152 argv0 = program_name;
00153 will_msg[0] = '\0';
00154 assert_msg[0] = '\0';
00155 }
00156
00157
00158 #else // __linux
00159
00160 void wvcrash_leave_will(const char *will) {}
00161 const char *wvcrash_read_will() { return NULL; }
00162
00163 #endif // __linux