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

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

#1 add test code and fix debug and logging error

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