Annotation of hatari/src/debug/log.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Hatari - log.c
        !             3:  *
        !             4:  * This file is distributed under the GNU Public License, version 2 or at
        !             5:  * your option any later version. Read the file gpl.txt for details.
        !             6:  *
        !             7:  * Logger functions.
        !             8:  *
        !             9:  * When Hatari runs, it can output information, debug, warning and error texts
        !            10:  * to the error log file and/or displays them in alert dialog boxes.
        !            11:  *
        !            12:  * It can also dynamically output trace messages, based on the content
        !            13:  * of LogTraceFlags. Multiple trace levels can be set at once, by setting
        !            14:  * the corresponding bits in LogTraceFlags.
        !            15:  */
        !            16: const char Log_fileid[] = "Hatari log.c : " __DATE__ " " __TIME__;
        !            17: 
        !            18: #include <stdio.h>
        !            19: #include <stdarg.h>
        !            20: #include <stdlib.h>
        !            21: #include <string.h>
        !            22: #include <ctype.h>
        !            23: 
        !            24: #include "main.h"
        !            25: #include "configuration.h"
        !            26: #include "dialog.h"
        !            27: #include "log.h"
        !            28: #include "screen.h"
        !            29: #include "file.h"
        !            30: 
        !            31: 
        !            32: static struct {
        !            33:        Uint32 Level;
        !            34:        const char *Name;
        !            35: }
        !            36: TraceOptions[] = {
        !            37:        { TRACE_NONE             , "none" },
        !            38: 
        !            39:        { TRACE_VIDEO_SYNC       , "video_sync" } ,
        !            40:        { TRACE_VIDEO_RES        , "video_res" } ,
        !            41:        { TRACE_VIDEO_COLOR      , "video_color" } ,
        !            42:        { TRACE_VIDEO_BORDER_V   , "video_border_v" } ,
        !            43:        { TRACE_VIDEO_BORDER_H   , "video_border_h" } ,
        !            44:        { TRACE_VIDEO_ADDR       , "video_addr" } ,
        !            45:        { TRACE_VIDEO_HBL        , "video_hbl" } ,
        !            46:        { TRACE_VIDEO_VBL        , "video_vbl" } ,
        !            47:        { TRACE_VIDEO_STE        , "video_ste" } ,
        !            48:        { TRACE_VIDEO_ALL        , "video_all" } ,
        !            49: 
        !            50:        { TRACE_MFP_EXCEPTION    , "mfp_exception" } ,
        !            51:        { TRACE_MFP_START        , "mfp_start" } ,
        !            52:        { TRACE_MFP_READ         , "mfp_read" } ,
        !            53:        { TRACE_MFP_WRITE        , "mfp_write" } ,
        !            54:        { TRACE_MFP_ALL          , "mfp_all" } ,
        !            55: 
        !            56:        { TRACE_PSG_READ         , "psg_read" } ,
        !            57:        { TRACE_PSG_WRITE        , "psg_write" } ,
        !            58:        { TRACE_PSG_ALL          , "psg_all" } ,
        !            59: 
        !            60:        { TRACE_CPU_PAIRING      , "cpu_pairing" } ,
        !            61:        { TRACE_CPU_DISASM       , "cpu_disasm" } ,
        !            62:        { TRACE_CPU_EXCEPTION    , "cpu_exception" } ,
        !            63:        { TRACE_CPU_ALL          , "cpu_all" } ,
        !            64: 
        !            65:        { TRACE_INT              , "int" } ,
        !            66: 
        !            67:        { TRACE_FDC              , "fdc" } ,
        !            68: 
        !            69:        { TRACE_IKBD_CMDS        , "ikbd_cmds" } ,
        !            70:        { TRACE_IKBD_ACIA        , "ikbd_acia" } ,
        !            71:        { TRACE_IKBD_EXEC        , "ikbd_exec" } ,
        !            72:        { TRACE_IKBD_ALL         , "ikbd_all" } ,
        !            73: 
        !            74:        { TRACE_BLITTER          , "blitter" } ,
        !            75: 
        !            76:        { TRACE_OS_BIOS          , "bios" },
        !            77:        { TRACE_OS_XBIOS         , "xbios" },
        !            78:        { TRACE_OS_GEMDOS        , "gemdos" },
        !            79:        { TRACE_OS_VDI           , "vdi" },
        !            80:        { TRACE_OS_ALL           , "os_all" } ,
        !            81: 
        !            82:        { TRACE_IOMEM_RD         , "io_read" } ,
        !            83:        { TRACE_IOMEM_WR         , "io_write" } ,
        !            84:        { TRACE_IOMEM_ALL        , "io_all" } ,
        !            85: 
        !            86:        { TRACE_DMASND           , "dmasound" } ,
        !            87: 
        !            88:        { TRACE_CROSSBAR         , "crossbar" } ,
        !            89: 
        !            90:        { TRACE_ALL              , "all" }
        !            91: };
        !            92: 
        !            93: 
        !            94: Uint32 LogTraceFlags = TRACE_NONE;
        !            95: FILE *TraceFile = NULL;
        !            96: 
        !            97: static FILE *hLogFile = NULL;
        !            98: static LOGTYPE TextLogLevel;
        !            99: static LOGTYPE AlertDlgLogLevel;
        !           100: 
        !           101: /*-----------------------------------------------------------------------*/
        !           102: /**
        !           103:  * Initialize the logging and tracing functionality (open the log files etc.).
        !           104:  * 
        !           105:  * Return zero if that fails.
        !           106:  */
        !           107: int Log_Init(void)
        !           108: {
        !           109:        TextLogLevel = ConfigureParams.Log.nTextLogLevel;
        !           110:        AlertDlgLogLevel = ConfigureParams.Log.nAlertDlgLogLevel;
        !           111: 
        !           112:        hLogFile = File_Open(ConfigureParams.Log.sLogFileName, "w");
        !           113:        TraceFile = File_Open(ConfigureParams.Log.sTraceFileName, "w");
        !           114:    
        !           115:        return (hLogFile && TraceFile);
        !           116: }
        !           117: 
        !           118: /**
        !           119:  * Set Alert log level temporarily without config change.
        !           120:  * 
        !           121:  * Return old level for restoring the original level with this.
        !           122:  */
        !           123: int Log_SetAlertLevel(int level)
        !           124: {
        !           125:        int old = AlertDlgLogLevel;
        !           126:        AlertDlgLogLevel = level;
        !           127:        return old;
        !           128: }
        !           129: 
        !           130: 
        !           131: /*-----------------------------------------------------------------------*/
        !           132: /**
        !           133:  * Un-Initialize - close log files etc.
        !           134:  */
        !           135: void Log_UnInit(void)
        !           136: {
        !           137:        hLogFile = File_Close(hLogFile);
        !           138:        TraceFile = File_Close(TraceFile);
        !           139: }
        !           140: 
        !           141: 
        !           142: /*-----------------------------------------------------------------------*/
        !           143: /**
        !           144:  * Output string to log file
        !           145:  */
        !           146: void Log_Printf(LOGTYPE nType, const char *psFormat, ...)
        !           147: {
        !           148:        va_list argptr;
        !           149: 
        !           150:        if (hLogFile && nType <= TextLogLevel)
        !           151:        {
        !           152:                va_start(argptr, psFormat);
        !           153:                vfprintf(hLogFile, psFormat, argptr);
        !           154:                va_end(argptr);
        !           155:                /* Add a new-line if necessary: */
        !           156:                if (psFormat[strlen(psFormat)-1] != '\n')
        !           157:                        fputs("\n", hLogFile);
        !           158:        }
        !           159: }
        !           160: 
        !           161: 
        !           162: /*-----------------------------------------------------------------------*/
        !           163: /**
        !           164:  * Show logging alert dialog box and output string to log file
        !           165:  */
        !           166: void Log_AlertDlg(LOGTYPE nType, const char *psFormat, ...)
        !           167: {
        !           168:        va_list argptr;
        !           169: 
        !           170:        /* Output to log file: */
        !           171:        if (hLogFile && nType <= TextLogLevel)
        !           172:        {
        !           173:                va_start(argptr, psFormat);
        !           174:                vfprintf(hLogFile, psFormat, argptr);
        !           175:                va_end(argptr);
        !           176:                /* Add a new-line if necessary: */
        !           177:                if (psFormat[strlen(psFormat)-1] != '\n')
        !           178:                        fputs("\n", hLogFile);
        !           179:        }
        !           180: 
        !           181:        /* Show alert dialog box: */
        !           182:        if (sdlscrn && nType <= AlertDlgLogLevel)
        !           183:        {
        !           184:                char *psTmpBuf;
        !           185:                psTmpBuf = malloc(2048);
        !           186:                if (!psTmpBuf)
        !           187:                {
        !           188:                        perror("Log_AlertDlg");
        !           189:                        return;
        !           190:                }
        !           191:                va_start(argptr, psFormat);
        !           192:                vsnprintf(psTmpBuf, 2048, psFormat, argptr);
        !           193:                va_end(argptr);
        !           194:                DlgAlert_Notice(psTmpBuf);
        !           195:                free(psTmpBuf);
        !           196:        }
        !           197: }
        !           198: 
        !           199: 
        !           200: /*-----------------------------------------------------------------------*/
        !           201: /**
        !           202:  * parse what log level should be used and return it
        !           203:  */
        !           204: LOGTYPE Log_ParseOptions(const char *arg)
        !           205: {
        !           206:        const char *levels[] = {
        !           207:                "fatal", "error", "warn", "info", "todo", "debug", NULL
        !           208:        };
        !           209:        LOGTYPE level = LOG_FATAL;
        !           210:        const char **level_str;
        !           211:        char *input, *str;
        !           212: 
        !           213:        input = strdup(arg);
        !           214:        str = input;
        !           215:        while (*str)
        !           216:        {
        !           217:                *str++ = tolower(*arg++);
        !           218:        }
        !           219:        for (level_str = levels; *level_str; level_str++, level++)
        !           220:        {
        !           221:                if (strcmp(input, *level_str) == 0)
        !           222:                {
        !           223:                        free(input);
        !           224:                        return level;
        !           225:                }
        !           226:        }
        !           227:        free(input);
        !           228:        return level;
        !           229: }
        !           230: 
        !           231: 
        !           232: #if ENABLE_TRACING
        !           233: 
        !           234: /*-----------------------------------------------------------------------*/
        !           235: /**
        !           236:  * Parse a list of comma separated strings.
        !           237:  * If the string is prefixed with an optional '+',
        !           238:  * corresponding trace flag is turned on.
        !           239:  * If the string is prefixed with a '-',
        !           240:  * corresponding trace flag is turned off.
        !           241:  * Result is stored in LogTraceFlags.
        !           242:  * Return error string (""=silent 'error') or NULL for success.
        !           243:  */
        !           244: const char* Log_SetTraceOptions (const char *OptionsStr)
        !           245: {
        !           246:        char *OptionsCopy;
        !           247:        char *cur, *sep;
        !           248:        int i;
        !           249:        int Mode;                               /* 0=add, 1=del */
        !           250:        int MaxOptions;
        !           251: 
        !           252:        MaxOptions = ARRAYSIZE(TraceOptions);
        !           253:        
        !           254:        /* special case for "help" : display the list of possible trace levels */
        !           255:        if (strcmp (OptionsStr, "help") == 0)
        !           256:        {
        !           257:                fprintf(stderr, "\nList of available trace levels :\n");
        !           258:                
        !           259:                for (i = 0; i < MaxOptions; i++)
        !           260:                        fprintf(stderr, "  %s\n", TraceOptions[i].Name);
        !           261:                
        !           262:                fprintf(stderr, "Multiple trace levels can be separated by ','\n");
        !           263:                fprintf(stderr, "Levels can be prefixed by '+' or '-' to be mixed.\n");
        !           264:                fprintf(stderr, "Giving just trace level 'none' disables all traces.\n\n");
        !           265:                return "";
        !           266:        }
        !           267:        
        !           268:        LogTraceFlags = TRACE_NONE;
        !           269:        if (strcmp (OptionsStr, "none") == 0)
        !           270:        {
        !           271:                return NULL;
        !           272:        }
        !           273:        
        !           274:        OptionsCopy = strdup(OptionsStr);
        !           275:        if (!OptionsCopy)
        !           276:        {
        !           277:                return "strdup error in ParseTraceOptions";
        !           278:        }
        !           279:        
        !           280:        cur = OptionsCopy;
        !           281:        while (cur)
        !           282:        {
        !           283:                sep = strchr(cur, ',');
        !           284:                if (sep)                        /* end of next options */
        !           285:                        *sep++ = '\0';
        !           286:                
        !           287:                Mode = 0;                               /* default is 'add' */
        !           288:                if (*cur == '+')
        !           289:                { Mode = 0; cur++; }
        !           290:                else if (*cur == '-')
        !           291:                { Mode = 1; cur++; }
        !           292:                
        !           293:                for (i = 0; i < MaxOptions; i++)
        !           294:                {
        !           295:                        if (strcmp(cur, TraceOptions[i].Name) == 0)
        !           296:                                break;
        !           297:                }
        !           298:                
        !           299:                if (i < MaxOptions)             /* option found */
        !           300:                {
        !           301:                        if (Mode == 0)
        !           302:                                LogTraceFlags |= TraceOptions[i].Level;
        !           303:                        else
        !           304:                                LogTraceFlags &= (~TraceOptions[i].Level);
        !           305:                }
        !           306:                else
        !           307:                {
        !           308:                        fprintf(stderr, "Unknown trace type '%s'\n", cur);
        !           309:                        free(OptionsCopy);
        !           310:                        return "Unknown trace type.";
        !           311:                }
        !           312:                
        !           313:                cur = sep;
        !           314:        }
        !           315:        
        !           316:        //fprintf(stderr, "trace parse <%x>\n", LogTraceFlags);
        !           317:        
        !           318:        free (OptionsCopy);
        !           319:        return NULL;
        !           320: }
        !           321: 
        !           322: 
        !           323: /**
        !           324:  * Readline match callback for trace type name completion.
        !           325:  * STATE = 0 -> different text from previous one.
        !           326:  * Return next match or NULL if no matches.
        !           327:  */
        !           328: char *Log_MatchTrace(const char *text, int state)
        !           329: {
        !           330:        static int i, len;
        !           331:        const char *name;
        !           332:        
        !           333:        if (!state) {
        !           334:                /* first match */
        !           335:                len = strlen(text);
        !           336:                i = 0;
        !           337:        }
        !           338:        /* next match */
        !           339:        while (i < ARRAYSIZE(TraceOptions)) {
        !           340:                name = TraceOptions[i++].Name;
        !           341:                if (strncasecmp(name, text, len) == 0)
        !           342:                        return (strdup(name));
        !           343:        }
        !           344:        return NULL;
        !           345: }
        !           346: 
        !           347: #else  /* !ENABLE_TRACING */
        !           348: 
        !           349: /** dummy */
        !           350: const char* Log_SetTraceOptions (const char *OptionsStr)
        !           351: {
        !           352:        return "Hatari has been compiled without ENABLE_TRACING!";
        !           353: }
        !           354: 
        !           355: /** dummy */
        !           356: char *Log_MatchTrace(const char *text, int state)
        !           357: {
        !           358:        return NULL;
        !           359: }
        !           360: 
        !           361: #endif /* !ENABLE_TRACING */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.