Sun, 20 Jun 2004 13:46:00 +0200
trunk: changeset 1585
Oops.
0 | 1 | /* |
2 | * libtu/output.c | |
3 | * | |
36 | 4 | * Copyright (c) Tuomo Valkonen 1999-2002. |
53 | 5 | * |
6 | * You may distribute and modify this library under the terms of either | |
7 | * the Clarified Artistic License or the GNU LGPL, version 2.1 or later. | |
0 | 8 | */ |
9 | ||
55 | 10 | #if defined(HAS_SYSTEM_ASPRINTF) |
11 | #define _GNU_SOURCE | |
12 | #endif | |
13 | ||
0 | 14 | #include <stdio.h> |
15 | #include <stdlib.h> | |
16 | #include <errno.h> | |
17 | #include <strings.h> | |
18 | #include <string.h> | |
19 | ||
70 | 20 | #include "misc.h" |
21 | #include "output.h" | |
22 | #include "util.h" | |
0 | 23 | |
35 | 24 | #if !defined(HAS_SYSTEM_ASPRINTF) |
59 | 25 | #include "snprintf_2.2/snprintf.h" |
25 | 26 | #endif |
27 | ||
0 | 28 | |
52 | 29 | static void default_warn_handler(const char *message); |
30 | ||
0 | 31 | |
32 | static bool verbose_mode=FALSE; | |
33 | static int verbose_indent_lvl=0; | |
34 | static bool progname_enable=TRUE; | |
52 | 35 | static WarnHandler *current_warn_handler=default_warn_handler; |
0 | 36 | |
37 | #define INDENTATOR_LENGTH 4 | |
38 | ||
39 | static char indentator[]={' ', ' ', ' ', ' '}; | |
40 | ||
35 | 41 | static void do_dispatch_message(const char *message); |
42 | ||
0 | 43 | |
44 | void verbose(const char *p, ...) | |
45 | { | |
62 | 46 | va_list args; |
47 | ||
48 | va_start(args, p); | |
49 | ||
50 | verbose_v(p, args); | |
51 | ||
52 | va_end(args); | |
0 | 53 | } |
62 | 54 | |
0 | 55 | |
56 | void verbose_v(const char *p, va_list args) | |
57 | { | |
62 | 58 | int i; |
59 | ||
60 | if(verbose_mode){ | |
61 | for(i=0; i<verbose_indent_lvl; i++) | |
62 | writef(stdout, indentator, INDENTATOR_LENGTH); | |
63 | ||
64 | vprintf(p, args); | |
65 | fflush(stdout); | |
66 | } | |
0 | 67 | } |
68 | ||
69 | ||
70 | void verbose_enable(bool enable) | |
71 | { | |
62 | 72 | verbose_mode=enable; |
0 | 73 | } |
74 | ||
75 | ||
76 | int verbose_indent(int depth) | |
77 | { | |
62 | 78 | int old=verbose_indent_lvl; |
79 | ||
80 | if(depth>=0) | |
81 | verbose_indent_lvl=depth; | |
82 | ||
83 | return old; | |
0 | 84 | } |
62 | 85 | |
0 | 86 | |
87 | void warn_progname_enable(bool enable) | |
88 | { | |
62 | 89 | progname_enable=enable; |
0 | 90 | } |
91 | ||
92 | ||
93 | static void put_prog_name() | |
94 | { | |
62 | 95 | const char*progname; |
96 | ||
97 | if(!progname_enable) | |
98 | return; | |
99 | ||
100 | progname=prog_execname(); | |
101 | ||
102 | if(progname==NULL) | |
103 | return; | |
104 | ||
105 | fprintf(stderr, "%s: ", (char*)progname); | |
0 | 106 | } |
107 | ||
27 | 108 | /* warn |
109 | */ | |
0 | 110 | |
35 | 111 | |
112 | static void fallback_warn() | |
113 | { | |
62 | 114 | put_prog_name(); |
115 | fprintf(stderr, "Oops. Error string compilation failed: %s", | |
116 | strerror(errno)); | |
35 | 117 | } |
62 | 118 | |
119 | ||
25 | 120 | #define CALL_V(NAME, ARGS) \ |
62 | 121 | do { va_list args; va_start(args, p); NAME ARGS; va_end(args); } while(0) |
27 | 122 | |
35 | 123 | #define DO_DISPATCH(NAME, ARGS) \ |
62 | 124 | do{ \ |
125 | char *msg; \ | |
126 | if((msg=NAME ARGS)!=NULL){ \ | |
127 | do_dispatch_message(msg); \ | |
128 | free(msg);\ | |
129 | }else{ \ | |
130 | fallback_warn(); \ | |
131 | } \ | |
132 | }while(0) | |
25 | 133 | |
33 | 134 | |
31 | 135 | void libtu_asprintf(char **ret, const char *p, ...) |
136 | { | |
62 | 137 | CALL_V(vasprintf, (ret, p, args)); |
31 | 138 | } |
139 | ||
140 | ||
141 | void libtu_vasprintf(char **ret, const char *p, va_list args) | |
142 | { | |
62 | 143 | vasprintf(ret, p, args); |
31 | 144 | } |
145 | ||
33 | 146 | |
0 | 147 | void warn(const char *p, ...) |
148 | { | |
62 | 149 | CALL_V(warn_v, (p, args)); |
25 | 150 | } |
151 | ||
152 | ||
153 | void warn_obj(const char *obj, const char *p, ...) | |
154 | { | |
62 | 155 | CALL_V(warn_obj_v, (obj, p, args)); |
25 | 156 | } |
157 | ||
158 | ||
159 | void warn_obj_line(const char *obj, int line, const char *p, ...) | |
160 | { | |
62 | 161 | CALL_V(warn_obj_line_v, (obj, line, p, args)); |
25 | 162 | } |
163 | ||
164 | ||
165 | void warn_obj_v(const char *obj, const char *p, va_list args) | |
166 | { | |
62 | 167 | warn_obj_line_v(obj, -1, p, args); |
25 | 168 | } |
169 | ||
170 | ||
0 | 171 | void warn_v(const char *p, va_list args) |
172 | { | |
62 | 173 | DO_DISPATCH(errmsg_v, (p, args)); |
0 | 174 | } |
175 | ||
176 | ||
177 | void warn_obj_line_v(const char *obj, int line, const char *p, va_list args) | |
178 | { | |
62 | 179 | DO_DISPATCH(errmsg_obj_line_v, (obj, line, p, args)); |
0 | 180 | } |
181 | ||
182 | ||
27 | 183 | void warn_err() |
184 | { | |
62 | 185 | DO_DISPATCH(errmsg_err, ()); |
27 | 186 | } |
187 | ||
188 | ||
189 | void warn_err_obj(const char *obj) | |
190 | { | |
62 | 191 | DO_DISPATCH(errmsg_err_obj, (obj)); |
27 | 192 | } |
193 | ||
194 | void warn_err_obj_line(const char *obj, int line) | |
195 | { | |
62 | 196 | DO_DISPATCH(errmsg_err_obj_line, (obj, line)); |
27 | 197 | } |
198 | ||
199 | ||
200 | /* errmsg | |
201 | */ | |
202 | ||
203 | #define CALL_V_RET(NAME, ARGS) \ | |
62 | 204 | char *ret; va_list args; va_start(args, p); ret=NAME ARGS; \ |
205 | va_end(args); return ret; | |
27 | 206 | |
207 | ||
208 | char* errmsg(const char *p, ...) | |
209 | { | |
62 | 210 | CALL_V_RET(errmsg_v, (p, args)); |
27 | 211 | } |
212 | ||
213 | ||
214 | char *errmsg_obj(const char *obj, const char *p, ...) | |
215 | { | |
62 | 216 | CALL_V_RET(errmsg_obj_v, (obj, p, args)); |
27 | 217 | } |
218 | ||
219 | ||
220 | char *errmsg_obj_line(const char *obj, int line, const char *p, ...) | |
221 | { | |
62 | 222 | CALL_V_RET(errmsg_obj_line_v, (obj, line, p, args)); |
27 | 223 | } |
224 | ||
225 | ||
226 | char* errmsg_obj_v(const char *obj, const char *p, va_list args) | |
227 | { | |
62 | 228 | return errmsg_obj_line_v(obj, -1, p, args); |
27 | 229 | } |
230 | ||
231 | ||
232 | char *errmsg_v(const char *p, va_list args) | |
233 | { | |
62 | 234 | char *res; |
235 | vasprintf(&res, p, args); | |
236 | return res; | |
27 | 237 | } |
238 | ||
239 | ||
25 | 240 | char *errmsg_obj_line_v(const char *obj, int line, const char *p, va_list args) |
241 | { | |
62 | 242 | char *res1=NULL, *res2, *res3; |
243 | ||
244 | if(obj!=NULL){ | |
245 | if(line>0) | |
246 | asprintf(&res1, TR("%s:%d: "), obj, line); | |
247 | else | |
248 | asprintf(&res1, "%s: ", obj); | |
249 | }else{ | |
250 | if(line>0) | |
251 | asprintf(&res1, TR("%d: "), line); | |
252 | } | |
253 | vasprintf(&res2, p, args); | |
254 | if(res1!=NULL){ | |
255 | if(res2==NULL) | |
256 | return NULL; | |
257 | res3=scat(res1, res2); | |
258 | free(res1); | |
259 | free(res2); | |
260 | return res3; | |
261 | } | |
262 | return res2; | |
25 | 263 | } |
264 | ||
265 | ||
266 | char *errmsg_err() | |
267 | { | |
62 | 268 | char *res; |
269 | asprintf(&res, "%s\n", strerror(errno)); | |
270 | return res; | |
25 | 271 | } |
272 | ||
273 | ||
274 | char *errmsg_err_obj(const char *obj) | |
275 | { | |
62 | 276 | char *res; |
277 | if(obj!=NULL) | |
278 | asprintf(&res, "%s: %s\n", obj, strerror(errno)); | |
279 | else | |
280 | asprintf(&res, "%s\n", strerror(errno)); | |
281 | return res; | |
0 | 282 | } |
283 | ||
284 | ||
25 | 285 | char *errmsg_err_obj_line(const char *obj, int line) |
286 | { | |
62 | 287 | char *res; |
288 | if(obj!=NULL){ | |
289 | if(line>0) | |
290 | asprintf(&res, TR("%s:%d: %s\n"), obj, line, strerror(errno)); | |
291 | else | |
292 | asprintf(&res, "%s: %s\n", obj, strerror(errno)); | |
293 | }else{ | |
294 | if(line>0) | |
295 | asprintf(&res, TR("%d: %s\n"), line, strerror(errno)); | |
296 | else | |
297 | asprintf(&res, TR("%s\n"), strerror(errno)); | |
298 | } | |
299 | return res; | |
25 | 300 | } |
31 | 301 | |
25 | 302 | |
0 | 303 | /* die |
304 | */ | |
305 | ||
35 | 306 | |
0 | 307 | void die(const char *p, ...) |
308 | { | |
62 | 309 | set_warn_handler(NULL); |
310 | CALL_V(die_v, (p, args)); | |
0 | 311 | } |
312 | ||
313 | ||
314 | void die_v(const char *p, va_list args) | |
315 | { | |
62 | 316 | set_warn_handler(NULL); |
317 | warn_v(p, args); | |
318 | exit(EXIT_FAILURE); | |
0 | 319 | } |
320 | ||
321 | ||
322 | void die_obj(const char *obj, const char *p, ...) | |
323 | { | |
62 | 324 | set_warn_handler(NULL); |
325 | CALL_V(die_obj_v, (obj, p, args)); | |
0 | 326 | } |
327 | ||
328 | ||
329 | void die_obj_line(const char *obj, int line, const char *p, ...) | |
330 | { | |
62 | 331 | set_warn_handler(NULL); |
332 | CALL_V(die_obj_line_v, (obj, line, p, args)); | |
0 | 333 | } |
334 | ||
335 | ||
336 | void die_obj_v(const char *obj, const char *p, va_list args) | |
337 | { | |
62 | 338 | set_warn_handler(NULL); |
339 | warn_obj_v(obj, p, args); | |
340 | exit(EXIT_FAILURE); | |
0 | 341 | } |
342 | ||
343 | ||
344 | void die_obj_line_v(const char *obj, int line, const char *p, va_list args) | |
345 | { | |
62 | 346 | set_warn_handler(NULL); |
347 | warn_obj_line_v(obj, line, p, args); | |
348 | exit(EXIT_FAILURE); | |
0 | 349 | } |
350 | ||
351 | ||
352 | void die_err() | |
353 | { | |
62 | 354 | set_warn_handler(NULL); |
355 | warn_err(); | |
356 | exit(EXIT_FAILURE); | |
0 | 357 | } |
358 | ||
359 | ||
360 | void die_err_obj(const char *obj) | |
361 | { | |
62 | 362 | set_warn_handler(NULL); |
363 | warn_err_obj(obj); | |
364 | exit(EXIT_FAILURE); | |
0 | 365 | } |
366 | ||
367 | ||
368 | void die_err_obj_line(const char *obj, int line) | |
369 | { | |
62 | 370 | set_warn_handler(NULL); |
371 | warn_err_obj_line(obj, line); | |
372 | exit(EXIT_FAILURE); | |
0 | 373 | } |
35 | 374 | |
375 | ||
376 | static void default_warn_handler(const char *message) | |
377 | { | |
62 | 378 | put_prog_name(); |
379 | fprintf(stderr, "%s", message); | |
380 | putc('\n', stderr); | |
35 | 381 | } |
382 | ||
383 | ||
384 | static void do_dispatch_message(const char *message) | |
385 | { | |
62 | 386 | if(current_warn_handler!=NULL) |
387 | current_warn_handler(message); | |
388 | else | |
389 | default_warn_handler(message); | |
35 | 390 | } |
391 | ||
392 | ||
393 | WarnHandler *set_warn_handler(WarnHandler *handler) | |
394 | { | |
62 | 395 | WarnHandler *old=current_warn_handler; |
396 | current_warn_handler=(handler!=NULL ? handler : default_warn_handler); | |
397 | return old; | |
35 | 398 | } |