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

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

#1 add debug util and arrange some code

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