view src/debug.c @ 386:f1f9920cc7b1

Add AM_GNU_GETTEXT macros AM_ICONV relies on config.rpath and autopoint/gettextize will only copy these in when the AM_GNU_GETTEXT macros are present. This is needed for the next commit that deletes config.rpath since it is cruft that should be copied in by autotools not embedded. Run autopoint to copy in config.rpath and leave it to automake to copy into the tarball.
author Paul Wise <pabs3@bonedaddy.net>
date Sat, 21 Dec 2019 21:25:44 +0800
parents 7a91e30826d8
children
line wrap: on
line source

#include "define.h"


struct pst_debug_func {
    char * name;
    struct pst_debug_func *next;
};


#define NUM_COL 32
#define MAX_DEPTH 32

static struct pst_debug_func *func_head = NULL;
static int func_depth = 0;
static int pst_debuglevel = 0;
static char indent[MAX_DEPTH*4+1];
static FILE *debug_fp = NULL;
#ifdef HAVE_SEMAPHORE_H
    static sem_t* debug_mutex = NULL;
#endif


void pst_debug_setlevel(int level)
{
  pst_debuglevel = level;
}

void pst_debug_lock()
{
    #ifdef HAVE_SEMAPHORE_H
        if (debug_mutex) sem_wait(debug_mutex);
    #endif
}


void pst_debug_unlock()
{
    #ifdef HAVE_SEMAPHORE_H
        if (debug_mutex) sem_post(debug_mutex);
    #endif
}


void pst_debug_init(const char* fname, void* output_mutex) {
    #ifdef HAVE_SEMAPHORE_H
        debug_mutex = (sem_t*)output_mutex;
    #endif
    memset(indent, ' ', MAX_DEPTH*4);
    indent[MAX_DEPTH*4] = '\0';
    if (debug_fp) pst_debug_close();
    if (!fname) return;
    if ((debug_fp = fopen(fname, "wb")) == NULL) {
        fprintf(stderr, "Opening of file %s failed\n", fname);
        exit(1);
    }
}


void pst_debug_func(int level, const char* function) {
    if (pst_debuglevel > level) return;
    struct pst_debug_func *func_ptr = pst_malloc (sizeof(struct pst_debug_func));
    func_ptr->name = strdup(function);
    func_ptr->next = func_head;
    func_head = func_ptr;
    func_depth++;
}


void pst_debug_func_ret(int level) {
    if (pst_debuglevel > level) return;
    //remove the head item
    struct pst_debug_func *func_ptr = func_head;
    if (func_head) {
        func_head = func_head->next;
        free(func_ptr->name);
        free(func_ptr);
        func_depth--;
    } else {
        DIE(("function list is empty!\n"));
    }
}


static void pst_debug_info(int level, int line, const char* file);
static void pst_debug_info(int level, int line, const char* file) {
    if (pst_debuglevel > level) return;
    int le = (func_depth > MAX_DEPTH) ? MAX_DEPTH : func_depth;
    if (le > 0) le--;
    char *func = (func_head ? func_head->name : "No Function");
    pst_debug_lock();
    fprintf(debug_fp, "%06d %.*s%s %s(%d) ", getpid(), le*4, indent, func, file, line);
}


void pst_debug(int level, int line, const char* file, const char *fmt, ...) {
    if (pst_debuglevel > level) return;
    if (debug_fp) {
        pst_debug_info(level, line, file);
        va_list ap;
        va_start(ap,fmt);
        vfprintf(debug_fp, fmt, ap);
        va_end(ap);
        fflush(debug_fp);
        pst_debug_unlock();
    }
}


void pst_debug_hexdump(int level, int line, const char *file, const char *buf, size_t size, int cols, int delta) {
    if (pst_debuglevel > level) return;
    if (debug_fp) {
        pst_debug_info(level, line, file);
        pst_debug_hexdumper(debug_fp, buf, size, cols, delta);
        pst_debug_unlock();
    }
}


void pst_debug_hexdumper(FILE *out, const char *buf, size_t size, int cols, int delta) {
    int le = (func_depth > MAX_DEPTH) ? MAX_DEPTH : func_depth;
    size_t off = 0, toff;
    int count = 0;

    if (!out) return;   // no file

    if (cols == -1) cols = NUM_COL;
    fprintf(out, "\n");
    while (off < size) {
        fprintf(out, "%06d %.*s%06"PRIx64"\t:", getpid(), le*4, indent, (int64_t)(off+delta));
        toff = off;
        while (count < cols && off < size) {
            fprintf(out, "%02hhx ", (unsigned char)buf[off]);
            off++; count++;
        }
        off = toff;
        while (count < cols) {
            // only happens at end of block to pad the text over to the text column
            fprintf(out, "   ");
            count++;
        }
        count = 0;
        fprintf(out, ":");
        while (count < cols && off < size) {
            fprintf(out, "%c", isgraph(buf[off])?buf[off]:'.');
            off++; count ++;
        }

        fprintf(out, "\n");
        count=0;
    }

    fprintf(out, "\n");
    fflush(out);
}


void pst_debug_close(void) {
    while (func_head) {
        struct pst_debug_func *func_ptr = func_head;
        func_head = func_head->next;
        free(func_ptr->name);
        free(func_ptr);
    }
    if (debug_fp) fclose(debug_fp);
    debug_fp = NULL;
}


void *pst_malloc(size_t size) {
    void *mem = malloc(size);
    if (!mem) {
        fprintf(stderr, "pst_malloc: Out Of memory [req: %ld]\n", (long)size);
        exit(1);
    }
    return mem;
}


void *pst_realloc(void *ptr, size_t size) {
    void *mem = realloc(ptr, size);
    if (!mem) {
        fprintf(stderr, "pst_realloc: Out Of memory [req: %ld]\n", (long)size);
        exit(1);
    }
    return mem;
}