|
|
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
13: * of HatariTraceFlags. Multiple trace levels can be set at once, by setting
14: * the corresponding bits in HatariTraceFlags
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[] = {
37: { HATARI_TRACE_VIDEO_SYNC , "video_sync" } ,
38: { HATARI_TRACE_VIDEO_RES , "video_res" } ,
39: { HATARI_TRACE_VIDEO_COLOR , "video_color" } ,
40: { HATARI_TRACE_VIDEO_BORDER_V , "video_border_v" } ,
41: { HATARI_TRACE_VIDEO_BORDER_H , "video_border_h" } ,
42: { HATARI_TRACE_VIDEO_ADDR , "video_addr" } ,
43: { HATARI_TRACE_VIDEO_HBL , "video_hbl" } ,
44: { HATARI_TRACE_VIDEO_VBL , "video_vbl" } ,
45: { HATARI_TRACE_VIDEO_STE , "video_ste" } ,
46: { HATARI_TRACE_VIDEO_ALL , "video_all" } ,
47:
48: { HATARI_TRACE_MFP_EXCEPTION , "mfp_exception" } ,
49: { HATARI_TRACE_MFP_START , "mfp_start" } ,
50: { HATARI_TRACE_MFP_READ , "mfp_read" } ,
51: { HATARI_TRACE_MFP_WRITE , "mfp_write" } ,
52: { HATARI_TRACE_MFP_ALL , "mfp_all" } ,
53:
1.1.1.5 ! root 54: { HATARI_TRACE_PSG_READ , "psg_read" } ,
! 55: { HATARI_TRACE_PSG_WRITE , "psg_write" } ,
1.1.1.4 root 56: { HATARI_TRACE_PSG_ALL , "psg_all" } ,
57:
58: { HATARI_TRACE_CPU_PAIRING , "cpu_pairing" } ,
59: { HATARI_TRACE_CPU_DISASM , "cpu_disasm" } ,
60: { HATARI_TRACE_CPU_EXCEPTION , "cpu_exception" } ,
61: { HATARI_TRACE_CPU_ALL , "cpu_all" } ,
62:
63: { HATARI_TRACE_INT , "int" } ,
64:
65: { HATARI_TRACE_FDC , "fdc" } ,
66:
67: { HATARI_TRACE_IKBD_CMDS , "ikbd_cmds" } ,
68: { HATARI_TRACE_IKBD_ACIA , "ikbd_acia" } ,
69: { HATARI_TRACE_IKBD_EXEC , "ikbd_exec" } ,
70: { HATARI_TRACE_IKBD_ALL , "ikbd_all" } ,
71:
72: { HATARI_TRACE_BLITTER , "blitter" } ,
73:
74: { HATARI_TRACE_OS_BIOS , "bios" },
75: { HATARI_TRACE_OS_XBIOS , "xbios" },
76: { HATARI_TRACE_OS_GEMDOS , "gemdos" },
77: { HATARI_TRACE_OS_VDI , "vdi" },
78: { HATARI_TRACE_OS_ALL , "os_all" } ,
79:
1.1.1.5 ! root 80: { HATARI_TRACE_IOMEM_RD , "io_read" } ,
! 81: { HATARI_TRACE_IOMEM_WR , "io_write" } ,
! 82:
1.1.1.4 root 83: { HATARI_TRACE_ALL , "all" }
84: };
85:
86:
87: Uint32 HatariTraceFlags = HATARI_TRACE_NONE;
88: FILE *TraceFile = NULL;
89:
90: static FILE *hLogFile = NULL;
91: static LOGTYPE TextLogLevel;
92: static LOGTYPE AlertDlgLogLevel;
1.1 root 93:
94: /*-----------------------------------------------------------------------*/
1.1.1.3 root 95: /**
1.1.1.4 root 96: * Initialize the logging and tracing functionality (open the log files etc.).
97: *
98: * Return zero if that fails.
1.1.1.3 root 99: */
1.1.1.4 root 100: int Log_Init(void)
1.1 root 101: {
1.1.1.4 root 102: TextLogLevel = ConfigureParams.Log.nTextLogLevel;
103: AlertDlgLogLevel = ConfigureParams.Log.nAlertDlgLogLevel;
104:
1.1.1.3 root 105: hLogFile = File_Open(ConfigureParams.Log.sLogFileName, "w");
1.1.1.4 root 106: TraceFile = File_Open(ConfigureParams.Log.sTraceFileName, "w");
107:
108: return (hLogFile && TraceFile);
1.1 root 109: }
110:
111:
112: /*-----------------------------------------------------------------------*/
1.1.1.3 root 113: /**
1.1.1.4 root 114: * Un-Initialize - close log files etc.
1.1.1.3 root 115: */
1.1 root 116: void Log_UnInit(void)
117: {
1.1.1.3 root 118: hLogFile = File_Close(hLogFile);
1.1.1.4 root 119: TraceFile = File_Close(TraceFile);
1.1 root 120: }
121:
122:
123: /*-----------------------------------------------------------------------*/
1.1.1.3 root 124: /**
125: * Output string to log file
126: */
1.1 root 127: void Log_Printf(LOGTYPE nType, const char *psFormat, ...)
128: {
129: va_list argptr;
130:
1.1.1.4 root 131: if (hLogFile && nType <= TextLogLevel)
1.1 root 132: {
133: va_start(argptr, psFormat);
134: vfprintf(hLogFile, psFormat, argptr);
135: va_end(argptr);
1.1.1.4 root 136: /* Add a new-line if necessary: */
137: if (psFormat[strlen(psFormat)-1] != '\n')
138: fputs("\n", hLogFile);
1.1 root 139: }
140: }
141:
142:
143: /*-----------------------------------------------------------------------*/
1.1.1.3 root 144: /**
145: * Show logging alert dialog box and output string to log file
146: */
1.1 root 147: void Log_AlertDlg(LOGTYPE nType, const char *psFormat, ...)
148: {
149: va_list argptr;
150:
151: /* Output to log file: */
1.1.1.4 root 152: if (hLogFile && nType <= TextLogLevel)
1.1 root 153: {
154: va_start(argptr, psFormat);
155: vfprintf(hLogFile, psFormat, argptr);
156: va_end(argptr);
157: /* Add a new-line if necessary: */
158: if (psFormat[strlen(psFormat)-1] != '\n')
159: fputs("\n", hLogFile);
160: }
161:
162: /* Show alert dialog box: */
1.1.1.4 root 163: if (sdlscrn && nType <= AlertDlgLogLevel)
1.1 root 164: {
165: char *psTmpBuf;
166: psTmpBuf = malloc(2048);
167: if (!psTmpBuf)
168: {
169: perror("Log_AlertDlg");
170: return;
171: }
172: va_start(argptr, psFormat);
173: vsnprintf(psTmpBuf, 2048, psFormat, argptr);
174: va_end(argptr);
175: DlgAlert_Notice(psTmpBuf);
176: free(psTmpBuf);
177: }
178: }
1.1.1.4 root 179:
180:
181: /*-----------------------------------------------------------------------*/
182: /**
183: * parse what log level should be used and return it
184: */
185: LOGTYPE Log_ParseOptions(const char *arg)
186: {
187: const char *levels[] = {
188: "fatal", "error", "warn", "info", "todo", "debug", NULL
189: };
190: LOGTYPE level = LOG_FATAL;
191: const char **level_str;
192: char *input, *str;
193:
194: input = strdup(arg);
195: str = input;
196: while (*str)
197: {
198: *str++ = tolower(*arg++);
199: }
200: for (level_str = levels; *level_str; level_str++, level++)
201: {
202: if (strcmp(input, *level_str) == 0)
203: {
204: free(input);
205: return level;
206: }
207: }
208: free(input);
209: return level;
210: }
211:
212: /*-----------------------------------------------------------------------*/
213: /**
214: * Parse a list of comma separated strings.
215: * If the string is prefixed with an optional '+',
216: * corresponding trace flag is turned on.
217: * If the string is prefixed with a '-',
218: * corresponding trace flag is turned off.
219: * Result is stored in HatariTraceFlags.
220: */
221: bool Log_SetTraceOptions (const char *OptionsStr)
222: {
223: char *OptionsCopy;
224: char *cur, *sep;
225: int i;
226: int Mode; /* 0=add, 1=del */
227: int MaxOptions;
228:
229: MaxOptions = sizeof(TraceOptions) / sizeof(TraceOptions[0]);
230:
231: /* special case for "help" : display the list of possible trace levels */
232: if (strcmp (OptionsStr, "help") == 0)
233: {
234: fprintf(stderr, "\nList of available trace levels :\n");
235:
236: for (i = 0; i < MaxOptions; i++)
237: fprintf(stderr, " %s\n", TraceOptions[i].Name);
238:
239: fprintf(stderr, "Multiple trace levels can be separated by ','\n");
240: fprintf(stderr, "Levels can be prefixed by '+' or '-' to be mixed.\n");
241: fprintf(stderr, "Giving just trace level 'none' disables all traces.\n\n");
242: return FALSE;
243: }
244:
245: #ifndef HATARI_TRACE_ACTIVATED
246: fprintf(stderr, "\nError: Trace option has not been activated during compile time.\n");
247: return FALSE;
248: #endif
249:
250: HatariTraceFlags = HATARI_TRACE_NONE;
251: if (strcmp (OptionsStr, "none") == 0)
252: {
253: return TRUE;
254: }
255:
256: OptionsCopy = strdup(OptionsStr);
257: if (!OptionsCopy)
258: {
259: fprintf(stderr, "strdup error in ParseTraceOptions\n");
260: return FALSE;
261: }
262:
263: cur = OptionsCopy;
264: while (cur)
265: {
266: sep = strchr(cur, ',');
267: if (sep) /* end of next options */
268: *sep++ = '\0';
269:
270: Mode = 0; /* default is 'add' */
271: if (*cur == '+')
272: { Mode = 0; cur++; }
273: else if (*cur == '-')
274: { Mode = 1; cur++; }
275:
276: for (i = 0; i < MaxOptions; i++)
277: {
278: if (strcmp(cur, TraceOptions[i].Name) == 0)
279: break;
280: }
281:
282: if (i < MaxOptions) /* option found */
283: {
284: if (Mode == 0)
285: HatariTraceFlags |= TraceOptions[i].Level;
286: else
287: HatariTraceFlags &= (~TraceOptions[i].Level);
288: }
289: else
290: {
291: fprintf(stderr, "unknown trace option %s\n", cur);
292: free(OptionsCopy);
293: return FALSE;
294: }
295:
296: cur = sep;
297: }
298:
299: //fprintf(stderr, "trace parse <%x>\n", HatariTraceFlags);
300:
301: free (OptionsCopy);
302: return TRUE;
303: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.