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

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

#1 add doxygen prologue to .c file

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