Hogwarts Wand Docs: ../server/ac_log.c

Wand Sourcecode: ../server/ac_log.c

//
// ac_log.c - debug logging
// 
// Copyright (C) 2006  Nathan (Acorn) Pooley
// 
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// version 2 as published by the Free Software Foundation.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License (gpl.txt) for more details. 
// 
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
// 
// You can contact the author, Nathan (Acorn) Pooley, by writing
// to Nathan (Acorn) Pooley, 949 Buckeye Drive, Sunnyvale, CA  94086, USA
// or through the form at http://www.rawbw.com/~acorn/wand/feedback.html
//

//#@DOC@ debug logging functions

//###########################################################################
//############################### INCLUDES ##################################
//###########################################################################

#include "ac_log.h"

#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

//###########################################################################
//############################### DEFINES ###################################
//###########################################################################

#define DEFAULT_FILENAME    "log.txt"

//###########################################################################
//############################### TYPEDEFS ##################################
//###########################################################################

struct AcLogRec {
    char *filename;
    FILE *fp;
    int  source;
    char **sourceNames;
    int  sourceCnt;

    int debugLevel;
    int lastPrintSource;
    int lastPrintLevel;
    int lastPrintCr;

    int lastLogSource;
    int lastLogCr;
    char *prompt;
};

//###########################################################################
//############################### PROTOTYPES ################################
//###########################################################################

//###########################################################################
//############################### GLOBALS ###################################
//###########################################################################

static AcLog g_default_log;

//###########################################################################
//############################### CODE ######################################
//###########################################################################

//===========================================================================
// AcLogFlush()
//===========================================================================
void AcLogFlush(AcLog *li)
{
    if (!li) li = &g_default_log;
    if (li && li->fp) {
        fflush(li->fp);
    }
}

//===========================================================================
// AcLogDestroy()
//===========================================================================
void AcLogDestroy(AcLog *li)
{
    if (!li && g_default_log.fp) li = &g_default_log;

    if (li->fp) {
        fflush(li->fp);
        fclose(li->fp);
        li->fp = 0;
    }
    if (li->sourceNames) {
        int i;
        for (i=0; i<li->sourceCnt; i++) {
            if (li->sourceNames[i]) {
                free(li->sourceNames[i]);
            }
        }
        free(li->sourceNames);
        li->sourceNames = 0;
    }
    if (&g_default_log == li) {
        return;
    }
    if (li->filename) {
        free(li->filename);
    }
    if (li->prompt) {
        free(li->prompt);
    }
    free(li);
}

//===========================================================================
// AcLogCreate()
//===========================================================================
AcLog *AcLogCreate(char *filename, int append, int isdefault)
{
    AcLog *li;

    if (!filename) {
        li = &g_default_log;
        if (!li->filename) {
            li->filename = strdup(DEFAULT_FILENAME);
        } else if (li->fp && li->sourceNames && isdefault) {
            return li;
        }
        isdefault = 1;
    } else if (g_default_log.filename && 
        !strcmp(g_default_log.filename, filename)) {
        li = &g_default_log;
        isdefault = 1;
    } else {
        if (isdefault) {
            li = &g_default_log;
        } else {
            li = calloc(1,sizeof(AcLog));
        }
        if (li->filename) {
            if (li->fp && strcmp(filename,li->filename)) {
                fclose(li->fp);
                li->fp = 0;
            }
            free(li->filename);
        }
        li->filename = strdup(filename);
    }

    if (!li->fp) {
        if (append) {
            li->fp = fopen(li->filename,"a");
        } else {
            li->fp = fopen(li->filename,"w");
        }

        if (!li->fp) {
            fprintf(stderr,"AcLogCreate: Could not write %s\n",filename);
            return 0;
        }
        li->source = -1;
    }

    if (!li->sourceNames) {
        li->sourceNames = malloc(sizeof(char*));
        li->sourceCnt = 1;
        li->sourceNames[0] = strdup("default");
    }

    fprintf(li->fp,"\n======================= Begin log %s\n",li->filename);

    li->lastLogSource = -1;
    li->lastLogCr = 1;
    li->lastPrintSource = -1;
    li->lastPrintLevel  = -1;
    li->lastPrintCr  = 1;
    li->prompt = strdup("> ");

    return li;
}

//===========================================================================
// AcLogSetDebugLevel()
//===========================================================================
void AcLogSetDebugLevel(AcLog *li, int val)
{
    li->debugLevel = val;
}

//===========================================================================
// AcLogCreateSource()
//===========================================================================
int AcLogCreateSource(AcLog *li, const char *name)
{
    char **list;

    if (!li) {
        li = AcLogCreate(0,1,1);
        if (!li || !li->sourceNames) {
            return 0;
        }
    }

    list = realloc(li->sourceNames,sizeof(char*)*(li->sourceCnt + 1));
    if (!list) return 0;
    li->sourceNames = list;
    list[li->sourceCnt] = strdup(name);
    return li->sourceCnt++;
}

//===========================================================================
// AcLogWrite()
//===========================================================================
void AcLogWrite(AcLog *li, int source, const char *buf, unsigned int cnt)
{
    char *sname = 0;
    char buf7[1000];
    char buf8[1000];
    char buf9[1000];
    char *p7 = buf7;
    char *p8 = buf8;
    char *p9 = buf9;
    int i = 0;

    if (!li) {
        li = AcLogCreate(0,1,1);
        if (!li) {
            return;
        }
    }
    if (!li->fp) {
        return;
    }

    if (source >= 0 && source<li->sourceCnt) {
        sname = li->sourceNames[source];
    }

    //
    // sources with names not beginning '+' print normally (no ascii hex)
    //
    if (sname && sname[0] && sname[0]!='+') {
        if (!cnt) return;
        if (li->lastLogSource != source) {
            if (!li->lastLogCr) {
                fprintf(li->fp,"\n");
            }
            fprintf(li->fp,"#### Source %3d %s\n",
                source,
                sname?sname:"");
        }
        fprintf(li->fp,"%s",buf);
        if (buf[cnt-1] == '\n') {
            li->lastLogCr = 1;
        } else {
            li->lastLogCr = 0;
        }
        li->lastLogSource = source;
        return;
    }

    if (!li->lastLogCr) {
        fprintf(li->fp,"\n");
    }

    fprintf(li->fp,"#### Source %3d %s\n",
        source,
        sname?sname:"");

    li->lastLogSource = source;
    li->lastLogCr = 1;

    while(1) {
        int c;

        if (i>=cnt || (i&0x7)==0) {
            if (p7!=buf7) {
                fprintf(li->fp,"  %-42s  %-8s   %s\n",buf7,buf8,buf9);
                p7 = buf7;
                p8 = buf8;
                p9 = buf9;
            }
            if (i>=cnt) break;
        }

        c = buf[i];

        if (c<' ' || c>'}' || c=='\\') {
            p9 += sprintf(p9,"\\%02x",((unsigned char*)buf)[i]);
        } else {
            p9 += sprintf(p9,"%c",c);
        }
        if (c<=' ' || c>'}') c = '.';
        p7 += sprintf(p7,"0x%02x ",((unsigned char*)buf)[i]);
        p8 += sprintf(p8,"%c",c);
        i++;
    }
}

//===========================================================================
// AcLogPrintf()
//===========================================================================
int AcLogPrintf(AcLog *li, int source, const char *fmt, ...)
{
    int cnt;
    va_list va;
    char buf[1000];
    char *bufp = buf;
    int printLevel = 1000;

    if (!li) {
        li = AcLogCreate(0,1,1);
        if (!li) {
            return 0;
        }
    }

    va_start(va, fmt);
    cnt = vsnprintf(buf,sizeof(buf)-1,fmt,va);
    va_end(va);

    if (cnt>1 && buf[1]==':') {
        int val = buf[0];
        if (isdigit(val)) {
            val = val - '0';
        } else if (islower(val)) {
            val = val - 'a' + 10;
        } else if (isupper(val)) {
            val = val - 'A' + 10 + 26;
        } else {
            val = -1;
        }
        if (val >= 0) {
            printLevel = val;
            bufp = buf+2;
            cnt -= 2;
        }
    }

    if (!cnt) return 0;

    if (printLevel <= li->debugLevel) {
        if (li->lastPrintCr == 0 &&
            (li->lastPrintSource != source ||
             li->lastPrintLevel  != printLevel)) {
            printf("\n");
        }
        printf("%s",bufp);
        if (bufp[cnt-1] == '\n') {
            li->lastPrintCr = 1;
        } else {
            li->lastPrintCr = 0;
        }
        li->lastPrintSource = source;
        li->lastPrintLevel  = printLevel;
    }

    AcLogWrite(li,source,bufp,cnt);
    return cnt;
}

//===========================================================================
// AcLogPrompt()
//===========================================================================
//
// Print prompt.
// If prompt is NULL then print last prompt.
// force:
//     1 = always print prompt
//     0 = only print prompt if something was printed since last one, or
//            if string has changed.
//    -1 = do not print prompt (just set it)
//    -2 = do not print prompt, but do print next time called with force=0
//
void AcLogPrompt(AcLog *li, char *prompt, int force)
{
    if (!li) {
        li = AcLogCreate(0,1,1);
        if (!li) {
            printf("\n%s",prompt?prompt:"> ");
        }
    }

    if (prompt && strcmp(prompt,li->prompt)) {
        free(li->prompt);
        li->prompt = strdup(prompt);
        if (force == 0) force = 1;
    }

    if (force == -2) {
        if (li->lastPrintLevel == -2) {
            li->lastPrintLevel = -1;
        }
        return;
    }

    //
    // printlevel -2 indicates prompt
    //
    if (force==0 && li->lastPrintLevel != -2) {
        force = 1;
    }

    if (force > 0) {
        if (li->lastPrintCr == 0) {
            printf("\n");
        }
        printf("%s",li->prompt);
        fflush(stdout);
        li->lastPrintCr = 0;
        li->lastPrintLevel = -2;
    }
}


This file Copyright (C) 2006 by Nathan (Acorn) Pooley
Go to TOP Wand page
Go to Acorn's personal webpage
Go to Hogwarts website: www.gotohogwarts.com
Snout: www.snout.org/game
Gadgets of Justice Unlimited
Snout GC (Wiki)
Snout Wiki
File created by do_doc at Wed May 30 03:25:00 PDT 2007