'hidden' contacts
[dyskinesia.git] / src / dlogf.c
blob76417b6a1f48eb28dcf36fa3314dd18f9b5fe063
1 /* coded by Ketmar // Vampire Avalon (psyc://ketmar.no-ip.org/~Ketmar)
2 * Understanding is not required. Only obedience.
4 * This program is free software. It comes without any warranty, to
5 * the extent permitted by applicable law. You can redistribute it
6 * and/or modify it under the terms of the Do What The Fuck You Want
7 * To Public License, Version 2, as published by Sam Hocevar. See
8 * http://sam.zoy.org/wtfpl/COPYING for more details.
9 */
10 #include "dlogf.h"
13 #ifdef __cplusplus
14 extern "C" {
15 #endif
17 #ifdef WINNT
18 # include <windows.h>
19 #else
20 # include <time.h>
21 # include <sys/types.h>
22 # include <time.h>
23 #endif
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <unistd.h>
31 #ifndef NO_DEBUG_LOG
32 static char *dbgLogFileName = NULL;
33 static int dlogFNTouched = -1;
34 static int dbgLogWriteToScreen = -1; /* default: no; not touched */
35 static FILE *dlogFile = NULL;
37 static int initialized = 0;
38 static char modulePath[4096];
40 #ifdef WINNT
41 static DWORD mypid;
42 #else
43 pid_t mypid;
44 #endif
47 static void dlogfInit (void) {
48 #ifdef WINNT
49 char *p;
50 DWORD len = GetModuleFileName(NULL, modulePath, sizeof(modulePath)/sizeof(char)-1);
51 for (p = modulePath; *p; p++) if (*p == '\\') *p == '/';
52 while (len >= 0) {
53 if (!len) { strcpy(modulePath, "./"); break; }
54 len--;
55 if (modulePath[len] == '/') {
56 len++;
57 modulePath[len] = '\0';
58 break;
61 mypid = GetCurrentProcessId();
62 #else
63 if (getcwd(modulePath, sizeof(modulePath)/sizeof(char)-1)) {
64 if (!modulePath[0]) strcpy(modulePath, "/tmp/");
65 else {
66 if (modulePath[strlen(modulePath)-1] != '/') strcat(modulePath, "/");
68 } else strcpy(modulePath, "/tmp/");
69 mypid = getpid();
70 #endif
71 if (dlogFNTouched < 0) dlogfSetFile("debug.log");
72 if (dbgLogWriteToScreen < 0) dlogfSetStdErr(0);
73 initialized = 1;
77 void dlogfDeinit (void) {
78 if (dlogFile) fclose(dlogFile);
79 dlogFile = NULL;
83 void dlogfSetStdErr (int doIt) {
84 #ifdef WINNT
85 if (doIt) {
86 SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), ENABLE_PROCESSED_INPUT);
87 SetConsoleMode(GetStdHandle(STD_ERROR_HANDLE), ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT);
89 #endif
90 dbgLogWriteToScreen = doIt ? 1 : 0;
94 void dlogfSetFile (const char *fname) {
95 dlogFNTouched = 1;
96 if (dbgLogFileName) free(dbgLogFileName);
97 dbgLogFileName = NULL;
98 if (!fname || !fname[0]) return;
99 char buf[8192];
100 buf[0] = '\0';
101 #ifdef WINNT
102 if (fname[0] != '/' && fname[0] != '\\' && (strlen(fname) < 3 || fname[1] != ':')) strcpy(buf, modulePath);
103 #else
104 if (fname[0] != '/') strcpy(buf, modulePath);
105 #endif
106 strcat(buf, fname);
107 dbgLogFileName = malloc((strlen(buf)+1)*sizeof(char));
108 if (dbgLogFileName) strcpy(dbgLogFileName, buf);
112 #define DBG_TMP_BUF_SIZE 65536
113 static char *fmtBuf (const char *sbuf, const char *pfx) {
114 static char buf[DBG_TMP_BUF_SIZE*4+1024];
115 const char *p = sbuf;
116 char *d = buf;
117 size_t left = sizeof(buf)-4;
118 int lastWasN = 0, plen = strlen(pfx);
119 strcpy(d, pfx); left -= plen; d += plen;
120 while (left > 0 && *p) {
121 while (*p == '\r') p++;
122 if (lastWasN) {
123 #if WINNT
124 *d++ = '\r'; *d++ = '\n'; left -= 2;
125 #else
126 *d++ = '\n'; left--;
127 #endif
128 if (left < strlen(pfx)) break; // no room
129 strcpy(d, pfx); left -= plen; d += plen;
130 lastWasN = 0;
132 if (*p == '\n') {
133 lastWasN = 1;
134 p++;
135 continue;
137 *d++ = *p++; left--;
139 #if WINNT
140 if (d == buf || d[-1] != '\n') strcpy(d, "\r\n"); else *d = '\0';
141 #else
142 if (d == buf || d[-1] != '\n') strcpy(d, "\n"); else *d = '\0';
143 #endif
144 return buf;
148 void dlogfVA (const char *fmt, va_list inap) {
149 va_list ap2;
150 static char buf[DBG_TMP_BUF_SIZE+1024];
151 const char *xbuf = NULL;
152 #ifdef WINNT
153 SYSTEMTIME t;
154 #else
155 time_t t;
156 struct tm bt;
157 #endif
158 char timebuf[64];
160 if (!fmt) return;
162 if (!initialized) dlogfInit();
164 memset(buf, 0, DBG_TMP_BUF_SIZE);
165 va_copy(ap2, inap);
166 vsnprintf(buf, DBG_TMP_BUF_SIZE, fmt, ap2);
167 va_end(ap2);
168 buf[DBG_TMP_BUF_SIZE] = '\0';
170 #ifdef WINNT
171 GetLocalTime(&t);
172 sprintf(timebuf, "[%05i] %04i/%02i/%02i %02i:%02i:%02i: ",
173 (int)mypid,
174 t.wYear, t.wMonth, t.wDay,
175 t.wHour, t.wMinute, t.wSecond
177 #else
178 t = time(NULL);
179 localtime_r(&t, &bt);
180 sprintf(timebuf, "[%05i] %04i/%02i/%02i %02i:%02i:%02i: ",
181 (int)mypid,
182 bt.tm_year+1900, bt.tm_mon, bt.tm_mday,
183 bt.tm_hour, bt.tm_min, bt.tm_sec
185 #endif
187 xbuf = fmtBuf(buf, timebuf);
189 if (dbgLogFileName) {
190 if (!dlogFile) dlogFile = fopen(dbgLogFileName, "ab");
191 if (dlogFile) {
192 fputs(xbuf, dlogFile);
193 fflush(dlogFile);
197 if (dbgLogWriteToScreen) {
198 #ifdef WINNT
199 HANDLE oh = GetStdHandle(STD_ERROR_HANDLE);
200 if (oh != INVALID_HANDLE_VALUE) WriteConsole(oh, xbuf, strlen(xbuf), &wr, NULL);
201 #else
202 fputs(xbuf, stderr);
203 fflush(stderr);
205 #endif
209 void __attribute__((format(printf, 1, 2))) dlogf (const char *fmt, ...) {
210 va_list ap;
211 va_start(ap, fmt);
212 dlogfVA(fmt, ap);
213 va_end(ap);
217 #endif /* NO_DEBUG_LOG */
219 #ifdef __cplusplus
221 #endif