1 /* Written by Krzysztof Kowalczyk (http://blog.kowalczyk.info)
2 The author disclaims copyright to this source code. */
6 /* Simple logging. 'slog' stands for "simple logging". I figured that 'log'
7 is a very common name so used something else, but still short as a prefix
10 /* TODO: slogfmt(const char *fmt, ...) */
12 /* TODO: extend to more than one file, by keeping a list of file names */
13 const TCHAR
* g_cur_fileName
= NULL
;
15 /* initialize logging system, should be called before any logging calls */
22 /* deinitialize logging system. Should be called before the program quits */
23 void slog_deinit(void)
25 slog_file_log_stop(NULL
);
28 /* start logging to a file 'fileName'. From now on until slog_file_log_stop()
29 all slog* logging will also go to a file. If a file of that name already
30 exists, it'll overwrite it. */
31 BOOL
slog_file_log_start(const TCHAR
*fileName
)
33 if (!fileName
) return FALSE
;
34 g_cur_fileName
= tstr_dup(fileName
);
39 /* like 'slog_file_log_start' but will create a unique file based on 'fileName'.
40 If a 'fileName' has extension, it'll try the first available
41 '$file-$NNN.$ext' file (e.g. "my-app-log-000.txt") if 'fileName' is "my-app-log.txt"
42 If there is no extension, it'll be '$file-$NNN' */
43 int slog_file_log_unique_start(const TCHAR
*fileName
)
45 assert(0); /* not implemented */
49 void slog_file_log_stop(const TCHAR
*fileName
)
51 /* 'fileName' is currently unused. The idea is that it should match the
52 name given to slog_file_log_start */
54 free((void*)g_cur_fileName
);
55 g_cur_fileName
= NULL
;
59 /* log 'txt' to all currently enabled loggers */
60 void slog_str(const char *txt
)
69 if (!g_cur_fileName
) return;
71 /* we're using this inefficient way of re-opening the file for each
72 log so that we can also watch this file life using tail-like program */
73 fh
= CreateFile(g_cur_fileName
, GENERIC_WRITE
, FILE_SHARE_READ
, NULL
,
74 OPEN_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
75 if (INVALID_HANDLE_VALUE
== fh
)
77 SetFilePointer(fh
, 0, NULL
, FILE_END
);
78 to_write_cb
= (DWORD
)strlen(txt
);
79 f_ok
= WriteFile(fh
, (void*)txt
, to_write_cb
, &written_cb
, NULL
);
80 assert(f_ok
&& (written_cb
== to_write_cb
));
84 void slog_str_printf(const char *format
, ...)
89 va_start(args
, format
);
90 tmp
= str_printf_args(format
, args
);
97 static WCHAR
* last_error_as_wstr(void)
101 FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM
| FORMAT_MESSAGE_IGNORE_INSERTS
,
102 NULL
, GetLastError(), MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
),
103 (LPTSTR
) &msgBuf
, 0, NULL
);
104 if (!msgBuf
) return NULL
;
105 copy
= wstr_dup(msgBuf
);
110 void slog_last_error(const char *optional_prefix
)
112 WCHAR
*txt
= last_error_as_wstr();
114 slog_str(optional_prefix
);
119 /* TODO: converting by casting isn't always correct but here we don't care much */
120 char *wstr_to_str(const WCHAR
*txt
)
122 char *txt_copy
, *tmp
;
124 if (!txt
) return NULL
;
126 txt_copy
= (char*)malloc(tstr_len(txt
) + 1);
127 if (!txt_copy
) return NULL
;
131 *tmp
++ = (char)*txt
++;
137 void slog_wstr(const WCHAR
*txt
)
141 txt_copy
= wstr_to_str(txt
);
142 if (!txt_copy
) return;
147 /* log 'txt' to all currently enabled loggers and add newline */
148 void slog_str_nl(const char *txt
)
150 /* TODO: given the 'reopen the file each time' implementation of
151 slgotxt, this should be optimized */
156 void slog_wstr_nl(const WCHAR
*txt
)