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