1 /*
2 * $Id$
3 *
4 * Copyright (C) 2009 Rutger Hofman, VU Amsterdam
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 * 02111-1307, USA.
20 *
21 * Written by Rutger Hofman
22 */
23
24 #include <sysdep.h>
25
26 #include <stdarg.h>
27 #include <errno.h>
28 #include <string.h>
29 #include <stdbool.h>
30
31 #include <urjtag/log.h>
32 #include <urjtag/error.h>
33 #include <urjtag/jtag.h>
34
35 urj_error_state_t urj_error_state;
36
37 static int stderr_vprintf (const char *fmt, va_list ap);
38 static int stdout_vprintf (const char *fmt, va_list ap);
39
40 urj_log_state_t urj_log_state =
41 {
42 .level = URJ_LOG_LEVEL_NORMAL,
43 .out_vprintf = stdout_vprintf,
44 .err_vprintf = stderr_vprintf,
45 };
46
47 static int
stderr_vprintf(const char * fmt,va_list ap)48 stderr_vprintf(const char *fmt, va_list ap)
49 {
50 return vfprintf (stderr, fmt, ap);
51 }
52
53 static int
stdout_vprintf(const char * fmt,va_list ap)54 stdout_vprintf(const char *fmt, va_list ap)
55 {
56 int r = vfprintf (stdout, fmt, ap);
57
58 fflush (stdout);
59
60 return r;
61 }
62
63 static int
log_printf(int (* p)(const char *,va_list),const char * fmt,...)64 log_printf (int (*p) (const char *, va_list), const char *fmt, ...)
65 {
66 va_list ap;
67 int r;
68
69 va_start (ap, fmt);
70 r = (*p) (fmt, ap);
71 va_end (ap);
72
73 return r;
74 }
75
76 int
urj_do_log(urj_log_level_t level,const char * file,size_t line,const char * func,const char * fmt,...)77 urj_do_log (urj_log_level_t level, const char *file, size_t line,
78 const char *func, const char *fmt, ...)
79 {
80 int (*p) (const char *fmt, va_list ap);
81 va_list ap;
82 int r = 0;
83
84 if (level < urj_log_state.level)
85 return 0;
86
87 if (level < URJ_LOG_LEVEL_WARNING)
88 p = urj_log_state.out_vprintf;
89 else
90 p = urj_log_state.err_vprintf;
91
92 if (level == URJ_LOG_LEVEL_WARNING || level == URJ_LOG_LEVEL_ERROR
93 || level <= URJ_LOG_LEVEL_DETAIL)
94 r += log_printf (p, "%s: ", urj_log_level_string (level));
95
96 if (urj_log_state.level <= URJ_LOG_LEVEL_DEBUG)
97 r += log_printf (p, "%s:%i %s(): ", file, line, func);
98
99 va_start (ap, fmt);
100 r += (*p) (fmt, ap);
101 va_end (ap);
102
103 return r;
104 }
105
106 urj_error_t
urj_error_get(void)107 urj_error_get (void)
108 {
109 return urj_error_state.errnum;
110 }
111
112 void
urj_error_reset(void)113 urj_error_reset (void)
114 {
115 urj_error_state.errnum = URJ_ERROR_OK;
116 }
117
118 static const struct {
119 const urj_log_level_t level;
120 const char *name;
121 } levels[] = {
122 #define L(LVL, lvl) { URJ_LOG_LEVEL_##LVL, #lvl, }
123 L(ALL, all),
124 L(COMM, comm),
125 L(DEBUG, debug),
126 L(DETAIL, detail),
127 L(NORMAL, normal),
128 L(WARNING, warning),
129 L(ERROR, error),
130 L(SILENT, silent),
131 #undef L
132 };
133
134 const char *
urj_log_level_string(urj_log_level_t level)135 urj_log_level_string (urj_log_level_t level)
136 {
137 size_t i;
138
139 for (i = 0; i < ARRAY_SIZE (levels); ++i)
140 if (levels[i].level == level)
141 return levels[i].name;
142
143 return "unknown";
144 }
145
146 urj_log_level_t
urj_string_log_level(const char * slevel)147 urj_string_log_level (const char *slevel)
148 {
149 size_t i;
150
151 for (i = 0; i < ARRAY_SIZE (levels); ++i)
152 if (!strcmp (levels[i].name, slevel))
153 return levels[i].level;
154
155 return -1;
156 }
157
158 const char *
urj_error_string(urj_error_t err)159 urj_error_string (urj_error_t err)
160 {
161 switch (err)
162 {
163 case URJ_ERROR_OK: return "no error";
164 case URJ_ERROR_ALREADY: return "already defined";
165 case URJ_ERROR_OUT_OF_MEMORY: return "out of memory";
166 case URJ_ERROR_NO_CHAIN: return "no chain";
167 case URJ_ERROR_NO_PART: return "no part";
168 case URJ_ERROR_NO_ACTIVE_INSTRUCTION: return "no active instruction";
169 case URJ_ERROR_NO_DATA_REGISTER: return "no data register";
170 case URJ_ERROR_INVALID: return "invalid parameter";
171 case URJ_ERROR_NOTFOUND: return "not found";
172 case URJ_ERROR_NO_BUS_DRIVER: return "no bus driver";
173 case URJ_ERROR_BUFFER_EXHAUSTED: return "buffer exhausted";
174 case URJ_ERROR_ILLEGAL_STATE: return "illegal state";
175 case URJ_ERROR_ILLEGAL_TRANSITION: return "illegal state transition";
176 case URJ_ERROR_OUT_OF_BOUNDS: return "out of bounds";
177 case URJ_ERROR_TIMEOUT: return "timeout";
178 case URJ_ERROR_UNSUPPORTED: return "unsupported";
179 case URJ_ERROR_SYNTAX: return "syntax";
180 case URJ_ERROR_FILEIO: return "file I/O";
181
182 case URJ_ERROR_IO: return "I/O error from OS";
183 case URJ_ERROR_FTD: return "ftdi/ftd2xx error";
184 case URJ_ERROR_USB: return "libusb error";
185
186 case URJ_ERROR_BUS: return "bus";
187 case URJ_ERROR_BUS_DMA: return "bus DMA";
188
189 case URJ_ERROR_FLASH: return "flash";
190 case URJ_ERROR_FLASH_DETECT: return "flash detect";
191 case URJ_ERROR_FLASH_PROGRAM: return "flash program";
192 case URJ_ERROR_FLASH_ERASE: return "flash erase";
193 case URJ_ERROR_FLASH_LOCK: return "flash lock";
194 case URJ_ERROR_FLASH_UNLOCK: return "flash unlock";
195
196 case URJ_ERROR_BSDL_VHDL: return "vhdl subsystem";
197 case URJ_ERROR_BSDL_BSDL: return "bsdl subsystem";
198
199 case URJ_ERROR_BFIN: return "blackfin";
200
201 case URJ_ERROR_PLD: return "pld subsystem";
202
203 case URJ_ERROR_UNIMPLEMENTED: return "unimplemented";
204
205 case URJ_ERROR_FIRMWARE: return "firmware";
206 }
207
208 return "UNDEFINED ERROR";
209 }
210
211 const char *
urj_error_describe(void)212 urj_error_describe (void)
213 {
214 static char msg[URJ_ERROR_MSG_LEN + 1024 + 256 + 20];
215
216 if (urj_error_state.errnum == URJ_ERROR_IO)
217 {
218 snprintf (msg, sizeof msg, "%s: %s %s",
219 "system error", strerror(urj_error_state.sys_errno),
220 urj_error_state.msg);
221 }
222 else
223 {
224 snprintf (msg, sizeof msg, "%s: %s",
225 urj_error_string (urj_error_state.errnum),
226 urj_error_state.msg);
227 }
228
229 return msg;
230 }
231
232 void
urj_log_error_describe(urj_log_level_t level)233 urj_log_error_describe (urj_log_level_t level)
234 {
235 if (urj_error_get () == URJ_ERROR_OK)
236 return;
237
238 urj_do_log (level,
239 urj_error_state.file, urj_error_state.line,
240 urj_error_state.function,
241 "%s\n", urj_error_describe ());
242
243 urj_error_reset ();
244 }
245