Annotation of previous_trunk/src/debug/log.c, revision 1.1.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:        Uint64 Level;
                     34:        const char *Name;
                     35: }
                     36: TraceOptions[] = {
                     37:        { TRACE_NONE             , "none" },
                     38: 
                     39:        { TRACE_PSG_READ         , "psg_read" } ,
                     40:        { TRACE_PSG_WRITE        , "psg_write" } ,
                     41:        { TRACE_PSG_ALL          , "psg_all" } ,
                     42: 
                     43:        { TRACE_CPU_PAIRING      , "cpu_pairing" } ,
                     44:        { TRACE_CPU_DISASM       , "cpu_disasm" } ,
                     45:        { TRACE_CPU_EXCEPTION    , "cpu_exception" } ,
                     46:        { TRACE_CPU_ALL          , "cpu_all" } ,
                     47: 
                     48:        { TRACE_INT              , "int" } ,
                     49: 
                     50:        { TRACE_FDC              , "fdc" } ,
                     51: 
                     52:        { TRACE_IKBD_CMDS        , "ikbd_cmds" } ,
                     53:        { TRACE_IKBD_ACIA        , "ikbd_acia" } ,
                     54:        { TRACE_IKBD_EXEC        , "ikbd_exec" } ,
                     55: 
                     56:        { TRACE_IOMEM_RD         , "io_read" } ,
                     57:        { TRACE_IOMEM_WR         , "io_write" } ,
                     58:        { TRACE_IOMEM_ALL        , "io_all" } ,
                     59: 
                     60:     { TRACE_DSP_HOST_INTERFACE, "dsp_host_interface" },
                     61:     { TRACE_DSP_HOST_COMMAND , "dsp_host_command" },
                     62:     { TRACE_DSP_HOST_SSI        , "dsp_host_ssi" },
                     63:     { TRACE_DSP_INTERRUPT       , "dsp_interrupt" },
                     64:     { TRACE_DSP_DISASM  , "dsp_disasm" },
                     65:     { TRACE_DSP_DISASM_REG      , "dsp_disasm_reg" },
                     66:     { TRACE_DSP_DISASM_MEM      , "dsp_disasm_mem" },
                     67:     { TRACE_DSP_STATE   , "dsp_state" },
                     68:     { TRACE_DSP_ALL             , "dsp_all" },
                     69: 
                     70:        { TRACE_ALL              , "all" }
                     71: };
                     72: 
                     73: 
                     74: Uint64 LogTraceFlags = TRACE_NONE;
                     75: FILE *TraceFile = NULL;
                     76: 
                     77: static FILE *hLogFile = NULL;
                     78: static LOGTYPE TextLogLevel;
                     79: static LOGTYPE AlertDlgLogLevel;
                     80: 
                     81: /*-----------------------------------------------------------------------*/
                     82: /**
                     83:  * Initialize the logging and tracing functionality (open the log files etc.).
                     84:  * 
                     85:  * Return zero if that fails.
                     86:  */
                     87: int Log_Init(void)
                     88: {
                     89:        TextLogLevel = ConfigureParams.Log.nTextLogLevel;
                     90:        AlertDlgLogLevel = ConfigureParams.Log.nAlertDlgLogLevel;
                     91: 
                     92:        hLogFile = File_Open(ConfigureParams.Log.sLogFileName, "w");
                     93:        TraceFile = File_Open(ConfigureParams.Log.sTraceFileName, "w");
                     94:    
                     95:        return (hLogFile && TraceFile);
                     96: }
                     97: 
                     98: /**
                     99:  * Set Alert log level temporarily without config change.
                    100:  * 
                    101:  * Return old level for restoring the original level with this.
                    102:  */
                    103: int Log_SetAlertLevel(int level)
                    104: {
                    105:        int old = AlertDlgLogLevel;
                    106:        AlertDlgLogLevel = level;
                    107:        return old;
                    108: }
                    109: 
                    110: 
                    111: /*-----------------------------------------------------------------------*/
                    112: /**
                    113:  * Un-Initialize - close log files etc.
                    114:  */
                    115: void Log_UnInit(void)
                    116: {
                    117:        hLogFile = File_Close(hLogFile);
                    118:        TraceFile = File_Close(TraceFile);
                    119: }
                    120: 
                    121: 
                    122: /*-----------------------------------------------------------------------*/
                    123: /**
                    124:  * Output string to log file
                    125:  */
                    126: void Log_Printf(LOGTYPE nType, const char *psFormat, ...)
                    127: {
                    128:        va_list argptr;
                    129: 
                    130:        if (hLogFile && nType <= TextLogLevel)
                    131:        {
                    132:                va_start(argptr, psFormat);
                    133:                vfprintf(hLogFile, psFormat, argptr);
                    134:                va_end(argptr);
                    135:                /* Add a new-line if necessary: */
                    136:                if (psFormat[strlen(psFormat)-1] != '\n')
                    137:                        fputs("\n", hLogFile);
                    138:        }
                    139: }
                    140: 
                    141: 
                    142: /*-----------------------------------------------------------------------*/
                    143: /**
                    144:  * Show logging alert dialog box and output string to log file
                    145:  */
                    146: void Log_AlertDlg(LOGTYPE nType, const char *psFormat, ...)
                    147: {
                    148:        va_list argptr;
                    149: 
                    150:        /* Output to log file: */
                    151:        if (hLogFile && nType <= TextLogLevel)
                    152:        {
                    153:                va_start(argptr, psFormat);
                    154:                vfprintf(hLogFile, psFormat, argptr);
                    155:                va_end(argptr);
                    156:                /* Add a new-line if necessary: */
                    157:                if (psFormat[strlen(psFormat)-1] != '\n')
                    158:                        fputs("\n", hLogFile);
                    159:        }
                    160: 
                    161:        /* Show alert dialog box: */
                    162:        if (sdlscrn && nType <= AlertDlgLogLevel)
                    163:        {
                    164:                char *psTmpBuf;
                    165:                psTmpBuf = malloc(2048);
                    166:                if (!psTmpBuf)
                    167:                {
                    168:                        perror("Log_AlertDlg");
                    169:                        return;
                    170:                }
                    171:                va_start(argptr, psFormat);
                    172:                vsnprintf(psTmpBuf, 2048, psFormat, argptr);
                    173:                va_end(argptr);
                    174:                DlgAlert_Notice(psTmpBuf);
                    175:                free(psTmpBuf);
                    176:        }
                    177: }
                    178: 
                    179: 
                    180: /*-----------------------------------------------------------------------*/
                    181: /**
                    182:  * parse what log level should be used and return it
                    183:  */
                    184: LOGTYPE Log_ParseOptions(const char *arg)
                    185: {
                    186:        const char *levels[] = {
                    187:                "fatal", "error", "warn", "info", "todo", "debug", NULL
                    188:        };
                    189:        LOGTYPE level = LOG_FATAL;
                    190:        const char **level_str;
                    191:        char *input, *str;
                    192: 
                    193:        input = strdup(arg);
                    194:        str = input;
                    195:        while (*str)
                    196:        {
                    197:                *str++ = tolower(*arg++);
                    198:        }
                    199:        for (level_str = levels; *level_str; level_str++, level++)
                    200:        {
                    201:                if (strcmp(input, *level_str) == 0)
                    202:                {
                    203:                        free(input);
                    204:                        return level;
                    205:                }
                    206:        }
                    207:        free(input);
                    208:        return level;
                    209: }
                    210: 
                    211: 
                    212: #if ENABLE_TRACING
                    213: 
                    214: /*-----------------------------------------------------------------------*/
                    215: /**
                    216:  * Parse a list of comma separated strings.
                    217:  * If the string is prefixed with an optional '+',
                    218:  * corresponding trace flag is turned on.
                    219:  * If the string is prefixed with a '-',
                    220:  * corresponding trace flag is turned off.
                    221:  * Result is stored in LogTraceFlags.
                    222:  * Return error string (""=silent 'error') or NULL for success.
                    223:  */
                    224: const char* Log_SetTraceOptions (const char *OptionsStr)
                    225: {
                    226:        char *OptionsCopy;
                    227:        char *cur, *sep;
                    228:        int i;
                    229:        int Mode;                               /* 0=add, 1=del */
                    230:        int MaxOptions;
                    231: 
                    232:        MaxOptions = ARRAYSIZE(TraceOptions);
                    233:        
                    234:        /* special case for "help" : display the list of possible trace levels */
                    235:        if (strcmp (OptionsStr, "help") == 0)
                    236:        {
                    237:                fprintf(stderr, "\nList of available trace levels :\n");
                    238:                
                    239:                for (i = 0; i < MaxOptions; i++)
                    240:                        fprintf(stderr, "  %s\n", TraceOptions[i].Name);
                    241:                
                    242:                fprintf(stderr, "Multiple trace levels can be separated by ','\n");
                    243:                fprintf(stderr, "Levels can be prefixed by '+' or '-' to be mixed.\n");
                    244:                fprintf(stderr, "Giving just trace level 'none' disables all traces.\n\n");
                    245:                return "";
                    246:        }
                    247:        
                    248:        LogTraceFlags = TRACE_NONE;
                    249:        if (strcmp (OptionsStr, "none") == 0)
                    250:        {
                    251:                return NULL;
                    252:        }
                    253:        
                    254:        OptionsCopy = strdup(OptionsStr);
                    255:        if (!OptionsCopy)
                    256:        {
                    257:                return "strdup error in ParseTraceOptions";
                    258:        }
                    259:        
                    260:        cur = OptionsCopy;
                    261:        while (cur)
                    262:        {
                    263:                sep = strchr(cur, ',');
                    264:                if (sep)                        /* end of next options */
                    265:                        *sep++ = '\0';
                    266:                
                    267:                Mode = 0;                               /* default is 'add' */
                    268:                if (*cur == '+')
                    269:                { Mode = 0; cur++; }
                    270:                else if (*cur == '-')
                    271:                { Mode = 1; cur++; }
                    272:                
                    273:                for (i = 0; i < MaxOptions; i++)
                    274:                {
                    275:                        if (strcmp(cur, TraceOptions[i].Name) == 0)
                    276:                                break;
                    277:                }
                    278:                
                    279:                if (i < MaxOptions)             /* option found */
                    280:                {
                    281:                        if (Mode == 0)
                    282:                                LogTraceFlags |= TraceOptions[i].Level;
                    283:                        else
                    284:                                LogTraceFlags &= (~TraceOptions[i].Level);
                    285:                }
                    286:                else
                    287:                {
                    288:                        fprintf(stderr, "Unknown trace type '%s'\n", cur);
                    289:                        free(OptionsCopy);
                    290:                        return "Unknown trace type.";
                    291:                }
                    292:                
                    293:                cur = sep;
                    294:        }
                    295:        
                    296:        //fprintf(stderr, "trace parse <%x>\n", LogTraceFlags);
                    297:        
                    298:        free (OptionsCopy);
                    299:        return NULL;
                    300: }
                    301: 
                    302: 
                    303: /**
                    304:  * Readline match callback for trace type name completion.
                    305:  * STATE = 0 -> different text from previous one.
                    306:  * Return next match or NULL if no matches.
                    307:  */
                    308: char *Log_MatchTrace(const char *text, int state)
                    309: {
                    310:        static int i, len;
                    311:        const char *name;
                    312:        
                    313:        if (!state) {
                    314:                /* first match */
                    315:                len = strlen(text);
                    316:                i = 0;
                    317:        }
                    318:        /* next match */
                    319:        while (i < ARRAYSIZE(TraceOptions)) {
                    320:                name = TraceOptions[i++].Name;
                    321:                if (strncasecmp(name, text, len) == 0)
                    322:                        return (strdup(name));
                    323:        }
                    324:        return NULL;
                    325: }
                    326: 
                    327: #else  /* !ENABLE_TRACING */
                    328: 
                    329: /** dummy */
                    330: const char* Log_SetTraceOptions (const char *OptionsStr)
                    331: {
                    332:        return "Hatari has been compiled without ENABLE_TRACING!";
                    333: }
                    334: 
                    335: /** dummy */
                    336: char *Log_MatchTrace(const char *text, int state)
                    337: {
                    338:        return NULL;
                    339: }
                    340: 
                    341: #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.