source: libcf/trunk/src/cf_debug.c@ 16

Last change on this file since 16 was 16, checked in by cheese, 11 years ago

#1 add function for non-context debugging message printing

File size: 6.1 KB
Line 
1/**
2 * cf_debug.c
3 */
4#include "cf_debug.h"
5#include "cf_local.h"
6
7#include <stdlib.h>
8#include <ctype.h>
9#include <stdarg.h>
10#include <string.h>
11
12#ifdef _WIN32
13# include <io.h>
14#else
15# include <unistd.h>
16#endif
17
18#define IS_READABLE_CHAR(__c) (' ' <= __c && __c <= '~')
19
20#define CHECK_INVALID_CTX(__ctx) \
21 if (__ctx == NULL) \
22 return CF_ERROR_DEBUG_INVALID_CTX
23
24#define GET_CTX_OSTREAM(__ctx) \
25 ((((CF_DEBUG_CTX *)__ctx)->fp == NULL) \
26 ? stderr \
27 : ((CF_DEBUG_CTX *)__ctx)->fp)
28
29typedef struct __cf_debug_callstack__
30{
31 char file[NAME_LENGTH + 1];
32 char func[NAME_LENGTH + 1];
33 int line;
34
35 struct __cf_debug_callstack__ * caller;
36} S_CF_DEBUG_CALLSTACK, CF_DEBUG_CALLSTACK;
37
38/* implementation of CF_Debug_Ctx */
39typedef struct __cf_debug_ctx__
40{
41 char file[NAME_LENGTH + 1];
42 char func[NAME_LENGTH + 1];
43 int line;
44
45 FILE * fp;
46
47 CF_DEBUG_CALLSTACK callstack;
48} S_CF_DEBUG_CTX, CF_DEBUG_CTX;
49
50int
51CF_Debug_Local_Print (FILE * fp,
52 const char * file,
53 const char * func,
54 const int line,
55 const char * fmt,
56 va_list valist)
57{
58 fprintf (fp, "[DEBUG][%s:%d][%s] ", file, line, func);
59 vfprintf (fp, fmt, valist);
60
61 return CF_OK;
62}
63
64int
65CF_Debug_Local_PrintBin (FILE * fp,
66 const char * file,
67 const char * func,
68 const int line,
69 const unsigned char * bin,
70 const int len)
71{
72 int i, j;
73
74 for (i = 0 ; i < len ; i += 16)
75 {
76 fprintf (fp, "[DEBUG][%s:%d][%s] ", file, line, func);
77 fprintf (fp, "%06x : ", i);
78
79 for (j = 0 ; j < 16 ; j++)
80 {
81 if (i+j < len)
82 fprintf (fp, "%02x ", bin[i+j]);
83 else
84 fprintf (fp, " ");
85 }
86 fprintf (fp, " ");
87
88 for (j = 0 ; j < 16 ; j++)
89 {
90 if (i+j < len)
91 fprintf (fp, "%c", IS_READABLE_CHAR(bin[i+j]) ? bin[i+j] : '.');
92 }
93 fprintf (fp, "\n");
94 }
95
96 return CF_OK;
97}
98
99CF_Debug_Ctx
100CF_Debug_CreateCtx (void)
101{
102 CF_DEBUG_CTX * ctx = NULL;
103
104 ctx = (CF_DEBUG_CTX *) calloc (sizeof (CF_DEBUG_CTX), 1);
105
106 return (CF_Debug_Ctx) ctx;
107}
108
109int
110CF_Debug_DestroyCtx (CF_Debug_Ctx ctx)
111{
112 CF_DEBUG_CTX * context = (CF_DEBUG_CTX *) ctx;
113 CF_DEBUG_CALLSTACK * pop = NULL;
114 CF_DEBUG_CALLSTACK * next = NULL;
115
116 CHECK_INVALID_CTX (ctx);
117
118 if (context->fp != NULL)
119 fclose (context->fp);
120
121 for (pop = next = context->callstack.caller ; pop ; pop = next)
122 {
123 next = next->caller;
124 free (pop);
125 }
126
127 free (context);
128
129 return CF_OK;
130}
131
132int
133CF_Debug_SetOutputFD (CF_Debug_Ctx ctx,
134 int fd)
135{
136 int result = 0;
137 int dupfd = 0;
138
139 CF_DEBUG_CTX * context = (CF_DEBUG_CTX *) ctx;
140 FILE * fp = NULL;
141
142 CHECK_INVALID_CTX (ctx);
143
144 TRY
145 {
146 dupfd = dup (fd);
147 if (dupfd < 0)
148 {
149 result = -1;
150 TRY_BREAK;
151 }
152
153 fp = fdopen (dupfd, "a+");
154 if (fp == NULL)
155 {
156 close (dupfd);
157 result = -2;
158 TRY_BREAK;
159 }
160
161 context->fp = fp;
162 }
163 CATCH_IF (result < 0)
164 {
165 return CF_ERROR_DEBUG_SET_OUTPUT_FD;
166 }
167
168 return CF_OK;
169}
170
171int
172CF_Debug_Print (FILE * fp,
173 const char * file,
174 const char * func,
175 const int line,
176 const char * fmt, ...)
177{
178 va_list valist;
179
180 va_start (valist, fmt);
181 CF_Debug_Local_Print (fp, file, func, line, fmt, valist);
182 va_end (valist);
183
184 return CF_OK;
185}
186
187int
188CF_Debug_PrintBin (FILE * fp,
189 const char * file,
190 const char * func,
191 const int line,
192 const unsigned char * bin,
193 const int len,
194 const char * fmt, ...)
195{
196 va_list valist;
197
198 va_start (valist, fmt);
199 CF_Debug_Local_Print (fp, file, func, line, fmt, valist);
200 va_end (valist);
201
202 CF_Debug_Local_PrintBin (fp, file, func, line, bin, len);
203
204 return CF_OK;
205}
206
207int
208CF_Debug_UpdateCtx (CF_Debug_Ctx ctx,
209 const char * file,
210 const char * func,
211 const int line)
212{
213 CF_DEBUG_CTX * context = (CF_DEBUG_CTX *) ctx;
214
215 CHECK_INVALID_CTX (ctx);
216
217 strncpy (context->file, file, strlen (file));
218 strncpy (context->func, func, strlen (func));
219 context->line = line;
220
221 return CF_OK;
222}
223
224int
225CF_Debug_Trace (CF_Debug_Ctx ctx,
226 const char * fmt, ...)
227{
228 va_list valist;
229 CF_DEBUG_CTX * context = (CF_DEBUG_CTX *) ctx;
230
231 CHECK_INVALID_CTX (ctx);
232
233 va_start (valist, fmt);
234 CF_Debug_Local_Print (GET_CTX_OSTREAM (context),
235 context->file,
236 context->func,
237 context->line,
238 fmt, valist);
239 va_end (valist);
240
241 return CF_OK;
242}
243
244int
245CF_Debug_TraceBin (CF_Debug_Ctx ctx,
246 const unsigned char * bin,
247 const int len,
248 const char * fmt, ...)
249{
250 va_list valist;
251 FILE * fp = NULL;
252 CF_DEBUG_CTX * context = (CF_DEBUG_CTX *) ctx;
253
254 CHECK_INVALID_CTX (ctx);
255
256 va_start (valist, fmt);
257 CF_Debug_Local_Print (GET_CTX_OSTREAM (context),
258 context->file,
259 context->func,
260 context->line,
261 fmt, valist);
262 va_end (valist);
263
264 CF_Debug_Local_PrintBin (context->fp,
265 context->file,
266 context->func,
267 context->line,
268 bin, len);
269
270 return CF_OK;
271}
272
273int
274CF_Debug_CallStackPush (CF_Debug_Ctx ctx,
275 const char * file,
276 const char * func,
277 const int line)
278{
279 CF_DEBUG_CTX * context = (CF_DEBUG_CTX *) ctx;
280 CF_DEBUG_CALLSTACK * push = NULL;
281
282 CHECK_INVALID_CTX (ctx);
283
284 push = (CF_DEBUG_CALLSTACK *) calloc (sizeof (CF_DEBUG_CALLSTACK), 1);
285 if (push == NULL)
286 return CF_ERROR_DEBUG_PUSH_CALLSTACK;
287
288 /* push to callstack */
289 sprintf (push->file, "%s", file);
290 sprintf (push->func, "%s", func);
291 push->line = line;
292 push->caller = context->callstack.caller;
293 context->callstack.caller = push;
294
295 CF_Debug_UpdateCtx (ctx, file, func, line);
296
297 return CF_OK;
298}
299
300int
301CF_Debug_CallStackPop (CF_Debug_Ctx ctx,
302 CF_Debug_CallStack * callstack)
303{
304 CF_DEBUG_CTX * context = (CF_DEBUG_CTX *) ctx;
305 CF_DEBUG_CALLSTACK * pop = NULL;
306
307 CHECK_INVALID_CTX (ctx);
308
309 pop = context->callstack.caller;
310 if (pop == NULL)
311 return CF_ERROR_DEBUG_POP_CALLSTACK;
312
313 if (callstack != NULL)
314 {
315 sprintf (callstack->file , "%s", pop->file);
316 sprintf (callstack->function, "%s", pop->func);
317 callstack->line = pop->line;
318 }
319
320 memset (context->file, 0x00, sizeof (context->file));
321 memset (context->func, 0x00, sizeof (context->func));
322 context->line = 0;
323
324 /* restore current context */
325 if (pop->caller != NULL)
326 {
327 CF_Debug_UpdateCtx (ctx,
328 pop->caller->file,
329 pop->caller->func,
330 pop->caller->line);
331 }
332
333 context->callstack.caller = pop->caller;
334 free (pop);
335
336 return CF_OK;
337}
Note: See TracBrowser for help on using the repository browser.