1 /* Pioneers - Implementation of the excellent Settlers of Catan board game.
2  *   Go buy a copy.
3  *
4  * Copyright (C) 1999 Dave Cole
5  * Copyright (C) 2003 Bas Wijnen <shevek@fmf.nl>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21 
22 #include "config.h"
23 #include <stdio.h>
24 #include <time.h>
25 #include <string.h>
26 #include <ctype.h>
27 
28 #include "log.h"
29 #include "driver.h"
30 
31 static gboolean debug_enabled = FALSE;
32 
33 /* The default function to use to write messages, when nothing else has been
34  * specified.
35  */
36 #define LOG_FUNC_DEFAULT log_message_string_console
37 
log_set_func(LogFunc func)38 void log_set_func(LogFunc func)
39 {
40 	if (func != NULL)
41 		driver->log_write = func;
42 	else
43 		driver->log_write = LOG_FUNC_DEFAULT;
44 }
45 
log_set_func_default(void)46 void log_set_func_default(void)
47 {
48 	driver->log_write = LOG_FUNC_DEFAULT;
49 }
50 
log_message_string_console(gint msg_type,const gchar * text)51 void log_message_string_console(gint msg_type, const gchar * text)
52 {
53 	const gchar *prefix = NULL;
54 
55 	switch (msg_type) {
56 	case MSG_ERROR:
57 		/* Log prefix */
58 		prefix = _("*ERROR* ");
59 		break;
60 	case MSG_INFO:
61 		/* Log prefix for info message */
62 		prefix = "- ";
63 		break;
64 	case MSG_CHAT:
65 		/* Log prefix */
66 		prefix = _("Chat: ");
67 		break;
68 	case MSG_RESOURCE:
69 		/* Log prefix */
70 		prefix = _("Resource: ");
71 		break;
72 	case MSG_BUILD:
73 		/* Log prefix */
74 		prefix = _("Build: ");
75 		break;
76 	case MSG_DICE:
77 		/* Log prefix */
78 		prefix = _("Dice: ");
79 		break;
80 	case MSG_STEAL:
81 		/* Log prefix */
82 		prefix = _("Steal: ");
83 		break;
84 	case MSG_TRADE:
85 		/* Log prefix */
86 		prefix = _("Trade: ");
87 		break;
88 	case MSG_DEVCARD:
89 		/* Log prefix */
90 		prefix = _("Development: ");
91 		break;
92 	case MSG_LARGESTARMY:
93 		/* Log prefix */
94 		prefix = _("Army: ");
95 		break;
96 	case MSG_LONGESTROAD:
97 		/* Log prefix */
98 		prefix = _("Road: ");
99 		break;
100 	case MSG_BEEP:
101 		/* Log prefix */
102 		prefix = _("*BEEP* ");
103 		break;
104 	case MSG_TIMESTAMP:
105 		break;		/* No prefix */
106 	case MSG_PLAYER1:
107 		/* Log prefix */
108 		prefix = _("Player 1: ");
109 		break;
110 	case MSG_PLAYER2:
111 		/* Log prefix */
112 		prefix = _("Player 2: ");
113 		break;
114 	case MSG_PLAYER3:
115 		/* Log prefix */
116 		prefix = _("Player 3: ");
117 		break;
118 	case MSG_PLAYER4:
119 		/* Log prefix */
120 		prefix = _("Player 4: ");
121 		break;
122 	case MSG_PLAYER5:
123 		/* Log prefix */
124 		prefix = _("Player 5: ");
125 		break;
126 	case MSG_PLAYER6:
127 		/* Log prefix */
128 		prefix = _("Player 6: ");
129 		break;
130 	case MSG_PLAYER7:
131 		/* Log prefix */
132 		prefix = _("Player 7: ");
133 		break;
134 	case MSG_PLAYER8:
135 		/* Log prefix */
136 		prefix = _("Player 8: ");
137 		break;
138 	case MSG_SPECTATOR_CHAT:
139 		/* Log prefix */
140 		prefix = _("Spectator: ");
141 		break;
142 	default:
143 		/* Log prefix */
144 		prefix = _("** UNKNOWN MESSAGE TYPE ** ");
145 	}
146 
147 	if (prefix)
148 		fprintf(stderr, "%s%s", prefix, text);
149 	else
150 		fprintf(stderr, "%s", text);
151 }
152 
debug_type(int type)153 static const char *debug_type(int type)
154 {
155 	switch (type) {
156 	case MSG_ERROR:
157 		return "ERROR";
158 	case MSG_INFO:
159 		return "INFO";
160 	case MSG_CHAT:
161 		return "CHAT";
162 	case MSG_RESOURCE:
163 		return "RESOURCE";
164 	case MSG_BUILD:
165 		return "BUILD";
166 	case MSG_DICE:
167 		return "DICE";
168 	case MSG_STEAL:
169 		return "STEAL";
170 	case MSG_TRADE:
171 		return "TRADE";
172 	case MSG_DEVCARD:
173 		return "DEVCARD";
174 	case MSG_LARGESTARMY:
175 		return "LARGESTARMY";
176 	case MSG_LONGESTROAD:
177 		return "LONGESTROAD";
178 	case MSG_BEEP:
179 		return "BEEP";
180 	case MSG_PLAYER1:
181 		return "PLAYER1";
182 	case MSG_PLAYER2:
183 		return "PLAYER2";
184 	case MSG_PLAYER3:
185 		return "PLAYER3";
186 	case MSG_PLAYER4:
187 		return "PLAYER4";
188 	case MSG_PLAYER5:
189 		return "PLAYER5";
190 	case MSG_PLAYER6:
191 		return "PLAYER6";
192 	case MSG_PLAYER7:
193 		return "PLAYER7";
194 	case MSG_PLAYER8:
195 		return "PLAYER8";
196 	case MSG_SPECTATOR_CHAT:
197 		return "SPECTATOR_CHAT";
198 	default:
199 		return "*UNKNOWN MESSAGE TYPE*";
200 	}
201 }
202 
log_message_chat(const gchar * player_name,const gchar * joining_text,gint msg_type,const gchar * chat)203 void log_message_chat(const gchar * player_name,
204 		      const gchar * joining_text, gint msg_type,
205 		      const gchar * chat)
206 {
207 	if (driver->log_write && driver->log_write != LOG_FUNC_DEFAULT) {
208 		log_message(MSG_INFO, "%s%s", player_name, joining_text);
209 		debug("[%s] %s", debug_type(msg_type), chat);
210 
211 		/* No timestamp here: */
212 		driver->log_write(msg_type, chat);
213 		driver->log_write(msg_type, "\n");
214 	} else {
215 		log_message(msg_type, "%s%s%s\n", player_name,
216 			    joining_text, chat);
217 	}
218 }
219 
log_message(gint msg_type,const gchar * fmt,...)220 void log_message(gint msg_type, const gchar * fmt, ...)
221 {
222 	gchar *text;
223 	gchar *timestamp;
224 	va_list ap;
225 	time_t t;
226 	struct tm *alpha;
227 
228 	va_start(ap, fmt);
229 	text = g_strdup_vprintf(fmt, ap);
230 	va_end(ap);
231 
232 	debug("[%s] %s", debug_type(msg_type), text);
233 
234 	t = time(NULL);
235 	alpha = localtime(&t);
236 
237 	timestamp = g_strdup_printf("%02d:%02d:%02d ", alpha->tm_hour,
238 				    alpha->tm_min, alpha->tm_sec);
239 
240 	if (driver->log_write) {
241 		driver->log_write(MSG_TIMESTAMP, timestamp);
242 		driver->log_write(msg_type, text);
243 	} else {
244 		LOG_FUNC_DEFAULT(MSG_TIMESTAMP, timestamp);
245 		LOG_FUNC_DEFAULT(msg_type, text);
246 	}
247 	g_free(text);
248 	g_free(timestamp);
249 }
250 
set_enable_debug(gboolean enabled)251 void set_enable_debug(gboolean enabled)
252 {
253 	debug_enabled = enabled;
254 }
255 
debug(const gchar * fmt,...)256 void debug(const gchar * fmt, ...)
257 {
258 	va_list ap;
259 	gchar *buff;
260 	gint idx;
261 	time_t t;
262 	struct tm *alpha;
263 
264 	if (!debug_enabled)
265 		return;
266 
267 	va_start(ap, fmt);
268 	buff = g_strdup_vprintf(fmt, ap);
269 	va_end(ap);
270 
271 	t = time(NULL);
272 	alpha = localtime(&t);
273 
274 	g_print("%02d:%02d:%02d ", alpha->tm_hour,
275 		alpha->tm_min, alpha->tm_sec);
276 
277 	for (idx = 0; buff[idx] != '\0'; idx++) {
278 		if (isprint(buff[idx]))
279 			g_print("%c", buff[idx]);
280 		else
281 			switch (buff[idx]) {
282 			case '\n':
283 				g_print("\\n");
284 				break;
285 			case '\r':
286 				g_print("\\r");
287 				break;
288 			case '\t':
289 				g_print("\\t");
290 				break;
291 			default:
292 				g_print("\\x%02x", (buff[idx] & 0xff));
293 				break;
294 			}
295 	}
296 	g_print("\n");
297 	g_free(buff);
298 }
299