|
|
1.1 root 1: /*
1.1.1.4 root 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
1.1.1.6 ! root 13: * of LogTraceFlags. Multiple trace levels can be set at once, by setting
! 14: * the corresponding bits in LogTraceFlags.
1.1.1.4 root 15: */
1.1.1.5 root 16: const char Log_fileid[] = "Hatari log.c : " __DATE__ " " __TIME__;
1.1 root 17:
18: #include <stdio.h>
19: #include <stdarg.h>
1.1.1.4 root 20: #include <stdlib.h>
21: #include <string.h>
22: #include <ctype.h>
1.1 root 23:
24: #include "main.h"
25: #include "configuration.h"
26: #include "dialog.h"
27: #include "log.h"
28: #include "screen.h"
1.1.1.3 root 29: #include "file.h"
1.1 root 30:
31:
1.1.1.4 root 32: struct {
33: Uint32 Level;
34: const char *Name;
35: }
36: TraceOptions[] = {
1.1.1.6 ! root 37: { TRACE_NONE , "none" },
1.1.1.4 root 38:
1.1.1.6 ! root 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" } ,
1.1.1.5 root 85:
1.1.1.6 ! root 86: { TRACE_DMASND , "dmasound" } ,
! 87:
! 88: { TRACE_ALL , "all" }
1.1.1.4 root 89: };
90:
91:
1.1.1.6 ! root 92: Uint32 LogTraceFlags = TRACE_NONE;
1.1.1.4 root 93: FILE *TraceFile = NULL;
94:
95: static FILE *hLogFile = NULL;
96: static LOGTYPE TextLogLevel;
97: static LOGTYPE AlertDlgLogLevel;
1.1 root 98:
99: /*-----------------------------------------------------------------------*/
1.1.1.3 root 100: /**
1.1.1.4 root 101: * Initialize the logging and tracing functionality (open the log files etc.).
102: *
103: * Return zero if that fails.
1.1.1.3 root 104: */
1.1.1.4 root 105: int Log_Init(void)
1.1 root 106: {
1.1.1.4 root 107: TextLogLevel = ConfigureParams.Log.nTextLogLevel;
108: AlertDlgLogLevel = ConfigureParams.Log.nAlertDlgLogLevel;
109:
1.1.1.3 root 110: hLogFile = File_Open(ConfigureParams.Log.sLogFileName, "w");
1.1.1.4 root 111: TraceFile = File_Open(ConfigureParams.Log.sTraceFileName, "w");
112:
113: return (hLogFile && TraceFile);
1.1 root 114: }
115:
116:
117: /*-----------------------------------------------------------------------*/
1.1.1.3 root 118: /**
1.1.1.4 root 119: * Un-Initialize - close log files etc.
1.1.1.3 root 120: */
1.1 root 121: void Log_UnInit(void)
122: {
1.1.1.3 root 123: hLogFile = File_Close(hLogFile);
1.1.1.4 root 124: TraceFile = File_Close(TraceFile);
1.1 root 125: }
126:
127:
128: /*-----------------------------------------------------------------------*/
1.1.1.3 root 129: /**
130: * Output string to log file
131: */
1.1 root 132: void Log_Printf(LOGTYPE nType, const char *psFormat, ...)
133: {
134: va_list argptr;
135:
1.1.1.4 root 136: if (hLogFile && nType <= TextLogLevel)
1.1 root 137: {
138: va_start(argptr, psFormat);
139: vfprintf(hLogFile, psFormat, argptr);
140: va_end(argptr);
1.1.1.4 root 141: /* Add a new-line if necessary: */
142: if (psFormat[strlen(psFormat)-1] != '\n')
143: fputs("\n", hLogFile);
1.1 root 144: }
145: }
146:
147:
148: /*-----------------------------------------------------------------------*/
1.1.1.3 root 149: /**
150: * Show logging alert dialog box and output string to log file
151: */
1.1 root 152: void Log_AlertDlg(LOGTYPE nType, const char *psFormat, ...)
153: {
154: va_list argptr;
155:
156: /* Output to log file: */
1.1.1.4 root 157: if (hLogFile && nType <= TextLogLevel)
1.1 root 158: {
159: va_start(argptr, psFormat);
160: vfprintf(hLogFile, psFormat, argptr);
161: va_end(argptr);
162: /* Add a new-line if necessary: */
163: if (psFormat[strlen(psFormat)-1] != '\n')
164: fputs("\n", hLogFile);
165: }
166:
167: /* Show alert dialog box: */
1.1.1.4 root 168: if (sdlscrn && nType <= AlertDlgLogLevel)
1.1 root 169: {
170: char *psTmpBuf;
171: psTmpBuf = malloc(2048);
172: if (!psTmpBuf)
173: {
174: perror("Log_AlertDlg");
175: return;
176: }
177: va_start(argptr, psFormat);
178: vsnprintf(psTmpBuf, 2048, psFormat, argptr);
179: va_end(argptr);
180: DlgAlert_Notice(psTmpBuf);
181: free(psTmpBuf);
182: }
183: }
1.1.1.4 root 184:
185:
186: /*-----------------------------------------------------------------------*/
187: /**
188: * parse what log level should be used and return it
189: */
190: LOGTYPE Log_ParseOptions(const char *arg)
191: {
192: const char *levels[] = {
193: "fatal", "error", "warn", "info", "todo", "debug", NULL
194: };
195: LOGTYPE level = LOG_FATAL;
196: const char **level_str;
197: char *input, *str;
198:
199: input = strdup(arg);
200: str = input;
201: while (*str)
202: {
203: *str++ = tolower(*arg++);
204: }
205: for (level_str = levels; *level_str; level_str++, level++)
206: {
207: if (strcmp(input, *level_str) == 0)
208: {
209: free(input);
210: return level;
211: }
212: }
213: free(input);
214: return level;
215: }
216:
217: /*-----------------------------------------------------------------------*/
218: /**
219: * Parse a list of comma separated strings.
220: * If the string is prefixed with an optional '+',
221: * corresponding trace flag is turned on.
222: * If the string is prefixed with a '-',
223: * corresponding trace flag is turned off.
1.1.1.6 ! root 224: * Result is stored in LogTraceFlags.
! 225: * Return error string or NULL for success.
1.1.1.4 root 226: */
1.1.1.6 ! root 227: const char* Log_SetTraceOptions (const char *OptionsStr)
1.1.1.4 root 228: {
1.1.1.6 ! root 229: #if ENABLE_TRACING
! 230:
1.1.1.4 root 231: char *OptionsCopy;
232: char *cur, *sep;
233: int i;
234: int Mode; /* 0=add, 1=del */
235: int MaxOptions;
236:
237: MaxOptions = sizeof(TraceOptions) / sizeof(TraceOptions[0]);
238:
239: /* special case for "help" : display the list of possible trace levels */
240: if (strcmp (OptionsStr, "help") == 0)
241: {
242: fprintf(stderr, "\nList of available trace levels :\n");
243:
244: for (i = 0; i < MaxOptions; i++)
245: fprintf(stderr, " %s\n", TraceOptions[i].Name);
246:
247: fprintf(stderr, "Multiple trace levels can be separated by ','\n");
248: fprintf(stderr, "Levels can be prefixed by '+' or '-' to be mixed.\n");
249: fprintf(stderr, "Giving just trace level 'none' disables all traces.\n\n");
1.1.1.6 ! root 250: return NULL;
1.1.1.4 root 251: }
252:
1.1.1.6 ! root 253: LogTraceFlags = TRACE_NONE;
1.1.1.4 root 254: if (strcmp (OptionsStr, "none") == 0)
255: {
1.1.1.6 ! root 256: return NULL;
1.1.1.4 root 257: }
258:
259: OptionsCopy = strdup(OptionsStr);
260: if (!OptionsCopy)
261: {
1.1.1.6 ! root 262: return "strdup error in ParseTraceOptions";
1.1.1.4 root 263: }
264:
265: cur = OptionsCopy;
266: while (cur)
267: {
268: sep = strchr(cur, ',');
269: if (sep) /* end of next options */
270: *sep++ = '\0';
271:
272: Mode = 0; /* default is 'add' */
273: if (*cur == '+')
274: { Mode = 0; cur++; }
275: else if (*cur == '-')
276: { Mode = 1; cur++; }
277:
278: for (i = 0; i < MaxOptions; i++)
279: {
280: if (strcmp(cur, TraceOptions[i].Name) == 0)
281: break;
282: }
283:
284: if (i < MaxOptions) /* option found */
285: {
286: if (Mode == 0)
1.1.1.6 ! root 287: LogTraceFlags |= TraceOptions[i].Level;
1.1.1.4 root 288: else
1.1.1.6 ! root 289: LogTraceFlags &= (~TraceOptions[i].Level);
1.1.1.4 root 290: }
291: else
292: {
1.1.1.6 ! root 293: fprintf(stderr, "Unknown trace type '%s'\n", cur);
1.1.1.4 root 294: free(OptionsCopy);
1.1.1.6 ! root 295: return "Unknown trace type.";
1.1.1.4 root 296: }
297:
298: cur = sep;
299: }
300:
1.1.1.6 ! root 301: //fprintf(stderr, "trace parse <%x>\n", LogTraceFlags);
1.1.1.4 root 302:
303: free (OptionsCopy);
1.1.1.6 ! root 304: return NULL;
! 305:
! 306: #else /* ENABLE_TRACING */
! 307: return "Hatari has been compiled without ENABLE_TRACING!";
! 308: #endif
1.1.1.4 root 309: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.