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

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