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