#include "set_error.h"
extern "C" {
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
}
class err_buffer {
public:
char errmsg1[1024];
char errmsg2[1024];
char * errmsg;
char * errmsgb;
short errmsglen;
pid_t pid;
inline err_buffer(pid_t processid) :
errmsg(errmsg1), errmsgb(errmsg2), errmsglen(0), pid(processid) {};
inline ~err_buffer(void) {};
};
// static Semaphore sema;
static char supress_autodisp = 0;
static char supress_error = 0;
static char autoinit = -1;
extern "C" void AutoDispOff(void) {
supress_autodisp = -1;
}
#define max_erbu 10
static err_buffer * erbus[max_erbu];
static err_buffer * FindErBu(void) {
pid_t me = getpid();
{
err_buffer ** e = erbus;
short x = max_erbu-1;
do {
if (*e) {
if ( (*e)->pid == me) return *e;
}
e++;
} while (x--);
}
// kein erbu gefunden, also neuen allokieren...
err_buffer ** e = erbus;
short x = max_erbu-1;
do {
if ( *e == 0 ) break;
e++;
} while (x--);
if (x < 0) return 0; // mehr prozesse geht nicht
supress_error = -1;
*e = new err_buffer(me);
supress_error = 0;
return *e; // kann null sein -> fehler
}
static void internal_disp_error(err_buffer * eb);
static void internal_add_error(err_buffer * eb, const char * msg1, const char * msg2);
static void autodisp(err_buffer * eb) {
if (supress_autodisp) return;
// sema.Obtain();
if (eb->errmsglen != 0) {
internal_add_error(eb, "The error-handler detected an untreated malfunction. This might\n",
"be harmless, but if the program should crash, please remember\n"
"the following error-message for your bug-report");
internal_disp_error(eb);
}
// sema.Release();
}
static void DelErBus(void) {
err_buffer ** e = erbus;
short x = max_erbu-1;
do {
if ( *e ) {
autodisp(*e);
delete *e;
*e = 0;
}
e++;
} while (x--);
}
static void close_down(void) {
DelErBus();
}
static void come_up(void) {
autoinit = 0;
err_buffer ** e = erbus;
short x = max_erbu-1;
do {
*e++ = 0;
} while (x--);
atexit(close_down);
}
static void internal_add_error(err_buffer * eb, const char * msg1, const char * msg2) {
char * m = eb->errmsgb;
const char * o = msg1;
short x;
for (x = 0; x < 1024-4; x++) {
if (0 == (*m++ = *o++)) break;
}
m--;
o = msg2;
for (; x < 1024-4; x++) {
if (0 == (*m++ = *o++)) break;
}
if (eb->errmsglen != 0) {
m--;
o = ", reason:\n ";
for (; x < 1024-4; x++) {
if (0 == (*m++ = *o++)) break;
}
m--;
o = eb->errmsg;
for (; x < 1024-4; x++) {
if (0 == (*m++ = *o++)) break;
}
}
else {
m--;
if (x < 1024-4) {
*m++ = 10;
x++;
}
}
eb->errmsglen = x;
char * t = eb->errmsg;
eb->errmsg = eb->errmsgb;
eb->errmsgb = t;
eb->errmsg[eb->errmsglen] = 0;
}
static char * internal_get_error(err_buffer * eb) {
eb->errmsg[eb->errmsglen] = 0;
eb->errmsglen = 0;
return eb->errmsg;
}
static void internal_disp_error(err_buffer * eb) {
fprintf(stderr, "MALFUNCTION:\n%s",internal_get_error(eb));
}
extern "C" void set_error(const char * msg1, const char * msg2) {
if (supress_error) return;
// sema.Obtain();
if (autoinit) {
come_up();
}
err_buffer * eb = FindErBu();
if (!eb) {
// sema.Release();
return;
}
if (eb->errmsglen) {
autodisp(eb);
}
char * m = eb->errmsg;
const char * o = msg1;
short x;
for (x = 0; x < 1024-4; x++) {
if (0 == (*m++ = *o++)) break;
}
m--;
o = msg2;
for (; x < 1024-4; x++) {
if (0 == (*m++ = *o++)) break;
}
m--;
if (x < 1024-4) {
*m++ = 10;
x++;
}
eb->errmsglen = x;
eb->errmsg[eb->errmsglen] = 0;
// sema.Release();
}
extern "C" void add_error(const char * msg1, const char * msg2) {
if (supress_error) return;
// sema.Obtain();
if (autoinit) {
come_up();
}
err_buffer * eb = FindErBu();
if (!eb) {
// sema.Release();
return;
}
internal_add_error(eb, msg1, msg2);
// sema.Release();
}
extern "C" char * get_error(void) {
// sema.Obtain();
if (autoinit) {
come_up();
}
err_buffer * eb = FindErBu();
if (!eb) {
// sema.Release();
return "**FATAL** error handler malfunction";
}
eb->errmsg[eb->errmsglen] = 0;
eb->errmsglen = 0;
// sema.Release();
return eb->errmsg;
}
extern "C" int test_error(void) {
// sema.Obtain();
if (autoinit) {
come_up();
}
err_buffer * eb = FindErBu();
if (!eb) {
// sema.Release();
return 0;
}
// sema.Release();
if (eb->errmsglen) return -1;
return 0;
}
extern "C" void disp_error(void) {
// sema.Obtain();
if (autoinit) {
come_up();
}
err_buffer * eb = FindErBu();
if (!eb) {
// sema.Release();
return;
}
internal_disp_error(eb);
// sema.Release();
}
syntax highlighted by Code2HTML, v. 0.9.1