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

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

#1 add more omitted code and enhance stability

File size: 4.7 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#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_context__
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
50void
51CF_Debug_VA_Message (CF_DEBUG_CTX * ctx,
52 const char * fmt,
53 va_list valist)
54{
55 fprintf (GET_CTX_OSTREAM (ctx), "[DEBUG][%s %s(%d)] ",
56 ctx->file,
57 ctx->func,
58 ctx->line);
59 vfprintf (GET_CTX_OSTREAM (ctx), fmt, valist);
60}
61
62CF_Debug_Ctx
63CF_Debug_CreateCtx (void)
64{
65 CF_DEBUG_CTX * ctx = NULL;
66
67 ctx = (CF_DEBUG_CTX *) calloc (sizeof (CF_DEBUG_CTX), 1);
68
69 return (CF_Debug_Ctx) ctx;
70}
71
72int
73CF_Debug_DestroyCtx (CF_Debug_Ctx ctx)
74{
75 CF_DEBUG_CTX * context = (CF_DEBUG_CTX *) ctx;
76 CF_DEBUG_CALLSTACK * pop = NULL;
77 CF_DEBUG_CALLSTACK * next = NULL;
78
79 CHECK_INVALID_CTX (ctx);
80
81 if (context->fp != NULL)
82 fclose (context->fp);
83
84 for (pop = next = context->callstack.caller ; pop ; pop = next)
85 {
86 next = next->caller;
87 free (pop);
88 }
89
90 free (context);
91
92 return CF_OK;
93}
94
95int
96CF_Debug_SetOutputFD (CF_Debug_Ctx ctx,
97 int fd)
98{
99 int result = 0;
100 int dupfd = 0;
101
102 CF_DEBUG_CTX * context = (CF_DEBUG_CTX *) ctx;
103 FILE * fp = NULL;
104
105 CHECK_INVALID_CTX (ctx);
106
107 TRY
108 {
109 dupfd = dup (fd);
110 if (dupfd < 0)
111 {
112 result = -1;
113 TRY_BREAK;
114 }
115
116 fp = fdopen (dupfd, "a+");
117 if (fp == NULL)
118 {
119 close (dupfd);
120 result = -2;
121 TRY_BREAK;
122 }
123
124 context->fp = fp;
125 }
126 CATCH_IF (result < 0)
127 {
128 return CF_ERROR_DEBUG_SET_OUTPUT_FD;
129 }
130
131 return CF_OK;
132}
133
134int
135CF_Debug_Trace (CF_Debug_Ctx ctx,
136 const char * fmt, ...)
137{
138 va_list valist;
139
140 CHECK_INVALID_CTX (ctx);
141
142 va_start (valist, fmt);
143 CF_Debug_VA_Message ((CF_DEBUG_CTX *) ctx, fmt, valist);
144 va_end (valist);
145
146 return CF_OK;
147}
148
149int
150CF_Debug_TraceBin (CF_Debug_Ctx ctx,
151 const unsigned char * bin,
152 const int len,
153 const char * fmt, ...)
154{
155 int i, j;
156 va_list valist;
157 FILE * fp = GET_CTX_OSTREAM (ctx);
158
159 CHECK_INVALID_CTX (ctx);
160
161 va_start (valist, fmt);
162 CF_Debug_VA_Message ((CF_DEBUG_CTX *) ctx, fmt, valist);
163
164 for (i = 0 ; i < len ; i += 16)
165 {
166 fprintf (fp, "[DEBUG][%s %s(%d)] ", __FILE__, __func__, __LINE__);
167 fprintf (fp, "%06x : ", i);
168
169 for (j = 0 ; j < 16 ; j++)
170 {
171 if (i+j < len)
172 fprintf (fp, "%02x ", bin[i+j]);
173 else
174 fprintf (fp, " ");
175 }
176 fprintf (fp, " ");
177
178 for (j = 0 ; j < 16 ; j++)
179 {
180 if (i+j < len)
181 fprintf (fp, "%c", IS_READABLE_CHAR(bin[i+j]) ? bin[i+j] : '.');
182 }
183 fprintf (fp, "\n");
184 }
185
186 return CF_OK;
187}
188
189int
190CF_Debug_CallStackPush (CF_Debug_Ctx ctx,
191 const char * file,
192 const char * func,
193 const int line)
194{
195 CF_DEBUG_CTX * context = (CF_DEBUG_CTX *) ctx;
196 CF_DEBUG_CALLSTACK * push = NULL;
197
198 CHECK_INVALID_CTX (ctx);
199
200 push = (CF_DEBUG_CALLSTACK *) calloc (sizeof (CF_DEBUG_CALLSTACK), 1);
201 if (push == NULL)
202 return CF_ERROR_DEBUG_PUSH_CALLSTACK;
203
204 /* push to callstack */
205 sprintf (push->file, "%s", file);
206 sprintf (push->func, "%s", func);
207 push->line = line;
208 push->caller = context->callstack.caller;
209 context->callstack.caller = push;
210
211 /* set current context */
212 sprintf (context->file, "%s", file);
213 sprintf (context->func, "%s", func);
214 context->line = line;
215
216 return CF_OK;
217}
218
219int
220CF_Debug_CallStackPop (CF_Debug_Ctx ctx,
221 CF_Debug_CallStack * callstack)
222{
223 CF_DEBUG_CTX * context = (CF_DEBUG_CTX *) ctx;
224 CF_DEBUG_CALLSTACK * pop = NULL;
225
226 CHECK_INVALID_CTX (ctx);
227
228 pop = context->callstack.caller;
229 if (pop == NULL)
230 return CF_ERROR_DEBUG_POP_CALLSTACK;
231
232 if (callstack != NULL)
233 {
234 sprintf (callstack->function, "%s", pop->func);
235 callstack->line = pop->line;
236 }
237
238 memset (context->file, 0x00, sizeof (context->file));
239 memset (context->func, 0x00, sizeof (context->func));
240 context->line = 0;
241
242 /* restore current context */
243 if (pop->caller != NULL)
244 {
245 sprintf (context->file, "%s", pop->caller->file);
246 sprintf (context->func, "%s", pop->caller->func);
247 context->line = pop->caller->line;
248 context->callstack.caller = pop->caller;
249 }
250
251 free (pop);
252
253 return CF_OK;
254}
Note: See TracBrowser for help on using the repository browser.