1 /*
2 * Copyright (C) Volition, Inc. 1999. All rights reserved.
3 *
4 * All source code herein is the property of Volition, Inc. You may not sell
5 * or otherwise commercially exploit the source or things you created based on the
6 * source.
7 *
8 */
9
10
11
12 #ifndef WIN32 // Goober5000
13
14 #ifndef NDEBUG
15
16 #include <stdio.h>
17 #include <stdarg.h>
18 #include <string.h>
19
20 #include "globalincs/pstypes.h"
21 #include "osapi/outwnd.h"
22 #include "osapi/osapi.h"
23 #include "osapi/osregistry.h"
24 #include "cfile/cfilesystem.h"
25 #include "globalincs/systemvars.h"
26 #include "globalincs/globals.h"
27 #include "parse/parselo.h"
28
29
30
31 void outwnd_print(const char *id = NULL, const char *temp = NULL);
32
33 #define MAX_LINE_WIDTH 128
34
35 bool outwnd_inited = false;
36 ubyte Outwnd_no_filter_file = 0; // 0 = .cfg file found, 1 = not found and warning not printed yet, 2 = not found and warning printed
37
38 struct outwnd_filter_struct {
39 char name[NAME_LENGTH];
40 bool enabled;
41
outwnd_filter_structoutwnd_filter_struct42 outwnd_filter_struct()
43 : enabled( false )
44 {
45 name[ 0 ] = 0;
46 }
47 };
48
49 SCP_vector<outwnd_filter_struct> OutwndFilter;
50
51 int outwnd_filter_loaded = 0;
52
53 // used for file logging
54 int Log_debug_output_to_file = 1;
55 FILE *Log_fp = NULL;
56 char *FreeSpace_logfilename = "fs2_open.log";
57
58 SCP_string safe_string;
59
60
load_filter_info(void)61 void load_filter_info(void)
62 {
63 FILE *fp = NULL;
64 char pathname[MAX_PATH_LEN];
65 char inbuf[NAME_LENGTH+4];
66 outwnd_filter_struct new_filter;
67 int z;
68
69 outwnd_filter_loaded = 1;
70
71 snprintf( pathname, MAX_PATH_LEN, "%s/%s/%s/%s", detect_home(), Osreg_user_dir, Pathtypes[CF_TYPE_DATA].path, NOX("debug_filter.cfg") );
72
73 fp = fopen(pathname, "rt");
74
75 if (!fp) {
76 Outwnd_no_filter_file = 1;
77
78 memset( &new_filter, 0, sizeof(outwnd_filter_struct) );
79 strcpy_s( new_filter.name, "error" );
80 new_filter.enabled = true;
81
82 OutwndFilter.push_back( new_filter );
83
84 memset( &new_filter, 0, sizeof(outwnd_filter_struct) );
85 strcpy_s( new_filter.name, "general" );
86 new_filter.enabled = true;
87
88 OutwndFilter.push_back( new_filter );
89
90 memset( &new_filter, 0, sizeof(outwnd_filter_struct) );
91 strcpy_s( new_filter.name, "warning" );
92 new_filter.enabled = true;
93
94 OutwndFilter.push_back( new_filter );
95
96 return;
97 }
98
99 Outwnd_no_filter_file = 0;
100
101 while ( fgets(inbuf, NAME_LENGTH+3, fp) ) {
102 memset( &new_filter, 0, sizeof(outwnd_filter_struct) );
103
104 if (*inbuf == '+')
105 new_filter.enabled = true;
106 else if (*inbuf == '-')
107 new_filter.enabled = false;
108 else
109 continue; // skip everything else
110
111 z = strlen(inbuf) - 1;
112 if (inbuf[z] == '\n')
113 inbuf[z] = 0;
114
115 Assert( strlen(inbuf+1) < NAME_LENGTH );
116 strcpy_s(new_filter.name, inbuf + 1);
117
118 if ( !stricmp(new_filter.name, "error") ) {
119 new_filter.enabled = true;
120 } else if ( !stricmp(new_filter.name, "general") ) {
121 new_filter.enabled = true;
122 } else if ( !stricmp(new_filter.name, "warning") ) {
123 new_filter.enabled = true;
124 }
125
126 OutwndFilter.push_back( new_filter );
127 }
128
129 if ( ferror(fp) && !feof(fp) )
130 nprintf(("Error", "Error reading \"%s\"\n", pathname));
131
132 fclose(fp);
133 }
134
save_filter_info(void)135 void save_filter_info(void)
136 {
137 FILE *fp = NULL;
138 char pathname[MAX_PATH_LEN];
139
140 if ( !outwnd_filter_loaded )
141 return;
142
143 if (Outwnd_no_filter_file)
144 return; // No file, don't save
145
146
147 snprintf( pathname, MAX_PATH_LEN, "%s/%s/%s/%s", detect_home(), Osreg_user_dir, Pathtypes[CF_TYPE_DATA].path, NOX("debug_filter.cfg") );
148
149 fp = fopen(pathname, "wt");
150
151 if (fp) {
152 for (uint i = 0; i < OutwndFilter.size(); i++)
153 fprintf(fp, "%c%s\n", OutwndFilter[i].enabled ? '+' : '-', OutwndFilter[i].name);
154
155 fclose(fp);
156 }
157 }
158
outwnd_printf2(const char * format,...)159 void outwnd_printf2(const char *format, ...)
160 {
161 SCP_string temp;
162 va_list args;
163
164 if (format == NULL)
165 return;
166
167 va_start(args, format);
168 vsprintf(temp, format, args);
169 va_end(args);
170
171 outwnd_print("General", temp.c_str());
172 }
173
outwnd_printf(const char * id,const char * format,...)174 void outwnd_printf(const char *id, const char *format, ...)
175 {
176 SCP_string temp;
177 va_list args;
178
179 if ( (id == NULL) || (format == NULL) )
180 return;
181
182 va_start(args, format);
183 vsprintf(temp, format, args);
184 va_end(args);
185
186 outwnd_print(id, temp.c_str());
187 }
188
outwnd_print(const char * id,const char * tmp)189 void outwnd_print(const char *id, const char *tmp)
190 {
191 uint i;
192
193 if ( (id == NULL) || (tmp == NULL) )
194 return;
195
196 if ( !outwnd_inited ) {
197 fputs("outwnd not initialized yet... \n", stdout);
198 fputs(tmp, stdout);
199 fflush(stdout);
200
201 return;
202 }
203
204 if (Outwnd_no_filter_file == 1) {
205 Outwnd_no_filter_file = 2;
206
207 outwnd_print( "general", "==========================================================================\n" );
208 outwnd_print( "general", "DEBUG SPEW: No debug_filter.cfg found, so only general, error, and warning\n" );
209 outwnd_print( "general", "categories can be shown and no debug_filter.cfg info will be saved.\n" );
210 outwnd_print( "general", "==========================================================================\n" );
211 }
212
213 if ( !id )
214 id = "General";
215
216 for (i = 0; i < OutwndFilter.size(); i++) {
217 if ( !stricmp(id, OutwndFilter[i].name) )
218 break;
219 }
220
221 // id found that isn't in the filter list yet
222 if ( i == OutwndFilter.size() ) {
223 // Only create new filters if there was a filter file
224 if (Outwnd_no_filter_file)
225 return;
226
227 Assert( strlen(id)+1 < NAME_LENGTH );
228 outwnd_filter_struct new_filter;
229
230 strcpy_s(new_filter.name, id);
231 new_filter.enabled = true;
232
233 OutwndFilter.push_back( new_filter );
234 save_filter_info();
235 }
236
237 if ( !OutwndFilter[i].enabled )
238 return;
239
240 if (Log_debug_output_to_file) {
241 if (Log_fp != NULL) {
242 fputs(tmp, Log_fp);
243 fflush(Log_fp);
244 }
245 } else {
246 fputs(tmp, stdout);
247 fflush(stdout);
248 }
249 }
250
251
outwnd_init(int display_under_freespace_window)252 void outwnd_init(int display_under_freespace_window)
253 {
254 outwnd_inited = true;
255
256 char pathname[MAX_PATH_LEN];
257
258 /* Set where the log file is going to go */
259 // Zacam: Set various conditions based on what type of log to generate.
260 if (Fred_running) {
261 FreeSpace_logfilename = "fred2_open.log";
262 } else if (Is_standalone) {
263 FreeSpace_logfilename = "fs2_standalone.log";
264 } else {
265 FreeSpace_logfilename = "fs2_open.log";
266 }
267
268 snprintf(pathname, MAX_PATH_LEN, "%s/%s/%s/%s", detect_home(), Osreg_user_dir, Pathtypes[CF_TYPE_DATA].path, FreeSpace_logfilename);
269
270 if (Log_fp == NULL) {
271 Log_fp = fopen(pathname, "wb");
272
273 if (Log_fp == NULL) {
274 outwnd_printf("Error", "Error opening %s\n", pathname);
275 } else {
276 time_t timedate = time(NULL);
277 char datestr[50];
278
279 memset( datestr, 0, sizeof(datestr) );
280 strftime( datestr, sizeof(datestr)-1, "%a %b %d %H:%M:%S %Y", localtime(&timedate) );
281
282 printf("Future debug output directed to: %s\n", pathname);
283 outwnd_printf("General", "Opened log '%s', %s ...\n", pathname, datestr);
284 }
285 }
286 }
287
outwnd_close()288 void outwnd_close()
289 {
290 if (Log_fp != NULL) {
291 time_t timedate = time(NULL);
292 char datestr[50];
293
294 memset( datestr, 0, sizeof(datestr) );
295 strftime( datestr, sizeof(datestr)-1, "%a %b %d %H:%M:%S %Y", localtime(&timedate) );
296
297 outwnd_printf("General", "... Log closed, %s\n", datestr);
298
299 fclose(Log_fp);
300 Log_fp = NULL;
301 }
302
303 outwnd_inited = false;
304 }
305
safe_point_print(const char * format,...)306 void safe_point_print(const char *format, ...)
307 {
308 SCP_string temp;
309 va_list args;
310
311 va_start(args, format);
312 vsprintf(temp, format, args);
313 va_end(args);
314
315 safe_string = temp;
316 }
317
safe_point(const char * file,int line,const char * format,...)318 void safe_point(const char *file, int line, const char *format, ...)
319 {
320 safe_point_print("last safepoint: %s, %d; [%s]", file, line, format);
321 }
322
323 #endif // NDEBUG
324
325 #endif // Goober5000 - #ifndef WIN32
326