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

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

#1 documentation with doxygen

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