Switch to side-by-side view

--- a
+++ b/src/utils/debuglog.cpp
@@ -0,0 +1,393 @@
+#ifndef lint
+static char rcsid [] = "@(#$Id: debuglog.cpp,v 1.1 2005-11-12 14:24:33 dockes Exp $  (C) 2002 OKYZ";
+#endif
+#ifndef TEST_DEBUGLOG
+
+#define __USE_GNU
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef INCLUDE_NEW_H
+#include <new.h>
+#endif
+
+#include <stack>
+
+#include "debuglog.h"
+
+#ifndef freeZ 
+#define freeZ(X) {if (X) {free(X);X=0;}}
+#endif
+
+#ifndef NO_NAMESPACES
+using namespace std;
+namespace DebugLog {
+
+#endif // NO_NAMESPACES
+
+class DebugLogWriter {
+  public:
+    virtual ~DebugLogWriter() {}
+    virtual int put(const char *s) = 0;
+};
+
+class DLFWImpl;
+class DebugLogFileWriter : public DebugLogWriter {
+    DLFWImpl *impl;
+  public:
+    DebugLogFileWriter();
+    ~DebugLogFileWriter();
+    virtual const char *getfilename();
+    virtual int setfilename(const char *fname, int trnc = 1);
+    virtual int put(const char *s);
+};
+
+class DLFWImpl {
+    char *filename;
+    FILE *fp;
+    int truncate;
+ public:
+    // Open output file if needed, return 0 if ok
+    void maybeopenfp() {
+	if (fp)
+	    return;
+	if (filename == 0)
+	    return;
+	if (!strcmp(filename, "stdout")) {
+	    fp = stdout;
+	} else if (!strcmp(filename, "stderr")) {
+	    fp = stderr;
+	} else {
+	    fp = fopen(filename, (truncate) ? "w" : "a");
+	    if (fp)
+		setvbuf(fp, 0, _IOLBF, 0);
+	}
+	return;
+    }
+
+    void maybeclosefp() { 
+#ifdef DEBUGDEBUG
+	fprintf(stderr, "DebugLogImpl::maybeclosefp: filename %p, fp %p\n",
+		filename, fp);
+#endif
+	// Close current file if open, and not stdout/stderr
+	if (fp && (filename == 0 || 
+		   (strcmp(filename, "stdout") && 
+		    strcmp(filename, "stderr")))) {
+	    fclose(fp);
+	}
+	fp = 0; 
+	freeZ(filename);
+    }
+
+ public:
+
+    DLFWImpl() : filename(0), fp(0), truncate(1) {
+	setfilename("stderr", 0);
+    }
+    ~DLFWImpl() { 
+	maybeclosefp();
+    }
+    int setfilename(const char *fn, int trnc) {
+	maybeclosefp();
+	filename = strdup(fn);
+	truncate = trnc;
+	return 0;
+    }
+    const char *getfilename() {
+	return filename;
+    }
+    int put(const char *s) {
+	maybeopenfp();
+	if (fp)
+	    return fputs(s, fp);
+	return -1;
+    }
+};
+
+DebugLogFileWriter::DebugLogFileWriter()
+{
+    impl = new DLFWImpl;
+}
+
+DebugLogFileWriter::~DebugLogFileWriter() 
+{ 
+    delete impl;
+}
+
+int DebugLogFileWriter::setfilename(const char *fn, int trnc) {
+    return impl ? impl->setfilename(fn, trnc) : -1;
+}
+
+const char *DebugLogFileWriter::getfilename() 
+{
+    return impl ? impl->getfilename() : 0;
+}
+
+int DebugLogFileWriter::put(const char *s) 
+{
+    return impl ? impl->put(s) : -1;
+};
+
+
+
+#ifdef _WINDOWS
+#include <windows.h>
+static void datestring(char *d) {
+    SYSTEMTIME buf;
+    GetLocalTime(&buf);
+    int year = buf.wYear % 100;
+
+    sprintf(d, "%02d%02d%02d%02d%02d%02d", year, int(buf.wMonth),
+	    int(buf.wDay), int(buf.wHour), int(buf.wMinute), int(buf.wSecond));
+}
+#define vsnprintf _vsnprintf
+
+#else // !WINDOWS ->
+
+#include <time.h>
+static void datestring(char *d)
+{
+    struct tm *tmp;
+    time_t tim = time((time_t)0);
+    tmp = localtime(&tim);
+    int year = tmp->tm_year % 100;
+    sprintf(d, "%02d%02d%02d%02d%02d%02d", year, tmp->tm_mon+1,
+	    tmp->tm_mday, tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
+}
+
+#endif // !WINDOWS
+
+void 
+DebugLog::prolog(int lev, const char *f, int line) 
+{
+    if (!writer)
+	return;
+    if (dodate) {
+	char dts[100];
+	datestring(dts);
+	writer->put(dts);
+    }
+    char buf[100];
+    sprintf(buf, ":%d:", lev);
+    writer->put(buf);
+#if DEBUGLOG_USE_THREADS
+    sprintf(buf, "%lx:", (unsigned long)pthread_self());
+    writer->put(buf);
+#endif
+    writer->put(f);
+    sprintf(buf, ":%d:", line);
+    writer->put(buf);
+}
+
+void 
+DebugLog::log(const char *s ...)
+{
+    if (!writer)
+	return;
+    va_list ap;
+    va_start(ap,s);
+
+#ifdef HAVE_VASPRINTF_nono // not sure vasprintf is really such a great idea
+    char *buf;
+    vasprintf(&buf, s, ap);
+    if (buf) {
+#else
+    char buf[4096];
+    // It's possible that they also wouldn't have vsnprintf but what then ?
+    vsnprintf(buf, 4096, s, ap);
+    {
+#endif
+	writer->put(buf);
+    }
+
+#ifdef HAVE_VASPRINTF_nono
+    if (buf)
+	free(buf);
+#endif
+}
+
+void 
+DebugLog::setloglevel(int lev)
+{
+    debuglevel = lev;
+    while (!levels.empty())
+	levels.pop();
+    pushlevel(lev);
+}
+
+void DebugLog::pushlevel(int lev)
+{
+    debuglevel = lev;
+    levels.push(lev);
+}
+
+void DebugLog::poplevel()
+{
+    if (levels.empty()) 
+	debuglevel = 0;
+    if (levels.size() > 1)
+	levels.pop();
+    debuglevel =  levels.top();
+}
+
+
+////////////////////////////////////////////////////////////
+// Global functions
+//////////////////////////////////////
+static DebugLogFileWriter lwriter;
+static DebugLogFileWriter *theWriter = &lwriter;
+const char *getfilename() 
+{
+    return theWriter ? theWriter->getfilename() : 0;
+}
+int setfilename(const char *fname, int trnc)
+{
+    return theWriter ? theWriter->setfilename(fname, trnc) : -1;
+}
+
+#if DEBUGLOG_USE_THREADS
+#include <pthread.h>
+static pthread_key_t dbl_key;
+static pthread_once_t key_once = PTHREAD_ONCE_INIT;
+
+static void thrdatadel(void *data)
+{
+    //    fprintf(stderr, "DebugLog:: thrdatadel: %p\n", data);
+    DebugLog *dbl = (DebugLog *)data;
+    delete dbl;
+    pthread_setspecific(dbl_key, 0);
+}
+static void once_routine(void)
+{
+    int status;
+    status = pthread_key_create(&dbl_key, thrdatadel);
+    if (status != 0) {
+	fprintf(stderr, "debuglog: cant initialize pthread "
+		"thread private storage key\n");
+	abort();
+    }
+}
+
+DebugLog *getdbl() 
+{
+    int status = pthread_once(&key_once, once_routine);
+    if (status != 0) {
+	fprintf(stderr, "debuglog: cant initialize pthread "
+		"thread private storage key (pthread_once)\n");
+	abort();
+    }
+    DebugLog *dbl;
+    if (!(dbl = (DebugLog *)pthread_getspecific(dbl_key))) {
+	dbl = new DebugLog;
+	dbl->setwriter(theWriter);
+	status = pthread_setspecific(dbl_key, dbl);
+	if (status) {
+	    fprintf(stderr, "debuglog: cant initialize pthread "
+		    "thread private storage key (pthread_setspecific)\n");
+	    abort();
+	}
+    }
+    return dbl;
+}
+
+#else // No threads ->
+
+static DebugLog *dbl;
+DebugLog *getdbl() 
+{
+    if (!dbl) {
+	dbl = new DebugLog;
+	dbl->setwriter(theWriter);
+    }
+    return dbl;
+}
+#endif
+
+#ifndef NO_NAMESPACES
+}
+#endif // NO_NAMESPACES
+
+////////////////////////////////////////// TEST DRIVER //////////////////
+#else /* TEST_DEBUGLOG */
+
+#include <stdio.h>
+#include "debuglog.h"
+
+#if DEBUGLOG_USE_THREADS
+#define TEST_THREADS
+#endif
+
+#ifdef TEST_THREADS 
+#include <pthread.h>
+#endif
+
+const int iloop = 5;
+void *thread_test(void *data)
+{
+    const char *s = (const char *)data;
+    int lev = atoi(s);
+    DebugLog::getdbl()->setloglevel(DEBDEB);
+    for (int i = 1; i < iloop;i++) {
+	switch (lev) {
+	case 1:	LOGFATAL(("Thread: %s count: %d\n", s, i));break;
+	case 2:	LOGERR(("Thread: %s count: %d\n", s, i));break;
+	default:
+	case 3:	LOGINFO(("Thread: %s count: %d\n", s, i));break;
+	}
+	sleep(1);
+    }
+    return 0;
+}
+
+
+int
+main(int argc, char **argv)
+{
+#ifdef TEST_THREADS
+    pthread_t t1, t2, t3;
+
+    char name1[20];
+    strcpy(name1, "1");
+    pthread_create(&t1, 0, thread_test, name1);
+
+    char name2[20];
+    strcpy(name2, "2");
+    pthread_create(&t2, 0, thread_test, name2);
+
+    char name3[20];
+    strcpy(name3, "3");
+    pthread_create(&t3, 0, thread_test, name3);
+
+    DebugLog::getdbl()->setloglevel(DEBDEB);
+    for (int i = 1; i < iloop;i++) {
+	LOGINFO(("LOGGING FROM MAIN\n"));
+	sleep(1);
+    }
+    sleep(2);
+    exit(0);
+#else
+    LOGFATAL(("FATAL\n","Val"));
+    DebugLog::getdbl()->logdate(1);
+    LOGERR(("ERR\n","Val"));
+    LOGINFO(("INFO\n","Val"));
+    LOGDEB0(("DEBUG %s\n","valeur"));
+
+    int lev;
+    printf("Testing push. Initial level: %d\n", DebugLog::getdbl()->getlevel());
+    for (lev = 0; lev < 4;lev++) {
+	DebugLog::getdbl()->pushlevel(lev);
+	printf("Lev now %d\n", DebugLog::getdbl()->getlevel());
+    }
+    printf("Testing pop\n");
+    for (lev = 0; lev < 7;lev++) {
+	DebugLog::getdbl()->poplevel();
+	printf("Lev now %d\n", DebugLog::getdbl()->getlevel());
+    }
+#endif
+}
+
+
+#endif /* TEST_DEBUGLOG */