1 /*
2  * log.c - Logging facility. Overhauled for libretro use.
3  *
4  * Written by
5  *  Ettore Perazzoli <ettore@comm2000.it>
6  *
7  * This file is part of VICE, the Versatile Commodore Emulator.
8  * See README for copyright notice.
9  *
10  *  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License as published by
12  *  the Free Software Foundation; either version 2 of the License, or
13  *  (at your option) any later version.
14  *
15  *  This program is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU General Public License for more details.
19  *
20  *  You should have received a copy of the GNU General Public License
21  *  along with this program; if not, write to the Free Software
22  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
23  *  02111-1307  USA.
24  *
25  */
26 
27 /* #define DBGLOGGING */
28 
29 #include "vice.h"
30 
31 #include <stdarg.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 
36 #include <libretro.h>
37 
38 #include "archdep.h"
39 #include "cmdline.h"
40 #include "lib.h"
41 #include "log.h"
42 #include "resources.h"
43 #include "util.h"
44 
45 #ifdef DBGLOGGING
46 #define DBG(x) printf x
47 #else
48 #define DBG(x)
49 #endif
50 
51 static FILE *log_file = NULL;
52 
53 static char **logs = NULL;
54 static log_t num_logs = 0;
55 
56 static int log_enabled = 1; /* cv: this flag allows to temporarly disable all logging */
57 static int verbose = 0;
58 static int locked = 0;
59 
60 extern retro_log_printf_t log_cb;
61 static char log_buf[ 4096 ]; /*create this here in case of tiny stack*/
62 
63 /* ------------------------------------------------------------------------- */
64 
65 
66 ////static char *log_file_name = NULL;
67 
68 ////static void log_file_open(void)
69 ////{
70 ////    if (log_file_name == NULL || *log_file_name == 0) {
71 ////        log_file = archdep_open_default_log_file();
72 ////    } else {
73 ////#ifndef __OS2__
74 ////        if (strcmp(log_file_name, "-") == 0) {
75 ////            log_file = stdout;
76 ////        } else
77 ////#endif
78 ////        log_file = fopen(log_file_name, MODE_WRITE_TEXT);
79 ////    }
80 ////    /* flush all data direct to the output stream. */
81 ////    if (log_file) {
82 ////        setbuf(log_file, NULL);
83 ////    }
84 ////}
85 
86 ////static int set_log_file_name(const char *val, void *param)
87 ////{
88 ////    if (locked) {
89 ////        return 0;
90 ////    }
91 
92 ////    if (util_string_set(&log_file_name, val) < 0) {
93 ////        return 0;
94 ////    }
95 
96 ////    if (log_file) {
97 ////        fclose(log_file);
98 ////        log_file_open();
99 ////    }
100 
101 ////    return 0;
102 ////}
103 
104 ////static int log_verbose_opt(const char *param, void *extra_param)
105 ////{
106 ////    verbose = vice_ptr_to_int(extra_param);
107 ////    return 0;
108 ////}
109 
110 ////static int log_silent_opt(const char *param, void *extra_param)
111 ////{
112 ////    int silent = vice_ptr_to_int(extra_param);
113 ////    log_enabled = ! silent;
114 ////    return 0;
115 ////}
116 
117 
118 ////int log_set_verbose(int n)
119 ////{
120 ////    if (n) {
121 ////        return log_verbose_opt(NULL, (void*)1);
122 ////    }
123 ////    return log_verbose_opt(NULL, (void*)0);
124 ////}
125 
126 
127 ////int log_set_silent(int n)
128 ////{
129 ////    log_enabled = !n;
130 ////    return 0;
131 ////}
132 
133 
134 
135 ////int log_verbose_init(int argc, char **argv)
136 ////{
137 ////    int i;
138 ////    DBG(("log_verbose_init: %d %s\n", argc, argv[0]));
139 ////    if (argc > 1) {
140 ////        for (i = 1; i < argc; i++) {
141 ////            DBG(("log_verbose_init: %d %s\n", i, argv[i]));
142 ////            if (strcmp("-verbose", argv[i]) == 0) {
143 ////                log_set_verbose(1);
144 ////                break;
145 ////            } else if (strcmp("-silent", argv[1]) == 0) {
146 ////                log_enabled = 0;
147 ////                break;
148 ////            }
149 ////        }
150 ////    }
151 ////    return 0;
152 ////}
153 
154 ////#ifndef __X1541__
155 ////static const resource_string_t resources_string[] = {
156 ////    { "LogFileName", "", RES_EVENT_NO, NULL,
157 ////      &log_file_name, set_log_file_name, NULL },
158 ////    RESOURCE_STRING_LIST_END
159 ////};
160 
161 ////static int log_logfile_opt(const char *param, void *extra_param)
162 ////{
163 ////    locked = 0;
164 ////    set_log_file_name(param, NULL);
165 ////    locked = 1;
166 ////    return 0;
167 ////}
168 
169 ////int log_resources_init(void)
170 ////{
171 ////    return resources_register_string(resources_string);
172 ////}
173 
174 ////void log_resources_shutdown(void)
175 ////{
176 ////    lib_free(log_file_name);
177 ////}
178 
179 ////static const cmdline_option_t cmdline_options[] =
180 ////{
181 ////    { "-logfile", CALL_FUNCTION, CMDLINE_ATTRIB_NEED_ARGS,
182 ////      log_logfile_opt, NULL, NULL, NULL,
183 ////      "<Name>", "Specify log file name" },
184 ////    { "-verbose", CALL_FUNCTION, CMDLINE_ATTRIB_NONE,
185 ////      log_verbose_opt, (void*)1, NULL, NULL,
186 ////      NULL, "Enable verbose log output." },
187 ////    { "-silent", CALL_FUNCTION, CMDLINE_ATTRIB_NONE,
188 ////      log_silent_opt, (void*)1, NULL, NULL,
189 ////      NULL, "Disable verbose log output." },
190 ////    CMDLINE_LIST_END
191 ////};
192 
193 ////int log_cmdline_options_init(void)
194 ////{
195 ////    return cmdline_register_options(cmdline_options);
196 ////}
197 ////#endif
198 
199 /////* ------------------------------------------------------------------------- */
200 
201 ////int log_init_with_fd(FILE *f)
202 ////{
203 ////    if (f == NULL) {
204 ////        return -1;
205 ////    }
206 
207 ////    log_file = f;
208 ////    return 0;
209 ////}
210 
211 ////int log_init(void)
212 ////{
213 ////#if 0
214 ////    /*
215 ////     * The current calling order in main.c (log_init() after processing
216 ////     * resources) makes this break if anything in the resource set_*
217 ////     * functions does a log_open().  On platforms that have no regular
218 ////     * stdout (e.g win32) no logging will be seen.  On win32 startup will
219 ////     * also be preceeded by a modal error requester.  / tlr
220 ////     */
221 ////    if (logs != NULL) {
222 ////        return -1;
223 ////    }
224 ////#endif
225 
226 ////    log_file_open();
227 
228 ////    return (log_file == NULL) ? -1 : 0;
229 ////}
230 
231 ////log_t log_open(const char *id)
232 ////{
233 ////    log_t new_log = 0;
234 ////    log_t i;
235 
236 ////    for (i = 0; i < num_logs; i++) {
237 ////        if (logs[i] == NULL) {
238 ////            new_log = i;
239 ////            break;
240 ////        }
241 ////    }
242 ////    if (i == num_logs) {
243 ////        new_log = num_logs++;
244 ////        logs = lib_realloc(logs, sizeof(*logs) * num_logs);
245 ////    }
246 
247 ////    logs[new_log] = lib_stralloc(id);
248 
249 ////    /* printf("log_open(%s) = %d\n", id, (int)new_log); */
250 ////    return new_log;
251 ////}
252 
253 ////int log_close(log_t log)
254 ////{
255 ////    /* printf("log_close(%d)\n", (int)log); */
256 ////    if (logs[(unsigned int)log] == NULL) {
257 ////        return -1;
258 ////    }
259 
260 ////    lib_free(logs[(unsigned int)log]);
261 ////    logs[(unsigned int)log] = NULL;
262 
263 ////    return 0;
264 ////}
265 
266 ////void log_close_all(void)
267 ////{
268 ////    log_t i;
269 
270 ////    for (i = 0; i < num_logs; i++) {
271 ////        log_close(i);
272 ////    }
273 
274 ////    lib_free(logs);
275 ////    logs = NULL;
276 ////}
277 
278 ////static int log_archdep(const char *logtxt, const char *fmt, va_list ap)
279 ////{
280 ////    /*
281 ////     * ------ Split into single lines ------
282 ////     */
283 ////    int rc = 0;
284 
285 ////    char *txt = lib_mvsprintf(fmt, ap);
286 
287 ////    char *beg = txt;
288 ////    char *end = txt + strlen(txt) + 1;
289 
290 ////    while (beg < end) {
291 ////        char *eol = strchr(beg, '\n');
292 
293 ////        if (eol) {
294 ////            *eol = '\0';
295 ////        }
296 
297 ////        if (archdep_default_logger(*beg ? logtxt : "", beg) < 0) {
298 ////            rc = -1;
299 ////            break;
300 ////        }
301 
302 ////        if (!eol) {
303 ////            break;
304 ////        }
305 
306 ////        beg = eol + 1;
307 ////    }
308 
309 ////    lib_free(txt);
310 
311 ////    return rc;
312 ////}
313 
314 
315 ////static int log_helper(log_t log, unsigned int level, const char *format,
316 ////                      va_list ap)
317 ////{
318 ////    static const char *level_strings[3] = {
319 ////        "",
320 ////        "Warning - ",
321 ////        "Error - "
322 ////    };
323 
324 ////    const signed int logi = (signed int)log;
325 ////    int rc = 0;
326 ////    char *logtxt = NULL;
327 
328 ////    if (!log_enabled) {
329 ////        return 0;
330 ////    }
331 
332 ////    if ((logi != LOG_DEFAULT) && (logi != LOG_ERR)) {
333 ////        if ((logs == NULL) || (logi < 0)|| (logi >= num_logs) || (logs[logi] == NULL)) {
334 ////#ifdef DEBUG
335 ////            log_archdep("log_helper: internal error (invalid id or closed log), messages follows:\n", format, ap);
336 ////#endif
337 ////            return -1;
338 ////        }
339 ////    }
340 
341 ////    if ((logi != LOG_DEFAULT) && (logi != LOG_ERR) && (*logs[logi] != '\0')) {
342 ////        logtxt = lib_msprintf("%s: %s", logs[logi], level_strings[level]);
343 ////    } else {
344 ////        logtxt = lib_msprintf("%s", level_strings[level]);
345 ////    }
346 
347 ////    if (log_file == NULL) {
348 ////        rc = log_archdep(logtxt, format, ap);
349 ////    } else {
350 ////#ifdef ARCHDEP_EXTRA_LOG_CALL
351 ////        log_archdep(logtxt, format, ap);
352 ////#endif
353 ////        if (fputs(logtxt, log_file) == EOF
354 ////            || vfprintf(log_file, format, ap) < 0
355 ////            || fputc ('\n', log_file) == EOF) {
356 ////            rc = -1;
357 ////        }
358 ////    }
359 
360 ////    lib_free(logtxt);
361 
362 ////    return rc;
363 ////}
364 
365 
log_helper(unsigned int level,const char * format,va_list ap)366 static int log_helper(unsigned int level, const char *format, va_list ap)
367 {
368     int rc;
369 
370 	rc = vsprintf( log_buf, format, ap );
371 
372 	if ( rc >= 0 )
373     {
374 		log_cb(level, "%s\n", log_buf);
375 		++rc;
376 	}
377 
378     return rc;
379 }
380 
log_message(log_t log,const char * format,...)381 int log_message(log_t log, const char *format, ...)
382 {
383     va_list ap;
384     int rc;
385 
386     va_start(ap, format);
387     /*rc = log_helper(log, 0, format, ap);*/
388     rc = log_helper(RETRO_LOG_INFO, format, ap);
389     va_end(ap);
390 
391     return rc;
392 }
393 
log_warning(log_t log,const char * format,...)394 int log_warning(log_t log, const char *format, ...)
395 {
396     va_list ap;
397     int rc;
398 
399     va_start(ap, format);
400     /*rc = log_helper(log, 1, format, ap);*/
401     rc = log_helper(RETRO_LOG_WARN, format, ap);
402     va_end(ap);
403 
404     return rc;
405 }
406 
log_error(log_t log,const char * format,...)407 int log_error(log_t log, const char *format, ...)
408 {
409     va_list ap;
410     int rc;
411 
412     va_start(ap, format);
413     /*rc = log_helper(log, 2, format, ap);*/
414     rc = log_helper(RETRO_LOG_ERROR, format, ap);
415     va_end(ap);
416 
417     return rc;
418 }
419 
log_debug(const char * format,...)420 int log_debug(const char *format, ...)
421 {
422     va_list ap;
423     int rc;
424 
425     va_start(ap, format);
426     /*rc = log_helper(LOG_DEFAULT, 0, format, ap);*/
427     rc = log_helper(RETRO_LOG_DEBUG, format, ap);
428     va_end(ap);
429 
430     return rc;
431 }
432 
log_verbose(const char * format,...)433 int log_verbose(const char *format, ...)
434 {
435     va_list ap;
436     int rc = 0;
437 
438     va_start(ap, format);
439     if (verbose) {
440         /*rc = log_helper(LOG_DEFAULT, 0, format, ap);*/
441         log_helper(RETRO_LOG_INFO, format, ap);
442     }
443     va_end(ap);
444 
445     return rc;
446 }
447 
448 /*
449 void log_enable(int on)
450 {
451     log_enabled = on;
452 }
453 */
454 
455 
456 /* ------------------------------------------------------------------------- */
457 
458 /* stubs */
log_resources_init(void)459 int log_resources_init(void) {return 0;}
log_resources_shutdown(void)460 void log_resources_shutdown(void) {}
log_cmdline_options_init(void)461 int log_cmdline_options_init(void) {return 0;}
log_init(void)462 int log_init(void) {return 0;}
log_init_with_fd(FILE * f)463 int log_init_with_fd(FILE *f) {return 0;}
log_open(const char * id)464 log_t log_open(const char *id) {return 0;}
log_close(log_t log)465 int log_close(log_t log) {return 0;}
log_close_all(void)466 void log_close_all(void) {}
log_enable(int on)467 void log_enable(int on) {}
log_set_verbose(int n)468 int log_set_verbose(int n) {verbose=n?1:0;return 0;}
log_verbose_init(int argc,char ** argv)469 int log_verbose_init(int argc, char **argv) {return 0;}
470 
471