1 /*
2 * Copyright (c) 2013 Hugh Bailey <obs.jim@gmail.com>
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17 #include <stdio.h>
18 #include <stdlib.h>
19
20 #include "c99defs.h"
21 #include "base.h"
22
23 #ifdef _DEBUG
24 static int log_output_level = LOG_DEBUG;
25 #else
26 static int log_output_level = LOG_INFO;
27 #endif
28
29 static int crashing = 0;
30 static void *log_param = NULL;
31 static void *crash_param = NULL;
32
def_log_handler(int log_level,const char * format,va_list args,void * param)33 static void def_log_handler(int log_level, const char *format, va_list args,
34 void *param)
35 {
36 char out[4096];
37 vsnprintf(out, sizeof(out), format, args);
38
39 if (log_level <= log_output_level) {
40 switch (log_level) {
41 case LOG_DEBUG:
42 fprintf(stdout, "debug: %s\n", out);
43 fflush(stdout);
44 break;
45
46 case LOG_INFO:
47 fprintf(stdout, "info: %s\n", out);
48 fflush(stdout);
49 break;
50
51 case LOG_WARNING:
52 fprintf(stdout, "warning: %s\n", out);
53 fflush(stdout);
54 break;
55
56 case LOG_ERROR:
57 fprintf(stderr, "error: %s\n", out);
58 fflush(stderr);
59 }
60 }
61
62 UNUSED_PARAMETER(param);
63 }
64
65 #ifdef _MSC_VER
66 #define NORETURN __declspec(noreturn)
67 #else
68 #define NORETURN __attribute__((noreturn))
69 #endif
70
def_crash_handler(const char * format,va_list args,void * param)71 NORETURN static void def_crash_handler(const char *format, va_list args,
72 void *param)
73 {
74 vfprintf(stderr, format, args);
75 exit(0);
76
77 UNUSED_PARAMETER(param);
78 }
79
80 static log_handler_t log_handler = def_log_handler;
81 static void (*crash_handler)(const char *, va_list, void *) = def_crash_handler;
82
base_get_log_handler(log_handler_t * handler,void ** param)83 void base_get_log_handler(log_handler_t *handler, void **param)
84 {
85 if (handler)
86 *handler = log_handler;
87 if (param)
88 *param = log_param;
89 }
90
base_set_log_handler(log_handler_t handler,void * param)91 void base_set_log_handler(log_handler_t handler, void *param)
92 {
93 if (!handler)
94 handler = def_log_handler;
95
96 log_param = param;
97 log_handler = handler;
98 }
99
base_set_crash_handler(void (* handler)(const char *,va_list,void *),void * param)100 void base_set_crash_handler(void (*handler)(const char *, va_list, void *),
101 void *param)
102 {
103 crash_param = param;
104 crash_handler = handler;
105 }
106
bcrash(const char * format,...)107 void bcrash(const char *format, ...)
108 {
109 va_list args;
110
111 if (crashing) {
112 fputs("Crashed in the crash handler", stderr);
113 exit(2);
114 }
115
116 crashing = 1;
117 va_start(args, format);
118 crash_handler(format, args, crash_param);
119 va_end(args);
120 }
121
blogva(int log_level,const char * format,va_list args)122 void blogva(int log_level, const char *format, va_list args)
123 {
124 log_handler(log_level, format, args, log_param);
125 }
126
blog(int log_level,const char * format,...)127 void blog(int log_level, const char *format, ...)
128 {
129 va_list args;
130
131 va_start(args, format);
132 blogva(log_level, format, args);
133 va_end(args);
134 }
135