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

1.1       root        1: /*
                      2:  * Hatari - log.c
                      3:  *
1.1.1.4   root        4:  * This file is distributed under the GNU General Public License, version 2
                      5:  * or at your option any later version. Read the file gpl.txt for details.
1.1       root        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"
1.1.1.2   root       30: #include "vdi.h"
1.1       root       31: 
1.1.1.5 ! root       32: int ExceptionDebugMask;
        !            33: 
        !            34: typedef struct {
        !            35:        Uint64 flag;
        !            36:        const char *name;
        !            37: } flagname_t;
        !            38: 
        !            39: static flagname_t ExceptionFlags[] = {
        !            40:        { EXCEPT_NONE,      "none" },
        !            41: 
        !            42:        { EXCEPT_BUS,       "bus" },
        !            43:        { EXCEPT_ADDRESS,   "address" },
        !            44:        { EXCEPT_ILLEGAL,   "illegal" },
        !            45:        { EXCEPT_ZERODIV,   "zerodiv" },
        !            46:        { EXCEPT_CHK,       "chk" },
        !            47:        { EXCEPT_TRAPV,     "trapv" },
        !            48:        { EXCEPT_PRIVILEGE, "privilege" },
        !            49:        { EXCEPT_NOHANDLER, "nohandler" },
        !            50: 
        !            51:        { EXCEPT_DSP,       "dsp" },
        !            52: 
        !            53:        { EXCEPT_AUTOSTART, "autostart" },
        !            54: 
        !            55:        { EXCEPT_ALL,       "all" }
        !            56: };
        !            57: 
1.1.1.3   root       58: #if ENABLE_TRACING
1.1.1.5 ! root       59: static flagname_t TraceFlags[] = {
1.1       root       60:        { TRACE_NONE             , "none" },
                     61: 
                     62:        { TRACE_VIDEO_SYNC       , "video_sync" } ,
                     63:        { TRACE_VIDEO_RES        , "video_res" } ,
                     64:        { TRACE_VIDEO_COLOR      , "video_color" } ,
                     65:        { TRACE_VIDEO_BORDER_V   , "video_border_v" } ,
                     66:        { TRACE_VIDEO_BORDER_H   , "video_border_h" } ,
                     67:        { TRACE_VIDEO_ADDR       , "video_addr" } ,
                     68:        { TRACE_VIDEO_HBL        , "video_hbl" } ,
                     69:        { TRACE_VIDEO_VBL        , "video_vbl" } ,
                     70:        { TRACE_VIDEO_STE        , "video_ste" } ,
                     71:        { TRACE_VIDEO_ALL        , "video_all" } ,
                     72: 
                     73:        { TRACE_MFP_EXCEPTION    , "mfp_exception" } ,
                     74:        { TRACE_MFP_START        , "mfp_start" } ,
                     75:        { TRACE_MFP_READ         , "mfp_read" } ,
                     76:        { TRACE_MFP_WRITE        , "mfp_write" } ,
                     77:        { TRACE_MFP_ALL          , "mfp_all" } ,
                     78: 
                     79:        { TRACE_PSG_READ         , "psg_read" } ,
                     80:        { TRACE_PSG_WRITE        , "psg_write" } ,
                     81:        { TRACE_PSG_ALL          , "psg_all" } ,
                     82: 
                     83:        { TRACE_CPU_PAIRING      , "cpu_pairing" } ,
                     84:        { TRACE_CPU_DISASM       , "cpu_disasm" } ,
                     85:        { TRACE_CPU_EXCEPTION    , "cpu_exception" } ,
                     86:        { TRACE_CPU_ALL          , "cpu_all" } ,
                     87: 
                     88:        { TRACE_INT              , "int" } ,
                     89: 
                     90:        { TRACE_FDC              , "fdc" } ,
                     91: 
1.1.1.4   root       92:        { TRACE_ACIA             , "acia" } ,
                     93: 
1.1       root       94:        { TRACE_IKBD_CMDS        , "ikbd_cmds" } ,
                     95:        { TRACE_IKBD_ACIA        , "ikbd_acia" } ,
                     96:        { TRACE_IKBD_EXEC        , "ikbd_exec" } ,
                     97:        { TRACE_IKBD_ALL         , "ikbd_all" } ,
                     98: 
                     99:        { TRACE_BLITTER          , "blitter" } ,
                    100: 
                    101:        { TRACE_OS_BIOS          , "bios" },
                    102:        { TRACE_OS_XBIOS         , "xbios" },
                    103:        { TRACE_OS_GEMDOS        , "gemdos" },
                    104:        { TRACE_OS_VDI           , "vdi" },
1.1.1.2   root      105:        { TRACE_OS_AES           , "aes" },
1.1       root      106:        { TRACE_OS_ALL           , "os_all" } ,
                    107: 
                    108:        { TRACE_IOMEM_RD         , "io_read" } ,
                    109:        { TRACE_IOMEM_WR         , "io_write" } ,
                    110:        { TRACE_IOMEM_ALL        , "io_all" } ,
                    111: 
                    112:        { TRACE_DMASND           , "dmasound" } ,
                    113: 
                    114:        { TRACE_CROSSBAR         , "crossbar" } ,
                    115: 
1.1.1.2   root      116:        { TRACE_VIDEL            , "videl" } ,
                    117: 
                    118:        { TRACE_DSP_HOST_INTERFACE, "dsp_host_interface" },
                    119:        { TRACE_DSP_HOST_COMMAND , "dsp_host_command" },
                    120:        { TRACE_DSP_HOST_SSI     , "dsp_host_ssi" },
                    121:        { TRACE_DSP_INTERRUPT    , "dsp_interrupt" },
                    122:        { TRACE_DSP_DISASM       , "dsp_disasm" },
                    123:        { TRACE_DSP_DISASM_REG   , "dsp_disasm_reg" },
                    124:        { TRACE_DSP_DISASM_MEM   , "dsp_disasm_mem" },
                    125:        { TRACE_DSP_STATE        , "dsp_state" },
                    126:        { TRACE_DSP_ALL          , "dsp_all" },
                    127: 
1.1.1.3   root      128:        { TRACE_DSP_SYMBOLS      , "dsp_symbols" },
                    129:        { TRACE_CPU_SYMBOLS      , "cpu_symbols" },
                    130: 
1.1.1.5 ! root      131:        { TRACE_NVRAM            , "nvram" } ,
        !           132: 
        !           133:        { TRACE_SCSI_CMD         , "scsi_cmd" } ,
        !           134: 
        !           135:        { TRACE_NATFEATS         , "natfeats" } ,
1.1.1.4   root      136: 
1.1       root      137:        { TRACE_ALL              , "all" }
                    138: };
1.1.1.3   root      139: #endif /* ENABLE_TRACING */
1.1       root      140: 
                    141: 
1.1.1.2   root      142: Uint64 LogTraceFlags = TRACE_NONE;
1.1       root      143: FILE *TraceFile = NULL;
                    144: 
                    145: static FILE *hLogFile = NULL;
                    146: static LOGTYPE TextLogLevel;
                    147: static LOGTYPE AlertDlgLogLevel;
                    148: 
                    149: /*-----------------------------------------------------------------------*/
                    150: /**
                    151:  * Initialize the logging and tracing functionality (open the log files etc.).
                    152:  * 
                    153:  * Return zero if that fails.
                    154:  */
                    155: int Log_Init(void)
                    156: {
                    157:        TextLogLevel = ConfigureParams.Log.nTextLogLevel;
                    158:        AlertDlgLogLevel = ConfigureParams.Log.nAlertDlgLogLevel;
                    159: 
                    160:        hLogFile = File_Open(ConfigureParams.Log.sLogFileName, "w");
                    161:        TraceFile = File_Open(ConfigureParams.Log.sTraceFileName, "w");
                    162:    
                    163:        return (hLogFile && TraceFile);
                    164: }
                    165: 
                    166: /**
                    167:  * Set Alert log level temporarily without config change.
                    168:  * 
                    169:  * Return old level for restoring the original level with this.
                    170:  */
                    171: int Log_SetAlertLevel(int level)
                    172: {
                    173:        int old = AlertDlgLogLevel;
                    174:        AlertDlgLogLevel = level;
                    175:        return old;
                    176: }
                    177: 
                    178: 
                    179: /*-----------------------------------------------------------------------*/
                    180: /**
                    181:  * Un-Initialize - close log files etc.
                    182:  */
                    183: void Log_UnInit(void)
                    184: {
                    185:        hLogFile = File_Close(hLogFile);
                    186:        TraceFile = File_Close(TraceFile);
                    187: }
                    188: 
                    189: 
                    190: /*-----------------------------------------------------------------------*/
                    191: /**
                    192:  * Output string to log file
                    193:  */
                    194: void Log_Printf(LOGTYPE nType, const char *psFormat, ...)
                    195: {
                    196:        va_list argptr;
                    197: 
                    198:        if (hLogFile && nType <= TextLogLevel)
                    199:        {
                    200:                va_start(argptr, psFormat);
                    201:                vfprintf(hLogFile, psFormat, argptr);
                    202:                va_end(argptr);
                    203:                /* Add a new-line if necessary: */
                    204:                if (psFormat[strlen(psFormat)-1] != '\n')
                    205:                        fputs("\n", hLogFile);
                    206:        }
                    207: }
                    208: 
                    209: 
                    210: /*-----------------------------------------------------------------------*/
                    211: /**
                    212:  * Show logging alert dialog box and output string to log file
                    213:  */
                    214: void Log_AlertDlg(LOGTYPE nType, const char *psFormat, ...)
                    215: {
                    216:        va_list argptr;
                    217: 
                    218:        /* Output to log file: */
                    219:        if (hLogFile && nType <= TextLogLevel)
                    220:        {
                    221:                va_start(argptr, psFormat);
                    222:                vfprintf(hLogFile, psFormat, argptr);
                    223:                va_end(argptr);
                    224:                /* Add a new-line if necessary: */
                    225:                if (psFormat[strlen(psFormat)-1] != '\n')
                    226:                        fputs("\n", hLogFile);
                    227:        }
                    228: 
                    229:        /* Show alert dialog box: */
                    230:        if (sdlscrn && nType <= AlertDlgLogLevel)
                    231:        {
                    232:                char *psTmpBuf;
                    233:                psTmpBuf = malloc(2048);
                    234:                if (!psTmpBuf)
                    235:                {
                    236:                        perror("Log_AlertDlg");
                    237:                        return;
                    238:                }
                    239:                va_start(argptr, psFormat);
                    240:                vsnprintf(psTmpBuf, 2048, psFormat, argptr);
                    241:                va_end(argptr);
                    242:                DlgAlert_Notice(psTmpBuf);
                    243:                free(psTmpBuf);
                    244:        }
                    245: }
                    246: 
                    247: 
                    248: /*-----------------------------------------------------------------------*/
                    249: /**
                    250:  * parse what log level should be used and return it
                    251:  */
                    252: LOGTYPE Log_ParseOptions(const char *arg)
                    253: {
                    254:        const char *levels[] = {
                    255:                "fatal", "error", "warn", "info", "todo", "debug", NULL
                    256:        };
                    257:        LOGTYPE level = LOG_FATAL;
                    258:        const char **level_str;
                    259:        char *input, *str;
                    260: 
                    261:        input = strdup(arg);
                    262:        str = input;
                    263:        while (*str)
                    264:        {
1.1.1.5 ! root      265:                *str++ = tolower((unsigned char)*arg++);
1.1       root      266:        }
                    267:        for (level_str = levels; *level_str; level_str++, level++)
                    268:        {
                    269:                if (strcmp(input, *level_str) == 0)
                    270:                {
                    271:                        free(input);
                    272:                        return level;
                    273:                }
                    274:        }
                    275:        free(input);
                    276:        return level;
                    277: }
                    278: 
                    279: 
                    280: /*-----------------------------------------------------------------------*/
                    281: /**
                    282:  * Parse a list of comma separated strings.
                    283:  * If the string is prefixed with an optional '+',
1.1.1.5 ! root      284:  * corresponding mask flag is turned on.
1.1       root      285:  * If the string is prefixed with a '-',
1.1.1.5 ! root      286:  * corresponding mask flag is turned off.
1.1       root      287:  * Return error string (""=silent 'error') or NULL for success.
                    288:  */
1.1.1.5 ! root      289: static const char*
        !           290: Log_ParseOptionFlags (const char *FlagsStr, flagname_t *Flags, int MaxFlags, Uint64 *Mask)
1.1       root      291: {
1.1.1.5 ! root      292:        char *FlagsCopy;
1.1       root      293:        char *cur, *sep;
                    294:        int i;
                    295:        int Mode;                               /* 0=add, 1=del */
                    296:        
1.1.1.5 ! root      297:        /* special case for "help" : display the list of possible settings */
        !           298:        if (strcmp (FlagsStr, "help") == 0)
1.1       root      299:        {
1.1.1.5 ! root      300:                fprintf(stderr, "\nList of available option flags :\n");
1.1       root      301:                
1.1.1.5 ! root      302:                for (i = 0; i < MaxFlags; i++)
        !           303:                        fprintf(stderr, "  %s\n", Flags[i].name);
1.1       root      304:                
1.1.1.5 ! root      305:                fprintf(stderr, "Multiple flags can be separated by ','.\n");
        !           306:                fprintf(stderr, "They can be prefixed by '+' or '-' to be mixed.\n");
        !           307:                fprintf(stderr, "Giving just 'none' flag disables all of them.\n\n");
1.1       root      308:                return "";
                    309:        }
                    310:        
1.1.1.5 ! root      311:        if (strcmp (FlagsStr, "none") == 0)
1.1       root      312:        {
                    313:                return NULL;
                    314:        }
                    315:        
1.1.1.5 ! root      316:        FlagsCopy = strdup(FlagsStr);
        !           317:        if (!FlagsCopy)
1.1       root      318:        {
1.1.1.5 ! root      319:                return "strdup error in Log_OptionFlags";
1.1       root      320:        }
                    321:        
1.1.1.5 ! root      322:        cur = FlagsCopy;
1.1       root      323:        while (cur)
                    324:        {
                    325:                sep = strchr(cur, ',');
                    326:                if (sep)                        /* end of next options */
                    327:                        *sep++ = '\0';
                    328:                
                    329:                Mode = 0;                               /* default is 'add' */
                    330:                if (*cur == '+')
                    331:                { Mode = 0; cur++; }
                    332:                else if (*cur == '-')
                    333:                { Mode = 1; cur++; }
                    334:                
1.1.1.5 ! root      335:                for (i = 0; i < MaxFlags; i++)
1.1       root      336:                {
1.1.1.5 ! root      337:                        if (strcmp(cur, Flags[i].name) == 0)
1.1       root      338:                                break;
                    339:                }
                    340:                
1.1.1.5 ! root      341:                if (i < MaxFlags)               /* option found */
1.1       root      342:                {
                    343:                        if (Mode == 0)
1.1.1.5 ! root      344:                                *Mask |= Flags[i].flag;
1.1       root      345:                        else
1.1.1.5 ! root      346:                                *Mask &= (~Flags[i].flag);
1.1       root      347:                }
                    348:                else
                    349:                {
1.1.1.5 ! root      350:                        fprintf(stderr, "Unknown flag type '%s'\n", cur);
        !           351:                        free(FlagsCopy);
        !           352:                        return "Unknown flag type.";
1.1       root      353:                }
                    354:                
                    355:                cur = sep;
                    356:        }
1.1.1.2   root      357: 
1.1.1.5 ! root      358:        //fprintf(stderr, "flags parse <%x>\n", Mask);
1.1       root      359:        
1.1.1.5 ! root      360:        free (FlagsCopy);
1.1       root      361:        return NULL;
                    362: }
                    363: 
1.1.1.5 ! root      364: /**
        !           365:  * Parse exception flags and store results in ExceptionDebugMask.
        !           366:  * Return error string or NULL for success.
        !           367:  * 
        !           368:  * See Log_ParseOptionFlags() for details.
        !           369:  */
        !           370: const char* Log_SetExceptionDebugMask (const char *FlagsStr)
        !           371: {
        !           372:        const char *errstr;
        !           373: 
        !           374:        Uint64 mask = EXCEPT_NONE;
        !           375:        errstr = Log_ParseOptionFlags(FlagsStr, ExceptionFlags, ARRAYSIZE(ExceptionFlags), &mask);
        !           376:        ConfigureParams.Log.nExceptionDebugMask = mask;
        !           377:        return errstr;
        !           378: }
        !           379: 
        !           380: 
        !           381: #if ENABLE_TRACING
        !           382: 
        !           383: /**
        !           384:  * Parse trace flags and store results in LogTraceFlags.
        !           385:  * Return error string or NULL for success.
        !           386:  * 
        !           387:  * See Log_ParseOptionFlags() for details.
        !           388:  */
        !           389: const char* Log_SetTraceOptions (const char *FlagsStr)
        !           390: {
        !           391:        const char *errstr;
        !           392: 
        !           393:        LogTraceFlags = TRACE_NONE;
        !           394:        errstr = Log_ParseOptionFlags(FlagsStr, TraceFlags, ARRAYSIZE(TraceFlags), &LogTraceFlags);
        !           395: 
        !           396:        /* Enable Hatari flags needed for tracing selected items */
        !           397:        if (LogTraceFlags & (TRACE_OS_AES|TRACE_OS_VDI))
        !           398:                bVdiAesIntercept = true;
        !           399: 
        !           400:        return errstr;
        !           401: }
1.1       root      402: 
                    403: /**
                    404:  * Readline match callback for trace type name completion.
                    405:  * STATE = 0 -> different text from previous one.
                    406:  * Return next match or NULL if no matches.
                    407:  */
                    408: char *Log_MatchTrace(const char *text, int state)
                    409: {
                    410:        static int i, len;
                    411:        const char *name;
                    412:        
                    413:        if (!state) {
                    414:                /* first match */
                    415:                len = strlen(text);
                    416:                i = 0;
                    417:        }
                    418:        /* next match */
1.1.1.5 ! root      419:        while (i < ARRAYSIZE(TraceFlags)) {
        !           420:                name = TraceFlags[i++].name;
1.1       root      421:                if (strncasecmp(name, text, len) == 0)
                    422:                        return (strdup(name));
                    423:        }
                    424:        return NULL;
                    425: }
                    426: 
                    427: #else  /* !ENABLE_TRACING */
                    428: 
                    429: /** dummy */
1.1.1.5 ! root      430: const char* Log_SetTraceOptions (const char *FlagsStr)
1.1       root      431: {
                    432:        return "Hatari has been compiled without ENABLE_TRACING!";
                    433: }
                    434: 
                    435: /** dummy */
                    436: char *Log_MatchTrace(const char *text, int state)
                    437: {
                    438:        return NULL;
                    439: }
                    440: 
                    441: #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.